QHeaderview - many sections removed performance boost.
authorThorbjørn Lund Martsum <tmartsum@gmail.com>
Thu, 16 Feb 2012 09:12:30 +0000 (10:12 +0100)
committerQt by Nokia <qt-info@nokia.com>
Tue, 21 Feb 2012 11:51:46 +0000 (12:51 +0100)
When the QHeaderView model rowCount is decreased then the headerview
needs to remove some sections.

If e.g swapSections had occured then qheaderview before this patch did
a very slow removal by removing one section at a time and for each section
it restored visual and logical indexes.

By temporarily storing the logical index on the section we
can reduce the execution time of this a lot. The old code is only
faster when we remove one index (and is kept for that situation)

There is a complexity in difference (and many factors in our
qheaderview benchmark (the trunc part))

Change-Id: If45eab17fbca3364d458b004980570b5d013e4bd
Reviewed-by: Stephen Kelly <stephen.kelly@kdab.com>
src/widgets/itemviews/qheaderview.cpp
src/widgets/itemviews/qheaderview_p.h

index 299dcb3..6a1f949 100644 (file)
@@ -1799,7 +1799,8 @@ void QHeaderViewPrivate::_q_sectionsRemoved(const QModelIndex &parent,
         //Q_ASSERT(headerSectionCount() == sectionCount);
         removeSectionsFromSpans(logicalFirst, logicalLast);
     } else {
-        for (int l = logicalLast; l >= logicalFirst; --l) {
+        if (logicalFirst == logicalLast) { // Remove just one index.
+            int l = logicalFirst;
             int visual = visualIndices.at(l);
             for (int v = 0; v < sectionCount; ++v) {
                 if (v >= logicalIndices.count())
@@ -1815,8 +1816,27 @@ void QHeaderViewPrivate::_q_sectionsRemoved(const QModelIndex &parent,
             visualIndices.remove(l);
             //Q_ASSERT(headerSectionCount() == sectionCount);
             removeSectionsFromSpans(visual, visual);
+        } else {
+            sectionStartposRecalc = true; // We will need to recalc positions after removing items
+            for (int u = 0; u < sectionSpans.count(); ++u)  // Store spans info
+                sectionSpans.at(u).tmpLogIdx = logicalIndices.at(u);
+            for (int v = sectionSpans.count() - 1; v >= 0; --v) {  // Remove the sections
+                if (logicalFirst <= sectionSpans.at(v).tmpLogIdx && sectionSpans.at(v).tmpLogIdx <= logicalLast)
+                    removeSectionsFromSpans(v, v); // Invalidates the spans variable
+            }
+            visualIndices.resize(sectionSpans.count());
+            logicalIndices.resize(sectionSpans.count());
+            int* visual_data = visualIndices.data();
+            int* logical_data = logicalIndices.data();
+            for (int w = 0; w < sectionSpans.count(); ++w) { // Restore visual and logical indexes
+                int logindex = sectionSpans.at(w).tmpLogIdx;
+                if (logindex > logicalFirst)
+                    logindex -= changeCount;
+                visual_data[logindex] = w;
+                logical_data[w] = logindex;
+            }
         }
-        // ### handle sectionSelection, sectionHidden
+        // ### handle sectionSelection (sectionHidden is handled by updateHiddenSections)
     }
     sectionCount -= changeCount;
 
index 9d7d97f..4d1f4ba 100644 (file)
@@ -288,6 +288,7 @@ public:
     struct SectionSpan {
         int size;
         mutable int calculated_startpos;
+        mutable int tmpLogIdx;
         QHeaderView::ResizeMode resizeMode;
         inline SectionSpan() : size(0), resizeMode(QHeaderView::Interactive) {}
         inline SectionSpan(int length, QHeaderView::ResizeMode mode)