summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/gui/graphicsview/qgraphicsview.cpp28
-rw-r--r--src/gui/graphicsview/qgraphicsview_p.h2
-rw-r--r--tests/auto/qgraphicsview/tst_qgraphicsview.cpp115
3 files changed, 138 insertions, 7 deletions
diff --git a/src/gui/graphicsview/qgraphicsview.cpp b/src/gui/graphicsview/qgraphicsview.cpp
index 1e34320..b2cc478 100644
--- a/src/gui/graphicsview/qgraphicsview.cpp
+++ b/src/gui/graphicsview/qgraphicsview.cpp
@@ -839,13 +839,29 @@ void QGraphicsViewPrivate::processPendingUpdates()
dirtyRegion = QRegion();
}
+static inline bool intersectsViewport(const QRect &r, int width, int height)
+{ return !(r.left() > width) && !(r.right() < 0) && !(r.top() >= height) && !(r.bottom() < 0); }
+
+static inline bool containsViewport(const QRect &r, int width, int height)
+{ return r.left() <= 0 && r.top() <= 0 && r.right() >= width - 1 && r.bottom() >= height - 1; }
+
+static inline void QRect_unite(QRect *rect, const QRect &other)
+{
+ if (rect->isEmpty()) {
+ *rect = other;
+ } else {
+ rect->setCoords(qMin(rect->left(), other.left()), qMin(rect->top(), other.top()),
+ qMax(rect->right(), other.right()), qMax(rect->bottom(), other.bottom()));
+ }
+}
+
bool QGraphicsViewPrivate::updateRegion(const QRegion &r)
{
if (fullUpdatePending || viewportUpdateMode == QGraphicsView::NoViewportUpdate || r.isEmpty())
return false;
const QRect boundingRect = r.boundingRect();
- if (!boundingRect.intersects(viewport->rect()))
+ if (!intersectsViewport(boundingRect, viewport->width(), viewport->height()))
return false; // Update region outside viewport.
switch (viewportUpdateMode) {
@@ -854,8 +870,8 @@ bool QGraphicsViewPrivate::updateRegion(const QRegion &r)
viewport->update();
break;
case QGraphicsView::BoundingRectViewportUpdate:
- dirtyBoundingRect |= boundingRect;
- if (dirtyBoundingRect.contains(viewport->rect())) {
+ QRect_unite(&dirtyBoundingRect, boundingRect);
+ if (containsViewport(dirtyBoundingRect, viewport->width(), viewport->height())) {
fullUpdatePending = true;
viewport->update();
}
@@ -882,7 +898,7 @@ bool QGraphicsViewPrivate::updateRegion(const QRegion &r)
bool QGraphicsViewPrivate::updateRect(const QRect &r)
{
if (fullUpdatePending || viewportUpdateMode == QGraphicsView::NoViewportUpdate
- || !r.intersects(viewport->rect())) {
+ || !intersectsViewport(r, viewport->width(), viewport->height())) {
return false;
}
@@ -892,8 +908,8 @@ bool QGraphicsViewPrivate::updateRect(const QRect &r)
viewport->update();
break;
case QGraphicsView::BoundingRectViewportUpdate:
- dirtyBoundingRect |= r;
- if (dirtyBoundingRect.contains(viewport->rect())) {
+ QRect_unite(&dirtyBoundingRect, r);
+ if (containsViewport(dirtyBoundingRect, viewport->width(), viewport->height())) {
fullUpdatePending = true;
viewport->update();
}
diff --git a/src/gui/graphicsview/qgraphicsview_p.h b/src/gui/graphicsview/qgraphicsview_p.h
index 7b9fd5e..6617622 100644
--- a/src/gui/graphicsview/qgraphicsview_p.h
+++ b/src/gui/graphicsview/qgraphicsview_p.h
@@ -63,7 +63,7 @@
QT_BEGIN_NAMESPACE
-class QGraphicsViewPrivate : public QAbstractScrollAreaPrivate
+class Q_AUTOTEST_EXPORT QGraphicsViewPrivate : public QAbstractScrollAreaPrivate
{
Q_DECLARE_PUBLIC(QGraphicsView)
public:
diff --git a/tests/auto/qgraphicsview/tst_qgraphicsview.cpp b/tests/auto/qgraphicsview/tst_qgraphicsview.cpp
index 6db8f27..297c437 100644
--- a/tests/auto/qgraphicsview/tst_qgraphicsview.cpp
+++ b/tests/auto/qgraphicsview/tst_qgraphicsview.cpp
@@ -63,6 +63,7 @@
#include <QtGui/QBoxLayout>
#include <QtGui/QStyle>
#include <QtGui/QPushButton>
+#include <private/qgraphicsview_p.h>
//TESTED_CLASS=
//TESTED_FILES=
@@ -175,6 +176,7 @@ private slots:
void transformationAnchor();
void resizeAnchor();
void viewportUpdateMode();
+ void viewportUpdateMode2();
void acceptDrops();
void optimizationFlags();
void optimizationFlags_dontSavePainterState();
@@ -195,6 +197,8 @@ private slots:
void mouseTracking2();
void render();
void exposeRegion();
+ void update_data();
+ void update();
// task specific tests below me
void task172231_untransformableItems();
@@ -2229,6 +2233,52 @@ void tst_QGraphicsView::viewportUpdateMode()
QCOMPARE(view.lastUpdateRegions.size(), 0);
}
+void tst_QGraphicsView::viewportUpdateMode2()
+{
+ // Create a view with viewport rect equal to QRect(0, 0, 200, 200).
+ QGraphicsScene dummyScene;
+ CustomView view;
+ view.setViewportUpdateMode(QGraphicsView::BoundingRectViewportUpdate);
+ view.setScene(&dummyScene);
+ int left, top, right, bottom;
+ view.getContentsMargins(&left, &top, &right, &bottom);
+ view.resize(200 + left + right, 200 + top + bottom);
+ view.show();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&view);
+#endif
+ QTest::qWait(300);
+ const QRect viewportRect = view.viewport()->rect();
+ QCOMPARE(viewportRect, QRect(0, 0, 200, 200));
+ QGraphicsViewPrivate *viewPrivate = static_cast<QGraphicsViewPrivate *>(qt_widget_private(&view));
+
+ QRect boundingRect;
+ const QRect rect1(0, 0, 10, 10);
+ QVERIFY(viewPrivate->updateRect(rect1));
+ QVERIFY(!viewPrivate->fullUpdatePending);
+ boundingRect |= rect1;
+ QCOMPARE(viewPrivate->dirtyBoundingRect, boundingRect);
+
+ const QRect rect2(50, 50, 10, 10);
+ QVERIFY(viewPrivate->updateRect(rect2));
+ QVERIFY(!viewPrivate->fullUpdatePending);
+ boundingRect |= rect2;
+ QCOMPARE(viewPrivate->dirtyBoundingRect, boundingRect);
+
+ const QRect rect3(190, 190, 10, 10);
+ QVERIFY(viewPrivate->updateRect(rect3));
+ QVERIFY(viewPrivate->fullUpdatePending);
+ boundingRect |= rect3;
+ QCOMPARE(viewPrivate->dirtyBoundingRect, boundingRect);
+
+ view.lastUpdateRegions.clear();
+ viewPrivate->processPendingUpdates();
+ QTest::qWait(50);
+ QCOMPARE(view.lastUpdateRegions.size(), 1);
+ // Note that we adjust by 2 for antialiasing.
+ QCOMPARE(view.lastUpdateRegions.at(0), QRegion(boundingRect.adjusted(-2, -2, 2, 2) & viewportRect));
+}
+
void tst_QGraphicsView::acceptDrops()
{
QGraphicsView view;
@@ -3351,6 +3401,71 @@ void tst_QGraphicsView::exposeRegion()
QCOMPARE(item->paints, 0);
}
+void tst_QGraphicsView::update_data()
+{
+ // In view.viewport() coordinates. (viewport rect: QRect(0, 0, 200, 200))
+ QTest::addColumn<QRect>("updateRect");
+ QTest::newRow("empty") << QRect();
+ QTest::newRow("outside left") << QRect(-200, 0, 100, 100);
+ QTest::newRow("outside right") << QRect(400, 0 ,100, 100);
+ QTest::newRow("outside top") << QRect(0, -200, 100, 100);
+ QTest::newRow("outside bottom") << QRect(0, 400, 100, 100);
+ QTest::newRow("partially inside left") << QRect(-50, 0, 100, 100);
+ QTest::newRow("partially inside right") << QRect(-150, 0, 100, 100);
+ QTest::newRow("partially inside top") << QRect(0, -150, 100, 100);
+ QTest::newRow("partially inside bottom") << QRect(0, 150, 100, 100);
+ QTest::newRow("on topLeft edge") << QRect(-100, -100, 100, 100);
+ QTest::newRow("on topRight edge") << QRect(200, -100, 100, 100);
+ QTest::newRow("on bottomRight edge") << QRect(200, 200, 100, 100);
+ QTest::newRow("on bottomLeft edge") << QRect(-200, 200, 100, 100);
+ QTest::newRow("inside topLeft") << QRect(-99, -99, 100, 100);
+ QTest::newRow("inside topRight") << QRect(199, -99, 100, 100);
+ QTest::newRow("inside bottomRight") << QRect(199, 199, 100, 100);
+ QTest::newRow("inside bottomLeft") << QRect(-199, 199, 100, 100);
+ QTest::newRow("large1") << QRect(50, -100, 100, 400);
+ QTest::newRow("large2") << QRect(-100, 50, 400, 100);
+ QTest::newRow("large3") << QRect(-100, -100, 400, 400);
+ QTest::newRow("viewport rect") << QRect(0, 0, 200, 200);
+}
+void tst_QGraphicsView::update()
+{
+ QFETCH(QRect, updateRect);
+
+ // Create a view with viewport rect equal to QRect(0, 0, 200, 200).
+ QGraphicsScene dummyScene;
+ CustomView view;
+ view.setScene(&dummyScene);
+ int left, top, right, bottom;
+ view.getContentsMargins(&left, &top, &right, &bottom);
+ view.resize(200 + left + right, 200 + top + bottom);
+ view.show();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&view);
+#endif
+ QTest::qWait(300);
+ const QRect viewportRect = view.viewport()->rect();
+ QCOMPARE(viewportRect, QRect(0, 0, 200, 200));
+
+ const bool intersects = updateRect.intersects(viewportRect);
+ QGraphicsViewPrivate *viewPrivate = static_cast<QGraphicsViewPrivate *>(qt_widget_private(&view));
+ QCOMPARE(viewPrivate->updateRect(updateRect), intersects);
+ QCOMPARE(viewPrivate->updateRegion(updateRect), intersects);
+
+ view.lastUpdateRegions.clear();
+ viewPrivate->processPendingUpdates();
+ QVERIFY(viewPrivate->dirtyRegion.isEmpty());
+ QVERIFY(viewPrivate->dirtyBoundingRect.isEmpty());
+ QTest::qWait(50);
+ if (!intersects) {
+ QVERIFY(view.lastUpdateRegions.isEmpty());
+ } else {
+ QCOMPARE(view.lastUpdateRegions.size(), 1);
+ // Note that we adjust by 2 for antialiasing.
+ QCOMPARE(view.lastUpdateRegions.at(0), QRegion(updateRect.adjusted(-2, -2, 2, 2) & viewportRect));
+ }
+ QVERIFY(!viewPrivate->fullUpdatePending);
+}
+
void tst_QGraphicsView::task253415_reconnectUpdateSceneOnSceneChanged()
{
QGraphicsView view;