summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/widgets/itemviews/qabstractitemview.cpp22
-rw-r--r--src/widgets/itemviews/qabstractitemview_p.h1
-rw-r--r--tests/auto/widgets/itemviews/qabstractitemview/tst_qabstractitemview.cpp119
-rw-r--r--tests/auto/widgets/itemviews/qtableview/tst_qtableview.cpp3
4 files changed, 135 insertions, 10 deletions
diff --git a/src/widgets/itemviews/qabstractitemview.cpp b/src/widgets/itemviews/qabstractitemview.cpp
index 6aa2ba08cd..2caf5d1eb3 100644
--- a/src/widgets/itemviews/qabstractitemview.cpp
+++ b/src/widgets/itemviews/qabstractitemview.cpp
@@ -1055,7 +1055,7 @@ void QAbstractItemView::setCurrentIndex(const QModelIndex &index)
d->selectionModel->setCurrentIndex(index, command);
d->currentIndexSet = true;
if ((command & QItemSelectionModel::Current) == 0)
- d->pressedPosition = visualRect(currentIndex()).center() + d->offset();
+ d->currentSelectionStartIndex = index;
}
}
@@ -1707,10 +1707,12 @@ void QAbstractItemView::mousePressEvent(QMouseEvent *event)
QItemSelectionModel::SelectionFlags command = selectionCommand(index, event);
d->noSelectionOnMousePress = command == QItemSelectionModel::NoUpdate || !index.isValid();
QPoint offset = d->offset();
- if ((command & QItemSelectionModel::Current) == 0)
+ if ((command & QItemSelectionModel::Current) == 0) {
d->pressedPosition = pos + offset;
- else if (!indexAt(d->pressedPosition - offset).isValid())
- d->pressedPosition = visualRect(currentIndex()).center() + offset;
+ d->currentSelectionStartIndex = index;
+ }
+ else if (!d->currentSelectionStartIndex.isValid())
+ d->currentSelectionStartIndex = currentIndex();
if (edit(index, NoEditTriggers, event))
return;
@@ -1722,7 +1724,7 @@ void QAbstractItemView::mousePressEvent(QMouseEvent *event)
d->autoScroll = false;
d->selectionModel->setCurrentIndex(index, QItemSelectionModel::NoUpdate);
d->autoScroll = autoScroll;
- QRect rect(d->pressedPosition - offset, pos);
+ QRect rect(visualRect(d->currentSelectionStartIndex).center(), pos);
if (command.testFlag(QItemSelectionModel::Toggle)) {
command &= ~QItemSelectionModel::Toggle;
d->ctrlDragSelectionFlag = d->selectionModel->isSelected(index) ? QItemSelectionModel::Deselect : QItemSelectionModel::Select;
@@ -2319,16 +2321,16 @@ void QAbstractItemView::keyPressEvent(QKeyEvent *event)
// note that we don't check if the new current index is enabled because moveCursor() makes sure it is
if (command & QItemSelectionModel::Current) {
d->selectionModel->setCurrentIndex(newCurrent, QItemSelectionModel::NoUpdate);
- if (!indexAt(d->pressedPosition - d->offset()).isValid())
- d->pressedPosition = visualRect(oldCurrent).center() + d->offset();
- QRect rect(d->pressedPosition - d->offset(), visualRect(newCurrent).center());
+ if (!d->currentSelectionStartIndex.isValid())
+ d->currentSelectionStartIndex = oldCurrent;
+ QRect rect(visualRect(d->currentSelectionStartIndex).center(), visualRect(newCurrent).center());
setSelection(rect, command);
} else {
d->selectionModel->setCurrentIndex(newCurrent, command);
- d->pressedPosition = visualRect(newCurrent).center() + d->offset();
+ d->currentSelectionStartIndex = newCurrent;
if (newCurrent.isValid()) {
// We copy the same behaviour as for mousePressEvent().
- QRect rect(d->pressedPosition - d->offset(), QSize(1, 1));
+ QRect rect(visualRect(newCurrent).center(), QSize(1, 1));
setSelection(rect, command);
}
}
diff --git a/src/widgets/itemviews/qabstractitemview_p.h b/src/widgets/itemviews/qabstractitemview_p.h
index c5753a91ff..b792228312 100644
--- a/src/widgets/itemviews/qabstractitemview_p.h
+++ b/src/widgets/itemviews/qabstractitemview_p.h
@@ -370,6 +370,7 @@ public:
QPersistentModelIndex enteredIndex;
QPersistentModelIndex pressedIndex;
+ QPersistentModelIndex currentSelectionStartIndex;
Qt::KeyboardModifiers pressedModifiers;
QPoint pressedPosition;
bool pressedAlreadySelected;
diff --git a/tests/auto/widgets/itemviews/qabstractitemview/tst_qabstractitemview.cpp b/tests/auto/widgets/itemviews/qabstractitemview/tst_qabstractitemview.cpp
index 79f51d27c7..90580aea05 100644
--- a/tests/auto/widgets/itemviews/qabstractitemview/tst_qabstractitemview.cpp
+++ b/tests/auto/widgets/itemviews/qabstractitemview/tst_qabstractitemview.cpp
@@ -53,6 +53,8 @@
#include <qscreen.h>
#include <qscopedpointer.h>
#include <qstyleditemdelegate.h>
+#include <qstringlistmodel.h>
+#include <qsortfilterproxymodel.h>
static inline void setFrameless(QWidget *w)
{
@@ -252,6 +254,7 @@ private slots:
void QTBUG31411_noSelection();
void QTBUG39324_settingSameInstanceOfIndexWidget();
void sizeHintChangeTriggersLayout();
+ void shiftSelectionAfterChangingModelContents();
};
class MyAbstractItemDelegate : public QAbstractItemDelegate
@@ -1884,5 +1887,121 @@ void tst_QAbstractItemView::QTBUG39324_settingSameInstanceOfIndexWidget()
table->show();
}
+void tst_QAbstractItemView::shiftSelectionAfterChangingModelContents()
+{
+ QStringList list;
+ list << "A" << "B" << "C" << "D" << "E" << "F";
+ QStringListModel model(list);
+ QSortFilterProxyModel proxyModel;
+ proxyModel.setSourceModel(&model);
+ proxyModel.sort(0, Qt::AscendingOrder);
+ proxyModel.setDynamicSortFilter(true);
+
+ QPersistentModelIndex indexA(proxyModel.index(0, 0));
+ QPersistentModelIndex indexB(proxyModel.index(1, 0));
+ QPersistentModelIndex indexC(proxyModel.index(2, 0));
+ QPersistentModelIndex indexD(proxyModel.index(3, 0));
+ QPersistentModelIndex indexE(proxyModel.index(4, 0));
+ QPersistentModelIndex indexF(proxyModel.index(5, 0));
+
+ QListView view;
+ view.setModel(&proxyModel);
+ view.setSelectionMode(QAbstractItemView::ExtendedSelection);
+ view.show();
+ QTest::qWaitForWindowExposed(&view);
+
+ // Click "C"
+ QTest::mouseClick(view.viewport(), Qt::LeftButton, Qt::NoModifier, view.visualRect(indexC).center());
+ QModelIndexList selected = view.selectionModel()->selectedIndexes();
+ QCOMPARE(selected.count(), 1);
+ QVERIFY(selected.contains(indexC));
+
+ // Insert new item "B1"
+ model.insertRow(0);
+ model.setData(model.index(0, 0), "B1");
+
+ // Shift-click "D" -> we expect that "C" and "D" are selected
+ QTest::mouseClick(view.viewport(), Qt::LeftButton, Qt::ShiftModifier, view.visualRect(indexD).center());
+ selected = view.selectionModel()->selectedIndexes();
+ QCOMPARE(selected.count(), 2);
+ QVERIFY(selected.contains(indexC));
+ QVERIFY(selected.contains(indexD));
+
+ // Click "D"
+ QTest::mouseClick(view.viewport(), Qt::LeftButton, Qt::NoModifier, view.visualRect(indexD).center());
+ selected = view.selectionModel()->selectedIndexes();
+ QCOMPARE(selected.count(), 1);
+ QVERIFY(selected.contains(indexD));
+
+ // Remove items "B" and "C"
+ model.removeRows(proxyModel.mapToSource(indexB).row(), 1);
+ model.removeRows(proxyModel.mapToSource(indexC).row(), 1);
+ QVERIFY(!indexB.isValid());
+ QVERIFY(!indexC.isValid());
+
+ // Shift-click "F" -> we expect that "D", "E", and "F" are selected
+ QTest::mouseClick(view.viewport(), Qt::LeftButton, Qt::ShiftModifier, view.visualRect(indexF).center());
+ selected = view.selectionModel()->selectedIndexes();
+ QCOMPARE(selected.count(), 3);
+ QVERIFY(selected.contains(indexD));
+ QVERIFY(selected.contains(indexE));
+ QVERIFY(selected.contains(indexF));
+
+ // Move to "A" by pressing "Up" repeatedly
+ while (view.currentIndex() != indexA) {
+ QTest::keyClick(&view, Qt::Key_Up);
+ }
+ selected = view.selectionModel()->selectedIndexes();
+ QCOMPARE(selected.count(), 1);
+ QVERIFY(selected.contains(indexA));
+
+ // Change the sort order
+ proxyModel.sort(0, Qt::DescendingOrder);
+
+ // Shift-click "F" -> All items should be selected
+ QTest::mouseClick(view.viewport(), Qt::LeftButton, Qt::ShiftModifier, view.visualRect(indexF).center());
+ selected = view.selectionModel()->selectedIndexes();
+ QCOMPARE(selected.count(), model.rowCount());
+
+ // Restore the old sort order
+ proxyModel.sort(0, Qt::AscendingOrder);
+
+ // Click "D"
+ QTest::mouseClick(view.viewport(), Qt::LeftButton, Qt::NoModifier, view.visualRect(indexD).center());
+ selected = view.selectionModel()->selectedIndexes();
+ QCOMPARE(selected.count(), 1);
+ QVERIFY(selected.contains(indexD));
+
+ // Insert new item "B2"
+ model.insertRow(0);
+ model.setData(model.index(0, 0), "B2");
+
+ // Press Shift+Down -> "D" and "E" should be selected.
+ QTest::keyClick(&view, Qt::Key_Down, Qt::ShiftModifier);
+ selected = view.selectionModel()->selectedIndexes();
+ QCOMPARE(selected.count(), 2);
+ QVERIFY(selected.contains(indexD));
+ QVERIFY(selected.contains(indexE));
+
+ // Click "A" to reset the current selection starting point;
+ //then select "D" via QAbstractItemView::setCurrentIndex(const QModelIndex&).
+ QTest::mouseClick(view.viewport(), Qt::LeftButton, Qt::NoModifier, view.visualRect(indexA).center());
+ view.setCurrentIndex(indexD);
+ selected = view.selectionModel()->selectedIndexes();
+ QCOMPARE(selected.count(), 1);
+ QVERIFY(selected.contains(indexD));
+
+ // Insert new item "B3"
+ model.insertRow(0);
+ model.setData(model.index(0, 0), "B3");
+
+ // Press Shift+Down -> "D" and "E" should be selected.
+ QTest::keyClick(&view, Qt::Key_Down, Qt::ShiftModifier);
+ selected = view.selectionModel()->selectedIndexes();
+ QCOMPARE(selected.count(), 2);
+ QVERIFY(selected.contains(indexD));
+ QVERIFY(selected.contains(indexE));
+}
+
QTEST_MAIN(tst_QAbstractItemView)
#include "tst_qabstractitemview.moc"
diff --git a/tests/auto/widgets/itemviews/qtableview/tst_qtableview.cpp b/tests/auto/widgets/itemviews/qtableview/tst_qtableview.cpp
index a11d423896..75f77f8107 100644
--- a/tests/auto/widgets/itemviews/qtableview/tst_qtableview.cpp
+++ b/tests/auto/widgets/itemviews/qtableview/tst_qtableview.cpp
@@ -4288,6 +4288,9 @@ void tst_QTableView::taskQTBUG_4516_clickOnRichTextLabel()
QLabel label("rich text");
label.setTextFormat(Qt::RichText);
view.setIndexWidget(model.index(1,1), &label);
+ view.show();
+ QVERIFY(QTest::qWaitForWindowExposed(&view));
+
view.setCurrentIndex(model.index(0,0));
QCOMPARE(view.currentIndex(), model.index(0,0));