summaryrefslogtreecommitdiffstats
path: root/src/gui
diff options
context:
space:
mode:
authorAndreas Aardal Hanssen <andreas.aardal.hanssen@nokia.com>2009-06-18 12:28:29 (GMT)
committerAndreas Aardal Hanssen <andreas.aardal.hanssen@nokia.com>2009-06-18 12:28:29 (GMT)
commit0d839e3655d985920aff81882bd444605d97c21c (patch)
tree249092fc5bcb4d0c448474114efa60416679de5e /src/gui
parentac8bf5ec1f99d0e00e3ffefe53306c0d511376bf (diff)
downloadQt-0d839e3655d985920aff81882bd444605d97c21c.zip
Qt-0d839e3655d985920aff81882bd444605d97c21c.tar.gz
Qt-0d839e3655d985920aff81882bd444605d97c21c.tar.bz2
Changes after first round of code reviewing.
This change removes all code that handles ItemIgnoresTransformations from QGraphicsView, and changes the APIs of the scene index intersectors. Reviewed-by: Alexis
Diffstat (limited to 'src/gui')
-rw-r--r--src/gui/graphicsview/qgraphicsitem.cpp33
-rw-r--r--src/gui/graphicsview/qgraphicsitem_p.h9
-rw-r--r--src/gui/graphicsview/qgraphicsscene.cpp141
-rw-r--r--src/gui/graphicsview/qgraphicsscene.h17
-rw-r--r--src/gui/graphicsview/qgraphicsscene_p.h4
-rw-r--r--src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp96
-rw-r--r--src/gui/graphicsview/qgraphicsscenebsptreeindex.h2
-rw-r--r--src/gui/graphicsview/qgraphicsscenebsptreeindex_p.h5
-rw-r--r--src/gui/graphicsview/qgraphicssceneindex.cpp216
-rw-r--r--src/gui/graphicsview/qgraphicssceneindex.h2
-rw-r--r--src/gui/graphicsview/qgraphicssceneindex_p.h19
-rw-r--r--src/gui/graphicsview/qgraphicsview.cpp161
-rw-r--r--src/gui/graphicsview/qgraphicsview_p.h7
13 files changed, 368 insertions, 344 deletions
diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp
index 593d7be..75683d8 100644
--- a/src/gui/graphicsview/qgraphicsitem.cpp
+++ b/src/gui/graphicsview/qgraphicsitem.cpp
@@ -857,6 +857,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
@@ -951,11 +956,6 @@ void QGraphicsItemPrivate::setParentItemHelper(QGraphicsItem *newParent)
// Deliver post-change notification
q->itemChange(QGraphicsItem::ItemParentHasChanged, newParentVariant);
- if (scene) {
- // Deliver the change to the index
- scene->d_func()->index->itemChanged(q, QGraphicsItem::ItemParentHasChanged, newParentVariant);
- }
-
if (isObject)
emit static_cast<QGraphicsObject *>(q)->parentChanged();
}
@@ -1426,6 +1426,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);
@@ -3577,17 +3579,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);
- //Z Value has changed, we have to notify the index.
- d_ptr->scene->d_func()->index->itemChanged(this, ItemZValueChange, z);
- }
itemChange(ItemZValueHasChanged, newZVariant);
@@ -9655,17 +9660,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;
}
diff --git a/src/gui/graphicsview/qgraphicsitem_p.h b/src/gui/graphicsview/qgraphicsitem_p.h
index 9c1ee4f..1c95a62 100644
--- a/src/gui/graphicsview/qgraphicsitem_p.h
+++ b/src/gui/graphicsview/qgraphicsitem_p.h
@@ -158,6 +158,15 @@ public:
inline virtual ~QGraphicsItemPrivate()
{ }
+ static const QGraphicsItemPrivate *get(const QGraphicsItem *item)
+ {
+ return item->d_ptr;
+ }
+ static QGraphicsItemPrivate *get(QGraphicsItem *item)
+ {
+ return item->d_ptr;
+ }
+
void updateAncestorFlag(QGraphicsItem::GraphicsItemFlag childFlag,
AncestorFlag flag = NoFlag, bool enabled = false, bool root = true);
void setIsMemberOfGroup(bool enabled);
diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp
index 380ac20..55f0f20 100644
--- a/src/gui/graphicsview/qgraphicsscene.cpp
+++ b/src/gui/graphicsview/qgraphicsscene.cpp
@@ -774,41 +774,8 @@ QList<QGraphicsItem *> QGraphicsScenePrivate::itemsAtPosition(const QPoint &scre
{
Q_Q(const QGraphicsScene);
QGraphicsView *view = widget ? qobject_cast<QGraphicsView *>(widget->parentWidget()) : 0;
- QList<QGraphicsItem *> items;
- if (view)
- items = view->items(view->viewport()->mapFromGlobal(screenPos));
- else
- items = q->items(scenePos);
- return items;
-}
-
-/*!
- \internal
-
- Checks if item collides with the path and mode, but also checks that if it
- doesn't collide, maybe its frame rect will.
-*/
-bool QGraphicsScenePrivate::itemCollidesWithPath(QGraphicsItem *item,
- const QPainterPath &path,
- Qt::ItemSelectionMode mode)
-{
- if (item->collidesWithPath(path, mode))
- return true;
- if (item->isWidget()) {
- // Check if this is a window, and if its frame rect collides.
- QGraphicsWidget *widget = static_cast<QGraphicsWidget *>(item);
- if (widget->isWindow()) {
- QRectF frameRect = widget->windowFrameRect();
- QPainterPath framePath;
- framePath.addRect(frameRect);
- bool intersects = path.intersects(frameRect);
- if (mode == Qt::IntersectsItemShape || mode == Qt::IntersectsItemBoundingRect)
- return intersects || path.contains(frameRect.topLeft())
- || framePath.contains(path.elementAt(0));
- return !intersects && path.contains(frameRect.topLeft());
- }
- }
- return false;
+ return q->items(scenePos, Qt::IntersectsItemShape, Qt::AscendingOrder,
+ view ? view->viewportTransform() : QTransform());
}
/*!
@@ -820,7 +787,7 @@ void QGraphicsScenePrivate::storeMouseButtonsForMouseGrabber(QGraphicsSceneMouse
if (event->buttons() & i) {
mouseGrabberButtonDownPos.insert(Qt::MouseButton(i),
mouseGrabberItems.last()->d_ptr->genericMapFromScene(event->scenePos(),
- event->widget()));
+ event->widget()));
mouseGrabberButtonDownScenePos.insert(Qt::MouseButton(i), event->scenePos());
mouseGrabberButtonDownScreenPos.insert(Qt::MouseButton(i), event->screenPos());
}
@@ -1282,6 +1249,8 @@ QGraphicsScene::~QGraphicsScene()
QRectF QGraphicsScene::sceneRect() const
{
Q_D(const QGraphicsScene);
+ /// ### Remove? The growing items bounding rect might be managed
+ // by the scene.
return d->index->indexedRect();
}
void QGraphicsScene::setSceneRect(const QRectF &rect)
@@ -1332,6 +1301,8 @@ void QGraphicsScene::setSceneRect(const QRectF &rect)
void QGraphicsScene::render(QPainter *painter, const QRectF &target, const QRectF &source,
Qt::AspectRatioMode aspectRatioMode)
{
+ // ### Switch to using the recursive rendering algorithm instead.
+
// Default source rect = scene rect
QRectF sourceRect = source;
if (sourceRect.isNull())
@@ -1431,14 +1402,16 @@ void QGraphicsScene::setItemIndexMethod(ItemIndexMethod method)
d->indexMethod = method;
- QList<QGraphicsItem *> oldItems = d->index->items();
+ QList<QGraphicsItem *> oldItems = d->index->items(Qt::AscendingOrder);
delete d->index;
if (method == BspTreeIndex)
d->index = new QGraphicsSceneBspTreeIndex(this);
else
d->index = new QGraphicsSceneLinearIndex(this);
- for (int i = 0; i < oldItems.size(); ++i)
+ for (int i = oldItems.size() - 1; i >= 0; --i)
d->index->addItem(oldItems.at(i));
+
+ d->index->sceneRectChanged(d->sceneRect);
}
/*!
@@ -1476,7 +1449,7 @@ void QGraphicsScene::setItemIndexMethod(ItemIndexMethod method)
int QGraphicsScene::bspTreeDepth() const
{
Q_D(const QGraphicsScene);
- QGraphicsSceneBspTreeIndex *bspTree = qobject_cast<QGraphicsSceneBspTreeIndex*>(d->index);
+ QGraphicsSceneBspTreeIndex *bspTree = qobject_cast<QGraphicsSceneBspTreeIndex *>(d->index);
return bspTree ? bspTree->bspTreeDepth() : 0;
}
void QGraphicsScene::setBspTreeDepth(int depth)
@@ -1487,14 +1460,11 @@ void QGraphicsScene::setBspTreeDepth(int depth)
return;
}
- QGraphicsSceneBspTreeIndex *bspTree = qobject_cast<QGraphicsSceneBspTreeIndex*>(d->index);
+ QGraphicsSceneBspTreeIndex *bspTree = qobject_cast<QGraphicsSceneBspTreeIndex *>(d->index);
if (!bspTree) {
qWarning("QGraphicsScene::setBspTreeDepth: can not apply if indexing method is not BSP");
return;
}
- if (bspTree->bspTreeDepth() == depth)
- return;
-
bspTree->setBspTreeDepth(depth);
}
@@ -1502,37 +1472,21 @@ void QGraphicsScene::setBspTreeDepth(int depth)
\property QGraphicsScene::sortCacheEnabled
\brief whether sort caching is enabled
\since 4.5
+ \obsolete
- When enabled, this property adds a cache that speeds up sorting and
- transformations for scenes with deep hierarchies (i.e., items with many
- levels of descendents), at the cost of using more memory (approx. 100 more
- bytes of memory per item).
-
- Items that are not part of a deep hierarchy suffer no penalty from this
- cache.
+ Since Qt 4.6, this property has no effect.
*/
bool QGraphicsScene::isSortCacheEnabled() const
{
Q_D(const QGraphicsScene);
- QGraphicsSceneBspTreeIndex *bspTree = qobject_cast<QGraphicsSceneBspTreeIndex*>(d->index);
- if (!bspTree) {
- qWarning("QGraphicsScene::isSortCacheEnabled: can not apply if indexing method is not BSP");
- return false;
- }
- return bspTree->d_func()->sortCacheEnabled;
+ return d->sortCacheEnabled;
}
void QGraphicsScene::setSortCacheEnabled(bool enabled)
{
Q_D(QGraphicsScene);
- QGraphicsSceneBspTreeIndex *bspTree = qobject_cast<QGraphicsSceneBspTreeIndex*>(d->index);
- if (!bspTree) {
- qWarning("QGraphicsScene::isSortCacheEnabled: can not apply if indexing method is not BSP");
+ if (d->sortCacheEnabled == enabled)
return;
- }
- if (enabled == bspTree->d_func()->sortCacheEnabled)
- return;
- if ((bspTree->d_func()->sortCacheEnabled = enabled))
- bspTree->d_func()->invalidateSortCache();
+ d->sortCacheEnabled = enabled;
}
/*!
@@ -1544,6 +1498,7 @@ void QGraphicsScene::setSortCacheEnabled(bool enabled)
*/
QRectF QGraphicsScene::itemsBoundingRect() const
{
+ // Does not take untransformable items into account.
QRectF boundingRect;
foreach (QGraphicsItem *item, items())
boundingRect |= item->sceneBoundingRect();
@@ -1558,7 +1513,19 @@ QRectF QGraphicsScene::itemsBoundingRect() const
QList<QGraphicsItem *> QGraphicsScene::items() const
{
Q_D(const QGraphicsScene);
- return d->index->items();
+ return d->index->items(Qt::AscendingOrder);
+}
+
+/*!
+ Returns an ordered list of all items on the scene. \a order decides the
+ sorting.
+
+ \sa addItem(), removeItem()
+*/
+QList<QGraphicsItem *> QGraphicsScene::items(Qt::SortOrder order) const
+{
+ Q_D(const QGraphicsScene);
+ return d->index->items(order);
}
/*!
@@ -1732,6 +1699,7 @@ QList<QGraphicsItem *> QGraphicsScene::collidingItems(const QGraphicsItem *item,
return QList<QGraphicsItem *>();
}
+ // Does not support ItemIgnoresTransformations.
QList<QGraphicsItem *> tmp;
foreach (QGraphicsItem *itemInVicinity, d->index->estimateItems(item->sceneBoundingRect(), Qt::AscendingOrder, QTransform())) {
if (item != itemInVicinity && item->collidesWithItem(itemInVicinity, mode))
@@ -1756,6 +1724,13 @@ QGraphicsItem *QGraphicsScene::itemAt(const QPointF &pos) const
return itemsAtPoint.isEmpty() ? 0 : itemsAtPoint.first();
}
+QGraphicsItem *QGraphicsScene::itemAt(const QPointF &pos, const QTransform &deviceTransform) const
+{
+ QList<QGraphicsItem *> itemsAtPoint = items(pos, Qt::IntersectsItemShape,
+ Qt::AscendingOrder, deviceTransform);
+ return itemsAtPoint.isEmpty() ? 0 : itemsAtPoint.first();
+}
+
/*!
\fn QGraphicsScene::itemAt(qreal x, qreal y) const
\overload
@@ -1831,6 +1806,21 @@ void QGraphicsScene::setSelectionArea(const QPainterPath &path)
*/
void QGraphicsScene::setSelectionArea(const QPainterPath &path, Qt::ItemSelectionMode mode)
{
+ setSelectionArea(path, Qt::IntersectsItemShape, QTransform());
+}
+
+/*!
+ \overload
+ \since 4.3
+
+ Sets the selection area to \a path using \a mode to determine if items are
+ included in the selection area.
+
+ \sa clearSelection(), selectionArea()
+*/
+void QGraphicsScene::setSelectionArea(const QPainterPath &path, Qt::ItemSelectionMode mode,
+ const QTransform &deviceTransform)
+{
Q_D(QGraphicsScene);
// Note: with boolean path operations, we can improve performance here
@@ -1846,7 +1836,7 @@ void QGraphicsScene::setSelectionArea(const QPainterPath &path, Qt::ItemSelectio
bool changed = false;
// Set all items in path to selected.
- foreach (QGraphicsItem *item, items(path, mode)) {
+ foreach (QGraphicsItem *item, items(path, mode, Qt::AscendingOrder, deviceTransform)) {
if (item->flags() & QGraphicsItem::ItemIsSelectable) {
if (!item->isSelected())
changed = true;
@@ -1904,7 +1894,10 @@ void QGraphicsScene::clear()
{
Q_D(QGraphicsScene);
QList<QGraphicsItem *> items = d->index->items();
+#if 1
QList<QGraphicsItem *> toDelete;
+ // ### As the item list is already in ascending order,
+ // the items should be deleted in topological order.
// Recursive descent delete
for (int i = 0; i < items.size(); ++i) {
if (QGraphicsItem *item = items.at(i)) {
@@ -1912,11 +1905,13 @@ void QGraphicsScene::clear()
toDelete << item;
}
}
- //We delete all top level items
+ // We delete all top level items
qDeleteAll(toDelete);
+#else
+ qDeleteAll(items);
+#endif
d->lastItemCount = 0;
d->index->clear();
- d->largestUntransformableItem = QRectF();
d->allItemsIgnoreHoverEvents = true;
d->allItemsUseDefaultCursor = true;
}
@@ -4129,16 +4124,6 @@ void QGraphicsScenePrivate::drawSubtreeRecursive(QGraphicsItem *item, QPainter *
children = &this->topLevelItems;
} else {
QRectF sceneRect = viewTransform.inverted().mapRect(QRectF(exposedRegion->boundingRect().adjusted(-1, -1, 1, 1)));
- if (!largestUntransformableItem.isEmpty()) {
- // ### Nuke this when we move the indexing code into a separate
- // class. All the largestUntransformableItem code should then go
- // away, and the estimate function should return untransformable
- // items as well.
- QRectF untr = largestUntransformableItem;
- QRectF ltri = viewTransform.inverted().mapRect(untr);
- ltri.adjust(-untr.width(), -untr.height(), untr.width(), untr.height());
- sceneRect.adjust(-ltri.width(), -ltri.height(), ltri.width(), ltri.height());
- }
tmp = index->estimateItems(sceneRect, Qt::DescendingOrder, viewTransform);
QList<QGraphicsItem *> tli;
diff --git a/src/gui/graphicsview/qgraphicsscene.h b/src/gui/graphicsview/qgraphicsscene.h
index b922be5..421adbd 100644
--- a/src/gui/graphicsview/qgraphicsscene.h
+++ b/src/gui/graphicsview/qgraphicsscene.h
@@ -153,6 +153,7 @@ public:
QRectF itemsBoundingRect() const;
QList<QGraphicsItem *> items() const;
+ QList<QGraphicsItem *> items(Qt::SortOrder order) const; // ### Qt 5: unify
QList<QGraphicsItem *> items(const QPointF &pos, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform = QTransform()) const;
QList<QGraphicsItem *> items(const QRectF &rect, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform = QTransform()) const;
@@ -165,17 +166,25 @@ public:
QList<QGraphicsItem *> items(const QPainterPath &path, Qt::ItemSelectionMode mode = Qt::IntersectsItemShape) const; // ### obsolete
QList<QGraphicsItem *> collidingItems(const QGraphicsItem *item, Qt::ItemSelectionMode mode = Qt::IntersectsItemShape) const;
- QGraphicsItem *itemAt(const QPointF &pos) const;
+
+ QGraphicsItem *itemAt(const QPointF &pos) const; // ### obsolete
+ QGraphicsItem *itemAt(const QPointF &pos, const QTransform &deviceTransform) const;
inline QList<QGraphicsItem *> items(qreal x, qreal y, qreal w, qreal h, Qt::ItemSelectionMode mode = Qt::IntersectsItemShape) const
- { return items(QRectF(x, y, w, h), mode); }
- inline QGraphicsItem *itemAt(qreal x, qreal y) const
+ { return items(QRectF(x, y, w, h), mode); } // ### obsolete
+ inline QList<QGraphicsItem *> items(qreal x, qreal y, qreal w, qreal h, Qt::ItemSelectionMode mode, Qt::SortOrder order,
+ const QTransform &deviceTransform = QTransform()) const
+ { return items(QRectF(x, y, w, h), mode, order, deviceTransform); }
+ inline QGraphicsItem *itemAt(qreal x, qreal y) const // ### obsolete
{ return itemAt(QPointF(x, y)); }
+ inline QGraphicsItem *itemAt(qreal x, qreal y, const QTransform &deviceTransform) const
+ { return itemAt(QPointF(x, y), deviceTransform); }
QList<QGraphicsItem *> selectedItems() const;
QPainterPath selectionArea() const;
void setSelectionArea(const QPainterPath &path);
- void setSelectionArea(const QPainterPath &path, Qt::ItemSelectionMode);
+ void setSelectionArea(const QPainterPath &path, Qt::ItemSelectionMode mode);
+ void setSelectionArea(const QPainterPath &path, Qt::ItemSelectionMode mode, const QTransform &deviceTransform);
QGraphicsItemGroup *createItemGroup(const QList<QGraphicsItem *> &items);
void destroyItemGroup(QGraphicsItemGroup *group);
diff --git a/src/gui/graphicsview/qgraphicsscene_p.h b/src/gui/graphicsview/qgraphicsscene_p.h
index 538ff3f..a081e04 100644
--- a/src/gui/graphicsview/qgraphicsscene_p.h
+++ b/src/gui/graphicsview/qgraphicsscene_p.h
@@ -96,7 +96,6 @@ public:
QRectF sceneRect;
bool hasSceneRect;
QRectF growingItemsBoundingRect;
- QRectF largestUntransformableItem;
void _q_emitUpdated();
QList<QRectF> updatedRects;
@@ -162,7 +161,6 @@ public:
QList<QGraphicsItem *> itemsAtPosition(const QPoint &screenPos,
const QPointF &scenePos,
QWidget *widget) const;
- static bool itemCollidesWithPath(QGraphicsItem *item, const QPainterPath &path, Qt::ItemSelectionMode mode);
void storeMouseButtonsForMouseGrabber(QGraphicsSceneMouseEvent *event);
QList<QGraphicsView *> views;
@@ -188,6 +186,8 @@ public:
void mousePressEventHandler(QGraphicsSceneMouseEvent *mouseEvent);
QGraphicsWidget *windowForItem(const QGraphicsItem *item) const;
+ bool sortCacheEnabled; // for compatibility
+
void drawItemHelper(QGraphicsItem *item, QPainter *painter,
const QStyleOptionGraphicsItem *option, QWidget *widget,
bool painterStateProtection);
diff --git a/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp b/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp
index 969d3c5..40cafa6 100644
--- a/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp
+++ b/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp
@@ -170,11 +170,6 @@ void QGraphicsSceneBspTreeIndexPrivate::_q_updateIndex()
unindexedItems = indexedItems;
lastItemCount = indexedItems.size();
q->scene()->update();
-
- // Take this opportunity to reset our largest-item counter for
- // untransformable items. When the items are inserted into the BSP
- // tree, we'll get an accurate calculation.
- scenePrivate->largestUntransformableItem = QRectF();
}
// Insert all unindexed items into the tree.
@@ -185,19 +180,6 @@ void QGraphicsSceneBspTreeIndexPrivate::_q_updateIndex()
continue;
bsp.insertItem(item, rect);
-
- // If the item ignores view transformations, update our
- // largest-item-counter to ensure that the view can accurately
- // discover untransformable items when drawing.
- if (item->d_ptr->itemIsUntransformable()) {
- QGraphicsItem *topmostUntransformable = item;
- while (topmostUntransformable && (topmostUntransformable->d_ptr->ancestorFlags
- & QGraphicsItemPrivate::AncestorIgnoresTransformations)) {
- topmostUntransformable = topmostUntransformable->parentItem();
- }
- // ### Verify that this is the correct largest untransformable rectangle.
- scenePrivate->largestUntransformableItem |= item->mapToItem(topmostUntransformable, item->boundingRect()).boundingRect();
- }
}
}
unindexedItems.clear();
@@ -467,17 +449,23 @@ void QGraphicsSceneBspTreeIndex::addItem(QGraphicsItem *item)
// Indexing requires sceneBoundingRect(), but because \a item might
// not be completely constructed at this point, we need to store it in
// a temporary list and schedule an indexing for later.
- d->unindexedItems << item;
- item->d_func()->index = -1;
- d->startIndexTimer(0);
+ item->d_ptr->index = -1;
+ if (item->d_ptr->itemIsUntransformable()) {
+ d->untransformableItems << item;
+ } else {
+ d->unindexedItems << item;
+ d->startIndexTimer(0);
+ }
}
/*!
This really add the item in the BSP.
\internal
*/
-void QGraphicsSceneBspTreeIndexPrivate::addToIndex(QGraphicsItem *item)
+void QGraphicsSceneBspTreeIndexPrivate::addToBspTree(QGraphicsItem *item)
{
+ if (item->d_ptr->itemIsUntransformable())
+ return;
if (item->d_func()->index != -1) {
bsp.insertItem(item, item->sceneBoundingRect());
foreach (QGraphicsItem *child, item->children())
@@ -496,10 +484,11 @@ void QGraphicsSceneBspTreeIndexPrivate::addToIndex(QGraphicsItem *item)
void QGraphicsSceneBspTreeIndex::removeItem(QGraphicsItem *item)
{
Q_D(QGraphicsSceneBspTreeIndex);
+
// Note: This will access item's sceneBoundingRect(), which (as this is
// C++) is why we cannot call removeItem() from QGraphicsItem's
// destructor.
- d->removeFromIndex(item);
+ d->removeFromBspTree(item);
// Invalidate any sort caching; arrival of a new item means we need to
// resort.
@@ -511,7 +500,10 @@ void QGraphicsSceneBspTreeIndex::removeItem(QGraphicsItem *item)
d->freeItemIndexes << index;
d->indexedItems[index] = 0;
} else {
- d->unindexedItems.removeAll(item);
+ if (item->d_ptr->itemIsUntransformable())
+ d->untransformableItems.removeOne(item);
+ else
+ d->unindexedItems.removeOne(item);
}
}
@@ -539,7 +531,10 @@ void QGraphicsSceneBspTreeIndex::deleteItem(QGraphicsItem *item)
} else {
// Recently added items are purged immediately. unindexedItems() never
// contains stale items.
- d->unindexedItems.removeAll(item);
+ if (item->d_ptr->itemIsUntransformable())
+ d->untransformableItems.removeOne(item);
+ else
+ d->unindexedItems.removeOne(item);
scene()->update();
}
}
@@ -548,8 +543,11 @@ void QGraphicsSceneBspTreeIndex::deleteItem(QGraphicsItem *item)
Really remove the item from the BSP
\internal
*/
-void QGraphicsSceneBspTreeIndexPrivate::removeFromIndex(QGraphicsItem *item)
+void QGraphicsSceneBspTreeIndexPrivate::removeFromBspTree(QGraphicsItem *item)
{
+ if (item->d_ptr->itemIsUntransformable())
+ return;
+
if (item->d_func()->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren) {
// ### remove from child index only if applicable
return;
@@ -579,7 +577,7 @@ void QGraphicsSceneBspTreeIndex::prepareBoundingRectChange(const QGraphicsItem *
// Note: This will access item's sceneBoundingRect(), which (as this is
// C++) is why we cannot call removeItem() from QGraphicsItem's
// destructor.
- d->removeFromIndex(const_cast<QGraphicsItem *>(item));
+ d->removeFromBspTree(const_cast<QGraphicsItem *>(item));
}
/*!
@@ -633,7 +631,8 @@ QList<QGraphicsItem *> QGraphicsSceneBspTreeIndex::items(Qt::SortOrder order) co
Q_D(const QGraphicsSceneBspTreeIndex);
const_cast<QGraphicsSceneBspTreeIndexPrivate*>(d)->purgeRemovedItems();
QList<QGraphicsItem *> itemList;
- // If freeItemIndexes is empty, we know there are no holes in indexedItems and
+
+ // If freeItemIndexes is empty, we know there are no holes in indexedItems and
// unindexedItems.
if (d->freeItemIndexes.isEmpty()) {
if (d->unindexedItems.isEmpty()) {
@@ -649,6 +648,7 @@ QList<QGraphicsItem *> QGraphicsSceneBspTreeIndex::items(Qt::SortOrder order) co
itemList << item;
}
}
+ itemList += d->untransformableItems;
if (order != -1) {
//We sort descending order
d->sortItems(&itemList, order, d->sortCacheEnabled);
@@ -692,6 +692,8 @@ int QGraphicsSceneBspTreeIndex::bspTreeDepth()
void QGraphicsSceneBspTreeIndex::setBspTreeDepth(int depth)
{
Q_D(QGraphicsSceneBspTreeIndex);
+ if (d->bspTreeDepth == depth)
+ return;
d->bspTreeDepth = depth;
d->resetIndex();
}
@@ -716,19 +718,41 @@ void QGraphicsSceneBspTreeIndex::sceneRectChanged(const QRectF &rect)
update the BSP tree if necessary.
*/
-void QGraphicsSceneBspTreeIndex::itemChanged(const QGraphicsItem *item, QGraphicsItem::GraphicsItemChange change, const QVariant &value)
+void QGraphicsSceneBspTreeIndex::itemChange(const QGraphicsItem *item, QGraphicsItem::GraphicsItemChange change, const QVariant &value)
{
Q_D(QGraphicsSceneBspTreeIndex);
switch (change) {
- case QGraphicsItem::ItemZValueChange:
- case QGraphicsItem::ItemParentChange: {
- d->invalidateSortCache();
- break;
+ case QGraphicsItem::ItemFlagsChange: {
+ // Handle ItemIgnoresTransformations
+ bool ignoredTransform = item->flags() & QGraphicsItem::ItemIgnoresTransformations;
+ bool willIgnoreTransform = value.toUInt() & QGraphicsItem::ItemIgnoresTransformations;
+ if (ignoredTransform != willIgnoreTransform) {
+ QGraphicsItem *thatItem = const_cast<QGraphicsItem *>(item);
+ removeItem(thatItem);
+ addItem(thatItem);
}
- default:
- break;
+ break;
+ }
+ case QGraphicsItem::ItemZValueChange:
+ d->invalidateSortCache();
+ break;
+ case QGraphicsItem::ItemParentChange: {
+ d->invalidateSortCache();
+ // Handle ItemIgnoresTransformations
+ QGraphicsItem *newParent = qVariantValue<QGraphicsItem *>(value);
+ bool ignoredTransform = item->d_ptr->itemIsUntransformable();
+ bool willIgnoreTransform = (item->flags() & QGraphicsItem::ItemIgnoresTransformations) || (newParent && newParent->d_ptr->itemIsUntransformable());
+ if (ignoredTransform != willIgnoreTransform) {
+ QGraphicsItem *thatItem = const_cast<QGraphicsItem *>(item);
+ removeItem(thatItem);
+ addItem(thatItem);
+ }
+ break;
+ }
+ default:
+ break;
}
- return QGraphicsSceneIndex::itemChanged(item, change, value);
+ return QGraphicsSceneIndex::itemChange(item, change, value);
}
/*!
\reimp
diff --git a/src/gui/graphicsview/qgraphicsscenebsptreeindex.h b/src/gui/graphicsview/qgraphicsscenebsptreeindex.h
index 0444a30..504ea8b 100644
--- a/src/gui/graphicsview/qgraphicsscenebsptreeindex.h
+++ b/src/gui/graphicsview/qgraphicsscenebsptreeindex.h
@@ -98,7 +98,7 @@ protected:
void prepareBoundingRectChange(const QGraphicsItem *item);
void sceneRectChanged(const QRectF &rect);
- void itemChanged(const QGraphicsItem *item, QGraphicsItem::GraphicsItemChange change, const QVariant &value);
+ void itemChange(const QGraphicsItem *item, QGraphicsItem::GraphicsItemChange change, const QVariant &value);
private :
Q_DECLARE_PRIVATE(QGraphicsSceneBspTreeIndex)
diff --git a/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.h b/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.h
index b6f782d..ed12fac 100644
--- a/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.h
+++ b/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.h
@@ -82,6 +82,7 @@ public:
QList<QGraphicsItem *> indexedItems;
QList<QGraphicsItem *> unindexedItems;
+ QList<QGraphicsItem *> untransformableItems;
QList<int> freeItemIndexes;
bool purgePending;
@@ -92,8 +93,8 @@ public:
void startIndexTimer(int interval = QGRAPHICSSCENE_INDEXTIMER_TIMEOUT);
void resetIndex();
- void addToIndex(QGraphicsItem *item);
- void removeFromIndex(QGraphicsItem *item);
+ void addToBspTree(QGraphicsItem *item);
+ void removeFromBspTree(QGraphicsItem *item);
void _q_updateSortCache();
bool sortCacheEnabled;
diff --git a/src/gui/graphicsview/qgraphicssceneindex.cpp b/src/gui/graphicsview/qgraphicssceneindex.cpp
index 4ca1c02..eb3abc1 100644
--- a/src/gui/graphicsview/qgraphicssceneindex.cpp
+++ b/src/gui/graphicsview/qgraphicssceneindex.cpp
@@ -61,6 +61,7 @@
#include "qgraphicsscene.h"
#include "qgraphicsitem_p.h"
#include "qgraphicsscene_p.h"
+#include "qgraphicswidget.h"
#ifndef QT_NO_GRAPHICSVIEW
@@ -69,61 +70,118 @@ QT_BEGIN_NAMESPACE
class QGraphicsSceneIndexRectIntersector : public QGraphicsSceneIndexIntersector
{
public:
- QGraphicsSceneIndexRectIntersector(QGraphicsScene *scene) : QGraphicsSceneIndexIntersector(scene) {}
- bool intersect(const QRectF &brect) const
+ bool intersect(const QGraphicsItem *item, const QRectF &exposeRect, Qt::ItemSelectionMode mode,
+ const QTransform &transform, const QTransform &deviceTransform) const
{
+ QRectF brect = item->boundingRect();
+ _q_adjustRect(&brect);
+
+ // ### Add test for this (without making things slower?)
+ Q_UNUSED(exposeRect);
+
bool keep = true;
- if (mode == Qt::ContainsItemShape || mode == Qt::ContainsItemBoundingRect)
- keep = rect.contains(transform.mapRect(brect)) && rect != brect;
- else
- keep = rect.intersects(transform.mapRect(brect));
-
- if (keep && (mode == Qt::ContainsItemShape || mode == Qt::IntersectsItemShape)) {
- QPainterPath rectPath;
- rectPath.addRect(rect);
- keep = QGraphicsScenePrivate::get(scene)->itemCollidesWithPath(item, transform.inverted().map(rectPath), mode);
+ if (QGraphicsItemPrivate::get(item)->itemIsUntransformable()) {
+ // Untransformable items; map the scene rect to item coordinates.
+ QRectF itemRect = (deviceTransform * transform.inverted()).mapRect(sceneRect);
+ if (mode == Qt::ContainsItemShape || mode == Qt::ContainsItemBoundingRect)
+ keep = itemRect.contains(brect) && itemRect != brect;
+ else
+ keep = itemRect.intersects(brect);
+ if (keep && (mode == Qt::ContainsItemShape || mode == Qt::IntersectsItemShape)) {
+ QPainterPath itemPath;
+ itemPath.addRect(itemRect);
+ keep = QGraphicsSceneIndexPrivate::itemCollidesWithPath(item, itemPath, mode);
+ }
+ } else {
+ if (mode == Qt::ContainsItemShape || mode == Qt::ContainsItemBoundingRect)
+ keep = sceneRect.contains(transform.mapRect(brect)) && sceneRect != brect;
+ else
+ keep = sceneRect.intersects(transform.mapRect(brect));
+ if (keep && (mode == Qt::ContainsItemShape || mode == Qt::IntersectsItemShape)) {
+ QPainterPath rectPath;
+ rectPath.addRect(sceneRect);
+ keep = QGraphicsSceneIndexPrivate::itemCollidesWithPath(item, transform.inverted().map(rectPath), mode);
+ }
}
return keep;
}
+
+ QRectF sceneRect;
};
class QGraphicsSceneIndexPointIntersector : public QGraphicsSceneIndexIntersector
{
public:
- QGraphicsSceneIndexPointIntersector(QGraphicsScene *scene) : QGraphicsSceneIndexIntersector(scene) {}
- bool intersect(const QRectF &brect) const
+ bool intersect(const QGraphicsItem *item, const QRectF &exposeRect, Qt::ItemSelectionMode mode,
+ const QTransform &transform, const QTransform &deviceTransform) const
{
+ QRectF brect = item->boundingRect();
+ _q_adjustRect(&brect);
+
+ // ### Add test for this (without making things slower?)
+ Q_UNUSED(exposeRect);
+
bool keep = false;
- if (rect.intersects(transform.mapRect(brect)))
- if (item->contains(transform.inverted().map(pos)))
- keep = true;
- if (keep && (mode == Qt::ContainsItemShape || mode == Qt::IntersectsItemShape)) {
- QPainterPath rectPath;
- rectPath.addRect(rect);
- keep = QGraphicsScenePrivate::get(scene)->itemCollidesWithPath(item, transform.inverted().map(rectPath), mode);
+ if (QGraphicsItemPrivate::get(item)->itemIsUntransformable()) {
+ // Untransformable items; map the scene point to item coordinates.
+ QPointF itemPoint = (deviceTransform * transform.inverted()).map(scenePoint);
+ keep = brect.contains(itemPoint);
+ if (keep && (mode == Qt::ContainsItemShape || mode == Qt::IntersectsItemShape)) {
+ QPainterPath pointPath;
+ pointPath.addRect(QRectF(itemPoint, QSizeF(1, 1)));
+ keep = QGraphicsSceneIndexPrivate::itemCollidesWithPath(item, pointPath, mode);
+ }
+ } else {
+ QRectF sceneBrect = transform.mapRect(brect);
+ keep = sceneBrect.contains(scenePoint);
+ if (keep && (mode == Qt::ContainsItemShape || mode == Qt::IntersectsItemShape)) {
+ QPainterPath pointPath;
+ pointPath.addRect(QRectF(transform.inverted().map(scenePoint), QSizeF(1, 1)));
+ keep = QGraphicsSceneIndexPrivate::itemCollidesWithPath(item, pointPath, mode);
+ }
}
return keep;
}
- QPointF pos;
+
+ QPointF scenePoint;
};
class QGraphicsSceneIndexPathIntersector : public QGraphicsSceneIndexIntersector
{
public:
- QGraphicsSceneIndexPathIntersector(QGraphicsScene *scene) : QGraphicsSceneIndexIntersector(scene) {}
- bool intersect(const QRectF &brect) const
+ bool intersect(const QGraphicsItem *item, const QRectF &exposeRect, Qt::ItemSelectionMode mode,
+ const QTransform &transform, const QTransform &deviceTransform) const
{
- bool keep = true;
- if (mode == Qt::ContainsItemShape || mode == Qt::ContainsItemBoundingRect)
- keep = rect.contains(transform.mapRect(brect)) && rect != brect;
- else
- keep = rect.intersects(transform.mapRect(brect));
+ QRectF brect = item->boundingRect();
+ _q_adjustRect(&brect);
+
+ // ### Add test for this (without making things slower?)
+ Q_UNUSED(exposeRect);
- if (keep && (mode == Qt::ContainsItemShape || mode == Qt::IntersectsItemShape))
- keep = QGraphicsScenePrivate::get(scene)->itemCollidesWithPath(item, transform.inverted().map(path), mode);
+ bool keep = true;
+ if (QGraphicsItemPrivate::get(item)->itemIsUntransformable()) {
+ // Untransformable items; map the scene rect to item coordinates.
+ QPainterPath itemPath = (deviceTransform * transform.inverted()).map(scenePath);
+ if (mode == Qt::ContainsItemShape || mode == Qt::ContainsItemBoundingRect)
+ keep = itemPath.contains(brect);
+ else
+ keep = itemPath.intersects(brect);
+ if (keep && (mode == Qt::ContainsItemShape || mode == Qt::IntersectsItemShape))
+ keep = QGraphicsSceneIndexPrivate::itemCollidesWithPath(item, itemPath, mode);
+ } else {
+ if (mode == Qt::ContainsItemShape || mode == Qt::ContainsItemBoundingRect)
+ keep = scenePath.contains(transform.mapRect(brect));
+ else
+ keep = scenePath.intersects(transform.mapRect(brect));
+ if (keep && (mode == Qt::ContainsItemShape || mode == Qt::IntersectsItemShape)) {
+ QPainterPath itemPath = transform.inverted().map(scenePath);
+ keep = QGraphicsSceneIndexPrivate::itemCollidesWithPath(item, itemPath, mode);
+ }
+ }
return keep;
}
- QPainterPath path;
+
+ QPainterPath scenePath;
};
/*!
@@ -131,9 +189,9 @@ public:
*/
QGraphicsSceneIndexPrivate::QGraphicsSceneIndexPrivate(QGraphicsScene *scene) : scene(scene)
{
- pointIntersector = new QGraphicsSceneIndexPointIntersector(scene);
- rectIntersector = new QGraphicsSceneIndexRectIntersector(scene);
- pathIntersector = new QGraphicsSceneIndexPathIntersector(scene);
+ pointIntersector = new QGraphicsSceneIndexPointIntersector;
+ rectIntersector = new QGraphicsSceneIndexRectIntersector;
+ pathIntersector = new QGraphicsSceneIndexPathIntersector;
}
/*!
@@ -148,19 +206,50 @@ QGraphicsSceneIndexPrivate::~QGraphicsSceneIndexPrivate()
/*!
\internal
+
+ Checks if item collides with the path and mode, but also checks that if it
+ doesn't collide, maybe its frame rect will.
+*/
+bool QGraphicsSceneIndexPrivate::itemCollidesWithPath(const QGraphicsItem *item,
+ const QPainterPath &path,
+ Qt::ItemSelectionMode mode)
+{
+ if (item->collidesWithPath(path, mode))
+ return true;
+ if (item->isWidget()) {
+ // Check if this is a window, and if its frame rect collides.
+ const QGraphicsWidget *widget = static_cast<const QGraphicsWidget *>(item);
+ if (widget->isWindow()) {
+ QRectF frameRect = widget->windowFrameRect();
+ QPainterPath framePath;
+ framePath.addRect(frameRect);
+ bool intersects = path.intersects(frameRect);
+ if (mode == Qt::IntersectsItemShape || mode == Qt::IntersectsItemBoundingRect)
+ return intersects || path.contains(frameRect.topLeft())
+ || framePath.contains(path.elementAt(0));
+ return !intersects && path.contains(frameRect.topLeft());
+ }
+ }
+ return false;
+}
+
+/*!
+ \internal
*/
-void QGraphicsSceneIndexPrivate::recursive_items_helper(QGraphicsItem *item, QGraphicsSceneIndexIntersector *intersector,
- QList<QGraphicsItem *> *items,
- const QTransform &parentTransform,
- const QTransform &viewTransform,
- Qt::ItemSelectionMode mode, Qt::SortOrder order,
- qreal parentOpacity) const
+void QGraphicsSceneIndexPrivate::recursive_items_helper(QGraphicsItem *item, QRectF exposeRect,
+ QGraphicsSceneIndexIntersector *intersector,
+ QList<QGraphicsItem *> *items,
+ const QTransform &parentTransform,
+ const QTransform &viewTransform,
+ Qt::ItemSelectionMode mode, Qt::SortOrder order,
+ qreal parentOpacity) const
{
// Calculate opacity.
qreal opacity;
if (item) {
if (!item->d_ptr->visible)
return;
+
QGraphicsItem *p = item->d_ptr->parent;
bool itemIgnoresParentOpacity = item->d_ptr->flags & QGraphicsItem::ItemIgnoresParentOpacity;
bool parentDoesntPropagateOpacity = (p && (p->d_ptr->flags & QGraphicsItem::ItemDoesntPropagateOpacityToChildren));
@@ -186,9 +275,7 @@ void QGraphicsSceneIndexPrivate::recursive_items_helper(QGraphicsItem *item, QGr
_q_adjustRect(&brect);
//We fill the intersector with needed informations
- intersector->transform = transform;
- intersector->item = item;
- keep = intersector->intersect(brect);
+ keep = intersector->intersect(item, exposeRect, mode, transform, viewTransform);
}
bool childClip = (item && (item->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape));
@@ -211,7 +298,7 @@ void QGraphicsSceneIndexPrivate::recursive_items_helper(QGraphicsItem *item, QGr
// Clip.
if (childClip)
- intersector->rect &= transform.map(item->shape()).controlPointRect();
+ exposeRect &= transform.map(item->shape()).controlPointRect();
// Process children behind
int i = 0;
@@ -220,7 +307,7 @@ void QGraphicsSceneIndexPrivate::recursive_items_helper(QGraphicsItem *item, QGr
QGraphicsItem *child = children.at(i);
if (!(child->d_ptr->flags & QGraphicsItem::ItemStacksBehindParent))
break;
- recursive_items_helper(child, intersector, items, transform, viewTransform,
+ recursive_items_helper(child, exposeRect, intersector, items, transform, viewTransform,
mode, order, opacity);
}
}
@@ -232,7 +319,7 @@ void QGraphicsSceneIndexPrivate::recursive_items_helper(QGraphicsItem *item, QGr
// Process children in front
if (!dontProcessChildren) {
for (; i < children.size(); ++i)
- recursive_items_helper(children.at(i), intersector, items, transform, viewTransform,
+ recursive_items_helper(children.at(i), exposeRect, intersector, items, transform, viewTransform,
mode, order, opacity);
}
@@ -311,12 +398,12 @@ QRectF QGraphicsSceneIndex::indexedRect() const
QList<QGraphicsItem *> QGraphicsSceneIndex::items(const QPointF &pos, Qt::ItemSelectionMode mode,
Qt::SortOrder order, const QTransform &deviceTransform) const
{
+
Q_D(const QGraphicsSceneIndex);
QList<QGraphicsItem *> itemList;
- d->pointIntersector->mode = mode;
- d->pointIntersector->rect = QRectF(pos, QSize(1,1));
- d->pointIntersector->pos = pos;
- d->recursive_items_helper(0, d->pointIntersector, &itemList, QTransform(), deviceTransform, mode, order);
+ d->pointIntersector->scenePoint = pos;
+ d->recursive_items_helper(0, QRectF(pos, QSizeF(1, 1)), d->pointIntersector, &itemList,
+ QTransform(), deviceTransform, mode, order);
return itemList;
}
@@ -346,10 +433,11 @@ QList<QGraphicsItem *> QGraphicsSceneIndex::items(const QRectF &rect, Qt::ItemSe
Qt::SortOrder order, const QTransform &deviceTransform) const
{
Q_D(const QGraphicsSceneIndex);
+ QRectF exposeRect = rect;
+ _q_adjustRect(&exposeRect);
QList<QGraphicsItem *> itemList;
- d->rectIntersector->mode = mode;
- d->rectIntersector->rect = rect;
- d->recursive_items_helper(0, d->rectIntersector, &itemList, QTransform(), deviceTransform, mode, order);
+ d->rectIntersector->sceneRect = rect;
+ d->recursive_items_helper(0, exposeRect, d->rectIntersector, &itemList, QTransform(), deviceTransform, mode, order);
return itemList;
}
@@ -380,14 +468,12 @@ QList<QGraphicsItem *> QGraphicsSceneIndex::items(const QPolygonF &polygon, Qt::
{
Q_D(const QGraphicsSceneIndex);
QList<QGraphicsItem *> itemList;
- QRectF polyRect(polygon.boundingRect());
- _q_adjustRect(&polyRect);
- d->pathIntersector->mode = mode;
- d->pathIntersector->rect = polyRect;
+ QRectF exposeRect = polygon.boundingRect();
+ _q_adjustRect(&exposeRect);
QPainterPath path;
path.addPolygon(polygon);
- d->pathIntersector->path = path;
- d->recursive_items_helper(0, d->pathIntersector, &itemList, QTransform(), deviceTransform, mode, order);
+ d->pathIntersector->scenePath = path;
+ d->recursive_items_helper(0, exposeRect, d->pathIntersector, &itemList, QTransform(), deviceTransform, mode, order);
return itemList;
}
@@ -418,12 +504,10 @@ QList<QGraphicsItem *> QGraphicsSceneIndex::items(const QPainterPath &path, Qt::
{
Q_D(const QGraphicsSceneIndex);
QList<QGraphicsItem *> itemList;
- QRectF pathRect(path.controlPointRect());
- _q_adjustRect(&pathRect);
- d->pathIntersector->mode = mode;
- d->pathIntersector->rect = pathRect;
- d->pathIntersector->path = path;
- d->recursive_items_helper(0, d->pathIntersector, &itemList, QTransform(), deviceTransform, mode, order);
+ QRectF exposeRect = path.controlPointRect();
+ _q_adjustRect(&exposeRect);
+ d->pathIntersector->scenePath = path;
+ d->recursive_items_helper(0, exposeRect, d->pathIntersector, &itemList, QTransform(), deviceTransform, mode, order);
return itemList;
}
@@ -508,7 +592,7 @@ void QGraphicsSceneIndex::deleteItem(QGraphicsItem *item)
\sa QGraphicsItem::GraphicsItemChange
*/
-void QGraphicsSceneIndex::itemChanged(const QGraphicsItem *item, QGraphicsItem::GraphicsItemChange change, const QVariant &value)
+void QGraphicsSceneIndex::itemChange(const QGraphicsItem *item, QGraphicsItem::GraphicsItemChange change, const QVariant &value)
{
Q_UNUSED(item);
Q_UNUSED(change);
diff --git a/src/gui/graphicsview/qgraphicssceneindex.h b/src/gui/graphicsview/qgraphicssceneindex.h
index ddce9d4..25ece04 100644
--- a/src/gui/graphicsview/qgraphicssceneindex.h
+++ b/src/gui/graphicsview/qgraphicssceneindex.h
@@ -104,7 +104,7 @@ protected:
virtual void removeItem(QGraphicsItem *item) = 0;
virtual void deleteItem(QGraphicsItem *item);
- virtual void itemChanged(const QGraphicsItem *item, QGraphicsItem::GraphicsItemChange, const QVariant &value);
+ virtual void itemChange(const QGraphicsItem *item, QGraphicsItem::GraphicsItemChange, const QVariant &value);
virtual void prepareBoundingRectChange(const QGraphicsItem *item);
virtual void sceneRectChanged(const QRectF &rect);
diff --git a/src/gui/graphicsview/qgraphicssceneindex_p.h b/src/gui/graphicsview/qgraphicssceneindex_p.h
index d0d181b..576ee98 100644
--- a/src/gui/graphicsview/qgraphicssceneindex_p.h
+++ b/src/gui/graphicsview/qgraphicssceneindex_p.h
@@ -75,9 +75,12 @@ public:
QGraphicsSceneIndexPrivate(QGraphicsScene *scene);
~QGraphicsSceneIndexPrivate();
- void recursive_items_helper(QGraphicsItem *item, QGraphicsSceneIndexIntersector *intersector, QList<QGraphicsItem *> *items,
- const QTransform &parentTransform, const QTransform &viewTransform,
- Qt::ItemSelectionMode mode, Qt::SortOrder order, qreal parentOpacity = 1.0) const;
+ static bool itemCollidesWithPath(const QGraphicsItem *item, const QPainterPath &path, Qt::ItemSelectionMode mode);
+
+ void recursive_items_helper(QGraphicsItem *item, QRectF exposeRect,
+ QGraphicsSceneIndexIntersector *intersector, QList<QGraphicsItem *> *items,
+ const QTransform &parentTransform, const QTransform &viewTransform,
+ Qt::ItemSelectionMode mode, Qt::SortOrder order, qreal parentOpacity = 1.0) const;
QGraphicsScene *scene;
QGraphicsSceneIndexPointIntersector *pointIntersector;
QGraphicsSceneIndexRectIntersector *rectIntersector;
@@ -87,14 +90,10 @@ public:
class QGraphicsSceneIndexIntersector
{
public:
- QGraphicsSceneIndexIntersector(QGraphicsScene *scene) : scene(scene) { }
+ QGraphicsSceneIndexIntersector() { }
virtual ~QGraphicsSceneIndexIntersector() { }
- virtual bool intersect(const QRectF &rect) const = 0;
- Qt::ItemSelectionMode mode;
- QGraphicsItem *item;
- QGraphicsScene *scene;
- QRectF rect;
- QTransform transform;
+ virtual bool intersect(const QGraphicsItem *item, const QRectF &exposeRect, Qt::ItemSelectionMode mode,
+ const QTransform &transform, const QTransform &deviceTransform) const = 0;
};
QT_END_NAMESPACE
diff --git a/src/gui/graphicsview/qgraphicsview.cpp b/src/gui/graphicsview/qgraphicsview.cpp
index 8c40878..a1e6d9c 100644
--- a/src/gui/graphicsview/qgraphicsview.cpp
+++ b/src/gui/graphicsview/qgraphicsview.cpp
@@ -914,44 +914,32 @@ extern QPainterPath qt_regionToPath(const QRegion &region);
is at risk of painting 1 pixel outside the bounding rect. Therefore we
must search for items with an adjustment of (-1, -1, 1, 1).
*/
-QList<QGraphicsItem *> QGraphicsViewPrivate::findItems(const QRegion &exposedRegion, bool *allItems) const
+QList<QGraphicsItem *> QGraphicsViewPrivate::findItems(const QRegion &exposedRegion, bool *allItems,
+ const QTransform &viewTransform) const
{
Q_Q(const QGraphicsView);
// Step 1) If all items are contained within the expose region, then
- // return a list of all visible items.
+ // return a list of all visible items. ### the scene's growing bounding
+ // rect does not take into account untransformable items.
const QRectF exposedRegionSceneBounds = q->mapToScene(exposedRegion.boundingRect().adjusted(-1, -1, 1, 1))
.boundingRect();
if (exposedRegionSceneBounds.contains(scene->d_func()->growingItemsBoundingRect)) {
Q_ASSERT(allItems);
*allItems = true;
- // All items are guaranteed within the exposed region, don't bother using the index.
- QList<QGraphicsItem *> itemList(scene->d_func()->index->items(Qt::DescendingOrder));
- int i = 0;
- while (i < itemList.size()) {
- const QGraphicsItem *item = itemList.at(i);
- // But we only want to include items that are visible
- // The following check is basically the same as item->d_ptr->isInvisible(), except
- // that we don't check whether the item clips children to shape or propagates its
- // opacity (we loop through all items, so those checks are wrong in this context).
- if (!item->isVisible() || item->d_ptr->isClippedAway() || item->d_ptr->isFullyTransparent())
- itemList.removeAt(i);
- else
- ++i;
- }
- return itemList;
+ // All items are guaranteed within the exposed region.
+ return scene->items(Qt::DescendingOrder);
}
// Step 2) If the expose region is a simple rect and the view is only
// translated or scaled, search for items using
// QGraphicsScene::items(QRectF).
- bool simpleRectLookup = (scene->d_func()->largestUntransformableItem.isNull()
- && exposedRegion.numRects() == 1 && matrix.type() <= QTransform::TxScale);
+ bool simpleRectLookup = exposedRegion.numRects() == 1 && matrix.type() <= QTransform::TxScale;
if (simpleRectLookup) {
- return scene->d_func()->index->items(exposedRegionSceneBounds,
- Qt::IntersectsItemBoundingRect,
- Qt::DescendingOrder);
+ return scene->items(exposedRegionSceneBounds,
+ Qt::IntersectsItemBoundingRect,
+ Qt::DescendingOrder, viewTransform);
}
// If the region is complex or the view has a complex transform, adjust
@@ -961,16 +949,9 @@ QList<QGraphicsItem *> QGraphicsViewPrivate::findItems(const QRegion &exposedReg
foreach (const QRect &r, exposedRegion.rects())
adjustedRegion += r.adjusted(-1, -1, 1, 1);
- const QPainterPath exposedPath(qt_regionToPath(adjustedRegion));
- if (scene->d_func()->largestUntransformableItem.isNull()) {
- const QPainterPath exposedScenePath(q->mapToScene(exposedPath));
- return scene->d_func()->index->items(exposedScenePath,
- Qt::IntersectsItemBoundingRect,
- Qt::DescendingOrder);
- }
-
- // NB! Path must be in viewport coordinates.
- return itemsInArea(exposedPath, Qt::IntersectsItemBoundingRect, Qt::DescendingOrder);
+ const QPainterPath exposedScenePath(q->mapToScene(qt_regionToPath(adjustedRegion)));
+ return scene->items(exposedScenePath, Qt::IntersectsItemBoundingRect,
+ Qt::DescendingOrder, viewTransform);
}
/*!
@@ -1875,6 +1856,8 @@ void QGraphicsView::fitInView(const QGraphicsItem *item, Qt::AspectRatioMode asp
void QGraphicsView::render(QPainter *painter, const QRectF &target, const QRect &source,
Qt::AspectRatioMode aspectRatioMode)
{
+ // ### Switch to using the recursive rendering algorithm instead.
+
Q_D(QGraphicsView);
if (!d->scene || !(painter && painter->isActive()))
return;
@@ -1972,67 +1955,6 @@ QList<QGraphicsItem *> QGraphicsView::items() const
}
/*!
- Returns all items in the area \a path, which is in viewport coordinates,
- also taking untransformable items into consideration. This function is
- considerably slower than just checking the scene directly. There is
- certainly room for improvement.
-*/
-QList<QGraphicsItem *> QGraphicsViewPrivate::itemsInArea(const QPainterPath &path,
- Qt::ItemSelectionMode mode,
- Qt::SortOrder order) const
-{
- Q_Q(const QGraphicsView);
-
- // Determine the size of the largest untransformable subtree of children
- // mapped to scene coordinates.
- QRectF untr = scene->d_func()->largestUntransformableItem;
- QRectF ltri = matrix.inverted().mapRect(untr);
- ltri.adjust(-untr.width(), -untr.height(), untr.width(), untr.height());
-
- QRectF rect = path.controlPointRect();
-
- // Find all possible items in the relevant area.
- // ### Improve this algorithm; it might be searching a too large area.
- QRectF adjustedRect = q->mapToScene(rect.adjusted(-1, -1, 1, 1).toRect()).boundingRect();
- adjustedRect.adjust(-ltri.width(), -ltri.height(), ltri.width(), ltri.height());
-
- // First build a (potentially large) list of all items in the vicinity
- // that might be untransformable.
- QList<QGraphicsItem *> allCandidates = scene->d_func()->index->estimateItems(adjustedRect, order, q->transform());
-
- // Then find the minimal list of items that are inside \a path, and
- // convert it to a set.
- QList<QGraphicsItem *> regularCandidates = scene->items(q->mapToScene(path), mode, order, q->transform());
- QSet<QGraphicsItem *> candSet = QSet<QGraphicsItem *>::fromList(regularCandidates);
-
- QTransform viewMatrix = q->viewportTransform();
-
- QList<QGraphicsItem *> result;
-
- //### this will disapear
-
- // Run through all candidates and keep all items that are in candSet, or
- // are untransformable and collide with \a path. ### We can improve this
- // algorithm.
- QList<QGraphicsItem *>::Iterator it = allCandidates.begin();
- while (it != allCandidates.end()) {
- QGraphicsItem *item = *it;
- if (item->d_ptr->itemIsUntransformable()) {
- // Check if this untransformable item collides with the
- // original selection rect.
- QTransform itemTransform = item->deviceTransform(viewMatrix);
- if (QGraphicsScenePrivate::itemCollidesWithPath(item, itemTransform.inverted().map(path), mode))
- result << item;
- } else {
- if (candSet.contains(item))
- result << item;
- }
- ++it;
- }
- return result;
-}
-
-/*!
Returns a list of all the items at the position \a pos in the view. The
items are listed in descending Z order (i.e., the first item in the list
is the top-most item, and the last item is the bottom-most item). \a pos
@@ -2051,17 +1973,22 @@ QList<QGraphicsItem *> QGraphicsView::items(const QPoint &pos) const
Q_D(const QGraphicsView);
if (!d->scene)
return QList<QGraphicsItem *>();
- if (d->scene->d_func()->largestUntransformableItem.isNull()) {
- if ((d->identityMatrix || d->matrix.type() <= QTransform::TxScale)) {
- QTransform xinv = viewportTransform().inverted();
- return d->scene->items(xinv.mapRect(QRectF(pos.x(), pos.y(), 1, 1)));
- }
- return d->scene->items(mapToScene(pos.x(), pos.y(), 1, 1));
+ // ### Unify these two, and use the items(QPointF) version in
+ // QGraphicsScene instead. The scene items function could use the viewport
+ // transform to map the point to a rect/polygon.
+ if ((d->identityMatrix || d->matrix.type() <= QTransform::TxScale)) {
+ // Use the rect version
+ QTransform xinv = viewportTransform().inverted();
+ return d->scene->items(xinv.mapRect(QRectF(pos.x(), pos.y(), 1, 1)),
+ Qt::IntersectsItemShape,
+ Qt::AscendingOrder,
+ viewportTransform());
}
-
- QPainterPath path;
- path.addRect(QRectF(pos.x(), pos.y(), 1, 1));
- return d->itemsInArea(path);
+ // Use the polygon version
+ return d->scene->items(mapToScene(pos.x(), pos.y(), 1, 1),
+ Qt::IntersectsItemShape,
+ Qt::AscendingOrder,
+ viewportTransform());
}
/*!
@@ -2088,12 +2015,7 @@ QList<QGraphicsItem *> QGraphicsView::items(const QRect &rect, Qt::ItemSelection
Q_D(const QGraphicsView);
if (!d->scene)
return QList<QGraphicsItem *>();
- if (d->scene->d_func()->largestUntransformableItem.isNull())
- return d->scene->items(mapToScene(rect), mode);
-
- QPainterPath path;
- path.addRect(rect);
- return d->itemsInArea(path);
+ return d->scene->items(mapToScene(rect), mode, Qt::AscendingOrder, viewportTransform());
}
/*!
@@ -2121,13 +2043,7 @@ QList<QGraphicsItem *> QGraphicsView::items(const QPolygon &polygon, Qt::ItemSel
Q_D(const QGraphicsView);
if (!d->scene)
return QList<QGraphicsItem *>();
- if (d->scene->d_func()->largestUntransformableItem.isNull())
- return d->scene->items(mapToScene(polygon), mode);
-
- QPainterPath path;
- path.addPolygon(polygon);
- path.closeSubpath();
- return d->itemsInArea(path);
+ return d->scene->items(mapToScene(polygon), mode, Qt::AscendingOrder, viewportTransform());
}
/*!
@@ -2147,9 +2063,7 @@ QList<QGraphicsItem *> QGraphicsView::items(const QPainterPath &path, Qt::ItemSe
Q_D(const QGraphicsView);
if (!d->scene)
return QList<QGraphicsItem *>();
- if (d->scene->d_func()->largestUntransformableItem.isNull())
- return d->scene->items(mapToScene(path), mode);
- return d->itemsInArea(path);
+ return d->scene->items(mapToScene(path), mode, Qt::AscendingOrder, viewportTransform());
}
/*!
@@ -2168,7 +2082,9 @@ QGraphicsItem *QGraphicsView::itemAt(const QPoint &pos) const
Q_D(const QGraphicsView);
if (!d->scene)
return 0;
- QList<QGraphicsItem *> itemsAtPos = items(pos);
+ // ### Use QGraphicsScene::itemAt() instead.
+ QList<QGraphicsItem *> itemsAtPos = d->scene->items(pos, Qt::IntersectsItemShape, Qt::AscendingOrder,
+ viewportTransform());
return itemsAtPos.isEmpty() ? 0 : itemsAtPos.first();
}
@@ -3073,7 +2989,8 @@ void QGraphicsView::mouseMoveEvent(QMouseEvent *event)
selectionArea.addPolygon(mapToScene(d->rubberBandRect));
selectionArea.closeSubpath();
if (d->scene)
- d->scene->setSelectionArea(selectionArea, d->rubberBandSelectionMode);
+ d->scene->setSelectionArea(selectionArea, d->rubberBandSelectionMode,
+ viewportTransform());
return;
}
} else
@@ -3280,7 +3197,7 @@ void QGraphicsView::paintEvent(QPaintEvent *event)
} else {
// Find all exposed items
bool allItems = false;
- QList<QGraphicsItem *> itemList = d->findItems(d->exposedRegion, &allItems);
+ QList<QGraphicsItem *> itemList = d->findItems(d->exposedRegion, &allItems, viewTransform);
if (!itemList.isEmpty()) {
// Generate the style options.
diff --git a/src/gui/graphicsview/qgraphicsview_p.h b/src/gui/graphicsview/qgraphicsview_p.h
index fac7bf9..760f54e 100644
--- a/src/gui/graphicsview/qgraphicsview_p.h
+++ b/src/gui/graphicsview/qgraphicsview_p.h
@@ -84,10 +84,6 @@ public:
qint64 horizontalScroll() const;
qint64 verticalScroll() const;
- QList<QGraphicsItem *> itemsInArea(const QPainterPath &path,
- Qt::ItemSelectionMode mode = Qt::IntersectsItemShape,
- Qt::SortOrder = Qt::AscendingOrder) const;
-
QPointF mousePressItemPoint;
QPointF mousePressScenePoint;
QPoint mousePressViewPoint;
@@ -176,7 +172,8 @@ public:
bool updateSceneSlotReimplementedChecked;
QRegion exposedRegion;
- QList<QGraphicsItem *> findItems(const QRegion &exposedRegion, bool *allItems) const;
+ QList<QGraphicsItem *> findItems(const QRegion &exposedRegion, bool *allItems,
+ const QTransform &viewTransform) const;
};
QT_END_NAMESPACE