343void QHeaderView::setModel(QAbstractItemModel *model)
345 if (model ==
this->model())
348 d->layoutChangePersistentSections.clear();
349 if (d->model && d->model != QAbstractItemModelPrivate::staticEmptyModel())
350 d->disconnectModel();
352 if (model && model != QAbstractItemModelPrivate::staticEmptyModel()) {
353 const bool hor = d->orientation == Qt::Horizontal;
354 d->modelConnections = {
355 QObject::connect(model, hor ? &QAbstractItemModel::columnsInserted
356 : &QAbstractItemModel::rowsInserted,
357 this, &QHeaderView::sectionsInserted),
358 QObject::connect(model, hor ? &QAbstractItemModel::columnsAboutToBeRemoved
359 : &QAbstractItemModel::rowsAboutToBeRemoved,
360 this, &QHeaderView::sectionsAboutToBeRemoved),
361 QObjectPrivate::connect(model, hor ? &QAbstractItemModel::columnsRemoved
362 : &QAbstractItemModel::rowsRemoved,
363 d, &QHeaderViewPrivate::sectionsRemoved),
364 QObjectPrivate::connect(model, hor ? &QAbstractItemModel::columnsAboutToBeMoved
365 : &QAbstractItemModel::rowsAboutToBeMoved,
366 d, &QHeaderViewPrivate::sectionsAboutToBeMoved),
367 QObjectPrivate::connect(model, hor ? &QAbstractItemModel::columnsMoved
368 : &QAbstractItemModel::rowsMoved,
369 d, &QHeaderViewPrivate::sectionsMoved),
371 QObject::connect(model, &QAbstractItemModel::headerDataChanged,
372 this, &QHeaderView::headerDataChanged),
373 QObjectPrivate::connect(model, &QAbstractItemModel::layoutAboutToBeChanged,
374 d, &QHeaderViewPrivate::sectionsAboutToBeChanged),
375 QObjectPrivate::connect(model, &QAbstractItemModel::layoutChanged,
376 d, &QHeaderViewPrivate::sectionsChanged)
380 d->state = QHeaderViewPrivate::NoClear;
381 QAbstractItemView::setModel(model);
382 d->state = QHeaderViewPrivate::NoState;
387 initializeSections();
423void QHeaderView::setOffset(
int newOffset)
426 if (d->headerOffset == newOffset)
429 const int ndelta = q26::saturate_cast<
int>(d->headerOffset - qint64{newOffset});
430 d->headerOffset = newOffset;
431 if (d->orientation == Qt::Horizontal) {
432 if (isRightToLeft()) {
433 if (
int r; !qMulOverflow<-1>(ndelta, &r))
434 d->viewport->scroll(r, 0);
436 warn_overflow(
"QHeaderView::setOffset",
"QWidget::scroll", newOffset);
438 d->viewport->scroll(ndelta, 0);
441 d->viewport->scroll(0, ndelta);
443 if (d->state == QHeaderViewPrivate::ResizeSection && !d->preventCursorChangeInSetOffset) {
444 QPoint cursorPos = QCursor::pos();
445 if (d->orientation == Qt::Horizontal)
446 QCursor::setPos(cursorPos.x() + ndelta, cursorPos.y());
448 QCursor::setPos(cursorPos.x(), cursorPos.y() + ndelta);
449 d->firstPos += ndelta;
450 d->lastPos += ndelta;
732void QHeaderView::moveSection(
int from,
int to)
736 d->executePostedLayout();
737 if (from < 0 || from >= d->sectionCount() || to < 0 || to >= d->sectionCount())
741 int logical = logicalIndex(from);
742 Q_ASSERT(logical != -1);
743 updateSection(logical);
747 if (d->noSectionMemoryUsage())
748 d->switchToFlexibleModeWithSectionMemoryUsage();
750 d->initializeIndexMapping();
752 int *visualIndices = d->visualIndices.data();
753 int *logicalIndices = d->logicalIndices.data();
754 int logical = logicalIndices[from];
758 while (visual < to) {
759 visualIndices[logicalIndices[visual + 1]] = visual;
760 logicalIndices[visual] = logicalIndices[visual + 1];
764 while (visual > to) {
765 visualIndices[logicalIndices[visual - 1]] = visual;
766 logicalIndices[visual] = logicalIndices[visual - 1];
770 visualIndices[logical] = to;
771 logicalIndices[to] = logical;
773 qMoveRange(d->sectionItems, from, from + 1, to);
775 d->sectionStartposRecalc =
true;
777 if (d->hasAutoResizeSections())
778 d->doDelayedResizeSections();
779 d->viewport->update();
781 emit sectionMoved(logical, from, to);
783 if (stretchLastSection()) {
784 const int lastSectionVisualIdx = visualIndex(d->lastSectionLogicalIdx);
785 if (from >= lastSectionVisualIdx || to >= lastSectionVisualIdx)
786 d->maybeRestorePrevLastSectionAndStretchLast();
796void QHeaderView::swapSections(
int first,
int second)
802 d->executePostedLayout();
803 if (first < 0 || first >= d->sectionCount() || second < 0 || second >= d->sectionCount())
806 if (d->noSectionMemoryUsage())
807 d->switchToFlexibleModeWithSectionMemoryUsage();
809 int firstSize = d->headerSectionSize(first);
810 ResizeMode firstMode = d->headerSectionResizeMode(first);
811 int firstLogical = d->logicalIndex(first);
813 int secondSize = d->headerSectionSize(second);
814 ResizeMode secondMode = d->headerSectionResizeMode(second);
815 int secondLogical = d->logicalIndex(second);
817 if (d->state == QHeaderViewPrivate::ResizeSection)
818 d->preventCursorChangeInSetOffset =
true;
820 d->createSectionItems(second, second, firstSize, firstMode);
821 d->createSectionItems(first, first, secondSize, secondMode);
823 d->initializeIndexMapping();
825 d->visualIndices[firstLogical] = second;
826 d->logicalIndices[second] = firstLogical;
828 d->visualIndices[secondLogical] = first;
829 d->logicalIndices[first] = secondLogical;
831 if (!d->hiddenSectionSize.isEmpty()) {
832 bool firstHidden = d->isVisualIndexHidden(first);
833 bool secondHidden = d->isVisualIndexHidden(second);
834 d->setVisualIndexHidden(first, secondHidden);
835 d->setVisualIndexHidden(second, firstHidden);
838 d->viewport->update();
839 emit sectionMoved(firstLogical, first, second);
840 emit sectionMoved(secondLogical, second, first);
842 if (stretchLastSection()) {
843 const int lastSectionVisualIdx = visualIndex(d->lastSectionLogicalIdx);
844 if (first >= lastSectionVisualIdx || second >= lastSectionVisualIdx)
845 d->maybeRestorePrevLastSectionAndStretchLast();
860void QHeaderView::resizeSection(
int logical,
int size)
863 if (logical < 0 || logical >= count() || size < 0 || size > maxSizeSection)
866 if (d->noSectionMemoryUsage())
867 d->switchToFlexibleModeWithSectionMemoryUsage();
871 size = qBound(minimumSectionSize(), size, maximumSectionSize());
873 if (isSectionHidden(logical)) {
874 d->hiddenSectionSize.insert(logical, size);
878 int visual = visualIndex(logical);
882 if (d->state == QHeaderViewPrivate::ResizeSection && !d->cascadingResizing && logical != d->section)
883 d->preventCursorChangeInSetOffset =
true;
885 int oldSize = d->headerSectionSize(visual);
889 d->executePostedLayout();
890 d->invalidateCachedSizeHint();
892 if (stretchLastSection() && logical == d->lastSectionLogicalIdx)
893 d->lastSectionSize = size;
895 d->createSectionItems(visual, visual, size, d->headerSectionResizeMode(visual));
897 if (!updatesEnabled()) {
898 if (d->hasAutoResizeSections())
899 d->doDelayedResizeSections();
900 emit sectionResized(logical, oldSize, size);
904 int w = d->viewport->width();
905 int h = d->viewport->height();
906 int pos = sectionViewportPosition(logical);
908 if (d->orientation == Qt::Horizontal)
910 r.setRect(0, 0, pos + size, h);
912 r.setRect(pos, 0, w - pos, h);
914 r.setRect(0, pos, w, h - pos);
916 if (d->hasAutoResizeSections()) {
917 d->doDelayedResizeSections();
918 r = d->viewport->rect();
928 QAbstractScrollArea *parent = qobject_cast<QAbstractScrollArea *>(parentWidget());
929 if (parent && parent->sizeAdjustPolicy() == QAbstractScrollArea::AdjustToContents)
930 parent->updateGeometry();
932 d->viewport->update(r.normalized());
933 emit sectionResized(logical, oldSize, size);
1005void QHeaderView::setSectionHidden(
int logicalIndex,
bool hide)
1008 if (logicalIndex < 0 || logicalIndex >= count())
1011 if (hide && d->noSectionMemoryUsage())
1012 d->switchToFlexibleModeWithSectionMemoryUsage();
1014 d->executePostedLayout();
1015 int visual = visualIndex(logicalIndex);
1016 Q_ASSERT(visual != -1);
1017 if (hide == d->isVisualIndexHidden(visual))
1020 const bool isHidingLastSection = (stretchLastSection() && logicalIndex == d->lastSectionLogicalIdx);
1021 if (isHidingLastSection)
1022 d->restoreSizeOnPrevLastSection();
1023 int size = d->headerSectionSize(visual);
1024 if (!d->hasAutoResizeSections())
1025 resizeSection(logicalIndex, 0);
1026 d->hiddenSectionSize.insert(logicalIndex, size);
1027 d->setVisualIndexHidden(visual,
true);
1028 if (isHidingLastSection)
1029 d->setNewLastSection(d->lastVisibleVisualIndex());
1030 if (d->hasAutoResizeSections())
1031 d->doDelayedResizeSections();
1033 int size = d->hiddenSectionSize.value(logicalIndex, d->defaultSectionSize);
1034 d->hiddenSectionSize.remove(logicalIndex);
1035 d->setVisualIndexHidden(visual,
false);
1036 resizeSection(logicalIndex, size);
1038 const bool newLastSection = (stretchLastSection() && visual > visualIndex(d->lastSectionLogicalIdx));
1039 if (newLastSection) {
1040 d->restoreSizeOnPrevLastSection();
1041 d->setNewLastSection(visual);
1404void QHeaderView::setSortIndicator(
int logicalIndex, Qt::SortOrder order)
1409 int old = d->sortIndicatorSection;
1410 if (old == logicalIndex && order == d->sortIndicatorOrder)
1412 d->sortIndicatorSection = logicalIndex;
1413 d->sortIndicatorOrder = order;
1415 if (logicalIndex >= d->sectionCount()) {
1416 emit sortIndicatorChanged(logicalIndex, order);
1420 if (old != logicalIndex
1421 && ((logicalIndex >= 0 && sectionResizeMode(logicalIndex) == ResizeToContents)
1422 || old >= d->sectionCount() || (old >= 0 && sectionResizeMode(old) == ResizeToContents))) {
1424 d->viewport->update();
1426 if (old >= 0 && old != logicalIndex)
1428 if (logicalIndex >= 0)
1429 updateSection(logicalIndex);
1432 emit sortIndicatorChanged(logicalIndex, order);
1876void QHeaderView::headerDataChanged(Qt::Orientation orientation,
int logicalFirst,
int logicalLast)
1879 if (d->orientation != orientation)
1882 if (logicalFirst < 0 || logicalLast < 0 || logicalFirst >= count() || logicalLast >= count())
1885 d->invalidateCachedSizeHint();
1887 int firstVisualIndex = INT_MAX, lastVisualIndex = -1;
1889 for (
int section = logicalFirst; section <= logicalLast; ++section) {
1890 const int visual = visualIndex(section);
1891 firstVisualIndex = qMin(firstVisualIndex, visual);
1892 lastVisualIndex = qMax(lastVisualIndex, visual);
1895 d->executePostedResize();
1896 const int first = d->headerSectionPosition(firstVisualIndex),
1897 last = d->headerSectionPosition(lastVisualIndex)
1898 + d->headerSectionSize(lastVisualIndex);
1900 if (orientation == Qt::Horizontal) {
1901 d->viewport->update(first, 0, last - first, d->viewport->height());
1903 d->viewport->update(0, first, d->viewport->width(), last - first);
1945void QHeaderView::sectionsInserted(
const QModelIndex &parent,
1946 int logicalFirst,
int logicalLast)
1950 if (parent != d->root || d->modelSectionCount() == d->sectionCount())
1952 int oldCount = d->sectionCount();
1954 d->invalidateCachedSizeHint();
1956 if (d->state == QHeaderViewPrivate::ResizeSection)
1957 d->preventCursorChangeInSetOffset =
true;
1960 int insertAt = logicalFirst;
1961 int insertCount = logicalLast - logicalFirst + 1;
1964 if (d->sortIndicatorSection >= logicalFirst)
1965 d->sortIndicatorSection += insertCount;
1967 if (d->noSectionMemoryUsage()) {
1968 const int addedCount = logicalLast - logicalFirst + 1;
1969 d->updateCountInNoSectionItemsMode(d->countInNoSectionItemsMode + addedCount);
1973 bool lastSectionActualChange =
false;
1974 if (stretchLastSection()) {
1976 int visualIndexForStretch = d->lastSectionLogicalIdx;
1977 if (d->lastSectionLogicalIdx >= 0 && d->lastSectionLogicalIdx < d->visualIndices.size())
1978 visualIndexForStretch = d->visualIndices[d->lastSectionLogicalIdx];
1981 if (d->lastSectionLogicalIdx < 0 || insertAt >= visualIndexForStretch)
1982 lastSectionActualChange =
true;
1984 if (d->lastSectionLogicalIdx >= logicalFirst)
1985 d->lastSectionLogicalIdx += insertCount;
1988 QHeaderViewPrivate::SectionItem section(d->defaultSectionSize, d->globalResizeMode);
1989 d->sectionStartposRecalc =
true;
1991 if (d->sectionItems.isEmpty() || insertAt >= d->sectionItems.size()) {
1992 int insertLength = d->defaultSectionSize * insertCount;
1993 d->length += insertLength;
1994 d->sectionItems.insert(d->sectionItems.size(), insertCount, section);
1997 int insertLength = d->defaultSectionSize * insertCount;
1998 d->length += insertLength;
1999 d->sectionItems.insert(insertAt, insertCount, section);
2003 if (d->globalResizeMode == Stretch)
2004 d->stretchSections = d->sectionCount();
2005 else if (d->globalResizeMode == ResizeToContents)
2006 d->contentsSections = d->sectionCount();
2009 d->sectionSelected.clear();
2012 if (!d->visualIndices.isEmpty() && !d->logicalIndices.isEmpty()) {
2013 Q_ASSERT(d->visualIndices.size() == d->logicalIndices.size());
2014 int mappingCount = d->visualIndices.size();
2015 for (
int i = 0; i < mappingCount; ++i) {
2016 if (d->visualIndices.at(i) >= logicalFirst)
2017 d->visualIndices[i] += insertCount;
2018 if (d->logicalIndices.at(i) >= logicalFirst)
2019 d->logicalIndices[i] += insertCount;
2021 for (
int j = logicalFirst; j <= logicalLast; ++j) {
2022 d->visualIndices.insert(j, j);
2023 d->logicalIndices.insert(j, j);
2028 QHash<
int,
int> newHiddenSectionSize;
2029 for (QHash<
int,
int>::const_iterator it = d->hiddenSectionSize.cbegin(),
2030 end = d->hiddenSectionSize.cend(); it != end; ++it) {
2031 const int oldIndex = it.key();
2032 const int newIndex = (oldIndex < logicalFirst) ? oldIndex : oldIndex + insertCount;
2033 newHiddenSectionSize[newIndex] = it.value();
2035 d->hiddenSectionSize.swap(newHiddenSectionSize);
2037 d->doDelayedResizeSections();
2038 emit sectionCountChanged(oldCount, count());
2040 if (lastSectionActualChange)
2041 d->maybeRestorePrevLastSectionAndStretchLast();
2044 if (!d->hasAutoResizeSections())
2045 d->viewport->update();
2080void QHeaderViewPrivate::sectionsRemoved(
const QModelIndex &parent,
2081 int logicalFirst,
int logicalLast)
2086 if (qMin(logicalFirst, logicalLast) < 0
2087 || qMax(logicalLast, logicalFirst) >= sectionCount())
2089 int oldCount = q->count();
2090 int changeCount = logicalLast - logicalFirst + 1;
2092 if (state == QHeaderViewPrivate::ResizeSection)
2093 preventCursorChangeInSetOffset =
true;
2096 if (sortIndicatorSection >= logicalFirst) {
2097 if (sortIndicatorSection <= logicalLast)
2098 sortIndicatorSection = -1;
2100 sortIndicatorSection -= changeCount;
2103 if (noSectionMemoryUsage()) {
2104 updateCountInNoSectionItemsMode(countInNoSectionItemsMode - changeCount);
2108 updateHiddenSections(logicalFirst, logicalLast);
2110 if (visualIndices.isEmpty() && logicalIndices.isEmpty()) {
2112 removeSectionsFromSectionItems(logicalFirst, logicalLast);
2114 if (logicalFirst == logicalLast) {
2115 int l = logicalFirst;
2116 int visual = visualIndices.at(l);
2117 Q_ASSERT(sectionCount() == logicalIndices.size());
2118 for (
int v = 0; v < sectionCount(); ++v) {
2120 int logical = logicalIndices.at(v);
2121 --(visualIndices[logical]);
2123 if (logicalIndex(v) > l)
2124 --(logicalIndices[v]);
2126 logicalIndices.remove(visual);
2127 visualIndices.remove(l);
2129 removeSectionsFromSectionItems(visual, visual);
2131 sectionStartposRecalc =
true;
2132 for (
int u = 0; u < sectionItems.size(); ++u)
2133 sectionItems.at(u).tmpLogIdx = logicalIndices.at(u);
2134 for (
int v = sectionItems.size() - 1; v >= 0; --v) {
2135 if (logicalFirst <= sectionItems.at(v).tmpLogIdx && sectionItems.at(v).tmpLogIdx <= logicalLast)
2136 removeSectionsFromSectionItems(v, v);
2138 visualIndices.resize(sectionItems.size());
2139 logicalIndices.resize(sectionItems.size());
2140 int* visual_data = visualIndices.data();
2141 int* logical_data = logicalIndices.data();
2142 for (
int w = 0; w < sectionItems.size(); ++w) {
2143 int logindex = sectionItems.at(w).tmpLogIdx;
2144 if (logindex > logicalFirst)
2145 logindex -= changeCount;
2146 visual_data[logindex] = w;
2147 logical_data[w] = logindex;
2154 if (sectionCount() <= 0)
2156 invalidateCachedSizeHint();
2157 emit q->sectionCountChanged(oldCount, q->count());
2159 if (q->stretchLastSection()) {
2160 const bool lastSectionRemoved = lastSectionLogicalIdx >= logicalFirst && lastSectionLogicalIdx <= logicalLast;
2161 if (lastSectionRemoved)
2162 setNewLastSection(lastVisibleVisualIndex());
2164 lastSectionLogicalIdx = logicalIndex(lastVisibleVisualIndex());
2165 doDelayedResizeSections();
2195void QHeaderViewPrivate::sectionsAboutToBeChanged(
const QList<QPersistentModelIndex> &,
2196 QAbstractItemModel::LayoutChangeHint hint)
2198 if ((hint == QAbstractItemModel::VerticalSortHint && orientation == Qt::Horizontal) ||
2199 (hint == QAbstractItemModel::HorizontalSortHint && orientation == Qt::Vertical))
2202 if (noSectionMemoryUsage()) {
2212 if ((orientation == Qt::Horizontal && model->rowCount(root) == 0)
2213 || model->columnCount(root) == 0)
2216 layoutChangePersistentSections.clear();
2217 layoutChangePersistentSections.reserve(std::min(10,
int(sectionItems.size())));
2219 if (stretchLastSection && lastSectionLogicalIdx >= 0 && lastSectionLogicalIdx < sectionItems.size()) {
2220 const int visual = visualIndex(lastSectionLogicalIdx);
2221 if (visual >= 0 && visual < sectionItems.size()) {
2222 auto &itemRef = sectionItems[visual];
2223 if (itemRef.size != lastSectionSize) {
2224 length += lastSectionSize - itemRef.size;
2225 itemRef.size = lastSectionSize;
2229 for (
int i = 0; i < sectionItems.size(); ++i) {
2230 auto s = sectionItems.at(i);
2232 if (s.size == defaultSectionSize && !s.isHidden && s.resizeMode == globalResizeMode)
2235 const int logical = logicalIndex(i);
2237 s.size = hiddenSectionSize.value(logical);
2240 layoutChangePersistentSections.append({orientation == Qt::Horizontal
2241 ? model->index(0, logical, root)
2242 : model->index(logical, 0, root),
2247void QHeaderViewPrivate::sectionsChanged(
const QList<QPersistentModelIndex> &,
2248 QAbstractItemModel::LayoutChangeHint hint)
2250 if ((hint == QAbstractItemModel::VerticalSortHint && orientation == Qt::Horizontal) ||
2251 (hint == QAbstractItemModel::HorizontalSortHint && orientation == Qt::Vertical))
2257 const auto oldPersistentSections = layoutChangePersistentSections;
2258 layoutChangePersistentSections.clear();
2260 const int newCount = modelSectionCount();
2261 const int oldCount = sectionCount();
2262 if (newCount == 0) {
2265 emit q->sectionCountChanged(oldCount, 0);
2269 if (noSectionMemoryUsage()) {
2271 updateCountInNoSectionItemsMode(newCount);
2276 bool hasPersistantIndexes =
false;
2277 for (
const auto &item : oldPersistentSections) {
2278 if (item.index.isValid()) {
2279 hasPersistantIndexes =
true;
2294 if (!hasPersistantIndexes) {
2295 if (oldCount != newCount)
2296 q->initializeSections();
2301 if (newCount != oldCount) {
2302 const int min = qBound(0, oldCount, newCount - 1);
2303 q->initializeSections(min, newCount - 1);
2306 sectionItems.fill(SectionItem(defaultSectionSize, globalResizeMode), newCount);
2309 hiddenSectionSize.clear();
2311 for (
const auto &item : oldPersistentSections) {
2312 const auto &index = item.index;
2313 if (!index.isValid())
2316 const int newLogicalIndex = (orientation == Qt::Horizontal
2320 const int newVisualIndex = visualIndex(newLogicalIndex);
2321 if (newVisualIndex < sectionItems.size()) {
2322 auto &newSection = sectionItems[newVisualIndex];
2323 newSection = item.section;
2325 if (newSection.isHidden) {
2327 newSection.isHidden =
false;
2328 q->setSectionHidden(newLogicalIndex,
true);
2333 recalcSectionStartPos();
2334 length = headerLength();
2336 if (stretchLastSection) {
2338 lastSectionLogicalIdx = -1;
2339 maybeRestorePrevLastSectionAndStretchLast();
2381void QHeaderView::initializeSections(
int start,
int end)
2385 Q_ASSERT(start >= 0);
2388 d->invalidateCachedSizeHint();
2389 int oldCount = d->sectionCount();
2391 if (end + 1 < d->sectionCount()) {
2392 int newCount = end + 1;
2393 d->removeSectionsFromSectionItems(newCount, d->sectionCount() - 1);
2394 if (!d->hiddenSectionSize.isEmpty()) {
2395 if (oldCount - newCount > d->hiddenSectionSize.size()) {
2396 for (
int i = end + 1; i < d->sectionCount(); ++i)
2397 d->hiddenSectionSize.remove(i);
2399 QHash<
int,
int>::iterator it = d->hiddenSectionSize.begin();
2400 while (it != d->hiddenSectionSize.end()) {
2402 it = d->hiddenSectionSize.erase(it);
2410 int newSectionCount = end + 1;
2412 if (!d->logicalIndices.isEmpty()) {
2413 if (oldCount <= newSectionCount) {
2414 d->logicalIndices.resize(newSectionCount);
2415 d->visualIndices.resize(newSectionCount);
2416 for (
int i = oldCount; i < newSectionCount; ++i) {
2417 d->logicalIndices[i] = i;
2418 d->visualIndices[i] = i;
2422 for (
int i = 0; i < oldCount; ++i) {
2423 int v = d->logicalIndices.at(i);
2424 if (v < newSectionCount) {
2425 d->logicalIndices[j] = v;
2426 d->visualIndices[v] = j;
2430 d->logicalIndices.resize(newSectionCount);
2431 d->visualIndices.resize(newSectionCount);
2435 if (d->globalResizeMode == Stretch)
2436 d->stretchSections = newSectionCount;
2437 else if (d->globalResizeMode == ResizeToContents)
2438 d->contentsSections = newSectionCount;
2440 if (newSectionCount > oldCount)
2441 d->createSectionItems(start, end, d->defaultSectionSize, d->globalResizeMode);
2444 if (d->sectionCount() != oldCount)
2445 emit sectionCountChanged(oldCount, d->sectionCount());
2446 d->viewport->update();
2453void QHeaderView::currentChanged(
const QModelIndex ¤t,
const QModelIndex &old)
2457 if (d->orientation == Qt::Horizontal && current.column() != old.column()) {
2458 if (old.isValid() && old.parent() == d->root)
2459 d->viewport->update(QRect(sectionViewportPosition(old.column()), 0,
2460 sectionSize(old.column()), d->viewport->height()));
2461 if (current.isValid() && current.parent() == d->root)
2462 d->viewport->update(QRect(sectionViewportPosition(current.column()), 0,
2463 sectionSize(current.column()), d->viewport->height()));
2464 }
else if (d->orientation == Qt::Vertical && current.row() != old.row()) {
2465 if (old.isValid() && old.parent() == d->root)
2466 d->viewport->update(QRect(0, sectionViewportPosition(old.row()),
2467 d->viewport->width(), sectionSize(old.row())));
2468 if (current.isValid() && current.parent() == d->root)
2469 d->viewport->update(QRect(0, sectionViewportPosition(current.row()),
2470 d->viewport->width(), sectionSize(current.row())));
2531void QHeaderView::paintEvent(QPaintEvent *e)
2538 QPainter painter(d->viewport);
2539 const QPoint offset = d->scrollDelayOffset;
2540 QRect translatedEventRect = e->rect();
2541 translatedEventRect.translate(offset);
2545 if (d->orientation == Qt::Horizontal) {
2546 start = visualIndexAt(translatedEventRect.left());
2547 end = visualIndexAt(translatedEventRect.right());
2549 start = visualIndexAt(translatedEventRect.top());
2550 end = visualIndexAt(translatedEventRect.bottom());
2554 start = (start == -1 ? count() - 1 : start);
2555 end = (end == -1 ? 0 : end);
2557 start = (start == -1 ? 0 : start);
2558 end = (end == -1 ? count() - 1 : end);
2562 start = qMin(start, end);
2563 end = qMax(tmp, end);
2565 d->prepareSectionSelected();
2567 QRect currentSectionRect;
2568 const int width = d->viewport->width();
2569 const int height = d->viewport->height();
2570 const int rtlHorizontalOffset = d->reverse() ? 1 : 0;
2571 for (
int i = start; i <= end; ++i) {
2572 if (d->isVisualIndexHidden(i))
2575 const int logical = logicalIndex(i);
2576 if (d->orientation == Qt::Horizontal) {
2577 currentSectionRect.setRect(sectionViewportPosition(logical) + rtlHorizontalOffset,
2578 0, sectionSize(logical), height);
2580 currentSectionRect.setRect(0, sectionViewportPosition(logical),
2581 width, sectionSize(logical));
2583 currentSectionRect.translate(offset);
2585 QVariant variant = d->model->headerData(logical, d->orientation,
2587 if (variant.isValid() && variant.canConvert<QFont>()) {
2588 QFont sectionFont = qvariant_cast<QFont>(variant);
2589 painter.setFont(sectionFont);
2591 paintSection(&painter, currentSectionRect, logical);
2599 opt.state |= QStyle::State_Horizontal;
2600 if (currentSectionRect.left() > translatedEventRect.left()) {
2601 opt.rect = QRect(translatedEventRect.left(), 0,
2602 currentSectionRect.left() - translatedEventRect.left(), height);
2603 style()->drawControl(QStyle::CE_HeaderEmptyArea, &opt, &painter,
this);
2605 }
else if (currentSectionRect.right() < translatedEventRect.right()) {
2607 opt.state |= QStyle::State_Horizontal;
2608 opt.rect = QRect(currentSectionRect.right() + 1, 0,
2609 translatedEventRect.right() - currentSectionRect.right(), height);
2610 style()->drawControl(QStyle::CE_HeaderEmptyArea, &opt, &painter,
this);
2611 }
else if (currentSectionRect.bottom() < translatedEventRect.bottom()) {
2613 opt.state &= ~QStyle::State_Horizontal;
2614 opt.rect = QRect(0, currentSectionRect.bottom() + 1,
2615 width, height - currentSectionRect.bottom() - 1);
2616 style()->drawControl(QStyle::CE_HeaderEmptyArea, &opt, &painter,
this);
2621 for (
int a = 0, i = 0; i < d->sectionItems.count(); ++i) {
2622 QColor color((i & 4 ? 255 : 0), (i & 2 ? 255 : 0), (i & 1 ? 255 : 0));
2623 if (d->orientation == Qt::Horizontal)
2624 painter.fillRect(a - d->headerOffset, 0, d->sectionItems.at(i).size, 4, color);
2626 painter.fillRect(0, a - d->headerOffset, 4, d->sectionItems.at(i).size, color);
2627 a += d->sectionItems.at(i).size;
2637void QHeaderView::mousePressEvent(QMouseEvent *e)
2640 if (d->state != QHeaderViewPrivate::NoState || e->button() != Qt::LeftButton)
2642 int pos = d->orientation == Qt::Horizontal ? e->position().toPoint().x() : e->position().toPoint().y();
2643 int handle = d->sectionHandleAt(pos);
2644 d->originalSize = -1;
2646 d->firstPressed = d->pressed = logicalIndexAt(pos);
2647 if (d->clickableSections)
2648 emit sectionPressed(d->pressed);
2650 bool acceptMoveSection = d->movableSections;
2651 if (acceptMoveSection && d->pressed == 0 && !d->allowUserMoveOfSection0)
2652 acceptMoveSection =
false;
2654 if (acceptMoveSection) {
2656 d->section = d->pressed;
2657 if (d->section == -1)
2659 d->state = QHeaderViewPrivate::MoveSection;
2660 d->setupSectionIndicator(d->section, pos);
2661 }
else if (d->clickableSections && d->pressed != -1) {
2662 updateSection(d->pressed);
2663 d->state = QHeaderViewPrivate::SelectSections;
2665 }
else if (sectionResizeMode(handle) == Interactive) {
2666 d->originalSize = sectionSize(handle);
2667 d->state = QHeaderViewPrivate::ResizeSection;
2668 d->section = handle;
2669 d->preventCursorChangeInSetOffset =
false;
2675 d->clearCascadingSections();
2682void QHeaderView::mouseMoveEvent(QMouseEvent *e)
2685 const int pos = d->orientation == Qt::Horizontal ? e->position().toPoint().x() : e->position().toPoint().y();
2686 if (pos < 0 && d->state != QHeaderViewPrivate::SelectSections)
2688 if (e->buttons() == Qt::NoButton) {
2694 d->state = QHeaderViewPrivate::NoState;
2695 d->firstPressed = d->pressed = -1;
2698 case QHeaderViewPrivate::ResizeSection: {
2699 Q_ASSERT(d->originalSize != -1);
2700 if (d->cascadingResizing) {
2701 int delta = d->reverse() ? d->lastPos - pos : pos - d->lastPos;
2702 int visual = visualIndex(d->section);
2703 d->cascadingResize(visual, d->headerSectionSize(visual) + delta);
2705 int delta = d->reverse() ? d->firstPos - pos : pos - d->firstPos;
2706 int newsize = qBound(minimumSectionSize(), d->originalSize + delta, maximumSectionSize());
2707 resizeSection(d->section, newsize);
2712 case QHeaderViewPrivate::MoveSection: {
2713 if (d->shouldAutoScroll(e->position().toPoint())) {
2714 d->draggedPosition = e->pos() + d->offset();
2715 d->startAutoScroll();
2717 if (qAbs(pos - d->firstPos) >= QApplication::startDragDistance()
2719 || !d->sectionIndicator->isHidden()
2722 int visual = visualIndexAt(pos);
2725 if (visual == 0 && logicalIndex(0) == 0 && !d->allowUserMoveOfSection0)
2728 const int posThreshold = d->headerSectionPosition(visual) - d->headerOffset + d->headerSectionSize(visual) / 2;
2729 const int checkPos = d->reverse() ? d->viewport->width() - pos : pos;
2730 int moving = visualIndex(d->section);
2731 int oldTarget = d->target;
2732 if (visual < moving) {
2733 if (checkPos < posThreshold)
2734 d->target = d->logicalIndex(visual);
2736 d->target = d->logicalIndex(visual + 1);
2737 }
else if (visual > moving) {
2738 if (checkPos > posThreshold)
2739 d->target = d->logicalIndex(visual);
2741 d->target = d->logicalIndex(visual - 1);
2743 d->target = d->section;
2745 if (oldTarget != d->target || oldTarget == -1)
2746 d->updateSectionsBeforeAfter(d->target);
2747 d->updateSectionIndicator(d->section, pos);
2751 case QHeaderViewPrivate::SelectSections: {
2752 int logical = logicalIndexAt(qMax(-d->headerOffset, pos));
2753 if (logical == -1 && pos > 0)
2754 logical = logicalIndex(d->lastVisibleVisualIndex());
2755 if (logical == d->pressed)
2757 else if (d->pressed != -1)
2758 updateSection(d->pressed);
2759 d->pressed = logical;
2760 if (d->clickableSections && logical != -1) {
2761 emit sectionEntered(d->pressed);
2762 updateSection(d->pressed);
2766 case QHeaderViewPrivate::NoState: {
2768 int handle = d->sectionHandleAt(pos);
2769 bool hasCursor = testAttribute(Qt::WA_SetCursor);
2770 if (handle != -1 && (sectionResizeMode(handle) == Interactive)) {
2772 setCursor(d->orientation == Qt::Horizontal ? Qt::SplitHCursor : Qt::SplitVCursor);
2776#ifndef QT_NO_STATUSTIP
2777 int logical = logicalIndexAt(pos);
2780 statusTip = d->model->headerData(logical, d->orientation, Qt::StatusTipRole).toString();
2781 if (d->shouldClearStatusTip || !statusTip.isEmpty()) {
2782 QStatusTipEvent tip(statusTip);
2783 QCoreApplication::sendEvent(d->parent ? d->parent :
this, &tip);
2784 d->shouldClearStatusTip = !statusTip.isEmpty();
2800void QHeaderView::mouseReleaseEvent(QMouseEvent *e)
2803 int pos = d->orientation == Qt::Horizontal ? e->position().toPoint().x() : e->position().toPoint().y();
2805 case QHeaderViewPrivate::MoveSection:
2808 && !d->sectionIndicator->isHidden()
2811 int from = visualIndex(d->section);
2812 Q_ASSERT(from != -1);
2813 int to = visualIndex(d->target);
2815 moveSection(from, to);
2816 d->section = d->target = -1;
2817 d->updateSectionIndicator(d->section, pos);
2819 d->updateSectionsBeforeAfter(logicalIndex(from));
2823 case QHeaderViewPrivate::SelectSections:
2824 if (!d->clickableSections) {
2825 int section = logicalIndexAt(pos);
2826 updateSection(section);
2829 case QHeaderViewPrivate::NoState:
2830 if (d->clickableSections) {
2831 int section = logicalIndexAt(pos);
2832 if (section != -1 && section == d->firstPressed) {
2833 QRect firstPressedSectionRect;
2834 switch (d->orientation) {
2835 case Qt::Horizontal:
2836 firstPressedSectionRect.setRect(sectionViewportPosition(d->firstPressed),
2838 sectionSize(d->firstPressed),
2839 d->viewport->height());
2842 firstPressedSectionRect.setRect(0,
2843 sectionViewportPosition(d->firstPressed),
2844 d->viewport->width(),
2845 sectionSize(d->firstPressed));
2849 if (firstPressedSectionRect.contains(e->position().toPoint())) {
2850 d->flipSortIndicator(section);
2851 emit sectionClicked(section);
2854 if (d->pressed != -1)
2855 updateSection(d->pressed);
2858 case QHeaderViewPrivate::ResizeSection:
2859 d->originalSize = -1;
2860 d->clearCascadingSections();
2865 d->state = QHeaderViewPrivate::NoState;
2866 d->firstPressed = d->pressed = -1;
2899bool QHeaderView::viewportEvent(QEvent *e)
2902 switch (e->type()) {
2903#if QT_CONFIG(tooltip)
2904 case QEvent::ToolTip: {
2905 QHelpEvent *he =
static_cast<QHelpEvent*>(e);
2906 int logical = logicalIndexAt(he->pos());
2907 if (logical != -1) {
2908 QVariant variant = d->model->headerData(logical, d->orientation, Qt::ToolTipRole);
2909 if (variant.isValid()) {
2910 QToolTip::showText(he->globalPos(), variant.toString(),
this);
2916#if QT_CONFIG(whatsthis)
2917 case QEvent::QueryWhatsThis: {
2918 QHelpEvent *he =
static_cast<QHelpEvent*>(e);
2919 int logical = logicalIndexAt(he->pos());
2921 && d->model->headerData(logical, d->orientation, Qt::WhatsThisRole).isValid())
2924 case QEvent::WhatsThis: {
2925 QHelpEvent *he =
static_cast<QHelpEvent*>(e);
2926 int logical = logicalIndexAt(he->pos());
2927 if (logical != -1) {
2928 QVariant whatsthis = d->model->headerData(logical, d->orientation,
2930 if (whatsthis.isValid()) {
2931 QWhatsThis::showText(he->globalPos(), whatsthis.toString(),
this);
2937#if QT_CONFIG(statustip)
2938 case QEvent::StatusTip: {
2939 QHelpEvent *he =
static_cast<QHelpEvent*>(e);
2940 int logical = logicalIndexAt(he->pos());
2941 if (logical != -1) {
2942 QString statustip = d->model->headerData(logical, d->orientation,
2943 Qt::StatusTipRole).toString();
2944 if (!statustip.isEmpty())
2945 setStatusTip(statustip);
2949 case QEvent::Resize:
2950 case QEvent::FontChange:
2951 case QEvent::StyleChange:
2952 d->invalidateCachedSizeHint();
2955 case QEvent::Show: {
2956 QAbstractScrollArea *parent = qobject_cast<QAbstractScrollArea *>(parentWidget());
2957 if (parent && parent->isVisible())
2959 emit geometriesChanged();
2961 case QEvent::ContextMenu: {
2962 d->state = QHeaderViewPrivate::NoState;
2963 d->pressed = d->section = d->target = -1;
2964 d->updateSectionIndicator(d->section, -1);
2966 case QEvent::Wheel: {
2967 QAbstractScrollArea *asa = qobject_cast<QAbstractScrollArea *>(parentWidget());
2969 return QCoreApplication::sendEvent(asa->viewport(), e);
2974 return QAbstractItemView::viewportEvent(e);
2988void QHeaderView::initStyleOptionForIndex(QStyleOptionHeader *option,
int logicalIndex)
const
2990 Q_D(
const QHeaderView);
2994 QStyleOptionHeader &opt = *option;
2995 QStyleOptionHeaderV2 *optV2 = qstyleoption_cast<QStyleOptionHeaderV2*>(option);
2997 QStyle::State state = QStyle::State_None;
2998 if (window()->isActiveWindow())
2999 state |= QStyle::State_Active;
3000 if (d->clickableSections) {
3001 if (logicalIndex == d->hover)
3002 state |= QStyle::State_MouseOver;
3003 if (logicalIndex == d->pressed)
3004 state |= QStyle::State_Sunken;
3005 else if (d->highlightSelected) {
3006 if (d->sectionIntersectsSelection(logicalIndex))
3007 state |= QStyle::State_On;
3008 if (d->isSectionSelected(logicalIndex))
3009 state |= QStyle::State_Sunken;
3012 if (isSortIndicatorShown() && sortIndicatorSection() == logicalIndex)
3013 opt.sortIndicator = (sortIndicatorOrder() == Qt::AscendingOrder)
3014 ? QStyleOptionHeader::SortDown : QStyleOptionHeader::SortUp;
3017 QVariant textAlignment = d->model->headerData(logicalIndex, d->orientation,
3018 Qt::TextAlignmentRole);
3019 opt.section = logicalIndex;
3021 opt.textAlignment = textAlignment.isValid()
3022 ? QtPrivate::legacyFlagValueFromModelData<Qt::Alignment>(textAlignment)
3023 : d->defaultAlignment;
3025 opt.iconAlignment = Qt::AlignVCenter;
3026 opt.text = d->model->headerData(logicalIndex, d->orientation,
3027 Qt::DisplayRole).toString();
3029 const QVariant variant = d->model->headerData(logicalIndex, d->orientation,
3030 Qt::DecorationRole);
3031 opt.icon = qvariant_cast<QIcon>(variant);
3032 if (opt.icon.isNull())
3033 opt.icon = qvariant_cast<QPixmap>(variant);
3035 QVariant var = d->model->headerData(logicalIndex, d->orientation,
3037 if (var.isValid() && var.canConvert<QFont>())
3038 opt.fontMetrics = QFontMetrics(qvariant_cast<QFont>(var));
3040 optV2->textElideMode = d->textElideMode;
3042 QVariant foregroundBrush = d->model->headerData(logicalIndex, d->orientation,
3043 Qt::ForegroundRole);
3044 if (foregroundBrush.canConvert<QBrush>())
3045 opt.palette.setBrush(QPalette::ButtonText, qvariant_cast<QBrush>(foregroundBrush));
3047 QVariant backgroundBrush = d->model->headerData(logicalIndex, d->orientation,
3048 Qt::BackgroundRole);
3049 if (backgroundBrush.canConvert<QBrush>()) {
3050 opt.palette.setBrush(QPalette::Button, qvariant_cast<QBrush>(backgroundBrush));
3051 opt.palette.setBrush(QPalette::Window, qvariant_cast<QBrush>(backgroundBrush));
3055 int visual = visualIndex(logicalIndex);
3056 Q_ASSERT(visual != -1);
3057 bool first = d->isFirstVisibleSection(visual);
3058 bool last = d->isLastVisibleSection(visual);
3060 opt.position = QStyleOptionHeader::OnlyOneSection;
3062 opt.position = d->reverse() ? QStyleOptionHeader::End : QStyleOptionHeader::Beginning;
3064 opt.position = d->reverse() ? QStyleOptionHeader::Beginning : QStyleOptionHeader::End;
3066 opt.position = QStyleOptionHeader::Middle;
3067 opt.orientation = d->orientation;
3069 bool previousSelected = d->isSectionSelected(
this->logicalIndex(visual - 1));
3070 bool nextSelected = d->isSectionSelected(
this->logicalIndex(visual + 1));
3071 if (previousSelected && nextSelected)
3072 opt.selectedPosition = QStyleOptionHeader::NextAndPreviousAreSelected;
3073 else if (previousSelected)
3074 opt.selectedPosition = QStyleOptionHeader::PreviousIsSelected;
3075 else if (nextSelected)
3076 opt.selectedPosition = QStyleOptionHeader::NextIsSelected;
3078 opt.selectedPosition = QStyleOptionHeader::NotAdjacent;
3080 optV2->isSectionDragTarget = d->target == logicalIndex;
3090void QHeaderView::paintSection(QPainter *painter,
const QRect &rect,
int logicalIndex)
const
3092 if (!rect.isValid())
3095 QStyleOptionHeaderV2 opt;
3096 initStyleOption(&opt);
3098 QBrush oBrushButton = opt.palette.brush(QPalette::Button);
3099 QBrush oBrushWindow = opt.palette.brush(QPalette::Window);
3101 initStyleOptionForIndex(&opt, logicalIndex);
3105 QBrush nBrushButton = opt.palette.brush(QPalette::Button);
3106 QBrush nBrushWindow = opt.palette.brush(QPalette::Window);
3109 QPainterStateGuard psg(painter, QPainterStateGuard::InitialState::NoSave);
3110 if (oBrushButton != nBrushButton || oBrushWindow != nBrushWindow) {
3112 painter->setBrushOrigin(opt.rect.topLeft());
3116 style()->drawControl(QStyle::CE_Header, &opt, painter,
this);
3126QSize QHeaderView::sectionSizeFromContents(
int logicalIndex)
const
3128 Q_D(
const QHeaderView);
3129 Q_ASSERT(logicalIndex >= 0);
3134 QVariant variant = d->model->headerData(logicalIndex, d->orientation, Qt::SizeHintRole);
3135 if (variant.isValid())
3136 return qvariant_cast<QSize>(variant);
3139 QStyleOptionHeaderV2 opt;
3140 initStyleOption(&opt);
3141 opt.section = logicalIndex;
3142 QVariant var = d->model->headerData(logicalIndex, d->orientation,
3145 if (var.isValid() && var.canConvert<QFont>())
3146 fnt = qvariant_cast<QFont>(var);
3150 opt.fontMetrics = QFontMetrics(fnt);
3151 opt.text = d->model->headerData(logicalIndex, d->orientation,
3152 Qt::DisplayRole).toString();
3153 variant = d->model->headerData(logicalIndex, d->orientation, Qt::DecorationRole);
3154 opt.icon = qvariant_cast<QIcon>(variant);
3155 if (opt.icon.isNull())
3156 opt.icon = qvariant_cast<QPixmap>(variant);
3157 if (isSortIndicatorShown())
3158 opt.sortIndicator = QStyleOptionHeader::SortDown;
3159 return style()->sizeFromContents(QStyle::CT_HeaderSection, &opt, QSize(),
this);
3341QRegion QHeaderView::visualRegionForSelection(
const QItemSelection &selection)
const
3343 Q_D(
const QHeaderView);
3344 const int max = d->modelSectionCount();
3346 if (d->orientation == Qt::Horizontal) {
3347 int logicalLeft = max;
3348 int logicalRight = 0;
3350 if (d->visualIndices.empty()) {
3352 for (
const auto &r : selection) {
3353 if (r.parent().isValid() || !r.isValid())
3355 if (r.left() < logicalLeft)
3356 logicalLeft = r.left();
3357 if (r.right() > logicalRight)
3358 logicalRight = r.right();
3363 for (
const auto &r : selection) {
3364 if (r.parent().isValid() || !r.isValid())
3366 for (
int k = r.left(); k <= r.right(); ++k) {
3367 int visual = visualIndex(k);
3376 logicalLeft = logicalIndex(left);
3377 logicalRight = logicalIndex(right);
3380 if (logicalLeft < 0 || logicalLeft >= count() ||
3381 logicalRight < 0 || logicalRight >= count())
3384 int leftPos = sectionViewportPosition(logicalLeft);
3385 int rightPos = sectionViewportPosition(logicalRight);
3386 rightPos += sectionSize(logicalRight);
3387 return QRect(leftPos, 0, rightPos - leftPos, height());
3390 int logicalTop = max;
3391 int logicalBottom = 0;
3393 if (d->visualIndices.empty()) {
3395 for (
const auto &r : selection) {
3396 if (r.parent().isValid() || !r.isValid())
3398 if (r.top() < logicalTop)
3399 logicalTop = r.top();
3400 if (r.bottom() > logicalBottom)
3401 logicalBottom = r.bottom();
3407 for (
const auto &r : selection) {
3408 if (r.parent().isValid() || !r.isValid())
3410 for (
int k = r.top(); k <= r.bottom(); ++k) {
3411 int visual = visualIndex(k);
3416 if (visual > bottom)
3421 logicalTop = logicalIndex(top);
3422 logicalBottom = logicalIndex(bottom);
3425 if (logicalTop < 0 || logicalTop >= count() ||
3426 logicalBottom < 0 || logicalBottom >= count())
3429 int topPos = sectionViewportPosition(logicalTop);
3430 int bottomPos = sectionViewportPosition(logicalBottom) + sectionSize(logicalBottom);
3432 return QRect(0, topPos, width(), bottomPos - topPos);
3467void QHeaderViewPrivate::setupSectionIndicator(
int section,
int position)
3471 if (!sectionIndicator) {
3472 sectionIndicator =
new QLabel(viewport);
3477 int p = q->sectionViewportPosition(section);
3478 if (orientation == Qt::Horizontal) {
3479 w = q->sectionSize(section);
3480 h = viewport->height();
3482 w = viewport->width();
3483 h = q->sectionSize(section);
3486 sectionIndicator->resize(w, h);
3489 const qreal pixmapDevicePixelRatio = q->devicePixelRatio();
3490 QPixmap pm(QSize(w, h) * pixmapDevicePixelRatio);
3491 pm.setDevicePixelRatio(pixmapDevicePixelRatio);
3492 pm.fill(QColor(0, 0, 0, 45));
3493 QRect rect(0, 0, w, h);
3495 QPainter painter(&pm);
3496 const QVariant variant = model->headerData(section, orientation,
3498 if (variant.isValid() && variant.canConvert<QFont>()) {
3499 const QFont sectionFont = qvariant_cast<QFont>(variant);
3500 painter.setFont(sectionFont);
3502 painter.setFont(q->font());
3505 painter.setOpacity(0.75);
3506 q->paintSection(&painter, rect, section);
3510 sectionIndicator->setPixmap(pm);
3512 sectionIndicatorOffset = position - qMax(p, 0);
3667void QHeaderViewPrivate::resizeSections(QHeaderView::ResizeMode globalMode,
bool useGlobalMode)
3671 delayedResize.stop();
3673 executePostedLayout();
3675 if (noSectionMemoryUsage() && (hasAutoResizeSections() || globalMode != QHeaderView::Fixed))
3676 setHeaderMode(HeaderMode::FlexibleWithSectionMemoryUsage);
3678 if (sectionCount() == 0 )
3681 if (resizeRecursionBlock)
3683 resizeRecursionBlock =
true;
3685 invalidateCachedSizeHint();
3686 const int lastSectionVisualIdx = q->visualIndex(lastSectionLogicalIdx);
3689 int stretchSection = -1;
3690 if (stretchLastSection && !useGlobalMode)
3691 stretchSection = lastSectionVisualIdx;
3694 int lengthToStretch = (orientation == Qt::Horizontal ? viewport->width() : viewport->height());
3695 int numberOfStretchedSections = 0;
3696 QList<
int> section_sizes;
3697 for (
int i = 0; i < sectionCount(); ++i) {
3698 if (isVisualIndexHidden(i))
3701 QHeaderView::ResizeMode resizeMode;
3702 if (useGlobalMode && (i != stretchSection))
3703 resizeMode = globalMode;
3705 resizeMode = (i == stretchSection ? QHeaderView::Stretch : headerSectionResizeMode(i));
3707 if (resizeMode == QHeaderView::Stretch) {
3708 ++numberOfStretchedSections;
3709 section_sizes.append(headerSectionSize(i));
3714 int sectionSize = 0;
3715 if (resizeMode == QHeaderView::Interactive || resizeMode == QHeaderView::Fixed) {
3716 sectionSize = qBound(q->minimumSectionSize(), headerSectionSize(i), q->maximumSectionSize());
3718 int logicalIndex = q->logicalIndex(i);
3719 sectionSize = qMax(viewSectionSizeHint(logicalIndex),
3720 q->sectionSizeHint(logicalIndex));
3722 sectionSize = qBound(q->minimumSectionSize(),
3724 q->maximumSectionSize());
3726 section_sizes.append(sectionSize);
3727 lengthToStretch -= sectionSize;
3731 int stretchSectionLength = -1;
3732 int pixelReminder = 0;
3733 if (numberOfStretchedSections > 0 && lengthToStretch > 0) {
3734 int hintLengthForEveryStretchedSection = lengthToStretch / numberOfStretchedSections;
3735 stretchSectionLength = qMax(hintLengthForEveryStretchedSection, q->minimumSectionSize());
3736 pixelReminder = lengthToStretch % numberOfStretchedSections;
3740 int spanStartSection = 0;
3741 int previousSectionLength = 0;
3743 QHeaderView::ResizeMode previousSectionResizeMode = QHeaderView::Interactive;
3746 for (
int i = 0; i < sectionCount(); ++i) {
3747 int oldSectionLength = headerSectionSize(i);
3748 int newSectionLength = -1;
3749 QHeaderView::ResizeMode newSectionResizeMode = headerSectionResizeMode(i);
3751 if (isVisualIndexHidden(i)) {
3752 newSectionLength = 0;
3754 QHeaderView::ResizeMode resizeMode;
3756 resizeMode = globalMode;
3758 resizeMode = (i == stretchSection
3759 ? QHeaderView::Stretch
3760 : newSectionResizeMode);
3761 if (resizeMode == QHeaderView::Stretch && stretchSectionLength != -1) {
3762 if (i == lastSectionVisualIdx)
3763 newSectionLength = qMax(stretchSectionLength, lastSectionSize);
3765 newSectionLength = stretchSectionLength;
3766 if (pixelReminder > 0) {
3767 newSectionLength += 1;
3770 section_sizes.removeFirst();
3772 newSectionLength = section_sizes.takeFirst();
3777 if ((previousSectionResizeMode != newSectionResizeMode
3778 || previousSectionLength != newSectionLength) && i > 0) {
3779 createSectionItems(spanStartSection, i - 1, previousSectionLength, previousSectionResizeMode);
3781 spanStartSection = i;
3784 if (newSectionLength != oldSectionLength)
3785 emit q->sectionResized(logicalIndex(i), oldSectionLength, newSectionLength);
3787 previousSectionLength = newSectionLength;
3788 previousSectionResizeMode = newSectionResizeMode;
3791 createSectionItems(spanStartSection, sectionCount() - 1,
3792 previousSectionLength, previousSectionResizeMode);
3794 resizeRecursionBlock =
false;
3880void QHeaderViewPrivate::cascadingResize(
int visual,
int newSize)
3883 const int minimumSize = q->minimumSectionSize();
3884 const int oldSize = headerSectionSize(visual);
3885 int delta = newSize - oldSize;
3888 bool sectionResized =
false;
3891 for (
int i = firstCascadingSection; i < visual; ++i) {
3892 if (cascadingSectionSize.contains(i)) {
3893 int currentSectionSize = headerSectionSize(i);
3894 int originalSectionSize = cascadingSectionSize.value(i);
3895 if (currentSectionSize < originalSectionSize) {
3896 int newSectionSize = currentSectionSize + delta;
3897 resizeSectionItem(i, currentSectionSize, newSectionSize);
3898 if (newSectionSize >= originalSectionSize &&
false)
3899 cascadingSectionSize.remove(i);
3900 sectionResized =
true;
3908 if (!sectionResized) {
3909 newSize = qMax(newSize, minimumSize);
3910 if (oldSize != newSize)
3911 resizeSectionItem(visual, oldSize, newSize);
3915 for (
int i = visual + 1; i < sectionCount(); ++i) {
3916 if (isVisualIndexHidden(i))
3918 if (!sectionIsCascadable(i))
3920 int currentSectionSize = headerSectionSize(i);
3921 if (currentSectionSize <= minimumSize)
3923 int newSectionSize = qMax(currentSectionSize - delta, minimumSize);
3924 resizeSectionItem(i, currentSectionSize, newSectionSize);
3925 saveCascadingSectionSize(i, currentSectionSize);
3926 delta = delta - (currentSectionSize - newSectionSize);
3931 bool sectionResized =
false;
3934 for (
int i = lastCascadingSection; i > visual; --i) {
3935 if (!cascadingSectionSize.contains(i))
3937 int currentSectionSize = headerSectionSize(i);
3938 int originalSectionSize = cascadingSectionSize.value(i);
3939 if (currentSectionSize >= originalSectionSize)
3941 int newSectionSize = currentSectionSize - delta;
3942 resizeSectionItem(i, currentSectionSize, newSectionSize);
3943 if (newSectionSize >= originalSectionSize &&
false) {
3944 cascadingSectionSize.remove(i);
3946 sectionResized =
true;
3951 resizeSectionItem(visual, oldSize, qMax(newSize, minimumSize));
3954 if (delta < 0 && newSize < minimumSize) {
3955 for (
int i = visual - 1; i >= 0; --i) {
3956 if (isVisualIndexHidden(i))
3958 if (!sectionIsCascadable(i))
3960 int sectionSize = headerSectionSize(i);
3961 if (sectionSize <= minimumSize)
3963 resizeSectionItem(i, sectionSize, qMax(sectionSize + delta, minimumSize));
3964 saveCascadingSectionSize(i, sectionSize);
3970 if (!sectionResized) {
3971 for (
int i = visual + 1; i < sectionCount(); ++i) {
3972 if (isVisualIndexHidden(i))
3974 if (!sectionIsCascadable(i))
3976 int currentSectionSize = headerSectionSize(i);
3977 int newSectionSize = qMax(currentSectionSize - delta, minimumSize);
3978 resizeSectionItem(i, currentSectionSize, newSectionSize);
3984 if (hasAutoResizeSections())
3985 doDelayedResizeSections();
3990void QHeaderViewPrivate::setDefaultSectionSize(
int size)
3993 size = qBound(q->minimumSectionSize(), size, q->maximumSectionSize());
3994 executePostedLayout();
3995 invalidateCachedSizeHint();
3996 defaultSectionSize = size;
3997 customDefaultSectionSize =
true;
3998 if (state == QHeaderViewPrivate::ResizeSection)
3999 preventCursorChangeInSetOffset =
true;
4000 for (
int i = 0; i < sectionItems.size(); ++i) {
4001 QHeaderViewPrivate::SectionItem §ion = sectionItems[i];
4002 if (hiddenSectionSize.isEmpty() || !isVisualIndexHidden(i)) {
4005 const int newSize = (section.size == oldDefaultSectionSize || !section.size)
4008 if (newSize != section.size) {
4009 length += newSize - section.size;
4010 const int oldSectionSize = section.sectionSize();
4011 section.size = size;
4012 emit q->sectionResized(logicalIndex(i), oldSectionSize, size);
4017 sectionStartposRecalc =
true;
4018 if (hasAutoResizeSections())
4019 doDelayedResizeSections();
4022 if (noSectionMemoryUsage()) {
4023 length = countInNoSectionItemsMode * size;
4024 QAbstractItemView *parentView = qobject_cast<QAbstractItemView*>(q->parentWidget());
4026 parentView->viewport()->update();
4196void QHeaderViewPrivate::write(QDataStream &out)
const
4198 out <<
int(orientation);
4199 out <<
int(sortIndicatorOrder);
4200 out << sortIndicatorSection;
4201 out << sortIndicatorShown;
4203 out << visualIndices;
4204 out << logicalIndices;
4206 out << sectionsHiddenToBitVector();
4207 out << hiddenSectionSize;
4210 out << sectionCount();
4211 out << movableSections;
4212 out << clickableSections;
4213 out << highlightSelected;
4214 out << stretchLastSection;
4215 out << cascadingResizing;
4216 out << stretchSections;
4217 out << contentsSections;
4218 out << defaultSectionSize;
4219 out << minimumSectionSize;
4221 out <<
int(defaultAlignment);
4222 out <<
int(globalResizeMode);
4224 if (noSectionMemoryUsage()) {
4225 Q_ASSERT(sectionItems.isEmpty());
4226 out << QList<SectionItem>();
4229 out << sectionItems;
4232 out << resizeContentsPrecision;
4233 out << customDefaultSectionSize;
4234 out << lastSectionSize;
4235 out <<
int(sortIndicatorClearable);
4237 out << countInNoSectionItemsMode;
4238 out <<
int(headerMode);
4241bool QHeaderViewPrivate::read(QDataStream &in)
4244 int orient, order, align, global;
4245 int sortIndicatorSectionIn;
4246 bool sortIndicatorShownIn;
4248 QList<
int> visualIndicesIn;
4249 QList<
int> logicalIndicesIn;
4250 QHash<
int,
int> hiddenSectionSizeIn;
4251 bool movableSectionsIn;
4252 bool clickableSectionsIn;
4253 bool highlightSelectedIn;
4254 bool stretchLastSectionIn;
4255 bool cascadingResizingIn;
4256 int stretchSectionsIn;
4257 int contentsSectionsIn;
4258 int defaultSectionSizeIn;
4259 int minimumSectionSizeIn;
4260 QList<SectionItem> sectionItemsIn;
4265 in >> sortIndicatorSectionIn;
4266 in >> sortIndicatorShownIn;
4268 in >> visualIndicesIn;
4269 in >> logicalIndicesIn;
4271 QBitArray sectionHidden;
4272 in >> sectionHidden;
4273 in >> hiddenSectionSizeIn;
4276 int unusedSectionCount;
4277 in >> unusedSectionCount;
4279 if (in.status() != QDataStream::Ok || lengthIn < 0)
4282 in >> movableSectionsIn;
4283 in >> clickableSectionsIn;
4284 in >> highlightSelectedIn;
4285 in >> stretchLastSectionIn;
4286 in >> cascadingResizingIn;
4287 in >> stretchSectionsIn;
4288 in >> contentsSectionsIn;
4289 in >> defaultSectionSizeIn;
4290 in >> minimumSectionSizeIn;
4298 if (global < 0 || global > QHeaderView::ResizeToContents)
4302 if (align < 0 || align > Qt::AlignVertical_Mask)
4305 in >> sectionItemsIn;
4311 QList<SectionItem> newSectionItems;
4312 for (
int u = 0; u < sectionItemsIn.size(); ++u) {
4313 int count = sectionItemsIn.at(u).tmpDataStreamSectionCount;
4315 sectionItemsIn[u].size /= count;
4316 for (
int n = 0; n < count; ++n)
4317 newSectionItems.append(sectionItemsIn[u]);
4320 int sectionItemsLengthTotal = 0;
4321 for (
const SectionItem §ion : std::as_const(newSectionItems))
4322 sectionItemsLengthTotal += section.size;
4324 if (sectionItemsLengthTotal != lengthIn && newSectionItems.size() > 0)
4329 headerMode = HeaderMode::FlexibleWithSectionMemoryUsage;
4331 orientation =
static_cast<Qt::Orientation>(orient);
4332 sortIndicatorOrder =
static_cast<Qt::SortOrder>(order);
4333 sortIndicatorSection = sortIndicatorSectionIn;
4334 sortIndicatorShown = sortIndicatorShownIn;
4335 visualIndices = visualIndicesIn;
4336 logicalIndices = logicalIndicesIn;
4337 hiddenSectionSize = hiddenSectionSizeIn;
4340 movableSections = movableSectionsIn;
4341 clickableSections = clickableSectionsIn;
4342 highlightSelected = highlightSelectedIn;
4343 stretchLastSection = stretchLastSectionIn;
4344 cascadingResizing = cascadingResizingIn;
4345 stretchSections = stretchSectionsIn;
4346 contentsSections = contentsSectionsIn;
4347 defaultSectionSize = defaultSectionSizeIn;
4348 minimumSectionSize = minimumSectionSizeIn;
4350 defaultAlignment = Qt::Alignment(align);
4351 globalResizeMode =
static_cast<QHeaderView::ResizeMode>(global);
4353 sectionItems = newSectionItems;
4354 setHiddenSectionsFromBitVector(sectionHidden);
4355 recalcSectionStartPos();
4359 resizeContentsPrecision = tmpint;
4362 if (in >> tmpbool) {
4363 customDefaultSectionSize = tmpbool;
4364 if (!customDefaultSectionSize)
4365 updateDefaultSectionSizeFromStyle();
4368 lastSectionSize = -1;
4369 int inLastSectionSize;
4370 if (in >> inLastSectionSize)
4371 lastSectionSize = inLastSectionSize;
4373 lastSectionLogicalIdx = -1;
4374 if (stretchLastSection) {
4375 lastSectionLogicalIdx = q->logicalIndex(lastVisibleVisualIndex());
4376 doDelayedResizeSections();
4379 int inSortIndicatorClearable;
4380 if (in >> inSortIndicatorClearable)
4381 sortIndicatorClearable = inSortIndicatorClearable;
4383 in >> countInNoSectionItemsMode;
4386 if (!(in >> iHeaderMode)) {
4388 iHeaderMode =
static_cast<
int>(HeaderMode::FlexibleWithSectionMemoryUsage);
4391 const HeaderMode impMode =
static_cast<HeaderMode>(iHeaderMode);
4392 if (impMode == HeaderMode::FlexibleWithSectionMemoryUsage || impMode == HeaderMode::InitialNoSectionMemoryUsage) {
4393 headerMode = impMode;
4398 if (countInNoSectionItemsMode > 0 && sectionItems.isEmpty()) {
4399 headerMode = HeaderMode::InitialNoSectionMemoryUsage;
4401 else if (countInNoSectionItemsMode <= 0 && !sectionItems.isEmpty()) {
4402 headerMode = HeaderMode::FlexibleWithSectionMemoryUsage;
4406 headerMode = HeaderMode::FlexibleWithSectionMemoryUsage;
4412 const int currentCount = (orient == Qt::Horizontal ? model->columnCount(root) : model->rowCount(root));
4413 if (sectionItems.size() < currentCount) {
4415 if (noSectionMemoryUsage()) {
4416 countInNoSectionItemsMode = currentCount;
4417 length = defaultSectionSize * countInNoSectionItemsMode;
4420 if (!visualIndicesIn.isEmpty() && !logicalIndicesIn.isEmpty()) {
4421 for (
int i = sectionItems.size(); i < currentCount; ++i) {
4422 visualIndices.append(i);
4423 logicalIndices.append(i);
4426 const int insertCount = currentCount - sectionItems.size();
4427 const int insertLength = defaultSectionSizeIn * insertCount;
4428 lengthIn += insertLength;
4429 SectionItem section(defaultSectionSizeIn, globalResizeMode);
4430 sectionItems.insert(sectionItems.size(), insertCount, section);