QHeaderView: check that length is correct and fix restoring Qt4 state.

When multiple sections were grouped together, sectionItem.size was the total size of grouped sections, not the size of one section.
Length is supposed to be equal to the section items length, but the state saved might be corrupted.

Task-number: QTBUG-40462
Change-Id: I401a1583dd30880ccf5b4c105a237d6563f212e8
Reviewed-by: Thorbjørn Lund Martsum <tmartsum@gmail.com>
This commit is contained in:
Arnaud Bienner 2015-01-29 21:35:37 +01:00
parent b85b78f17d
commit cd7a36d341
2 changed files with 85 additions and 23 deletions

View File

@ -3641,6 +3641,17 @@ bool QHeaderViewPrivate::read(QDataStream &in)
QVector<int> visualIndicesIn;
QVector<int> logicalIndicesIn;
QHash<int, int> hiddenSectionSizeIn;
bool movableSectionsIn;
bool clickableSectionsIn;
bool highlightSelectedIn;
bool stretchLastSectionIn;
bool cascadingResizingIn;
int stretchSectionsIn;
int contentsSectionsIn;
int defaultSectionSizeIn;
int minimumSectionSizeIn;
QVector<SectionItem> sectionItemsIn;
in >> orient;
in >> order;
@ -3662,6 +3673,39 @@ bool QHeaderViewPrivate::read(QDataStream &in)
if (in.status() != QDataStream::Ok || lengthIn < 0)
return false;
in >> movableSectionsIn;
in >> clickableSectionsIn;
in >> highlightSelectedIn;
in >> stretchLastSectionIn;
in >> cascadingResizingIn;
in >> stretchSectionsIn;
in >> contentsSectionsIn;
in >> defaultSectionSizeIn;
in >> minimumSectionSizeIn;
in >> align;
in >> global;
in >> sectionItemsIn;
// In Qt4 we had a vector of spans where one span could hold information on more sections.
// Now we have an itemvector where one items contains information about one section
// For backward compatibility with Qt4 we do the following
QVector<SectionItem> newSectionItems;
for (int u = 0; u < sectionItemsIn.count(); ++u) {
int count = sectionItemsIn.at(u).tmpDataStreamSectionCount;
if (count > 0)
sectionItemsIn[u].size /= count;
for (int n = 0; n < count; ++n)
newSectionItems.append(sectionItemsIn[u]);
}
int sectionItemsLengthTotal = 0;
foreach (const SectionItem &section, newSectionItems)
sectionItemsLengthTotal += section.size;
if (sectionItemsLengthTotal != lengthIn)
return false;
orientation = static_cast<Qt::Orientation>(orient);
sortIndicatorOrder = static_cast<Qt::SortOrder>(order);
sortIndicatorSection = sortIndicatorSectionIn;
@ -3671,32 +3715,19 @@ bool QHeaderViewPrivate::read(QDataStream &in)
hiddenSectionSize = hiddenSectionSizeIn;
length = lengthIn;
in >> movableSections;
in >> clickableSections;
in >> highlightSelected;
in >> stretchLastSection;
in >> cascadingResizing;
in >> stretchSections;
in >> contentsSections;
in >> defaultSectionSize;
in >> minimumSectionSize;
movableSections = movableSectionsIn;
clickableSections = clickableSectionsIn;
highlightSelected = highlightSelectedIn;
stretchLastSection = stretchLastSectionIn;
cascadingResizing = cascadingResizingIn;
stretchSections = stretchSectionsIn;
contentsSections = contentsSectionsIn;
defaultSectionSize = defaultSectionSizeIn;
minimumSectionSize = minimumSectionSizeIn;
in >> align;
defaultAlignment = Qt::Alignment(align);
globalResizeMode = static_cast<QHeaderView::ResizeMode>(global);
in >> global;
globalResizeMode = (QHeaderView::ResizeMode)global;
in >> sectionItems;
// In Qt4 we had a vector of spans where one span could hold information on more sections.
// Now we have an itemvector where one items contains information about one section
// For backward compatibility with Qt4 we do the following
QVector<SectionItem> newSectionItems;
for (int u = 0; u < sectionItems.count(); ++u) {
int count = sectionItems.at(u).tmpDataStreamSectionCount;
for (int n = 0; n < count; ++n)
newSectionItems.append(sectionItems[u]);
}
sectionItems = newSectionItems;
setHiddenSectionsFromBitVector(sectionHidden);
recalcSectionStartPos();

View File

@ -1646,6 +1646,37 @@ void tst_QHeaderView::saveRestore()
QVERIFY(s1 == s2);
QVERIFY(!h2.restoreState(QByteArrayLiteral("Garbage")));
// QTBUG-40462
// Setting from Qt4, where information about multiple sections were grouped together in one
// sectionItem object
QByteArray settings_qt4 =
QByteArray::fromHex("000000ff00000000000000010000000100000000010000000000000000000000000000"
"0000000003e80000000a0101000100000000000000000000000064ffffffff00000081"
"0000000000000001000003e80000000a00000000");
QVERIFY(h2.restoreState(settings_qt4));
int sectionItemsLengthTotal = 0;
for (int i = 0; i < h2.count(); ++i)
sectionItemsLengthTotal += h2.sectionSize(i);
QVERIFY(sectionItemsLengthTotal == h2.length());
// Buggy setting where sum(sectionItems) != length. Check false is returned and this corrupted
// state isn't restored
QByteArray settings_buggy_length =
QByteArray::fromHex("000000ff000000000000000100000000000000050100000000000000000000000a4000"
"000000010000000600000258000000fb0000000a010100010000000000000000000000"
"0064ffffffff00000081000000000000000a000000d30000000100000000000000c800"
"000001000000000000008000000001000000000000005c00000001000000000000003c"
"0000000100000000000002580000000100000000000000000000000100000000000002"
"580000000100000000000002580000000100000000000003c000000001000000000000"
"03e8");
int old_length = h2.length();
QByteArray old_state = h2.saveState();
// Check setting is correctly recognized as corrupted
QVERIFY(!h2.restoreState(settings_buggy_length));
// Check nothing has been actually restored
QVERIFY(h2.length() == old_length);
QVERIFY(h2.saveState() == old_state);
}
void tst_QHeaderView::defaultSectionSizeTest()