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.cpp81
1 files changed, 68 insertions, 13 deletions
diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp
index 13f70e5..69e08d1 100644
--- a/src/gui/graphicsview/qgraphicsscene.cpp
+++ b/src/gui/graphicsview/qgraphicsscene.cpp
@@ -351,6 +351,8 @@ QGraphicsScenePrivate::QGraphicsScenePrivate()
dragDropItem(0),
enterWidget(0),
lastDropAction(Qt::IgnoreAction),
+ allItemsIgnoreHoverEvents(true),
+ allItemsUseDefaultCursor(true),
painterStateProtection(true),
sortCacheEnabled(false),
updatingSortCache(false),
@@ -622,6 +624,30 @@ void QGraphicsScenePrivate::_q_emitUpdated()
/*!
\internal
+*/
+void QGraphicsScenePrivate::registerTopLevelItem(QGraphicsItem *item)
+{
+ item->d_ptr->siblingIndex = topLevelItems.size();
+ topLevelItems.append(item);
+}
+
+/*!
+ \internal
+*/
+void QGraphicsScenePrivate::unregisterTopLevelItem(QGraphicsItem *item)
+{
+ int idx = item->d_ptr->siblingIndex;
+ int size = topLevelItems.size();
+ for (int i = idx; i < size - 1; ++i) {
+ QGraphicsItem *p = topLevelItems[i + 1];
+ topLevelItems[i] = p;
+ p->d_ptr->siblingIndex = i;
+ }
+ topLevelItems.removeLast();
+}
+
+/*!
+ \internal
Updates all items in the pending update list. At this point, the list is
unlikely to contain partially constructed items.
@@ -756,10 +782,6 @@ void QGraphicsScenePrivate::_q_removeItemLater(QGraphicsItem *item)
freeSceneTransformSlots.append(transformIndex);
}
- // Remove all children recursively.
- foreach (QGraphicsItem *child, item->children())
- _q_removeItemLater(child);
-
// Reset the mouse grabber
if (mouseGrabberItems.contains(item))
ungrabMouse(item, /* item is dying */ true);
@@ -880,11 +902,18 @@ void QGraphicsScenePrivate::grabMouse(QGraphicsItem *item, bool implicit)
{
// Append to list of mouse grabber items, and send a mouse grab event.
if (mouseGrabberItems.contains(item)) {
- if (mouseGrabberItems.last() == item)
- qWarning("QGraphicsItem::grabMouse: already a mouse grabber");
- else
+ if (mouseGrabberItems.last() == item) {
+ Q_ASSERT(!implicit);
+ if (!lastMouseGrabberItemHasImplicitMouseGrab) {
+ qWarning("QGraphicsItem::grabMouse: already a mouse grabber");
+ } else {
+ // Upgrade to an explicit mouse grab
+ lastMouseGrabberItemHasImplicitMouseGrab = false;
+ }
+ } else {
qWarning("QGraphicsItem::grabMouse: already blocked by mouse grabber: %p",
mouseGrabberItems.last());
+ }
return;
}
@@ -1036,6 +1065,12 @@ void QGraphicsScenePrivate::clearKeyboardGrabber()
ungrabKeyboard(keyboardGrabberItems.first());
}
+void QGraphicsScenePrivate::enableMouseTrackingOnViews()
+{
+ foreach (QGraphicsView *view, views)
+ view->viewport()->setMouseTracking(true);
+}
+
/*!
Returns all items for the screen position in \a event.
*/
@@ -1831,7 +1866,7 @@ inline bool qt_closestLeaf(const QGraphicsItem *item1, const QGraphicsItem *item
if (f1 != f2) return f2;
qreal z1 = d1->z;
qreal z2 = d2->z;
- return z1 != z2 ? z1 > z2 : item1 > item2;
+ return z1 != z2 ? z1 > z2 : d1->siblingIndex > d2->siblingIndex;
}
/*!
@@ -2747,12 +2782,13 @@ void QGraphicsScene::clear()
}
d->unindexedItems.clear();
qDeleteAll(unindexedParents);
-
d->indexedItems.clear();
d->freeItemIndexes.clear();
d->lastItemCount = 0;
d->bspTree.clear();
d->largestUntransformableItem = QRectF();
+ d->allItemsIgnoreHoverEvents = true;
+ d->allItemsUseDefaultCursor = true;
}
/*!
@@ -2856,7 +2892,6 @@ void QGraphicsScene::addItem(QGraphicsItem *item)
qWarning("QGraphicsScene::addItem: item has already been added to this scene");
return;
}
-
// Remove this item from its existing scene
if (QGraphicsScene *oldScene = item->scene())
oldScene->removeItem(item);
@@ -2897,6 +2932,10 @@ void QGraphicsScene::addItem(QGraphicsItem *item)
item->d_func()->index = -1;
d->startIndexTimer();
+ // Add to list of toplevels if this item is a toplevel.
+ if (!item->d_ptr->parent)
+ d->registerTopLevelItem(item);
+
// Update the scene's sort cache settings.
item->d_ptr->globalStackingOrder = -1;
d->invalidateSortCache();
@@ -2914,6 +2953,17 @@ void QGraphicsScene::addItem(QGraphicsItem *item)
++d->selectionChanging;
int oldSelectedItemSize = d->selectedItems.size();
+ // Enable mouse tracking if the item accepts hover events or has a cursor set.
+ if (d->allItemsIgnoreHoverEvents && d->itemAcceptsHoverEvents_helper(item)) {
+ d->allItemsIgnoreHoverEvents = false;
+ d->enableMouseTrackingOnViews();
+ }
+ if (d->allItemsUseDefaultCursor && item->hasCursor()) {
+ d->allItemsUseDefaultCursor = false;
+ if (d->allItemsIgnoreHoverEvents) // already enabled otherwise
+ d->enableMouseTrackingOnViews();
+ }
+
// Update selection lists
if (item->isSelected())
d->selectedItems << item;
@@ -3249,13 +3299,15 @@ void QGraphicsScene::removeItem(QGraphicsItem *item)
// Set the item's scene ptr to 0.
item->d_func()->scene = 0;
- // Detach the item from its parent.
+ // Remove from parent, or unregister from toplevels.
if (QGraphicsItem *parentItem = item->parentItem()) {
if (parentItem->scene()) {
Q_ASSERT_X(parentItem->scene() == this, "QGraphicsScene::removeItem",
"Parent item's scene is different from this item's scene");
item->setParentItem(0);
}
+ } else {
+ d->unregisterTopLevelItem(item);
}
// Remove from our item lists.
@@ -4214,6 +4266,9 @@ bool QGraphicsScenePrivate::itemAcceptsHoverEvents_helper(const QGraphicsItem *i
*/
bool QGraphicsScenePrivate::dispatchHoverEvent(QGraphicsSceneHoverEvent *hoverEvent)
{
+ if (allItemsIgnoreHoverEvents)
+ return false;
+
// Find the first item that accepts hover events, reusing earlier
// calculated data is possible.
if (cachedItemsUnderMouse.isEmpty()) {
@@ -4613,7 +4668,7 @@ static void _q_paintItem(QGraphicsItem *item, QPainter *painter,
? proxy->widget()->windowOpacity() : 1.0;
const qreal oldPainterOpacity = painter->opacity();
- if (qFuzzyCompare(windowOpacity + 1, qreal(1.0)))
+ if (qFuzzyIsNull(windowOpacity))
return;
// Set new painter opacity.
if (windowOpacity < 1.0)
@@ -5255,7 +5310,7 @@ void QGraphicsScene::itemUpdated(QGraphicsItem *item, const QRectF &rect)
// Deliver the actual update.
if (!d->updateAll) {
if (d->views.isEmpty() || ((d->connectedSignals & d->changedSignalMask) && !item->d_ptr->itemIsUntransformable()
- && qFuzzyCompare(item->boundingRegionGranularity(), qreal(0.0)))) {
+ && qFuzzyIsNull(item->boundingRegionGranularity()))) {
// This block of code is kept for compatibility. Since 4.5, by default
// QGraphicsView does not connect the signal and we use the below
// method of delivering updates.