From ad92e095ea34dda9d099fae30340a8fbb4c5380a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Nilsen?= Date: Thu, 4 Jun 2009 17:31:47 +0200 Subject: Compatibility fix for QGraphicsScene::sceneRectChanged()/sceneRect(). We have to keep the growingItemsBoundingRect up-to-date if there's no scene rect. The only difference now is that sceneRectChanged will not be emitted before entering the event-loop, but the documentation only states it'll be emitted when the scene rect changes, so we consider it harmless. Makes tst_QGraphicsView::sceneRect_growing and tst_QGrahicsScene::sceneRect happy. Reviewed-by: Andreas --- src/gui/graphicsview/qgraphicsitem.cpp | 1 + src/gui/graphicsview/qgraphicsitem_p.h | 4 ++- src/gui/graphicsview/qgraphicsscene.cpp | 33 +++++++++++++++++------- src/gui/graphicsview/qgraphicsscene_p.h | 5 +++- tests/auto/qgraphicsscene/tst_qgraphicsscene.cpp | 2 ++ 5 files changed, 34 insertions(+), 11 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index 47a9ae2..807ee06 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -5977,6 +5977,7 @@ void QGraphicsItem::removeFromIndex() void QGraphicsItem::prepareGeometryChange() { if (d_ptr->scene) { + d_ptr->geometryChanged = 1; d_ptr->paintedViewBoundingRectsNeedRepaint = 1; d_ptr->scene->d_func()->markDirty(this, QRectF(), /*invalidateChildren=*/true, diff --git a/src/gui/graphicsview/qgraphicsitem_p.h b/src/gui/graphicsview/qgraphicsitem_p.h index 9be9310..d884b16 100644 --- a/src/gui/graphicsview/qgraphicsitem_p.h +++ b/src/gui/graphicsview/qgraphicsitem_p.h @@ -148,6 +148,7 @@ public: paintedViewBoundingRectsNeedRepaint(0), dirtySceneTransform(1), itemChangesEnabled(0xffff), + geometryChanged(0), globalStackingOrder(-1), q_ptr(0) { @@ -399,7 +400,8 @@ public: quint32 paintedViewBoundingRectsNeedRepaint : 1; quint32 dirtySceneTransform : 1; quint32 itemChangesEnabled : 16; - quint32 padding : 3; // feel free to use + quint32 geometryChanged : 1; + quint32 padding : 2; // feel free to use // Optional stacking order int globalStackingOrder; diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index df3153f..c738f80 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -39,7 +39,6 @@ ** ****************************************************************************/ -static const int QGRAPHICSSCENE_INDEXTIMER_TIMEOUT = 2000; /*! \class QGraphicsScene @@ -682,7 +681,11 @@ void QGraphicsScenePrivate::_q_processDirtyItems() if (updateAll) return; + const QRectF oldGrowingItemsBoundingRect = growingItemsBoundingRect; processDirtyItemsRecursive(0); + if (!hasSceneRect && oldGrowingItemsBoundingRect != growingItemsBoundingRect) + emit q_func()->sceneRectChanged(growingItemsBoundingRect); + for (int i = 0; i < views.size(); ++i) views.at(i)->d_func()->processPendingUpdates(); } @@ -808,13 +811,13 @@ void QGraphicsScenePrivate::purgeRemovedItems() Starts or restarts the timer used for reindexing unindexed items. */ -void QGraphicsScenePrivate::startIndexTimer() +void QGraphicsScenePrivate::startIndexTimer(int interval) { Q_Q(QGraphicsScene); if (indexTimerId) { restartIndexTimer = true; } else { - indexTimerId = q->startTimer(QGRAPHICSSCENE_INDEXTIMER_TIMEOUT); + indexTimerId = q->startTimer(interval); } } @@ -2982,7 +2985,7 @@ void QGraphicsScene::addItem(QGraphicsItem *item) // a temporary list and schedule an indexing for later. d->unindexedItems << item; item->d_func()->index = -1; - d->startIndexTimer(); + d->startIndexTimer(0); // Add to list of toplevels if this item is a toplevel. if (!item->d_ptr->parent) @@ -5315,16 +5318,27 @@ void QGraphicsScenePrivate::processDirtyItemsRecursive(QGraphicsItem *item, bool // Process item. if (item && (item->d_ptr->dirty || item->d_ptr->paintedViewBoundingRectsNeedRepaint)) { const bool useCompatUpdate = views.isEmpty() || (connectedSignals & changedSignalMask); - if (useCompatUpdate && !item->d_ptr->itemIsUntransformable() - && qFuzzyIsNull(item->boundingRegionGranularity())) { + const bool untransformableItem = item->d_ptr->itemIsUntransformable(); + const QRectF itemBoundingRect = item->boundingRect(); + + if (item->d_ptr->geometryChanged) { + // Update growingItemsBoundingRect. + if (!hasSceneRect) { + QRectF itemSceneBoundingRect = item->d_ptr->sceneTransform.mapRect(itemBoundingRect); + _q_adjustRect(&itemSceneBoundingRect); + growingItemsBoundingRect |= itemSceneBoundingRect; + } + item->d_ptr->geometryChanged = 0; + } + + if (useCompatUpdate && !untransformableItem && 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. - q->update(item->sceneBoundingRect()); + q->update(item->d_ptr->sceneTransform.mapRect(itemBoundingRect)); } else { QRectF dirtyRect; bool uninitializedDirtyRect = true; - const bool untransformableItem = item->d_ptr->itemIsUntransformable(); for (int j = 0; j < views.size(); ++j) { QGraphicsView *view = views.at(j); @@ -5349,7 +5363,8 @@ void QGraphicsScenePrivate::processDirtyItemsRecursive(QGraphicsItem *item, bool continue; if (uninitializedDirtyRect) { - dirtyRect = adjustedItemBoundingRect(item); + dirtyRect = itemBoundingRect; + _q_adjustRect(&dirtyRect); if (!item->d_ptr->fullUpdatePending) { _q_adjustRect(&item->d_ptr->needsRepaint); dirtyRect &= item->d_ptr->needsRepaint; diff --git a/src/gui/graphicsview/qgraphicsscene_p.h b/src/gui/graphicsview/qgraphicsscene_p.h index f4964f2..fd7decf 100644 --- a/src/gui/graphicsview/qgraphicsscene_p.h +++ b/src/gui/graphicsview/qgraphicsscene_p.h @@ -71,6 +71,8 @@ #include #include +static const int QGRAPHICSSCENE_INDEXTIMER_TIMEOUT = 2000; + QT_BEGIN_NAMESPACE class QGraphicsView; @@ -138,7 +140,7 @@ public: int indexTimerId; bool restartIndexTimer; - void startIndexTimer(); + void startIndexTimer(int interval = QGRAPHICSSCENE_INDEXTIMER_TIMEOUT); bool stickyFocus; bool hasFocus; @@ -270,6 +272,7 @@ public: Q_ASSERT(item); item->d_ptr->dirty = 0; item->d_ptr->paintedViewBoundingRectsNeedRepaint = 0; + item->d_ptr->geometryChanged = 0; item->d_ptr->dirtyChildren = 0; item->d_ptr->needsRepaint = QRectF(); item->d_ptr->allChildrenDirty = 0; diff --git a/tests/auto/qgraphicsscene/tst_qgraphicsscene.cpp b/tests/auto/qgraphicsscene/tst_qgraphicsscene.cpp index 23d7a94..9f93ae0 100644 --- a/tests/auto/qgraphicsscene/tst_qgraphicsscene.cpp +++ b/tests/auto/qgraphicsscene/tst_qgraphicsscene.cpp @@ -274,7 +274,9 @@ void tst_QGraphicsScene::sceneRect() QCOMPARE(scene.sceneRect(), QRectF()); QGraphicsItem *item = scene.addRect(QRectF(0, 0, 10, 10)); + qApp->processEvents(); item->setPos(-5, -5); + qApp->processEvents(); QCOMPARE(scene.itemAt(0, 0), item); QCOMPARE(scene.itemAt(10, 10), (QGraphicsItem *)0); -- cgit v0.12