Fix QItemSelectionModel deselection range

Left and right were swapped which caused invalid selection ranges to be
emitted through selectionChanged.

Task-number: QTBUG-48402
Change-Id: I18692c2b50c49ab39065f9b360b37b7615227ee9
Reviewed-by: Gabriel de Dietrich <gabriel.dedietrich@theqtcompany.com>
This commit is contained in:
Joni Poikelin 2015-09-23 13:42:11 +03:00
parent 7183d08095
commit 61f2e9a9a7
2 changed files with 98 additions and 4 deletions

View File

@ -729,11 +729,11 @@ void QItemSelectionModelPrivate::_q_rowsAboutToBeRemoved(const QModelIndex &pare
deselected.append(*it);
it = ranges.erase(it);
} else if (start <= it->top() && it->top() <= end) { // Top intersection
deselected.append(QItemSelectionRange(it->topLeft(), model->index(end, it->left(), it->parent())));
deselected.append(QItemSelectionRange(it->topLeft(), model->index(end, it->right(), it->parent())));
*it = QItemSelectionRange(model->index(end + 1, it->left(), it->parent()), it->bottomRight());
++it;
} else if (start <= it->bottom() && it->bottom() <= end) { // Bottom intersection
deselected.append(QItemSelectionRange(model->index(start, it->right(), it->parent()), it->bottomRight()));
deselected.append(QItemSelectionRange(model->index(start, it->left(), it->parent()), it->bottomRight()));
*it = QItemSelectionRange(it->topLeft(), model->index(start - 1, it->right(), it->parent()));
++it;
} else if (it->top() < start && end < it->bottom()) { // Middle intersection
@ -741,8 +741,8 @@ void QItemSelectionModelPrivate::_q_rowsAboutToBeRemoved(const QModelIndex &pare
// and [4, 5] is removed, we need to split [3, 4, 5, 6] into [3], [4, 5] and [6].
// [4, 5] is appended to deselected, and [3] and [6] remain part of the selection
// in ranges.
const QItemSelectionRange removedRange(model->index(start, it->right(), it->parent()),
model->index(end, it->left(), it->parent()));
const QItemSelectionRange removedRange(model->index(start, it->left(), it->parent()),
model->index(end, it->right(), it->parent()));
deselected.append(removedRange);
QItemSelection::split(*it, removedRange, &newParts);
it = ranges.erase(it);

View File

@ -94,6 +94,9 @@ private slots:
void testChainedSelectionClear();
void testClearCurrentIndex();
void QTBUG48402_data();
void QTBUG48402();
private:
QAbstractItemModel *model;
QItemSelectionModel *selection;
@ -2756,5 +2759,96 @@ void tst_QItemSelectionModel::testClearCurrentIndex()
QVERIFY(currentIndexSpy.size() == 2);
}
void tst_QItemSelectionModel::QTBUG48402_data()
{
QTest::addColumn<int>("rows");
QTest::addColumn<int>("columns");
QTest::addColumn<int>("selectTop");
QTest::addColumn<int>("selectLeft");
QTest::addColumn<int>("selectBottom");
QTest::addColumn<int>("selectRight");
QTest::addColumn<int>("removeTop");
QTest::addColumn<int>("removeBottom");
QTest::addColumn<int>("deselectTop");
QTest::addColumn<int>("deselectLeft");
QTest::addColumn<int>("deselectBottom");
QTest::addColumn<int>("deselectRight");
QTest::newRow("4x4 top intersection")
<< 4 << 4
<< 0 << 2 << 1 << 3
<< 1 << 1
<< 1 << 2 << 1 << 3;
QTest::newRow("4x4 bottom intersection")
<< 4 << 4
<< 0 << 2 << 1 << 3
<< 0 << 0
<< 0 << 2 << 0 << 3;
QTest::newRow("4x4 middle intersection")
<< 4 << 4
<< 0 << 2 << 2 << 3
<< 1 << 1
<< 1 << 2 << 1 << 3;
QTest::newRow("4x4 full inclusion")
<< 4 << 4
<< 0 << 2 << 1 << 3
<< 0 << 1
<< 0 << 2 << 1 << 3;
}
class QTBUG48402_helper : public QObject
{
Q_OBJECT
public:
QModelIndex tl;
QModelIndex br;
public slots:
void changed(const QItemSelection &selected, const QItemSelection &deselected)
{
tl = deselected.first().topLeft();
br = deselected.first().bottomRight();
}
};
void tst_QItemSelectionModel::QTBUG48402()
{
QFETCH(int, rows);
QFETCH(int, columns);
QFETCH(int, selectTop);
QFETCH(int, selectLeft);
QFETCH(int, selectBottom);
QFETCH(int, selectRight);
QFETCH(int, removeTop);
QFETCH(int, removeBottom);
QFETCH(int, deselectTop);
QFETCH(int, deselectLeft);
QFETCH(int, deselectBottom);
QFETCH(int, deselectRight);
MyStandardItemModel model(rows, columns);
QItemSelectionModel selections(&model);
QModelIndex stl = model.index(selectTop, selectLeft);
QModelIndex sbr = model.index(selectBottom, selectRight);
QModelIndex dtl = model.index(deselectTop, deselectLeft);
QModelIndex dbr = model.index(deselectBottom, deselectRight);
selections.select(QItemSelection(stl, sbr), QItemSelectionModel::ClearAndSelect);
QTBUG48402_helper helper;
helper.connect(&selections, &QItemSelectionModel::selectionChanged, &helper, &QTBUG48402_helper::changed);
QVERIFY(selections.isSelected(stl));
QVERIFY(selections.isSelected(sbr));
QVERIFY(selections.hasSelection());
model.removeRows(removeTop, removeBottom - removeTop + 1);
QCOMPARE(QItemSelectionRange(helper.tl, helper.br), QItemSelectionRange(dtl, dbr));
}
QTEST_MAIN(tst_QItemSelectionModel)
#include "tst_qitemselectionmodel.moc"