summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Faure <david.faure@kdab.com>2017-05-22 20:01:04 +0200
committerAntti Kokko <antti.kokko@qt.io>2017-05-26 12:43:31 +0000
commitf6b36eaafec24b4c67efff621d380a4ca4257d0b (patch)
tree413c00b10b65a84bdf790289196395b4a6c484e2
parent31374105940bb15a68683a0ae691e7fe1f9b049a (diff)
QHeaderView: fix visual/logical index corruption when restoring statev5.9.0-rc2v5.9.0
This is a followup to 77a8e90cddcfa1c34518ef846a4838874a7bc0c7 which didn't handle the case where no columns had been moved. visualIndices and logicalIndices are empty until initializeIndexMapping() is called, in which case appending is wrong. As a result, visualIndex(i) would return -1 for the values over those added by read(), and an assert would happen at painting time. The fix is to leave visualIndices and logicalIndices empty if they are empty already, leaving it to initializeIndexMapping() to fill them later if necessary (e.g. when moving a column). Task-number: QTBUG-60837 Change-Id: Ia7e4b9d3122647984acd434dfaa0400df319d065 Reviewed-by: Marc Mutz <marc.mutz@kdab.com> Reviewed-by: Thorbjørn Lund Martsum <tmartsum@gmail.com>
-rw-r--r--src/widgets/itemviews/qheaderview.cpp8
-rw-r--r--tests/auto/widgets/itemviews/qheaderview/tst_qheaderview.cpp50
2 files changed, 55 insertions, 3 deletions
diff --git a/src/widgets/itemviews/qheaderview.cpp b/src/widgets/itemviews/qheaderview.cpp
index e0e993ce77..76f80c680e 100644
--- a/src/widgets/itemviews/qheaderview.cpp
+++ b/src/widgets/itemviews/qheaderview.cpp
@@ -3876,9 +3876,11 @@ bool QHeaderViewPrivate::read(QDataStream &in)
const int currentCount = (orient == Qt::Horizontal ? model->columnCount(root) : model->rowCount(root));
if (newSectionItems.count() < currentCount) {
// we have sections not in the saved state, give them default settings
- for (int i = newSectionItems.count(); i < currentCount; ++i) {
- visualIndicesIn.append(i);
- logicalIndicesIn.append(i);
+ if (!visualIndicesIn.isEmpty() && !logicalIndicesIn.isEmpty()) {
+ for (int i = newSectionItems.count(); i < currentCount; ++i) {
+ visualIndicesIn.append(i);
+ logicalIndicesIn.append(i);
+ }
}
const int insertCount = currentCount - newSectionItems.count();
const int insertLength = defaultSectionSizeIn * insertCount;
diff --git a/tests/auto/widgets/itemviews/qheaderview/tst_qheaderview.cpp b/tests/auto/widgets/itemviews/qheaderview/tst_qheaderview.cpp
index 7bfec2831d..b13e7b2f33 100644
--- a/tests/auto/widgets/itemviews/qheaderview/tst_qheaderview.cpp
+++ b/tests/auto/widgets/itemviews/qheaderview/tst_qheaderview.cpp
@@ -171,6 +171,7 @@ private slots:
void saveRestore();
void restoreQt4State();
void restoreToMoreColumns();
+ void restoreToMoreColumnsNoMovedColumns();
void restoreBeforeSetModel();
void defaultSectionSizeTest();
void defaultSectionSizeTestStyles();
@@ -1690,6 +1691,55 @@ void tst_QHeaderView::restoreToMoreColumns()
QCOMPARE(h4.hiddenSectionCount(), 1);
QCOMPARE(h4.sortIndicatorSection(), 2);
QCOMPARE(h4.sortIndicatorOrder(), Qt::DescendingOrder);
+ QCOMPARE(h4.logicalIndex(0), 2);
+ QCOMPARE(h4.logicalIndex(1), 1);
+ QCOMPARE(h4.logicalIndex(2), 0);
+ QCOMPARE(h4.visualIndex(0), 2);
+ QCOMPARE(h4.visualIndex(1), 1);
+ QCOMPARE(h4.visualIndex(2), 0);
+
+ // Repainting shouldn't crash
+ h4.show();
+ QVERIFY(QTest::qWaitForWindowExposed(&h4));
+}
+
+void tst_QHeaderView::restoreToMoreColumnsNoMovedColumns()
+{
+ // Given a model with 2 columns, for saving state
+ QHeaderView h1(Qt::Horizontal);
+ QStandardItemModel model1(1, 2);
+ h1.setModel(&model1);
+ QCOMPARE(h1.visualIndex(0), 0);
+ QCOMPARE(h1.visualIndex(1), 1);
+ QCOMPARE(h1.logicalIndex(0), 0);
+ QCOMPARE(h1.logicalIndex(1), 1);
+ const QByteArray savedState = h1.saveState();
+
+ // And a model with 3 columns, to apply that state upon
+ QHeaderView h2(Qt::Horizontal);
+ QStandardItemModel model2(1, 3);
+ h2.setModel(&model2);
+ QCOMPARE(h2.visualIndex(0), 0);
+ QCOMPARE(h2.visualIndex(1), 1);
+ QCOMPARE(h2.visualIndex(2), 2);
+ QCOMPARE(h2.logicalIndex(0), 0);
+ QCOMPARE(h2.logicalIndex(1), 1);
+ QCOMPARE(h2.logicalIndex(2), 2);
+
+ // When calling restoreState()
+ QVERIFY(h2.restoreState(savedState));
+
+ // Then the index mapping should still be as default
+ QCOMPARE(h2.visualIndex(0), 0);
+ QCOMPARE(h2.visualIndex(1), 1);
+ QCOMPARE(h2.visualIndex(2), 2);
+ QCOMPARE(h2.logicalIndex(0), 0);
+ QCOMPARE(h2.logicalIndex(1), 1);
+ QCOMPARE(h2.logicalIndex(2), 2);
+
+ // And repainting shouldn't crash
+ h2.show();
+ QVERIFY(QTest::qWaitForWindowExposed(&h2));
}
void tst_QHeaderView::restoreBeforeSetModel()