summaryrefslogtreecommitdiffstats
path: root/tests
diff options
context:
space:
mode:
authorTaras Kachmaryk <gigaxenum335@gmail.com>2022-11-25 15:58:43 +0200
committerTaras Kachmaryk <gigaxenum335@gmail.com>2022-11-26 16:07:15 +0200
commitf0cd18706f6ffca09a7bfbc84542a9e79b4a55f3 (patch)
treefdd6b48d642072e2aecd5432911fb85f1710f396 /tests
parent3ee7a9f85c9d4566223f44f7bab04abafdfca82c (diff)
QGraphicsView: fix jumping graphic items when dragging out of view
The algorithms for calculating the scene's position within the view did not compensate for scrollbars showing. The scrollbars should be ignored when positioning hte scene within the view, as alignment only cares about the positioning of the scene when the view is larger than the scene anyway. Add a test case that verifies that items don't jump up or down when dragging horizontally, and not left or right when dragging vertically. Mark variables in the modified function as const where applicable to make it easier to follow the code. Done-with: Volker Hilsheimer <volker.hilsheimer@qt.io> Fixes: QTBUG-46757 Change-Id: If205637dfe124e0034f68201b23f174d6863084d Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
Diffstat (limited to 'tests')
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicsview/tst_qgraphicsview.cpp108
1 files changed, 108 insertions, 0 deletions
diff --git a/tests/auto/widgets/graphicsview/qgraphicsview/tst_qgraphicsview.cpp b/tests/auto/widgets/graphicsview/qgraphicsview/tst_qgraphicsview.cpp
index d5807c1958..27fbcc2b3b 100644
--- a/tests/auto/widgets/graphicsview/qgraphicsview/tst_qgraphicsview.cpp
+++ b/tests/auto/widgets/graphicsview/qgraphicsview/tst_qgraphicsview.cpp
@@ -248,6 +248,8 @@ private slots:
#ifndef QT_NO_CURSOR
void QTBUG_7438_cursor();
#endif
+ void resizeContentsOnItemDrag_data();
+ void resizeContentsOnItemDrag();
public slots:
void dummySlot() {}
@@ -4960,5 +4962,111 @@ void tst_QGraphicsView::QTBUG_70255_scrollTo()
QCOMPARE(point, QPoint(0, -500));
}
+void tst_QGraphicsView::resizeContentsOnItemDrag_data()
+{
+ QTest::addColumn<Qt::Alignment>("alignment");
+ QTest::addColumn<Qt::Orientation>("orientation");
+ QTest::addRow("Center right") << Qt::Alignment(Qt::AlignCenter) << Qt::Horizontal;
+ QTest::addRow("Center down") << Qt::Alignment(Qt::AlignCenter) << Qt::Vertical;
+ QTest::addRow("BottomLeft right") << (Qt::AlignBottom | Qt::AlignLeft) << Qt::Horizontal;
+ QTest::addRow("TopRight down") << (Qt::AlignTop | Qt::AlignRight) << Qt::Vertical;
+}
+
+void tst_QGraphicsView::resizeContentsOnItemDrag()
+{
+ QFETCH(Qt::Alignment, alignment);
+ QFETCH(Qt::Orientation, orientation);
+
+ QGraphicsView view;
+ QGraphicsScene scene;
+ view.setFixedSize(200, 200);
+ view.setScene(&scene);
+
+ view.setAlignment(alignment);
+
+ class MovableItem : public QGraphicsEllipseItem
+ {
+ public:
+ using QGraphicsEllipseItem::QGraphicsEllipseItem;
+
+ QList<QPointF> scenePositions;
+
+ protected:
+ void mousePressEvent(QGraphicsSceneMouseEvent *event) override
+ {
+ scenePositions << event->scenePos();
+ }
+ void mouseMoveEvent(QGraphicsSceneMouseEvent *event) override
+ {
+ scenePositions << event->scenePos();
+ QGraphicsEllipseItem::mouseMoveEvent(event);
+ }
+ };
+
+ MovableItem item(-10, -10, 20, 20);
+ item.setFlags(QGraphicsItem::ItemIsMovable);
+ scene.addItem(&item);
+ view.show();
+ QVERIFY(QTest::qWaitForWindowExposed(&view));
+
+ // Position the item near the relevant edge of the view, with a few pixels
+ // to go until the scrollbars should be showing.
+ if (orientation == Qt::Horizontal)
+ item.setPos(view.width() - item.rect().width() - 5, 0);
+ else
+ item.setPos(0, view.height() - item.rect().height() - 5);
+ QApplication::processEvents(); // queued connection used to trigger recalculateContentSize
+ QPoint mousePos = view.mapFromScene(item.pos());
+
+ QTest::mousePress(view.viewport(), Qt::LeftButton, {}, mousePos);
+ QCOMPARE(item.scenePositions.count(), 1);
+ QCOMPARE(item.scenePositions.takeLast(), view.mapToScene(mousePos));
+
+ auto lastItemPos = item.pos();
+ auto lastScenePos = view.mapToScene(mousePos);
+ int overshoot = 0;
+ const QScrollBar *scrollBar = orientation == Qt::Horizontal
+ ? view.horizontalScrollBar()
+ : view.verticalScrollBar();
+ // Drag the item until the scroll bars become visible, and then for a few more pixels.
+ // Verify that the item doesn't jump when the scrollbar shows.
+ while (overshoot < 10) {
+ if (orientation == Qt::Horizontal)
+ mousePos.rx() += 1;
+ else
+ mousePos.ry() += 1;
+ QTest::mouseMove(view.viewport(), mousePos);
+ QApplication::processEvents(); // queued connection used to trigger recalculateContentSize
+ const bool scrollbarAvailable = scrollBar->maximum() > scrollBar->minimum();
+ bool allowMoreEvents = false;
+ if (scrollbarAvailable) {
+ if (!overshoot) {
+ QTRY_VERIFY(scrollBar->isVisible());
+ // scrollbar becoming visible triggers event replay, so we get more than one
+ allowMoreEvents = true;
+ }
+ ++overshoot;
+ }
+ if (allowMoreEvents)
+ QCOMPARE_GE(item.scenePositions.count(), 1);
+ else
+ QCOMPARE(item.scenePositions.count(), 1);
+ const auto scenePos = item.scenePositions.takeLast();
+ item.scenePositions.clear();
+
+ const auto same = orientation == Qt::Horizontal ? &QPointF::y : &QPointF::x;
+ const auto moved = orientation == Qt::Horizontal ? &QPointF::x : &QPointF::y;
+ QCOMPARE((item.pos().*same)(), (lastItemPos.*same)());
+ QCOMPARE_GE((item.pos().*moved)() - (lastItemPos.*moved)(), 1);
+ QCOMPARE_LE((item.pos().*moved)() - (lastItemPos.*moved)(), 2);
+ lastItemPos = item.pos();
+
+ QCOMPARE((scenePos.*same)(), (lastScenePos.*same)());
+ QCOMPARE_GE((scenePos.*moved)() - (lastScenePos.*moved)(), 1);
+ QCOMPARE_LE((scenePos.*moved)() - (lastScenePos.*moved)(), 2);
+ lastScenePos = scenePos;
+ }
+}
+
QTEST_MAIN(tst_QGraphicsView)
#include "tst_qgraphicsview.moc"