QHeaderView: fix restoreState() on a model with more columns

When saving state for a 3-columns headerview and then restoring that
state onto a 5-column headerview, the headerview shouldn't suddenly think
it has 3 columns.

Rather than making restoreState() fail, we adjust for the additional
columns, so that we can still apply the customizations from the user to
all other columns (hiding, moving, etc.).

Change-Id: I3f220aa322ea8b629d2fe345f8cde13e0ea615d6
Reviewed-by: Thorbjørn Lund Martsum <tmartsum@gmail.com>
This commit is contained in:
David Faure 2016-12-29 18:15:53 +01:00
parent 73dafaf265
commit 77a8e90cdd
2 changed files with 87 additions and 11 deletions

View File

@ -3857,6 +3857,20 @@ bool QHeaderViewPrivate::read(QDataStream &in)
if (sectionItemsLengthTotal != lengthIn) if (sectionItemsLengthTotal != lengthIn)
return false; return false;
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);
}
const int insertCount = currentCount - newSectionItems.count();
const int insertLength = defaultSectionSizeIn * insertCount;
lengthIn += insertLength;
SectionItem section(defaultSectionSizeIn, globalResizeMode);
newSectionItems.insert(newSectionItems.count(), insertCount, section); // append
}
orientation = static_cast<Qt::Orientation>(orient); orientation = static_cast<Qt::Orientation>(orient);
sortIndicatorOrder = static_cast<Qt::SortOrder>(order); sortIndicatorOrder = static_cast<Qt::SortOrder>(order);
sortIndicatorSection = sortIndicatorSectionIn; sortIndicatorSection = sortIndicatorSectionIn;

View File

@ -169,6 +169,9 @@ private slots:
void moveSectionAndReset(); void moveSectionAndReset();
void moveSectionAndRemove(); void moveSectionAndRemove();
void saveRestore(); void saveRestore();
void restoreQt4State();
void restoreToMoreColumns();
void restoreBeforeSetModel();
void defaultSectionSizeTest(); void defaultSectionSizeTest();
void defaultSectionSizeTestStyles(); void defaultSectionSizeTestStyles();
@ -1523,11 +1526,11 @@ public:
{ {
return hasIndex(row, column, parent) ? createIndex(row, column) : QModelIndex(); return hasIndex(row, column, parent) ? createIndex(row, column) : QModelIndex();
} }
int rowCount(const QModelIndex & /* parent */) const int rowCount(const QModelIndex & /*parent*/ = QModelIndex()) const
{ {
return 8; return 8;
} }
int columnCount(const QModelIndex &/*parent= QModelIndex()*/) const int columnCount(const QModelIndex &/*parent*/ = QModelIndex()) const
{ {
return m_col_count; return m_col_count;
} }
@ -1588,41 +1591,56 @@ void tst_QHeaderView::moveSectionAndRemove()
QCOMPARE(v.count(), 0); QCOMPARE(v.count(), 0);
} }
void tst_QHeaderView::saveRestore() static QByteArray savedState()
{ {
SimpleModel m; QStandardItemModel m(4, 4);
QHeaderView h1(Qt::Horizontal); QHeaderView h1(Qt::Horizontal);
h1.setModel(&m); h1.setModel(&m);
h1.swapSections(0, 2); h1.swapSections(0, 2);
h1.resizeSection(1, 10); h1.resizeSection(1, 10);
h1.setSortIndicatorShown(true); h1.setSortIndicatorShown(true);
h1.setSortIndicator(1,Qt::DescendingOrder); h1.setSortIndicator(2, Qt::DescendingOrder);
QByteArray s1 = h1.saveState(); h1.setSectionHidden(3, true);
return h1.saveState();
}
void tst_QHeaderView::saveRestore()
{
QStandardItemModel m(4, 4);
const QByteArray s1 = savedState();
QHeaderView h2(Qt::Vertical); QHeaderView h2(Qt::Vertical);
QSignalSpy spy(&h2, SIGNAL(sortIndicatorChanged(int,Qt::SortOrder))); QSignalSpy spy(&h2, SIGNAL(sortIndicatorChanged(int,Qt::SortOrder)));
h2.setModel(&m); h2.setModel(&m);
h2.restoreState(s1); QVERIFY(h2.restoreState(s1));
QCOMPARE(spy.count(), 1); QCOMPARE(spy.count(), 1);
QCOMPARE(spy.at(0).at(0).toInt(), 1); QCOMPARE(spy.at(0).at(0).toInt(), 2);
QCOMPARE(h2.logicalIndex(0), 2); QCOMPARE(h2.logicalIndex(0), 2);
QCOMPARE(h2.logicalIndex(2), 0); QCOMPARE(h2.logicalIndex(2), 0);
QCOMPARE(h2.sectionSize(1), 10); QCOMPARE(h2.sectionSize(1), 10);
QCOMPARE(h2.sortIndicatorSection(), 1); QCOMPARE(h2.sortIndicatorSection(), 2);
QCOMPARE(h2.sortIndicatorOrder(), Qt::DescendingOrder); QCOMPARE(h2.sortIndicatorOrder(), Qt::DescendingOrder);
QCOMPARE(h2.isSortIndicatorShown(), true); QCOMPARE(h2.isSortIndicatorShown(), true);
QVERIFY(!h2.isSectionHidden(2));
QVERIFY(h2.isSectionHidden(3));
QCOMPARE(h2.hiddenSectionCount(), 1);
QByteArray s2 = h2.saveState(); QByteArray s2 = h2.saveState();
QCOMPARE(s1, s2); QCOMPARE(s1, s2);
QVERIFY(!h2.restoreState(QByteArrayLiteral("Garbage")));
QVERIFY(!h2.restoreState(QByteArrayLiteral("Garbage")));
}
void tst_QHeaderView::restoreQt4State()
{
// QTBUG-40462 // QTBUG-40462
// Setting from Qt4, where information about multiple sections were grouped together in one // Setting from Qt4, where information about multiple sections were grouped together in one
// sectionItem object // sectionItem object
QStandardItemModel m(4, 10);
QHeaderView h2(Qt::Vertical);
QByteArray settings_qt4 = QByteArray settings_qt4 =
QByteArray::fromHex("000000ff00000000000000010000000100000000010000000000000000000000000000" QByteArray::fromHex("000000ff00000000000000010000000100000000010000000000000000000000000000"
"0000000003e80000000a0101000100000000000000000000000064ffffffff00000081" "0000000003e80000000a0101000100000000000000000000000064ffffffff00000081"
@ -1652,6 +1670,50 @@ void tst_QHeaderView::saveRestore()
QCOMPARE(h2.saveState(), old_state); QCOMPARE(h2.saveState(), old_state);
} }
void tst_QHeaderView::restoreToMoreColumns()
{
// Restore state onto a model with more columns
const QByteArray s1 = savedState();
QHeaderView h4(Qt::Horizontal);
QStandardItemModel fiveColumnsModel(1, 5);
h4.setModel(&fiveColumnsModel);
QCOMPARE(fiveColumnsModel.columnCount(), 5);
QCOMPARE(h4.count(), 5);
QVERIFY(h4.restoreState(s1));
QCOMPARE(fiveColumnsModel.columnCount(), 5);
QCOMPARE(h4.count(), 5);
QCOMPARE(h4.sectionSize(1), 10);
for (int i = 0; i < h4.count(); ++i)
QVERIFY(h4.sectionSize(i) > 0 || h4.isSectionHidden(i));
QVERIFY(!h4.isSectionHidden(2));
QVERIFY(h4.isSectionHidden(3));
QCOMPARE(h4.hiddenSectionCount(), 1);
QCOMPARE(h4.sortIndicatorSection(), 2);
QCOMPARE(h4.sortIndicatorOrder(), Qt::DescendingOrder);
}
void tst_QHeaderView::restoreBeforeSetModel()
{
QHeaderView h2(Qt::Horizontal);
const QByteArray s1 = savedState();
// First restore
QVERIFY(h2.restoreState(s1));
// Then setModel
QStandardItemModel model(4, 4);
h2.setModel(&model);
// Check the result
QCOMPARE(h2.logicalIndex(0), 2);
QCOMPARE(h2.logicalIndex(2), 0);
QCOMPARE(h2.sectionSize(1), 10);
QCOMPARE(h2.sortIndicatorSection(), 2);
QCOMPARE(h2.sortIndicatorOrder(), Qt::DescendingOrder);
QCOMPARE(h2.isSortIndicatorShown(), true);
QVERIFY(!h2.isSectionHidden(2));
QVERIFY(h2.isSectionHidden(3));
QCOMPARE(h2.hiddenSectionCount(), 1);
}
void tst_QHeaderView::defaultSectionSizeTest() void tst_QHeaderView::defaultSectionSizeTest()
{ {
// Setup // Setup