itemviews: Use the start of the current selection when getting the range

When doing a shift-select while moving the mouse then the start point
should be based on the start of the current selection and not the
pressed position. If there is no current selection start index, then
we can safely depend on pressed position as this will be the previous
index pressed on.

This resolves an issue introduced by
e02293a76d when fixing QTBUG-78797

Fixes: QTBUG-81542
Change-Id: Ia66c42b220452fdcbc8cfccc05dbc8a3911c3f5e
Reviewed-by: Richard Moe Gustavsen <richard.gustavsen@qt.io>
This commit is contained in:
Andy Shaw 2020-02-11 13:58:04 +01:00
parent bff56f953a
commit 2e0c29a4bb
2 changed files with 67 additions and 3 deletions

View File

@ -1844,10 +1844,16 @@ void QAbstractItemView::mouseMoveEvent(QMouseEvent *event)
|| edit(index, NoEditTriggers, event))
return;
if (d->selectionMode != SingleSelection)
topLeft = d->pressedPosition - d->offset();
else
if (d->selectionMode != SingleSelection) {
// Use the current selection start index if it is valid as this will be based on the
// start of the selection and not the last item being pressed which can be different
// when in extended selection
topLeft = d->currentSelectionStartIndex.isValid()
? visualRect(d->currentSelectionStartIndex).center()
: d->pressedPosition - d->offset();
} else {
topLeft = bottomRight;
}
d->checkMouseMove(index);

View File

@ -151,6 +151,7 @@ private slots:
void currentFollowsIndexWidget();
void checkFocusAfterActivationChanges_data();
void checkFocusAfterActivationChanges();
void dragSelectAfterNewPress();
};
class MyAbstractItemDelegate : public QAbstractItemDelegate
@ -2514,5 +2515,62 @@ void tst_QAbstractItemView::checkFocusAfterActivationChanges()
QVERIFY(view->hasFocus());
}
void tst_QAbstractItemView::dragSelectAfterNewPress()
{
QStandardItemModel model;
for (int i = 0; i < 10; ++i) {
QStandardItem *item = new QStandardItem(QString::number(i));
model.setItem(i, 0, item);
}
QListView view;
view.setFixedSize(160, 650); // Minimum width for windows with frame on Windows 8
view.setSelectionMode(QListView::ExtendedSelection);
view.setModel(&model);
centerOnScreen(&view);
moveCursorAway(&view);
view.show();
QVERIFY(QTest::qWaitForWindowExposed(&view));
QModelIndex index0 = model.index(0, 0);
QModelIndex index2 = model.index(2, 0);
view.setCurrentIndex(index0);
QCOMPARE(view.currentIndex(), index0);
// Select item 0 using a single click
QTest::mouseClick(view.viewport(), Qt::LeftButton, Qt::NoModifier,
view.visualRect(index0).center());
QCOMPARE(view.currentIndex(), index0);
// Press to select item 2
QTest::mousePress(view.viewport(), Qt::LeftButton, Qt::ShiftModifier,
view.visualRect(index2).center());
QCOMPARE(view.currentIndex(), index2);
// Verify that the selection worked OK
QModelIndexList selected = view.selectionModel()->selectedIndexes();
QCOMPARE(selected.count(), 3);
for (int i = 0; i < 2; ++i)
QVERIFY(selected.contains(model.index(i, 0)));
QModelIndex index5 = model.index(5, 0);
const QPoint releasePos = view.visualRect(index5).center();
// The mouse move event has to be created manually because the QTest framework does not
// contain a function for mouse moves with buttons pressed
QMouseEvent moveEvent2(QEvent::MouseMove, releasePos, Qt::NoButton, Qt::LeftButton,
Qt::ShiftModifier);
const bool moveEventReceived = qApp->notify(view.viewport(), &moveEvent2);
QVERIFY(moveEventReceived);
QTest::mouseRelease(view.viewport(), Qt::LeftButton, Qt::ShiftModifier, releasePos);
QCOMPARE(view.currentIndex(), index5);
// Verify that the selection worked OK
selected = view.selectionModel()->selectedIndexes();
QCOMPARE(selected.count(), 6);
for (int i = 0; i < 5; ++i)
QVERIFY(selected.contains(model.index(i, 0)));
}
QTEST_MAIN(tst_QAbstractItemView)
#include "tst_qabstractitemview.moc"