diff options
author | Volker Hilsheimer <volker.hilsheimer@qt.io> | 2021-10-21 12:03:57 +0200 |
---|---|---|
committer | Volker Hilsheimer <volker.hilsheimer@qt.io> | 2021-10-22 09:43:53 +0200 |
commit | 71aaf831d175a164b508ce169131a794d55d6fb0 (patch) | |
tree | c7c3edd7b90c7b9e66e28dedafdc5f6c2f8bf9b4 /src/widgets/itemviews | |
parent | 7d133a5613b7d9bae544fa56d26577c0c9d50ff4 (diff) |
QAbstractItemView: auto-scroll with selection rectangle
Some item views, such as QListView in icon mode, implement a selection
rectangle with which the user can "lasso" items. So far, dragging that
rectangle did not trigger auto scroll, so unless an item near the edge
was selected, the user had to stop the lassoing and scroll manually to
reach more items.
Since QAbtractItemView implements auto scrolling for drag'n'drop, we can
use that mechanism also when the selection rectangle is dragged. This
requires some modifications:
We need to make sure that scrolling the view during a drag-selection
generates mouse move events so that the selection is extended and the
rectangle is updated in subclasses.
And we need to stop using QCursor::pos to get the position of the mouse
pointer, as this makes the auto-scrolling untestable. Instead, record
the mouse position last seen during a mouseMove or dragMoveEvent in
content-coordinates (identical to pressedPosition).
As a drive-by, fix some coding-style issues in nearby code.
Done-with: Zhang Hao <zhanghao@uniontech.com>
Fixes: QTBUG-96124
Change-Id: I426f786e5842ae9f9fb04e9d34dc6d3379a6207f
Reviewed-by: Richard Moe Gustavsen <richard.gustavsen@qt.io>
Diffstat (limited to 'src/widgets/itemviews')
-rw-r--r-- | src/widgets/itemviews/qabstractitemview.cpp | 29 | ||||
-rw-r--r-- | src/widgets/itemviews/qabstractitemview_p.h | 1 |
2 files changed, 20 insertions, 10 deletions
diff --git a/src/widgets/itemviews/qabstractitemview.cpp b/src/widgets/itemviews/qabstractitemview.cpp index d782eb71ab..3fb77b72a6 100644 --- a/src/widgets/itemviews/qabstractitemview.cpp +++ b/src/widgets/itemviews/qabstractitemview.cpp @@ -1798,8 +1798,7 @@ void QAbstractItemView::mousePressEvent(QMouseEvent *event) // this is the mouse press event that closed the last editor (via focus event) d->pressClosedEditor = d->pressClosedEditorWatcher.isActive() && d->lastEditedIndex == index; - if (!d->selectionModel - || (d->state == EditingState && d->hasEditor(index))) + if (!d->selectionModel || (d->state == EditingState && d->hasEditor(index))) return; d->pressedAlreadySelected = d->selectionModel->isSelected(index); @@ -1808,10 +1807,9 @@ void QAbstractItemView::mousePressEvent(QMouseEvent *event) QItemSelectionModel::SelectionFlags command = selectionCommand(index, event); d->noSelectionOnMousePress = command == QItemSelectionModel::NoUpdate || !index.isValid(); QPoint offset = d->offset(); - d->pressedPosition = pos + offset; - if ((command & QItemSelectionModel::Current) == 0) { + d->pressedPosition = d->draggedPosition = pos + offset; + if (!(command & QItemSelectionModel::Current)) d->currentSelectionStartIndex = index; - } else if (!d->currentSelectionStartIndex.isValid()) d->currentSelectionStartIndex = currentIndex(); @@ -1863,6 +1861,8 @@ void QAbstractItemView::mouseMoveEvent(QMouseEvent *event) QPoint topLeft; QPoint bottomRight = event->position().toPoint(); + d->draggedPosition = bottomRight + d->offset(); + if (state() == ExpandingState || state() == CollapsingState) return; @@ -1922,10 +1922,10 @@ void QAbstractItemView::mouseMoveEvent(QMouseEvent *event) setSelection(selectionRect, command); // set at the end because it might scroll the view - if (index.isValid() - && (index != d->selectionModel->currentIndex()) - && d->isIndexEnabled(index)) + if (index.isValid() && (index != d->selectionModel->currentIndex()) && d->isIndexEnabled(index)) d->selectionModel->setCurrentIndex(index, QItemSelectionModel::NoUpdate); + else if (d->shouldAutoScroll(event->pos()) && !d->autoScrollTimer.isActive()) + startAutoScroll(); } } @@ -2047,6 +2047,7 @@ void QAbstractItemView::dragEnterEvent(QDragEnterEvent *event) void QAbstractItemView::dragMoveEvent(QDragMoveEvent *event) { Q_D(QAbstractItemView); + d->draggedPosition = event->position().toPoint() + d->offset(); if (dragDropMode() == InternalMove && (event->source() != this || !(event->possibleActions() & Qt::MoveAction))) return; @@ -3989,8 +3990,8 @@ void QAbstractItemView::doAutoScroll() int verticalValue = verticalScroll->value(); int horizontalValue = horizontalScroll->value(); - QPoint pos = d->viewport->mapFromGlobal(QCursor::pos()); - QRect area = QWidgetPrivate::get(d->viewport)->clipRect(); + const QPoint pos = d->draggedPosition - d->offset(); + const QRect area = QWidgetPrivate::get(d->viewport)->clipRect(); // do the scrolling if we are in the scroll margins if (pos.y() - area.top() < margin) @@ -4011,6 +4012,14 @@ void QAbstractItemView::doAutoScroll() d->dropIndicatorRect = QRect(); d->dropIndicatorPosition = QAbstractItemView::OnViewport; #endif + if (state() == QAbstractItemView::DragSelectingState) { + 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); + } d->viewport->update(); } } diff --git a/src/widgets/itemviews/qabstractitemview_p.h b/src/widgets/itemviews/qabstractitemview_p.h index 74850de992..14fae86c87 100644 --- a/src/widgets/itemviews/qabstractitemview_p.h +++ b/src/widgets/itemviews/qabstractitemview_p.h @@ -375,6 +375,7 @@ public: QPersistentModelIndex currentSelectionStartIndex; Qt::KeyboardModifiers pressedModifiers; QPoint pressedPosition; + QPoint draggedPosition; bool pressedAlreadySelected; bool releaseFromDoubleClick; |