summaryrefslogtreecommitdiffstats
path: root/src/widgets
diff options
context:
space:
mode:
authorVolker Hilsheimer <volker.hilsheimer@qt.io>2021-12-07 14:24:58 +0100
committerVolker Hilsheimer <volker.hilsheimer@qt.io>2021-12-10 23:51:18 +0000
commitbae0a159d8657885e46751710519ca0c3cc69092 (patch)
treeb3f3a138b8316dea43cfdd32eb1ac558bd487a6b /src/widgets
parent9da1f6b6080b667f7e879f953441b713ccff656b (diff)
Fix item view auto-scrolling during drag'n'drop
Amends 71aaf831d175a164b508ce169131a794d55d6fb0, which wrongly assumed that dragMoveEvent will be called and update the dragged position as we scroll the viewport. This is not the case, so we have to do so manually when the view is in DraggingState. Since dragMoveEvent cannot be faked, and since we cannot fake a mouseMoveEvent (it would throw off the drag'n'drop state machine), calculate the new draggedPosition based on old position and the new offset. As with all drag'n'drop, we cannot test this using an auto test. Task-number: QTBUG-96124 Fixes: QTBUG-98961 Change-Id: Ifcfc1a11aa7258ec4610a548a276b4dd4a814590 Reviewed-by: Zhang Hao <zhanghao@uniontech.com> Reviewed-by: Richard Moe Gustavsen <richard.gustavsen@qt.io>
Diffstat (limited to 'src/widgets')
-rw-r--r--src/widgets/itemviews/qabstractitemview.cpp32
1 files changed, 24 insertions, 8 deletions
diff --git a/src/widgets/itemviews/qabstractitemview.cpp b/src/widgets/itemviews/qabstractitemview.cpp
index dc507c24b1..43919a2efb 100644
--- a/src/widgets/itemviews/qabstractitemview.cpp
+++ b/src/widgets/itemviews/qabstractitemview.cpp
@@ -3982,14 +3982,14 @@ void QAbstractItemView::doAutoScroll()
}
}
- int verticalStep = verticalScroll->pageStep();
- int horizontalStep = horizontalScroll->pageStep();
+ const int verticalStep = verticalScroll->pageStep();
+ const int horizontalStep = horizontalScroll->pageStep();
if (d->autoScrollCount < qMax(verticalStep, horizontalStep))
++d->autoScrollCount;
- int margin = d->autoScrollMargin;
- int verticalValue = verticalScroll->value();
- int horizontalValue = horizontalScroll->value();
+ const int margin = d->autoScrollMargin;
+ const int verticalValue = verticalScroll->value();
+ const int horizontalValue = horizontalScroll->value();
const QPoint pos = d->draggedPosition - d->offset();
const QRect area = QWidgetPrivate::get(d->viewport)->clipRect();
@@ -4004,8 +4004,8 @@ void QAbstractItemView::doAutoScroll()
else if (area.right() - pos.x() < margin)
horizontalScroll->setValue(horizontalValue + d->autoScrollCount);
// if nothing changed, stop scrolling
- bool verticalUnchanged = (verticalValue == verticalScroll->value());
- bool horizontalUnchanged = (horizontalValue == horizontalScroll->value());
+ const bool verticalUnchanged = (verticalValue == verticalScroll->value());
+ const bool horizontalUnchanged = (horizontalValue == horizontalScroll->value());
if (verticalUnchanged && horizontalUnchanged) {
stopAutoScroll();
} else {
@@ -4013,13 +4013,29 @@ void QAbstractItemView::doAutoScroll()
d->dropIndicatorRect = QRect();
d->dropIndicatorPosition = QAbstractItemView::OnViewport;
#endif
- if (state() == QAbstractItemView::DragSelectingState) {
+ switch (state()) {
+ case QAbstractItemView::DragSelectingState: {
+ // mouseMoveEvent updates the drag-selection rectangle, so fake an event. This also
+ // updates draggedPosition taking the now scrolled viewport into account.
const QPoint globalPos = d->viewport->mapToGlobal(pos);
const QPoint windowPos = window()->mapFromGlobal(globalPos);
QMouseEvent mm(QEvent::MouseMove, pos, windowPos, globalPos,
Qt::NoButton, Qt::LeftButton, d->pressedModifiers,
Qt::MouseEventSynthesizedByQt);
QApplication::sendEvent(viewport(), &mm);
+ break;
+ }
+ case QAbstractItemView::DraggingState: {
+ // we can't simulate mouse (it would throw off the drag'n'drop state logic) or drag
+ // (we don't have the mime data or the actions) move events during drag'n'drop, so
+ // update our dragged position manually after the scroll. "pos" is the old
+ // draggedPosition - d->offset(), and d->offset() is now updated after scrolling, so
+ // pos + d->offset() gives us the new position.
+ d->draggedPosition = pos + d->offset();
+ break;
+ }
+ default:
+ break;
}
d->viewport->update();
}