362void QHeaderView::setModel(QAbstractItemModel *model)
364 if (model ==
this->model())
367 d->layoutChangePersistentSections.clear();
368 if (d->model && d->model != QAbstractItemModelPrivate::staticEmptyModel())
369 d->disconnectModel();
371 if (model && model != QAbstractItemModelPrivate::staticEmptyModel()) {
372 const bool hor = d->orientation == Qt::Horizontal;
373 d->modelConnections = {
374 QObject::connect(model, hor ? &QAbstractItemModel::columnsInserted
375 : &QAbstractItemModel::rowsInserted,
376 this, &QHeaderView::sectionsInserted),
377 QObject::connect(model, hor ? &QAbstractItemModel::columnsAboutToBeRemoved
378 : &QAbstractItemModel::rowsAboutToBeRemoved,
379 this, &QHeaderView::sectionsAboutToBeRemoved),
380 QObjectPrivate::connect(model, hor ? &QAbstractItemModel::columnsRemoved
381 : &QAbstractItemModel::rowsRemoved,
382 d, &QHeaderViewPrivate::sectionsRemoved),
383 QObjectPrivate::connect(model, hor ? &QAbstractItemModel::columnsAboutToBeMoved
384 : &QAbstractItemModel::rowsAboutToBeMoved,
385 d, &QHeaderViewPrivate::sectionsAboutToBeMoved),
386 QObjectPrivate::connect(model, hor ? &QAbstractItemModel::columnsMoved
387 : &QAbstractItemModel::rowsMoved,
388 d, &QHeaderViewPrivate::sectionsMoved),
390 QObject::connect(model, &QAbstractItemModel::headerDataChanged,
391 this, &QHeaderView::headerDataChanged),
392 QObjectPrivate::connect(model, &QAbstractItemModel::layoutAboutToBeChanged,
393 d, &QHeaderViewPrivate::sectionsAboutToBeChanged),
394 QObjectPrivate::connect(model, &QAbstractItemModel::layoutChanged,
395 d, &QHeaderViewPrivate::sectionsChanged)
399 d->state = QHeaderViewPrivate::NoClear;
400 QAbstractItemView::setModel(model);
401 d->state = QHeaderViewPrivate::NoState;
406 initializeSections();
442void QHeaderView::setOffset(
int newOffset)
445 if (d->headerOffset == newOffset)
448 const int ndelta = q26::saturating_cast<
int>(d->headerOffset - qint64{newOffset});
449 d->headerOffset = newOffset;
450 if (d->orientation == Qt::Horizontal) {
451 if (isRightToLeft()) {
452 if (
int r; !qMulOverflow<-1>(ndelta, &r))
453 d->viewport->scroll(r, 0);
455 warn_overflow(
"QHeaderView::setOffset",
"QWidget::scroll", newOffset);
457 d->viewport->scroll(ndelta, 0);
460 d->viewport->scroll(0, ndelta);
462 if (d->state == QHeaderViewPrivate::ResizeSection && !d->preventCursorChangeInSetOffset) {
463 QPoint cursorPos = QCursor::pos();
464 if (d->orientation == Qt::Horizontal)
465 QCursor::setPos(cursorPos.x() + ndelta, cursorPos.y());
467 QCursor::setPos(cursorPos.x(), cursorPos.y() + ndelta);
468 d->firstPos += ndelta;
469 d->lastPos += ndelta;
751void QHeaderView::moveSection(
int from,
int to)
755 d->executePostedLayout();
756 if (from < 0 || from >= d->sectionCount() || to < 0 || to >= d->sectionCount())
760 int logical = logicalIndex(from);
761 Q_ASSERT(logical != -1);
762 updateSection(logical);
766 if (d->noSectionMemoryUsage())
767 d->switchToFlexibleModeWithSectionMemoryUsage();
769 d->initializeIndexMapping();
771 int *visualIndices = d->visualIndices.data();
772 int *logicalIndices = d->logicalIndices.data();
773 int logical = logicalIndices[from];
777 while (visual < to) {
778 visualIndices[logicalIndices[visual + 1]] = visual;
779 logicalIndices[visual] = logicalIndices[visual + 1];
783 while (visual > to) {
784 visualIndices[logicalIndices[visual - 1]] = visual;
785 logicalIndices[visual] = logicalIndices[visual - 1];
789 visualIndices[logical] = to;
790 logicalIndices[to] = logical;
792 qMoveRange(d->sectionItems, from, from + 1, to);
794 d->sectionStartposRecalc =
true;
796 if (d->hasAutoResizeSections())
797 d->doDelayedResizeSections();
798 d->viewport->update();
800 emit sectionMoved(logical, from, to);
802 if (stretchLastSection()) {
803 const int lastSectionVisualIdx = visualIndex(d->lastSectionLogicalIdx);
804 if (from >= lastSectionVisualIdx || to >= lastSectionVisualIdx)
805 d->maybeRestorePrevLastSectionAndStretchLast();
815void QHeaderView::swapSections(
int first,
int second)
821 d->executePostedLayout();
822 if (first < 0 || first >= d->sectionCount() || second < 0 || second >= d->sectionCount())
825 if (d->noSectionMemoryUsage())
826 d->switchToFlexibleModeWithSectionMemoryUsage();
828 int firstSize = d->headerSectionSize(first);
829 ResizeMode firstMode = d->headerSectionResizeMode(first);
830 int firstLogical = d->logicalIndex(first);
832 int secondSize = d->headerSectionSize(second);
833 ResizeMode secondMode = d->headerSectionResizeMode(second);
834 int secondLogical = d->logicalIndex(second);
836 if (d->state == QHeaderViewPrivate::ResizeSection)
837 d->preventCursorChangeInSetOffset =
true;
839 d->createSectionItems(second, second, firstSize, firstMode);
840 d->createSectionItems(first, first, secondSize, secondMode);
842 d->initializeIndexMapping();
844 d->visualIndices[firstLogical] = second;
845 d->logicalIndices[second] = firstLogical;
847 d->visualIndices[secondLogical] = first;
848 d->logicalIndices[first] = secondLogical;
850 if (!d->hiddenSectionSize.isEmpty()) {
851 bool firstHidden = d->isVisualIndexHidden(first);
852 bool secondHidden = d->isVisualIndexHidden(second);
853 d->setVisualIndexHidden(first, secondHidden);
854 d->setVisualIndexHidden(second, firstHidden);
857 d->viewport->update();
858 emit sectionMoved(firstLogical, first, second);
859 emit sectionMoved(secondLogical, second, first);
861 if (stretchLastSection()) {
862 const int lastSectionVisualIdx = visualIndex(d->lastSectionLogicalIdx);
863 if (first >= lastSectionVisualIdx || second >= lastSectionVisualIdx)
864 d->maybeRestorePrevLastSectionAndStretchLast();
879void QHeaderView::resizeSection(
int logical,
int size)
882 if (logical < 0 || logical >= count() || size < 0 || size > maxSizeSection)
885 if (d->noSectionMemoryUsage())
886 d->switchToFlexibleModeWithSectionMemoryUsage();
890 size = qBound(minimumSectionSize(), size, maximumSectionSize());
892 if (isSectionHidden(logical)) {
893 d->hiddenSectionSize.insert(logical, size);
897 int visual = visualIndex(logical);
901 if (d->state == QHeaderViewPrivate::ResizeSection && !d->cascadingResizing && logical != d->section)
902 d->preventCursorChangeInSetOffset =
true;
904 int oldSize = d->headerSectionSize(visual);
908 d->executePostedLayout();
909 d->invalidateCachedSizeHint();
911 if (stretchLastSection() && logical == d->lastSectionLogicalIdx)
912 d->lastSectionSize = size;
914 d->createSectionItems(visual, visual, size, d->headerSectionResizeMode(visual));
916 if (!updatesEnabled()) {
917 if (d->hasAutoResizeSections())
918 d->doDelayedResizeSections();
919 emit sectionResized(logical, oldSize, size);
923 int w = d->viewport->width();
924 int h = d->viewport->height();
925 int pos = sectionViewportPosition(logical);
927 if (d->orientation == Qt::Horizontal)
929 r.setRect(0, 0, pos + size, h);
931 r.setRect(pos, 0, w - pos, h);
933 r.setRect(0, pos, w, h - pos);
935 if (d->hasAutoResizeSections()) {
936 d->doDelayedResizeSections();
937 r = d->viewport->rect();
947 QAbstractScrollArea *parent = qobject_cast<QAbstractScrollArea *>(parentWidget());
948 if (parent && parent->sizeAdjustPolicy() == QAbstractScrollArea::AdjustToContents)
949 parent->updateGeometry();
951 d->viewport->update(r.normalized());
952 emit sectionResized(logical, oldSize, size);
1024void QHeaderView::setSectionHidden(
int logicalIndex,
bool hide)
1027 if (logicalIndex < 0 || logicalIndex >= count())
1030 if (hide && d->noSectionMemoryUsage())
1031 d->switchToFlexibleModeWithSectionMemoryUsage();
1033 d->executePostedLayout();
1034 int visual = visualIndex(logicalIndex);
1035 Q_ASSERT(visual != -1);
1036 if (hide == d->isVisualIndexHidden(visual))
1039 const bool isHidingLastSection = (stretchLastSection() && logicalIndex == d->lastSectionLogicalIdx);
1040 if (isHidingLastSection)
1041 d->restoreSizeOnPrevLastSection();
1042 int size = d->headerSectionSize(visual);
1043 if (!d->hasAutoResizeSections())
1044 resizeSection(logicalIndex, 0);
1045 d->hiddenSectionSize.insert(logicalIndex, size);
1046 d->setVisualIndexHidden(visual,
true);
1047 if (isHidingLastSection)
1048 d->setNewLastSection(d->lastVisibleVisualIndex());
1049 if (d->hasAutoResizeSections())
1050 d->doDelayedResizeSections();
1052 int size = d->hiddenSectionSize.value(logicalIndex, d->defaultSectionSize);
1053 d->hiddenSectionSize.remove(logicalIndex);
1054 d->setVisualIndexHidden(visual,
false);
1055 resizeSection(logicalIndex, size);
1057 const bool newLastSection = (stretchLastSection() && visual > visualIndex(d->lastSectionLogicalIdx));
1058 if (newLastSection) {
1059 d->restoreSizeOnPrevLastSection();
1060 d->setNewLastSection(visual);
1895void QHeaderView::headerDataChanged(Qt::Orientation orientation,
int logicalFirst,
int logicalLast)
1898 if (d->orientation != orientation)
1901 if (logicalFirst < 0 || logicalLast < 0 || logicalFirst >= count() || logicalLast >= count())
1904 d->invalidateCachedSizeHint();
1906 int firstVisualIndex = INT_MAX, lastVisualIndex = -1;
1908 for (
int section = logicalFirst; section <= logicalLast; ++section) {
1909 const int visual = visualIndex(section);
1910 firstVisualIndex = qMin(firstVisualIndex, visual);
1911 lastVisualIndex = qMax(lastVisualIndex, visual);
1914 d->executePostedResize();
1915 const int first = d->headerSectionPosition(firstVisualIndex),
1916 last = d->headerSectionPosition(lastVisualIndex)
1917 + d->headerSectionSize(lastVisualIndex);
1919 if (orientation == Qt::Horizontal) {
1920 d->viewport->update(first, 0, last - first, d->viewport->height());
1922 d->viewport->update(0, first, d->viewport->width(), last - first);
1964void QHeaderView::sectionsInserted(
const QModelIndex &parent,
1965 int logicalFirst,
int logicalLast)
1969 if (parent != d->root || d->modelSectionCount() == d->sectionCount())
1971 int oldCount = d->sectionCount();
1973 d->invalidateCachedSizeHint();
1975 if (d->state == QHeaderViewPrivate::ResizeSection)
1976 d->preventCursorChangeInSetOffset =
true;
1979 int insertAt = logicalFirst;
1980 int insertCount = logicalLast - logicalFirst + 1;
1983 if (d->sortIndicatorSection >= logicalFirst)
1984 d->sortIndicatorSection += insertCount;
1986 if (d->noSectionMemoryUsage()) {
1987 const int addedCount = logicalLast - logicalFirst + 1;
1988 d->updateCountInNoSectionItemsMode(d->countInNoSectionItemsMode + addedCount);
1992 bool lastSectionActualChange =
false;
1993 if (stretchLastSection()) {
1995 int visualIndexForStretch = d->lastSectionLogicalIdx;
1996 if (d->lastSectionLogicalIdx >= 0 && d->lastSectionLogicalIdx < d->visualIndices.size())
1997 visualIndexForStretch = d->visualIndices[d->lastSectionLogicalIdx];
2000 if (d->lastSectionLogicalIdx < 0 || insertAt >= visualIndexForStretch)
2001 lastSectionActualChange =
true;
2003 if (d->lastSectionLogicalIdx >= logicalFirst)
2004 d->lastSectionLogicalIdx += insertCount;
2007 QHeaderViewPrivate::SectionItem section(d->defaultSectionSize, d->globalResizeMode);
2008 d->sectionStartposRecalc =
true;
2010 if (d->sectionItems.isEmpty() || insertAt >= d->sectionItems.size()) {
2011 int insertLength = d->defaultSectionSize * insertCount;
2012 d->length += insertLength;
2013 d->sectionItems.insert(d->sectionItems.size(), insertCount, section);
2016 int insertLength = d->defaultSectionSize * insertCount;
2017 d->length += insertLength;
2018 d->sectionItems.insert(insertAt, insertCount, section);
2022 if (d->globalResizeMode == Stretch)
2023 d->stretchSections = d->sectionCount();
2024 else if (d->globalResizeMode == ResizeToContents)
2025 d->contentsSections = d->sectionCount();
2028 d->sectionSelected.clear();
2031 if (!d->visualIndices.isEmpty() && !d->logicalIndices.isEmpty()) {
2032 Q_ASSERT(d->visualIndices.size() == d->logicalIndices.size());
2033 int mappingCount = d->visualIndices.size();
2034 for (
int i = 0; i < mappingCount; ++i) {
2035 if (d->visualIndices.at(i) >= logicalFirst)
2036 d->visualIndices[i] += insertCount;
2037 if (d->logicalIndices.at(i) >= logicalFirst)
2038 d->logicalIndices[i] += insertCount;
2040 for (
int j = logicalFirst; j <= logicalLast; ++j) {
2041 d->visualIndices.insert(j, j);
2042 d->logicalIndices.insert(j, j);
2047 QHash<
int,
int> newHiddenSectionSize;
2048 for (QHash<
int,
int>::const_iterator it = d->hiddenSectionSize.cbegin(),
2049 end = d->hiddenSectionSize.cend(); it != end; ++it) {
2050 const int oldIndex = it.key();
2051 const int newIndex = (oldIndex < logicalFirst) ? oldIndex : oldIndex + insertCount;
2052 newHiddenSectionSize[newIndex] = it.value();
2054 d->hiddenSectionSize.swap(newHiddenSectionSize);
2056 d->doDelayedResizeSections();
2057 emit sectionCountChanged(oldCount, count());
2059 if (lastSectionActualChange)
2060 d->maybeRestorePrevLastSectionAndStretchLast();
2063 if (!d->hasAutoResizeSections())
2064 d->viewport->update();
2099void QHeaderViewPrivate::sectionsRemoved(
const QModelIndex &parent,
2100 int logicalFirst,
int logicalLast)
2105 if (qMin(logicalFirst, logicalLast) < 0
2106 || qMax(logicalLast, logicalFirst) >= sectionCount())
2108 int oldCount = q->count();
2109 int changeCount = logicalLast - logicalFirst + 1;
2111 if (state == QHeaderViewPrivate::ResizeSection)
2112 preventCursorChangeInSetOffset =
true;
2115 if (sortIndicatorSection >= logicalFirst) {
2116 if (sortIndicatorSection <= logicalLast)
2117 sortIndicatorSection = -1;
2119 sortIndicatorSection -= changeCount;
2122 if (noSectionMemoryUsage()) {
2123 updateCountInNoSectionItemsMode(countInNoSectionItemsMode - changeCount);
2127 updateHiddenSections(logicalFirst, logicalLast);
2129 if (visualIndices.isEmpty() && logicalIndices.isEmpty()) {
2131 removeSectionsFromSectionItems(logicalFirst, logicalLast);
2133 if (logicalFirst == logicalLast) {
2134 int l = logicalFirst;
2135 int visual = visualIndices.at(l);
2136 Q_ASSERT(sectionCount() == logicalIndices.size());
2137 for (
int v = 0; v < sectionCount(); ++v) {
2139 int logical = logicalIndices.at(v);
2140 --(visualIndices[logical]);
2142 if (logicalIndex(v) > l)
2143 --(logicalIndices[v]);
2145 logicalIndices.remove(visual);
2146 visualIndices.remove(l);
2148 removeSectionsFromSectionItems(visual, visual);
2150 sectionStartposRecalc =
true;
2151 for (
int u = 0; u < sectionItems.size(); ++u)
2152 sectionItems.at(u).tmpLogIdx = logicalIndices.at(u);
2153 for (
int v = sectionItems.size() - 1; v >= 0; --v) {
2154 if (logicalFirst <= sectionItems.at(v).tmpLogIdx && sectionItems.at(v).tmpLogIdx <= logicalLast)
2155 removeSectionsFromSectionItems(v, v);
2157 visualIndices.resize(sectionItems.size());
2158 logicalIndices.resize(sectionItems.size());
2159 int* visual_data = visualIndices.data();
2160 int* logical_data = logicalIndices.data();
2161 for (
int w = 0; w < sectionItems.size(); ++w) {
2162 int logindex = sectionItems.at(w).tmpLogIdx;
2163 if (logindex > logicalFirst)
2164 logindex -= changeCount;
2165 visual_data[logindex] = w;
2166 logical_data[w] = logindex;
2173 if (sectionCount() <= 0)
2175 invalidateCachedSizeHint();
2176 emit q->sectionCountChanged(oldCount, q->count());
2178 if (q->stretchLastSection()) {
2179 const bool lastSectionRemoved = lastSectionLogicalIdx >= logicalFirst && lastSectionLogicalIdx <= logicalLast;
2180 if (lastSectionRemoved)
2181 setNewLastSection(lastVisibleVisualIndex());
2183 lastSectionLogicalIdx = logicalIndex(lastVisibleVisualIndex());
2184 doDelayedResizeSections();
2214void QHeaderViewPrivate::sectionsAboutToBeChanged(
const QList<QPersistentModelIndex> &,
2215 QAbstractItemModel::LayoutChangeHint hint)
2217 if ((hint == QAbstractItemModel::VerticalSortHint && orientation == Qt::Horizontal) ||
2218 (hint == QAbstractItemModel::HorizontalSortHint && orientation == Qt::Vertical))
2221 if (noSectionMemoryUsage()) {
2231 if ((orientation == Qt::Horizontal && model->rowCount(root) == 0)
2232 || model->columnCount(root) == 0)
2235 layoutChangePersistentSections.clear();
2236 layoutChangePersistentSections.reserve(std::min(10,
int(sectionItems.size())));
2238 if (stretchLastSection && lastSectionLogicalIdx >= 0 && lastSectionLogicalIdx < sectionItems.size()) {
2239 const int visual = visualIndex(lastSectionLogicalIdx);
2240 if (visual >= 0 && visual < sectionItems.size()) {
2241 auto &itemRef = sectionItems[visual];
2242 if (itemRef.size != lastSectionSize) {
2243 length += lastSectionSize - itemRef.size;
2244 itemRef.size = lastSectionSize;
2248 for (
int i = 0; i < sectionItems.size(); ++i) {
2249 auto s = sectionItems.at(i);
2251 if (s.size == defaultSectionSize && !s.isHidden && s.resizeMode == globalResizeMode)
2254 const int logical = logicalIndex(i);
2256 s.size = hiddenSectionSize.value(logical);
2259 layoutChangePersistentSections.append({orientation == Qt::Horizontal
2260 ? model->index(0, logical, root)
2261 : model->index(logical, 0, root),
2266void QHeaderViewPrivate::sectionsChanged(
const QList<QPersistentModelIndex> &,
2267 QAbstractItemModel::LayoutChangeHint hint)
2269 if ((hint == QAbstractItemModel::VerticalSortHint && orientation == Qt::Horizontal) ||
2270 (hint == QAbstractItemModel::HorizontalSortHint && orientation == Qt::Vertical))
2276 const auto oldPersistentSections = layoutChangePersistentSections;
2277 layoutChangePersistentSections.clear();
2279 const int newCount = modelSectionCount();
2280 const int oldCount = sectionCount();
2281 if (newCount == 0) {
2284 emit q->sectionCountChanged(oldCount, 0);
2288 if (noSectionMemoryUsage()) {
2290 updateCountInNoSectionItemsMode(newCount);
2295 bool hasPersistantIndexes =
false;
2296 for (
const auto &item : oldPersistentSections) {
2297 if (item.index.isValid()) {
2298 hasPersistantIndexes =
true;
2313 if (!hasPersistantIndexes) {
2314 if (oldCount != newCount)
2315 q->initializeSections();
2320 if (newCount != oldCount) {
2321 const int min = qBound(0, oldCount, newCount - 1);
2322 q->initializeSections(min, newCount - 1);
2325 sectionItems.fill(SectionItem(defaultSectionSize, globalResizeMode), newCount);
2328 hiddenSectionSize.clear();
2330 for (
const auto &item : oldPersistentSections) {
2331 const auto &index = item.index;
2332 if (!index.isValid())
2335 const int newLogicalIndex = (orientation == Qt::Horizontal
2339 const int newVisualIndex = visualIndex(newLogicalIndex);
2340 if (newVisualIndex < sectionItems.size()) {
2341 auto &newSection = sectionItems[newVisualIndex];
2342 newSection = item.section;
2344 if (newSection.isHidden) {
2346 newSection.isHidden =
false;
2347 q->setSectionHidden(newLogicalIndex,
true);
2352 recalcSectionStartPos();
2353 length = headerLength();
2355 if (stretchLastSection) {
2357 lastSectionLogicalIdx = -1;
2358 maybeRestorePrevLastSectionAndStretchLast();
2400void QHeaderView::initializeSections(
int start,
int end)
2404 Q_ASSERT(start >= 0);
2407 d->invalidateCachedSizeHint();
2408 int oldCount = d->sectionCount();
2410 if (end + 1 < d->sectionCount()) {
2411 int newCount = end + 1;
2412 d->removeSectionsFromSectionItems(newCount, d->sectionCount() - 1);
2413 if (!d->hiddenSectionSize.isEmpty()) {
2414 if (oldCount - newCount > d->hiddenSectionSize.size()) {
2415 for (
int i = end + 1; i < d->sectionCount(); ++i)
2416 d->hiddenSectionSize.remove(i);
2418 QHash<
int,
int>::iterator it = d->hiddenSectionSize.begin();
2419 while (it != d->hiddenSectionSize.end()) {
2421 it = d->hiddenSectionSize.erase(it);
2429 int newSectionCount = end + 1;
2431 if (!d->logicalIndices.isEmpty()) {
2432 if (oldCount <= newSectionCount) {
2433 d->logicalIndices.resize(newSectionCount);
2434 d->visualIndices.resize(newSectionCount);
2435 for (
int i = oldCount; i < newSectionCount; ++i) {
2436 d->logicalIndices[i] = i;
2437 d->visualIndices[i] = i;
2441 for (
int i = 0; i < oldCount; ++i) {
2442 int v = d->logicalIndices.at(i);
2443 if (v < newSectionCount) {
2444 d->logicalIndices[j] = v;
2445 d->visualIndices[v] = j;
2449 d->logicalIndices.resize(newSectionCount);
2450 d->visualIndices.resize(newSectionCount);
2454 if (d->globalResizeMode == Stretch)
2455 d->stretchSections = newSectionCount;
2456 else if (d->globalResizeMode == ResizeToContents)
2457 d->contentsSections = newSectionCount;
2459 if (newSectionCount > oldCount)
2460 d->createSectionItems(start, end, d->defaultSectionSize, d->globalResizeMode);
2463 if (d->sectionCount() != oldCount)
2464 emit sectionCountChanged(oldCount, d->sectionCount());
2465 d->viewport->update();
2472void QHeaderView::currentChanged(
const QModelIndex ¤t,
const QModelIndex &old)
2476 if (d->orientation == Qt::Horizontal && current.column() != old.column()) {
2477 if (old.isValid() && old.parent() == d->root)
2478 d->viewport->update(QRect(sectionViewportPosition(old.column()), 0,
2479 sectionSize(old.column()), d->viewport->height()));
2480 if (current.isValid() && current.parent() == d->root)
2481 d->viewport->update(QRect(sectionViewportPosition(current.column()), 0,
2482 sectionSize(current.column()), d->viewport->height()));
2483 }
else if (d->orientation == Qt::Vertical && current.row() != old.row()) {
2484 if (old.isValid() && old.parent() == d->root)
2485 d->viewport->update(QRect(0, sectionViewportPosition(old.row()),
2486 d->viewport->width(), sectionSize(old.row())));
2487 if (current.isValid() && current.parent() == d->root)
2488 d->viewport->update(QRect(0, sectionViewportPosition(current.row()),
2489 d->viewport->width(), sectionSize(current.row())));
2550void QHeaderView::paintEvent(QPaintEvent *e)
2557 QPainter painter(d->viewport);
2558 const QPoint offset = d->scrollDelayOffset;
2559 QRect translatedEventRect = e->rect();
2560 translatedEventRect.translate(offset);
2564 if (d->orientation == Qt::Horizontal) {
2565 start = visualIndexAt(translatedEventRect.left());
2566 end = visualIndexAt(translatedEventRect.right());
2568 start = visualIndexAt(translatedEventRect.top());
2569 end = visualIndexAt(translatedEventRect.bottom());
2573 start = (start == -1 ? count() - 1 : start);
2574 end = (end == -1 ? 0 : end);
2576 start = (start == -1 ? 0 : start);
2577 end = (end == -1 ? count() - 1 : end);
2581 start = qMin(start, end);
2582 end = qMax(tmp, end);
2584 d->prepareSectionSelected();
2586 QRect currentSectionRect;
2587 const int width = d->viewport->width();
2588 const int height = d->viewport->height();
2589 const int rtlHorizontalOffset = d->reverse() ? 1 : 0;
2590 for (
int i = start; i <= end; ++i) {
2591 if (d->isVisualIndexHidden(i))
2594 const int logical = logicalIndex(i);
2595 if (d->orientation == Qt::Horizontal) {
2596 currentSectionRect.setRect(sectionViewportPosition(logical) + rtlHorizontalOffset,
2597 0, sectionSize(logical), height);
2599 currentSectionRect.setRect(0, sectionViewportPosition(logical),
2600 width, sectionSize(logical));
2602 currentSectionRect.translate(offset);
2604 QVariant variant = d->model->headerData(logical, d->orientation,
2606 if (variant.isValid() && variant.canConvert<QFont>()) {
2607 QFont sectionFont = qvariant_cast<QFont>(variant);
2608 painter.setFont(sectionFont);
2610 paintSection(&painter, currentSectionRect, logical);
2618 opt.state |= QStyle::State_Horizontal;
2619 if (currentSectionRect.left() > translatedEventRect.left()) {
2620 opt.rect = QRect(translatedEventRect.left(), 0,
2621 currentSectionRect.left() - translatedEventRect.left(), height);
2622 style()->drawControl(QStyle::CE_HeaderEmptyArea, &opt, &painter,
this);
2624 }
else if (currentSectionRect.right() < translatedEventRect.right()) {
2626 opt.state |= QStyle::State_Horizontal;
2627 opt.rect = QRect(currentSectionRect.right() + 1, 0,
2628 translatedEventRect.right() - currentSectionRect.right(), height);
2629 style()->drawControl(QStyle::CE_HeaderEmptyArea, &opt, &painter,
this);
2630 }
else if (currentSectionRect.bottom() < translatedEventRect.bottom()) {
2632 opt.state &= ~QStyle::State_Horizontal;
2633 opt.rect = QRect(0, currentSectionRect.bottom() + 1,
2634 width, height - currentSectionRect.bottom() - 1);
2635 style()->drawControl(QStyle::CE_HeaderEmptyArea, &opt, &painter,
this);
2640 for (
int a = 0, i = 0; i < d->sectionItems.count(); ++i) {
2641 QColor color((i & 4 ? 255 : 0), (i & 2 ? 255 : 0), (i & 1 ? 255 : 0));
2642 if (d->orientation == Qt::Horizontal)
2643 painter.fillRect(a - d->headerOffset, 0, d->sectionItems.at(i).size, 4, color);
2645 painter.fillRect(0, a - d->headerOffset, 4, d->sectionItems.at(i).size, color);
2646 a += d->sectionItems.at(i).size;
2656void QHeaderView::mousePressEvent(QMouseEvent *e)
2659 if (d->state != QHeaderViewPrivate::NoState || e->button() != Qt::LeftButton)
2661 int pos = d->orientation == Qt::Horizontal ? e->position().toPoint().x() : e->position().toPoint().y();
2662 int handle = d->sectionHandleAt(pos);
2663 d->originalSize = -1;
2665 d->firstPressed = d->pressed = logicalIndexAt(pos);
2666 if (d->clickableSections)
2667 emit sectionPressed(d->pressed);
2669 bool acceptMoveSection = d->movableSections;
2670 if (acceptMoveSection && d->pressed == 0 && !d->allowUserMoveOfSection0)
2671 acceptMoveSection =
false;
2673 if (acceptMoveSection) {
2675 d->section = d->pressed;
2676 if (d->section == -1)
2678 d->state = QHeaderViewPrivate::MoveSection;
2679 d->setupSectionIndicator(d->section, pos);
2680 }
else if (d->clickableSections && d->pressed != -1) {
2681 updateSection(d->pressed);
2682 d->state = QHeaderViewPrivate::SelectSections;
2684 }
else if (sectionResizeMode(handle) == Interactive) {
2685 d->originalSize = sectionSize(handle);
2686 d->state = QHeaderViewPrivate::ResizeSection;
2687 d->section = handle;
2688 d->preventCursorChangeInSetOffset =
false;
2694 d->clearCascadingSections();
2701void QHeaderView::mouseMoveEvent(QMouseEvent *e)
2704 const int pos = d->orientation == Qt::Horizontal ? e->position().toPoint().x() : e->position().toPoint().y();
2705 if (pos < 0 && d->state != QHeaderViewPrivate::SelectSections)
2707 if (e->buttons() == Qt::NoButton) {
2713 d->state = QHeaderViewPrivate::NoState;
2714 d->firstPressed = d->pressed = -1;
2717 case QHeaderViewPrivate::ResizeSection: {
2718 Q_ASSERT(d->originalSize != -1);
2719 if (d->cascadingResizing) {
2720 int delta = d->reverse() ? d->lastPos - pos : pos - d->lastPos;
2721 int visual = visualIndex(d->section);
2722 d->cascadingResize(visual, d->headerSectionSize(visual) + delta);
2724 int delta = d->reverse() ? d->firstPos - pos : pos - d->firstPos;
2725 int newsize = qBound(minimumSectionSize(), d->originalSize + delta, maximumSectionSize());
2726 resizeSection(d->section, newsize);
2731 case QHeaderViewPrivate::MoveSection: {
2732 if (d->shouldAutoScroll(e->position().toPoint())) {
2733 d->draggedPosition = e->pos() + d->offset();
2734 d->startAutoScroll();
2736 if (qAbs(pos - d->firstPos) >= QApplication::startDragDistance()
2738 || !d->sectionIndicator->isHidden()
2741 int visual = visualIndexAt(pos);
2744 if (visual == 0 && logicalIndex(0) == 0 && !d->allowUserMoveOfSection0)
2747 const int posThreshold = d->headerSectionPosition(visual) - d->headerOffset + d->headerSectionSize(visual) / 2;
2748 const int checkPos = d->reverse() ? d->viewport->width() - pos : pos;
2749 int moving = visualIndex(d->section);
2750 int oldTarget = d->target;
2751 if (visual < moving) {
2752 if (checkPos < posThreshold)
2753 d->target = d->logicalIndex(visual);
2755 d->target = d->logicalIndex(visual + 1);
2756 }
else if (visual > moving) {
2757 if (checkPos > posThreshold)
2758 d->target = d->logicalIndex(visual);
2760 d->target = d->logicalIndex(visual - 1);
2762 d->target = d->section;
2764 if (oldTarget != d->target || oldTarget == -1)
2765 d->updateSectionsBeforeAfter(d->target);
2766 d->updateSectionIndicator(d->section, pos);
2770 case QHeaderViewPrivate::SelectSections: {
2771 int logical = logicalIndexAt(qMax(-d->headerOffset, pos));
2772 if (logical == -1 && pos > 0)
2773 logical = logicalIndex(d->lastVisibleVisualIndex());
2774 if (logical == d->pressed)
2776 else if (d->pressed != -1)
2777 updateSection(d->pressed);
2778 d->pressed = logical;
2779 if (d->clickableSections && logical != -1) {
2780 emit sectionEntered(d->pressed);
2781 updateSection(d->pressed);
2785 case QHeaderViewPrivate::NoState: {
2787 int handle = d->sectionHandleAt(pos);
2788 bool hasCursor = testAttribute(Qt::WA_SetCursor);
2789 if (handle != -1 && (sectionResizeMode(handle) == Interactive)) {
2791 setCursor(d->orientation == Qt::Horizontal ? Qt::SplitHCursor : Qt::SplitVCursor);
2795#ifndef QT_NO_STATUSTIP
2796 int logical = logicalIndexAt(pos);
2799 statusTip = d->model->headerData(logical, d->orientation, Qt::StatusTipRole).toString();
2800 if (d->shouldClearStatusTip || !statusTip.isEmpty()) {
2801 QStatusTipEvent tip(statusTip);
2802 QCoreApplication::sendEvent(d->parent ? d->parent :
this, &tip);
2803 d->shouldClearStatusTip = !statusTip.isEmpty();
2819void QHeaderView::mouseReleaseEvent(QMouseEvent *e)
2822 int pos = d->orientation == Qt::Horizontal ? e->position().toPoint().x() : e->position().toPoint().y();
2824 case QHeaderViewPrivate::MoveSection:
2827 && !d->sectionIndicator->isHidden()
2830 int from = visualIndex(d->section);
2831 Q_ASSERT(from != -1);
2832 int to = visualIndex(d->target);
2834 moveSection(from, to);
2835 d->section = d->target = -1;
2836 d->updateSectionIndicator(d->section, pos);
2838 d->updateSectionsBeforeAfter(logicalIndex(from));
2842 case QHeaderViewPrivate::SelectSections:
2843 if (!d->clickableSections) {
2844 int section = logicalIndexAt(pos);
2845 updateSection(section);
2848 case QHeaderViewPrivate::NoState:
2849 if (d->clickableSections) {
2850 int section = logicalIndexAt(pos);
2851 if (section != -1 && section == d->firstPressed) {
2852 QRect firstPressedSectionRect;
2853 switch (d->orientation) {
2854 case Qt::Horizontal:
2855 firstPressedSectionRect.setRect(sectionViewportPosition(d->firstPressed),
2857 sectionSize(d->firstPressed),
2858 d->viewport->height());
2861 firstPressedSectionRect.setRect(0,
2862 sectionViewportPosition(d->firstPressed),
2863 d->viewport->width(),
2864 sectionSize(d->firstPressed));
2868 if (firstPressedSectionRect.contains(e->position().toPoint())) {
2869 d->flipSortIndicator(section);
2870 emit sectionClicked(section);
2873 if (d->pressed != -1)
2874 updateSection(d->pressed);
2877 case QHeaderViewPrivate::ResizeSection:
2878 d->originalSize = -1;
2879 d->clearCascadingSections();
2884 d->state = QHeaderViewPrivate::NoState;
2885 d->firstPressed = d->pressed = -1;
2918bool QHeaderView::viewportEvent(QEvent *e)
2921 switch (e->type()) {
2922#if QT_CONFIG(tooltip)
2923 case QEvent::ToolTip: {
2924 QHelpEvent *he =
static_cast<QHelpEvent*>(e);
2925 int logical = logicalIndexAt(he->pos());
2926 if (logical != -1) {
2927 QVariant variant = d->model->headerData(logical, d->orientation, Qt::ToolTipRole);
2928 if (variant.isValid()) {
2929 QToolTip::showText(he->globalPos(), variant.toString(),
this);
2935#if QT_CONFIG(whatsthis)
2936 case QEvent::QueryWhatsThis: {
2937 QHelpEvent *he =
static_cast<QHelpEvent*>(e);
2938 int logical = logicalIndexAt(he->pos());
2940 && d->model->headerData(logical, d->orientation, Qt::WhatsThisRole).isValid())
2943 case QEvent::WhatsThis: {
2944 QHelpEvent *he =
static_cast<QHelpEvent*>(e);
2945 int logical = logicalIndexAt(he->pos());
2946 if (logical != -1) {
2947 QVariant whatsthis = d->model->headerData(logical, d->orientation,
2949 if (whatsthis.isValid()) {
2950 QWhatsThis::showText(he->globalPos(), whatsthis.toString(),
this);
2956 case QEvent::Resize:
2957 case QEvent::FontChange:
2958 case QEvent::StyleChange:
2959 d->invalidateCachedSizeHint();
2962 case QEvent::Show: {
2963 QAbstractScrollArea *parent = qobject_cast<QAbstractScrollArea *>(parentWidget());
2964 if (parent && parent->isVisible())
2966 emit geometriesChanged();
2968 case QEvent::ContextMenu: {
2969 d->state = QHeaderViewPrivate::NoState;
2970 d->pressed = d->section = d->target = -1;
2971 d->updateSectionIndicator(d->section, -1);
2973 case QEvent::Wheel: {
2974 QAbstractScrollArea *asa = qobject_cast<QAbstractScrollArea *>(parentWidget());
2976 return QCoreApplication::sendEvent(asa->viewport(), e);
2981 return QAbstractItemView::viewportEvent(e);
2995void QHeaderView::initStyleOptionForIndex(QStyleOptionHeader *option,
int logicalIndex)
const
2997 Q_D(
const QHeaderView);
3001 QStyleOptionHeader &opt = *option;
3002 QStyleOptionHeaderV2 *optV2 = qstyleoption_cast<QStyleOptionHeaderV2*>(option);
3004 QStyle::State state = QStyle::State_None;
3005 if (window()->isActiveWindow())
3006 state |= QStyle::State_Active;
3007 if (d->clickableSections) {
3008 if (logicalIndex == d->hover)
3009 state |= QStyle::State_MouseOver;
3010 if (logicalIndex == d->pressed)
3011 state |= QStyle::State_Sunken;
3012 else if (d->highlightSelected) {
3013 if (d->sectionIntersectsSelection(logicalIndex))
3014 state |= QStyle::State_On;
3015 if (d->isSectionSelected(logicalIndex))
3016 state |= QStyle::State_Sunken;
3019 if (isSortIndicatorShown() && sortIndicatorSection() == logicalIndex)
3020 opt.sortIndicator = (sortIndicatorOrder() == Qt::AscendingOrder)
3021 ? QStyleOptionHeader::SortDown : QStyleOptionHeader::SortUp;
3024 QVariant textAlignment = d->model->headerData(logicalIndex, d->orientation,
3025 Qt::TextAlignmentRole);
3026 opt.section = logicalIndex;
3028 opt.textAlignment = textAlignment.isValid()
3029 ? QtPrivate::legacyFlagValueFromModelData<Qt::Alignment>(textAlignment)
3030 : d->defaultAlignment;
3032 opt.iconAlignment = Qt::AlignVCenter;
3033 opt.text = d->model->headerData(logicalIndex, d->orientation,
3034 Qt::DisplayRole).toString();
3036 const QVariant variant = d->model->headerData(logicalIndex, d->orientation,
3037 Qt::DecorationRole);
3038 opt.icon = qvariant_cast<QIcon>(variant);
3039 if (opt.icon.isNull())
3040 opt.icon = qvariant_cast<QPixmap>(variant);
3042 QVariant var = d->model->headerData(logicalIndex, d->orientation,
3044 if (var.isValid() && var.canConvert<QFont>())
3045 opt.fontMetrics = QFontMetrics(qvariant_cast<QFont>(var));
3047 optV2->textElideMode = d->textElideMode;
3049 QVariant foregroundBrush = d->model->headerData(logicalIndex, d->orientation,
3050 Qt::ForegroundRole);
3051 if (foregroundBrush.canConvert<QBrush>())
3052 opt.palette.setBrush(QPalette::ButtonText, qvariant_cast<QBrush>(foregroundBrush));
3054 QVariant backgroundBrush = d->model->headerData(logicalIndex, d->orientation,
3055 Qt::BackgroundRole);
3056 if (backgroundBrush.canConvert<QBrush>()) {
3057 opt.palette.setBrush(QPalette::Button, qvariant_cast<QBrush>(backgroundBrush));
3058 opt.palette.setBrush(QPalette::Window, qvariant_cast<QBrush>(backgroundBrush));
3062 int visual = visualIndex(logicalIndex);
3063 Q_ASSERT(visual != -1);
3064 bool first = d->isFirstVisibleSection(visual);
3065 bool last = d->isLastVisibleSection(visual);
3067 opt.position = QStyleOptionHeader::OnlyOneSection;
3069 opt.position = d->reverse() ? QStyleOptionHeader::End : QStyleOptionHeader::Beginning;
3071 opt.position = d->reverse() ? QStyleOptionHeader::Beginning : QStyleOptionHeader::End;
3073 opt.position = QStyleOptionHeader::Middle;
3074 opt.orientation = d->orientation;
3076 bool previousSelected = d->isSectionSelected(
this->logicalIndex(visual - 1));
3077 bool nextSelected = d->isSectionSelected(
this->logicalIndex(visual + 1));
3078 if (previousSelected && nextSelected)
3079 opt.selectedPosition = QStyleOptionHeader::NextAndPreviousAreSelected;
3080 else if (previousSelected)
3081 opt.selectedPosition = QStyleOptionHeader::PreviousIsSelected;
3082 else if (nextSelected)
3083 opt.selectedPosition = QStyleOptionHeader::NextIsSelected;
3085 opt.selectedPosition = QStyleOptionHeader::NotAdjacent;
3087 optV2->isSectionDragTarget = d->target == logicalIndex;
3133QSize QHeaderView::sectionSizeFromContents(
int logicalIndex)
const
3135 Q_D(
const QHeaderView);
3136 Q_ASSERT(logicalIndex >= 0);
3141 QVariant variant = d->model->headerData(logicalIndex, d->orientation, Qt::SizeHintRole);
3142 if (variant.isValid())
3143 return qvariant_cast<QSize>(variant);
3146 QStyleOptionHeaderV2 opt;
3147 initStyleOption(&opt);
3148 opt.section = logicalIndex;
3149 QVariant var = d->model->headerData(logicalIndex, d->orientation,
3152 if (var.isValid() && var.canConvert<QFont>())
3153 fnt = qvariant_cast<QFont>(var);
3157 opt.fontMetrics = QFontMetrics(fnt);
3158 opt.text = d->model->headerData(logicalIndex, d->orientation,
3159 Qt::DisplayRole).toString();
3160 variant = d->model->headerData(logicalIndex, d->orientation, Qt::DecorationRole);
3161 opt.icon = qvariant_cast<QIcon>(variant);
3162 if (opt.icon.isNull())
3163 opt.icon = qvariant_cast<QPixmap>(variant);
3164 if (isSortIndicatorShown())
3165 opt.sortIndicator = QStyleOptionHeader::SortDown;
3166 return style()->sizeFromContents(QStyle::CT_HeaderSection, &opt, QSize(),
this);
3348QRegion QHeaderView::visualRegionForSelection(
const QItemSelection &selection)
const
3350 Q_D(
const QHeaderView);
3351 const int max = d->modelSectionCount();
3353 if (d->orientation == Qt::Horizontal) {
3354 int logicalLeft = max;
3355 int logicalRight = 0;
3357 if (d->visualIndices.empty()) {
3359 for (
const auto &r : selection) {
3360 if (r.parent().isValid() || !r.isValid())
3362 if (r.left() < logicalLeft)
3363 logicalLeft = r.left();
3364 if (r.right() > logicalRight)
3365 logicalRight = r.right();
3370 for (
const auto &r : selection) {
3371 if (r.parent().isValid() || !r.isValid())
3373 for (
int k = r.left(); k <= r.right(); ++k) {
3374 int visual = visualIndex(k);
3383 logicalLeft = logicalIndex(left);
3384 logicalRight = logicalIndex(right);
3387 if (logicalLeft < 0 || logicalLeft >= count() ||
3388 logicalRight < 0 || logicalRight >= count())
3391 int leftPos = sectionViewportPosition(logicalLeft);
3392 int rightPos = sectionViewportPosition(logicalRight);
3393 rightPos += sectionSize(logicalRight);
3394 return QRect(leftPos, 0, rightPos - leftPos, height());
3397 int logicalTop = max;
3398 int logicalBottom = 0;
3400 if (d->visualIndices.empty()) {
3402 for (
const auto &r : selection) {
3403 if (r.parent().isValid() || !r.isValid())
3405 if (r.top() < logicalTop)
3406 logicalTop = r.top();
3407 if (r.bottom() > logicalBottom)
3408 logicalBottom = r.bottom();
3414 for (
const auto &r : selection) {
3415 if (r.parent().isValid() || !r.isValid())
3417 for (
int k = r.top(); k <= r.bottom(); ++k) {
3418 int visual = visualIndex(k);
3423 if (visual > bottom)
3428 logicalTop = logicalIndex(top);
3429 logicalBottom = logicalIndex(bottom);
3432 if (logicalTop < 0 || logicalTop >= count() ||
3433 logicalBottom < 0 || logicalBottom >= count())
3436 int topPos = sectionViewportPosition(logicalTop);
3437 int bottomPos = sectionViewportPosition(logicalBottom) + sectionSize(logicalBottom);
3439 return QRect(0, topPos, width(), bottomPos - topPos);
3474void QHeaderViewPrivate::setupSectionIndicator(
int section,
int position)
3478 if (!sectionIndicator) {
3479 sectionIndicator =
new QLabel(viewport);
3484 int p = q->sectionViewportPosition(section);
3485 if (orientation == Qt::Horizontal) {
3486 w = q->sectionSize(section);
3487 h = viewport->height();
3489 w = viewport->width();
3490 h = q->sectionSize(section);
3493 sectionIndicator->resize(w, h);
3496 const qreal pixmapDevicePixelRatio = q->devicePixelRatio();
3497 QPixmap pm(QSize(w, h) * pixmapDevicePixelRatio);
3498 pm.setDevicePixelRatio(pixmapDevicePixelRatio);
3499 pm.fill(QColor(0, 0, 0, 45));
3500 QRect rect(0, 0, w, h);
3502 QPainter painter(&pm);
3503 const QVariant variant = model->headerData(section, orientation,
3505 if (variant.isValid() && variant.canConvert<QFont>()) {
3506 const QFont sectionFont = qvariant_cast<QFont>(variant);
3507 painter.setFont(sectionFont);
3509 painter.setFont(q->font());
3512 painter.setOpacity(0.75);
3513 q->paintSection(&painter, rect, section);
3517 sectionIndicator->setPixmap(pm);
3519 sectionIndicatorOffset = position - qMax(p, 0);
3674void QHeaderViewPrivate::resizeSections(QHeaderView::ResizeMode globalMode,
bool useGlobalMode)
3678 delayedResize.stop();
3680 executePostedLayout();
3682 if (noSectionMemoryUsage() && (hasAutoResizeSections() || globalMode != QHeaderView::Fixed))
3683 setHeaderMode(HeaderMode::FlexibleWithSectionMemoryUsage);
3685 if (sectionCount() == 0 )
3688 if (resizeRecursionBlock)
3690 resizeRecursionBlock =
true;
3692 invalidateCachedSizeHint();
3693 const int lastSectionVisualIdx = q->visualIndex(lastSectionLogicalIdx);
3696 int stretchSection = -1;
3697 if (stretchLastSection && !useGlobalMode)
3698 stretchSection = lastSectionVisualIdx;
3701 int lengthToStretch = (orientation == Qt::Horizontal ? viewport->width() : viewport->height());
3702 int numberOfStretchedSections = 0;
3703 QList<
int> section_sizes;
3704 for (
int i = 0; i < sectionCount(); ++i) {
3705 if (isVisualIndexHidden(i))
3708 QHeaderView::ResizeMode resizeMode;
3709 if (useGlobalMode && (i != stretchSection))
3710 resizeMode = globalMode;
3712 resizeMode = (i == stretchSection ? QHeaderView::Stretch : headerSectionResizeMode(i));
3714 if (resizeMode == QHeaderView::Stretch) {
3715 ++numberOfStretchedSections;
3716 section_sizes.append(headerSectionSize(i));
3721 int sectionSize = 0;
3722 if (resizeMode == QHeaderView::Interactive || resizeMode == QHeaderView::Fixed) {
3723 sectionSize = qBound(q->minimumSectionSize(), headerSectionSize(i), q->maximumSectionSize());
3725 int logicalIndex = q->logicalIndex(i);
3726 sectionSize = qMax(viewSectionSizeHint(logicalIndex),
3727 q->sectionSizeHint(logicalIndex));
3729 sectionSize = qBound(q->minimumSectionSize(),
3731 q->maximumSectionSize());
3733 section_sizes.append(sectionSize);
3734 lengthToStretch -= sectionSize;
3738 int stretchSectionLength = -1;
3739 int pixelReminder = 0;
3740 if (numberOfStretchedSections > 0 && lengthToStretch > 0) {
3741 int hintLengthForEveryStretchedSection = lengthToStretch / numberOfStretchedSections;
3742 stretchSectionLength = qMax(hintLengthForEveryStretchedSection, q->minimumSectionSize());
3743 pixelReminder = lengthToStretch % numberOfStretchedSections;
3747 int spanStartSection = 0;
3748 int previousSectionLength = 0;
3750 QHeaderView::ResizeMode previousSectionResizeMode = QHeaderView::Interactive;
3753 for (
int i = 0; i < sectionCount(); ++i) {
3754 int oldSectionLength = headerSectionSize(i);
3755 int newSectionLength = -1;
3756 QHeaderView::ResizeMode newSectionResizeMode = headerSectionResizeMode(i);
3758 if (isVisualIndexHidden(i)) {
3759 newSectionLength = 0;
3761 QHeaderView::ResizeMode resizeMode;
3763 resizeMode = globalMode;
3765 resizeMode = (i == stretchSection
3766 ? QHeaderView::Stretch
3767 : newSectionResizeMode);
3768 if (resizeMode == QHeaderView::Stretch && stretchSectionLength != -1) {
3769 if (i == lastSectionVisualIdx)
3770 newSectionLength = qMax(stretchSectionLength, lastSectionSize);
3772 newSectionLength = stretchSectionLength;
3773 if (pixelReminder > 0) {
3774 newSectionLength += 1;
3777 section_sizes.removeFirst();
3779 newSectionLength = section_sizes.takeFirst();
3784 if ((previousSectionResizeMode != newSectionResizeMode
3785 || previousSectionLength != newSectionLength) && i > 0) {
3786 createSectionItems(spanStartSection, i - 1, previousSectionLength, previousSectionResizeMode);
3788 spanStartSection = i;
3791 if (newSectionLength != oldSectionLength)
3792 emit q->sectionResized(logicalIndex(i), oldSectionLength, newSectionLength);
3794 previousSectionLength = newSectionLength;
3795 previousSectionResizeMode = newSectionResizeMode;
3798 createSectionItems(spanStartSection, sectionCount() - 1,
3799 previousSectionLength, previousSectionResizeMode);
3801 resizeRecursionBlock =
false;
3887void QHeaderViewPrivate::cascadingResize(
int visual,
int newSize)
3890 const int minimumSize = q->minimumSectionSize();
3891 const int oldSize = headerSectionSize(visual);
3892 int delta = newSize - oldSize;
3895 bool sectionResized =
false;
3898 for (
int i = firstCascadingSection; i < visual; ++i) {
3899 if (cascadingSectionSize.contains(i)) {
3900 int currentSectionSize = headerSectionSize(i);
3901 int originalSectionSize = cascadingSectionSize.value(i);
3902 if (currentSectionSize < originalSectionSize) {
3903 int newSectionSize = currentSectionSize + delta;
3904 resizeSectionItem(i, currentSectionSize, newSectionSize);
3905 if (newSectionSize >= originalSectionSize &&
false)
3906 cascadingSectionSize.remove(i);
3907 sectionResized =
true;
3915 if (!sectionResized) {
3916 newSize = qMax(newSize, minimumSize);
3917 if (oldSize != newSize)
3918 resizeSectionItem(visual, oldSize, newSize);
3922 for (
int i = visual + 1; i < sectionCount(); ++i) {
3923 if (isVisualIndexHidden(i))
3925 if (!sectionIsCascadable(i))
3927 int currentSectionSize = headerSectionSize(i);
3928 if (currentSectionSize <= minimumSize)
3930 int newSectionSize = qMax(currentSectionSize - delta, minimumSize);
3931 resizeSectionItem(i, currentSectionSize, newSectionSize);
3932 saveCascadingSectionSize(i, currentSectionSize);
3933 delta = delta - (currentSectionSize - newSectionSize);
3938 bool sectionResized =
false;
3941 for (
int i = lastCascadingSection; i > visual; --i) {
3942 if (!cascadingSectionSize.contains(i))
3944 int currentSectionSize = headerSectionSize(i);
3945 int originalSectionSize = cascadingSectionSize.value(i);
3946 if (currentSectionSize >= originalSectionSize)
3948 int newSectionSize = currentSectionSize - delta;
3949 resizeSectionItem(i, currentSectionSize, newSectionSize);
3950 if (newSectionSize >= originalSectionSize &&
false) {
3951 cascadingSectionSize.remove(i);
3953 sectionResized =
true;
3958 resizeSectionItem(visual, oldSize, qMax(newSize, minimumSize));
3961 if (delta < 0 && newSize < minimumSize) {
3962 for (
int i = visual - 1; i >= 0; --i) {
3963 if (isVisualIndexHidden(i))
3965 if (!sectionIsCascadable(i))
3967 int sectionSize = headerSectionSize(i);
3968 if (sectionSize <= minimumSize)
3970 resizeSectionItem(i, sectionSize, qMax(sectionSize + delta, minimumSize));
3971 saveCascadingSectionSize(i, sectionSize);
3977 if (!sectionResized) {
3978 for (
int i = visual + 1; i < sectionCount(); ++i) {
3979 if (isVisualIndexHidden(i))
3981 if (!sectionIsCascadable(i))
3983 int currentSectionSize = headerSectionSize(i);
3984 int newSectionSize = qMax(currentSectionSize - delta, minimumSize);
3985 resizeSectionItem(i, currentSectionSize, newSectionSize);
3991 if (hasAutoResizeSections())
3992 doDelayedResizeSections();
3997void QHeaderViewPrivate::setDefaultSectionSize(
int size)
4000 size = qBound(q->minimumSectionSize(), size, q->maximumSectionSize());
4001 executePostedLayout();
4002 invalidateCachedSizeHint();
4003 defaultSectionSize = size;
4004 customDefaultSectionSize =
true;
4005 if (state == QHeaderViewPrivate::ResizeSection)
4006 preventCursorChangeInSetOffset =
true;
4007 for (
int i = 0; i < sectionItems.size(); ++i) {
4008 QHeaderViewPrivate::SectionItem §ion = sectionItems[i];
4009 if (hiddenSectionSize.isEmpty() || !isVisualIndexHidden(i)) {
4012 const int newSize = (section.size == oldDefaultSectionSize || !section.size)
4015 if (newSize != section.size) {
4016 length += newSize - section.size;
4017 const int oldSectionSize = section.sectionSize();
4018 section.size = size;
4019 emit q->sectionResized(logicalIndex(i), oldSectionSize, size);
4024 sectionStartposRecalc =
true;
4025 if (hasAutoResizeSections())
4026 doDelayedResizeSections();
4029 if (noSectionMemoryUsage()) {
4030 length = countInNoSectionItemsMode * size;
4031 QAbstractItemView *parentView = qobject_cast<QAbstractItemView*>(q->parentWidget());
4033 parentView->viewport()->update();
4203void QHeaderViewPrivate::write(QDataStream &out)
const
4205 out <<
int(orientation);
4206 out <<
int(sortIndicatorOrder);
4207 out << sortIndicatorSection;
4208 out << sortIndicatorShown;
4210 out << visualIndices;
4211 out << logicalIndices;
4213 out << sectionsHiddenToBitVector();
4214 out << hiddenSectionSize;
4217 out << sectionCount();
4218 out << movableSections;
4219 out << clickableSections;
4220 out << highlightSelected;
4221 out << stretchLastSection;
4222 out << cascadingResizing;
4223 out << stretchSections;
4224 out << contentsSections;
4225 out << defaultSectionSize;
4226 out << minimumSectionSize;
4228 out <<
int(defaultAlignment);
4229 out <<
int(globalResizeMode);
4231 if (noSectionMemoryUsage()) {
4232 Q_ASSERT(sectionItems.isEmpty());
4233 out << QList<SectionItem>();
4236 out << sectionItems;
4239 out << resizeContentsPrecision;
4240 out << customDefaultSectionSize;
4241 out << lastSectionSize;
4242 out <<
int(sortIndicatorClearable);
4244 out << countInNoSectionItemsMode;
4245 out <<
int(headerMode);
4248bool QHeaderViewPrivate::read(QDataStream &in)
4251 int orient, order, align, global;
4252 int sortIndicatorSectionIn;
4253 bool sortIndicatorShownIn;
4255 QList<
int> visualIndicesIn;
4256 QList<
int> logicalIndicesIn;
4257 QHash<
int,
int> hiddenSectionSizeIn;
4258 bool movableSectionsIn;
4259 bool clickableSectionsIn;
4260 bool highlightSelectedIn;
4261 bool stretchLastSectionIn;
4262 bool cascadingResizingIn;
4263 int stretchSectionsIn;
4264 int contentsSectionsIn;
4265 int defaultSectionSizeIn;
4266 int minimumSectionSizeIn;
4267 QList<SectionItem> sectionItemsIn;
4272 in >> sortIndicatorSectionIn;
4273 in >> sortIndicatorShownIn;
4275 in >> visualIndicesIn;
4276 in >> logicalIndicesIn;
4278 QBitArray sectionHidden;
4279 in >> sectionHidden;
4280 in >> hiddenSectionSizeIn;
4283 int unusedSectionCount;
4284 in >> unusedSectionCount;
4286 if (in.status() != QDataStream::Ok || lengthIn < 0)
4289 in >> movableSectionsIn;
4290 in >> clickableSectionsIn;
4291 in >> highlightSelectedIn;
4292 in >> stretchLastSectionIn;
4293 in >> cascadingResizingIn;
4294 in >> stretchSectionsIn;
4295 in >> contentsSectionsIn;
4296 in >> defaultSectionSizeIn;
4297 in >> minimumSectionSizeIn;
4305 if (global < 0 || global > QHeaderView::ResizeToContents)
4309 if (align < 0 || align > Qt::AlignVertical_Mask)
4312 in >> sectionItemsIn;
4318 QList<SectionItem> newSectionItems;
4319 for (
int u = 0; u < sectionItemsIn.size(); ++u) {
4320 int count = sectionItemsIn.at(u).tmpDataStreamSectionCount;
4322 sectionItemsIn[u].size /= count;
4323 for (
int n = 0; n < count; ++n)
4324 newSectionItems.append(sectionItemsIn[u]);
4327 int sectionItemsLengthTotal = 0;
4328 for (
const SectionItem §ion : std::as_const(newSectionItems))
4329 sectionItemsLengthTotal += section.size;
4331 if (sectionItemsLengthTotal != lengthIn && newSectionItems.size() > 0)
4339 const auto isValidIndexMapping = [](
const QList<
int> &mapping, qsizetype sectionCount) {
4340 if (mapping.isEmpty())
4342 if (mapping.size() != sectionCount)
4344 QDuplicateTracker<
int> seenIndices;
4345 for (
int index : mapping) {
4346 if (index < 0 || index >= sectionCount)
4348 if (seenIndices.hasSeen(index))
4353 const qsizetype newSectionCount = newSectionItems.size();
4354 if (!isValidIndexMapping(visualIndicesIn, newSectionCount)
4355 || !isValidIndexMapping(logicalIndicesIn, newSectionCount)) {
4361 headerMode = HeaderMode::FlexibleWithSectionMemoryUsage;
4363 orientation =
static_cast<Qt::Orientation>(orient);
4364 sortIndicatorOrder =
static_cast<Qt::SortOrder>(order);
4365 sortIndicatorSection = sortIndicatorSectionIn;
4366 sortIndicatorShown = sortIndicatorShownIn;
4367 visualIndices = visualIndicesIn;
4368 logicalIndices = logicalIndicesIn;
4369 hiddenSectionSize = hiddenSectionSizeIn;
4372 movableSections = movableSectionsIn;
4373 clickableSections = clickableSectionsIn;
4374 highlightSelected = highlightSelectedIn;
4375 stretchLastSection = stretchLastSectionIn;
4376 cascadingResizing = cascadingResizingIn;
4377 stretchSections = stretchSectionsIn;
4378 contentsSections = contentsSectionsIn;
4379 defaultSectionSize = defaultSectionSizeIn;
4380 minimumSectionSize = minimumSectionSizeIn;
4382 defaultAlignment = Qt::Alignment(align);
4383 globalResizeMode =
static_cast<QHeaderView::ResizeMode>(global);
4385 sectionItems = newSectionItems;
4386 setHiddenSectionsFromBitVector(sectionHidden);
4387 recalcSectionStartPos();
4391 resizeContentsPrecision = tmpint;
4394 if (in >> tmpbool) {
4395 customDefaultSectionSize = tmpbool;
4396 if (!customDefaultSectionSize)
4397 updateDefaultSectionSizeFromStyle();
4400 lastSectionSize = -1;
4401 int inLastSectionSize;
4402 if (in >> inLastSectionSize)
4403 lastSectionSize = inLastSectionSize;
4405 lastSectionLogicalIdx = -1;
4406 if (stretchLastSection) {
4407 lastSectionLogicalIdx = q->logicalIndex(lastVisibleVisualIndex());
4408 doDelayedResizeSections();
4411 int inSortIndicatorClearable;
4412 if (in >> inSortIndicatorClearable)
4413 sortIndicatorClearable = inSortIndicatorClearable;
4415 in >> countInNoSectionItemsMode;
4418 if (!(in >> iHeaderMode)) {
4420 iHeaderMode =
static_cast<
int>(HeaderMode::FlexibleWithSectionMemoryUsage);
4423 const HeaderMode impMode =
static_cast<HeaderMode>(iHeaderMode);
4424 if (impMode == HeaderMode::FlexibleWithSectionMemoryUsage || impMode == HeaderMode::InitialNoSectionMemoryUsage) {
4425 headerMode = impMode;
4430 if (countInNoSectionItemsMode > 0 && sectionItems.isEmpty()) {
4431 headerMode = HeaderMode::InitialNoSectionMemoryUsage;
4433 else if (countInNoSectionItemsMode <= 0 && !sectionItems.isEmpty()) {
4434 headerMode = HeaderMode::FlexibleWithSectionMemoryUsage;
4438 headerMode = HeaderMode::FlexibleWithSectionMemoryUsage;
4444 const int currentCount = (orient == Qt::Horizontal ? model->columnCount(root) : model->rowCount(root));
4445 if (sectionItems.size() < currentCount) {
4447 if (noSectionMemoryUsage()) {
4448 countInNoSectionItemsMode = currentCount;
4449 length = defaultSectionSize * countInNoSectionItemsMode;
4452 if (!visualIndicesIn.isEmpty() && !logicalIndicesIn.isEmpty()) {
4453 for (
int i = sectionItems.size(); i < currentCount; ++i) {
4454 visualIndices.append(i);
4455 logicalIndices.append(i);
4458 const int insertCount = currentCount - sectionItems.size();
4459 const int insertLength = defaultSectionSizeIn * insertCount;
4460 lengthIn += insertLength;
4461 SectionItem section(defaultSectionSizeIn, globalResizeMode);
4462 sectionItems.insert(sectionItems.size(), insertCount, section);