summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBjørn Erik Nilsen <bjorn.nilsen@nokia.com>2009-06-08 11:09:14 (GMT)
committerAndreas Aardal Hanssen <andreas.aardal.hanssen@nokia.com>2009-06-09 07:36:05 (GMT)
commit0095e40b2efc0c43c0d908bb5b9828619bc087e7 (patch)
tree95850288ca3b4171e400c57b5d703b17fafbeb67
parent9cafd6bcf6f91c027904c998a0dd536feac8d4e0 (diff)
downloadQt-0095e40b2efc0c43c0d908bb5b9828619bc087e7.zip
Qt-0095e40b2efc0c43c0d908bb5b9828619bc087e7.tar.gz
Qt-0095e40b2efc0c43c0d908bb5b9828619bc087e7.tar.bz2
QGraphicsItem discard updates when it shouldn't.
Once a _q_processDirtyItems call is queued, it means we at least have one item that is marked as dirty and we must reset it when the _q_processDirtyItems slot is called. The problem however, was that we didn't reset the item's dirty state if a full scene update occurred in between, i.e. item->update(); scene.update(); We don't have to calculate the item's dirty rect if a full scene update occurs in between, but we still have to reset its state. Auto-test included.
-rw-r--r--src/gui/graphicsview/qgraphicsscene.cpp13
-rw-r--r--src/gui/graphicsview/qgraphicsview.cpp1
-rw-r--r--tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp28
3 files changed, 36 insertions, 6 deletions
diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp
index caf9309..ad392b0 100644
--- a/src/gui/graphicsview/qgraphicsscene.cpp
+++ b/src/gui/graphicsview/qgraphicsscene.cpp
@@ -679,19 +679,19 @@ void QGraphicsScenePrivate::_q_processDirtyItems()
{
processDirtyItemsEmitted = false;
- if (updateAll)
- return;
-
const bool wasPendingSceneUpdate = calledEmitUpdated;
const QRectF oldGrowingItemsBoundingRect = growingItemsBoundingRect;
processDirtyItemsRecursive(0);
if (!hasSceneRect && oldGrowingItemsBoundingRect != growingItemsBoundingRect)
emit q_func()->sceneRectChanged(growingItemsBoundingRect);
+ if (wasPendingSceneUpdate)
+ return;
+
for (int i = 0; i < views.size(); ++i)
views.at(i)->d_func()->processPendingUpdates();
- if (!wasPendingSceneUpdate && calledEmitUpdated) {
+ if (calledEmitUpdated) {
// We did a compatibility QGraphicsScene::update in processDirtyItemsRecursive
// and we cannot wait for the control to reach the eventloop before the
// changed signal is emitted, so we emit it now.
@@ -5322,7 +5322,6 @@ void QGraphicsScenePrivate::markDirty(QGraphicsItem *item, const QRectF &rect, b
void QGraphicsScenePrivate::processDirtyItemsRecursive(QGraphicsItem *item, bool dirtyAncestorContainsChildren)
{
- Q_ASSERT(!item || item->d_ptr->dirty || item->d_ptr->dirtyChildren);
Q_Q(QGraphicsScene);
// Calculate the full scene transform for this item.
@@ -5438,13 +5437,15 @@ void QGraphicsScenePrivate::processDirtyItemsRecursive(QGraphicsItem *item, bool
continue;
}
- if (dirtyAncestorContainsChildren) {
+ if (dirtyAncestorContainsChildren || updateAll) {
// No need to process this child's dirty rect, hence reset the dirty state.
// However, we have to continue the recursion because it might have a dirty
// view bounding rect that needs repaint. We also have to reset the dirty
// state of its descendants.
child->d_ptr->dirty = 0;
child->d_ptr->fullUpdatePending = 0;
+ if (updateAll)
+ child->d_ptr->paintedViewBoundingRectsNeedRepaint = 0;
}
processDirtyItemsRecursive(child, dirtyAncestorContainsChildren);
diff --git a/src/gui/graphicsview/qgraphicsview.cpp b/src/gui/graphicsview/qgraphicsview.cpp
index 87b5e3f..a9fc563 100644
--- a/src/gui/graphicsview/qgraphicsview.cpp
+++ b/src/gui/graphicsview/qgraphicsview.cpp
@@ -2496,6 +2496,7 @@ void QGraphicsView::updateScene(const QList<QRectF> &rects)
for (int i = 0; i < dirtyRects.size(); ++i)
dirtyViewportRects += dirtyRects.at(i);
d->dirtyRegion = QRegion();
+ d->dirtyBoundingRect = QRect();
bool fullUpdate = !d->accelerateScrolling || d->viewportUpdateMode == QGraphicsView::FullViewportUpdate;
bool boundingRectUpdate = (d->viewportUpdateMode == QGraphicsView::BoundingRectViewportUpdate)
diff --git a/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp b/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp
index 427ecf3..5b297f6 100644
--- a/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp
+++ b/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp
@@ -219,6 +219,7 @@ private slots:
void updateCachedItemAfterMove();
void deviceTransform_data();
void deviceTransform();
+ void update();
// task specific tests below me
void task141694_textItemEnsureVisible();
@@ -6427,5 +6428,32 @@ void tst_QGraphicsItem::deviceTransform()
QCOMPARE(rect3->deviceTransform(deviceX).map(QPointF(50, 50)), mapResult3);
}
+void tst_QGraphicsItem::update()
+{
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+ view.show();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&view);
+#endif
+ QTest::qWait(100);
+
+ EventTester *item = new EventTester;
+ scene.addItem(item);
+ QTest::qWait(100); // Make sure all pending updates are processed.
+ item->repaints = 0;
+
+ item->update(); // Item marked as dirty
+ scene.update(); // Entire scene marked as dirty
+ qApp->processEvents();
+ QCOMPARE(item->repaints, 1);
+
+ // Make sure the dirty state from the previous update is reset so that
+ // the item don't think it is already dirty and discards this update.
+ item->update();
+ qApp->processEvents();
+ QCOMPARE(item->repaints, 2);
+}
+
QTEST_MAIN(tst_QGraphicsItem)
#include "tst_qgraphicsitem.moc"