QHeaderView - do simple section move/rotate in moveSection

It is in nearly all cases much faster (in our benchmark it is
about a factor 8) - and it also makes the code more readable.

Change-Id: I075e1d1a96756e5e9a2bf53b5479094f7d87883d
Reviewed-by: Stephen Kelly <stephen.kelly@kdab.com>
bb10
Thorbjørn Martsum 2013-10-01 06:36:29 +02:00 committed by The Qt Project
parent 072f9cf888
commit f4044e853c
1 changed files with 19 additions and 42 deletions

View File

@ -724,6 +724,22 @@ int QHeaderView::sectionViewportPosition(int logicalIndex) const
\sa sectionPosition()
*/
template<typename Container>
static void qMoveRange(Container& c,
typename Container::size_type rangeStart,
typename Container::size_type rangeEnd,
typename Container::size_type targetPosition)
{
Q_ASSERT(targetPosition <= c.size());
Q_ASSERT(targetPosition < rangeStart || targetPosition >= rangeEnd);
const bool forwardMove = targetPosition > rangeStart;
typename Container::size_type first = std::min(rangeStart, targetPosition);
typename Container::size_type mid = forwardMove ? rangeEnd : rangeStart;
typename Container::size_type last = forwardMove ? targetPosition + 1 : rangeEnd;
std::rotate(c.begin() + first, c.begin() + mid, c.begin() + last);
}
/*!
Moves the section at visual index \a from to occupy visual index \a to.
@ -748,71 +764,32 @@ void QHeaderView::moveSection(int from, int to)
if (stretchLastSection() && to == d->lastVisibleVisualIndex())
d->lastSectionSize = sectionSize(from);
//int oldHeaderLength = length(); // ### for debugging; remove later
d->initializeIndexMapping();
QBitArray sectionHidden = d->sectionsHiddenToBitVector();
int *visualIndices = d->visualIndices.data();
int *logicalIndices = d->logicalIndices.data();
int logical = logicalIndices[from];
int visual = from;
int affected_count = qAbs(to - from) + 1;
QVarLengthArray<int> sizes(affected_count);
QVarLengthArray<ResizeMode> modes(affected_count);
// move sections and indices
if (to > from) {
sizes[to - from] = d->headerSectionSize(from);
modes[to - from] = d->headerSectionResizeMode(from);
while (visual < to) {
sizes[visual - from] = d->headerSectionSize(visual + 1);
modes[visual - from] = d->headerSectionResizeMode(visual + 1);
if (!sectionHidden.isEmpty())
sectionHidden.setBit(visual, sectionHidden.testBit(visual + 1));
visualIndices[logicalIndices[visual + 1]] = visual;
logicalIndices[visual] = logicalIndices[visual + 1];
++visual;
}
} else {
sizes[0] = d->headerSectionSize(from);
modes[0] = d->headerSectionResizeMode(from);
while (visual > to) {
sizes[visual - to] = d->headerSectionSize(visual - 1);
modes[visual - to] = d->headerSectionResizeMode(visual - 1);
if (!sectionHidden.isEmpty())
sectionHidden.setBit(visual, sectionHidden.testBit(visual - 1));
visualIndices[logicalIndices[visual - 1]] = visual;
logicalIndices[visual] = logicalIndices[visual - 1];
--visual;
}
}
if (!sectionHidden.isEmpty()) {
sectionHidden.setBit(to, d->isVisualIndexHidden(from));
d->setHiddenSectionsFromBitVector(sectionHidden);
}
visualIndices[logical] = to;
logicalIndices[to] = logical;
//Q_ASSERT(oldHeaderLength == length());
// move sizes
// ### check for items of section sizes here
if (to > from) {
for (visual = from; visual <= to; ++visual) {
int size = sizes[visual - from];
ResizeMode mode = modes[visual - from];
d->createSectionItems(visual, visual, size, mode);
}
} else {
for (visual = to; visual <= from; ++visual) {
int size = sizes[visual - to];
ResizeMode mode = modes[visual - to];
d->createSectionItems(visual, visual, size, mode);
}
}
//Q_ASSERT(d->headerLength() == length());
//Q_ASSERT(oldHeaderLength == length());
//Q_ASSERT(d->logicalIndices.count() == d->sectionCount);
qMoveRange(d->sectionItems, from, from + 1, to);
d->sectionStartposRecalc = true;
if (d->hasAutoResizeSections())
d->doDelayedResizeSections();