Qt 6.x
The Qt SDK
Loading...
Searching...
No Matches
qheaderview.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#include "qheaderview.h"
5
7#include <qapplication.h>
8#include <qbitarray.h>
9#include <qbrush.h>
10#include <qdebug.h>
11#include <qevent.h>
12#include <qlist.h>
13#include <qpainter.h>
14#include <qscrollbar.h>
15#include <qstyle.h>
16#include <qstyleoption.h>
17#if QT_CONFIG(tooltip)
18#include <qtooltip.h>
19#endif
20#include <qvarlengtharray.h>
21#include <qvariant.h>
22#if QT_CONFIG(whatsthis)
23#include <qwhatsthis.h>
24#endif
25#include <private/qheaderview_p.h>
26#include <private/qabstractitemmodel_p.h>
27#include <private/qabstractitemdelegate_p.h>
28
29#ifndef QT_NO_DATASTREAM
30#include <qdatastream.h>
31#endif
32
34
35#ifndef QT_NO_DATASTREAM
37{
38 section.write(out);
39 return out;
40}
41
43{
44 section.read(in);
45 return in;
46}
47#endif // QT_NO_DATASTREAM
48
49static const int maxSizeSection = 1048575; // since section size is in a bitfield (uint 20). See qheaderview_p.h
50 // if this is changed then the docs in maximumSectionSize should be changed.
51
274{
275 Q_D(QHeaderView);
276 d->setDefaultValues(orientation);
277 initialize();
278}
279
284 Qt::Orientation orientation, QWidget *parent)
286{
287 Q_D(QHeaderView);
288 d->setDefaultValues(orientation);
289 initialize();
290}
291
297{
298}
299
304{
305 Q_D(QHeaderView);
306 setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
307 setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
308 setFrameStyle(NoFrame);
309 setFocusPolicy(Qt::NoFocus);
310 d->viewport->setMouseTracking(true);
311 d->viewport->setBackgroundRole(QPalette::Button);
312 d->textElideMode = Qt::ElideNone;
313 delete d->itemDelegate;
314}
315
320{
321 if (model == this->model())
322 return;
323 Q_D(QHeaderView);
324 d->layoutChangePersistentSections.clear();
325 if (d->model && d->model != QAbstractItemModelPrivate::staticEmptyModel()) {
326 if (d->orientation == Qt::Horizontal) {
327 QObject::disconnect(d->model, SIGNAL(columnsInserted(QModelIndex,int,int)),
328 this, SLOT(sectionsInserted(QModelIndex,int,int)));
329 QObject::disconnect(d->model, SIGNAL(columnsAboutToBeRemoved(QModelIndex,int,int)),
331 QObject::disconnect(d->model, SIGNAL(columnsRemoved(QModelIndex,int,int)),
332 this, SLOT(_q_sectionsRemoved(QModelIndex,int,int)));
333 QObject::disconnect(d->model, SIGNAL(columnsAboutToBeMoved(QModelIndex,int,int,QModelIndex,int)),
334 this, SLOT(_q_sectionsAboutToBeMoved(QModelIndex,int,int,QModelIndex,int)));
335 QObject::disconnect(d->model, SIGNAL(columnsMoved(QModelIndex,int,int,QModelIndex,int)),
336 this, SLOT(_q_sectionsMoved(QModelIndex,int,int,QModelIndex,int)));
337 } else {
339 this, SLOT(sectionsInserted(QModelIndex,int,int)));
342 QObject::disconnect(d->model, SIGNAL(rowsRemoved(QModelIndex,int,int)),
343 this, SLOT(_q_sectionsRemoved(QModelIndex,int,int)));
344 QObject::disconnect(d->model, SIGNAL(rowsAboutToBeMoved(QModelIndex,int,int,QModelIndex,int)),
345 this, SLOT(_q_sectionsAboutToBeMoved(QModelIndex,int,int,QModelIndex,int)));
346 QObject::disconnect(d->model, SIGNAL(rowsMoved(QModelIndex,int,int,QModelIndex,int)),
347 this, SLOT(_q_sectionsMoved(QModelIndex,int,int,QModelIndex,int)));
348 }
350 this, SLOT(headerDataChanged(Qt::Orientation,int,int)));
355 }
356
358 if (d->orientation == Qt::Horizontal) {
359 QObject::connect(model, SIGNAL(columnsInserted(QModelIndex,int,int)),
360 this, SLOT(sectionsInserted(QModelIndex,int,int)));
361 QObject::connect(model, SIGNAL(columnsAboutToBeRemoved(QModelIndex,int,int)),
363 QObject::connect(model, SIGNAL(columnsRemoved(QModelIndex,int,int)),
364 this, SLOT(_q_sectionsRemoved(QModelIndex,int,int)));
365 QObject::connect(model, SIGNAL(columnsAboutToBeMoved(QModelIndex,int,int,QModelIndex,int)),
366 this, SLOT(_q_sectionsAboutToBeMoved(QModelIndex,int,int,QModelIndex,int)));
367 QObject::connect(model, SIGNAL(columnsMoved(QModelIndex,int,int,QModelIndex,int)),
368 this, SLOT(_q_sectionsMoved(QModelIndex,int,int,QModelIndex,int)));
369 } else {
371 this, SLOT(sectionsInserted(QModelIndex,int,int)));
374 QObject::connect(model, SIGNAL(rowsRemoved(QModelIndex,int,int)),
375 this, SLOT(_q_sectionsRemoved(QModelIndex,int,int)));
376 QObject::connect(model, SIGNAL(rowsAboutToBeMoved(QModelIndex,int,int,QModelIndex,int)),
377 this, SLOT(_q_sectionsAboutToBeMoved(QModelIndex,int,int,QModelIndex,int)));
378 QObject::connect(model, SIGNAL(rowsMoved(QModelIndex,int,int,QModelIndex,int)),
379 this, SLOT(_q_sectionsMoved(QModelIndex,int,int,QModelIndex,int)));
380 }
382 this, SLOT(headerDataChanged(Qt::Orientation,int,int)));
387 }
388
392
393 // Users want to set sizes and modes before the widget is shown.
394 // Thus, we have to initialize when the model is set,
395 // and not lazily like we do in the other views.
397}
398
406{
407 Q_D(const QHeaderView);
408 return d->orientation;
409}
410
419{
420 Q_D(const QHeaderView);
421 return d->offset;
422}
423
432void QHeaderView::setOffset(int newOffset)
433{
434 Q_D(QHeaderView);
435 if (d->offset == (int)newOffset)
436 return;
437 int ndelta = d->offset - newOffset;
438 d->offset = newOffset;
439 if (d->orientation == Qt::Horizontal)
440 d->viewport->scroll(isRightToLeft() ? -ndelta : ndelta, 0);
441 else
442 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());
447 else
448 QCursor::setPos(cursorPos.x(), cursorPos.y() + ndelta);
449 d->firstPos += ndelta;
450 d->lastPos += ndelta;
451 }
452}
453
462void QHeaderView::setOffsetToSectionPosition(int visualSectionNumber)
463{
464 Q_D(QHeaderView);
465 if (visualSectionNumber > -1 && visualSectionNumber < d->sectionCount()) {
466 int position = d->headerSectionPosition(d->adjustedVisualIndex(visualSectionNumber));
468 }
469}
470
478{
479 Q_D(const QHeaderView);
480 int size = (d->orientation == Qt::Horizontal ? viewport()->width() : viewport()->height());
481 int position = length() - size;
483}
484
492{
493 Q_D(const QHeaderView);
494 d->executePostedLayout();
495 d->executePostedResize();
496 //Q_ASSERT(d->headerLength() == d->length);
497 return d->length;
498}
499
507{
508 Q_D(const QHeaderView);
509 if (d->cachedSizeHint.isValid())
510 return d->cachedSizeHint;
511 d->cachedSizeHint = QSize(0, 0); //reinitialize the cached size hint
512 const int sectionCount = count();
513
514 // get size hint for the first n sections
515 int i = 0;
516 for (int checked = 0; checked < 100 && i < sectionCount; ++i) {
517 if (isSectionHidden(i))
518 continue;
519 checked++;
521 d->cachedSizeHint = d->cachedSizeHint.expandedTo(hint);
522 }
523 // get size hint for the last n sections
524 i = qMax(i, sectionCount - 100 );
525 for (int j = sectionCount - 1, checked = 0; j >= i && checked < 100; --j) {
526 if (isSectionHidden(j))
527 continue;
528 checked++;
530 d->cachedSizeHint = d->cachedSizeHint.expandedTo(hint);
531 }
532 return d->cachedSizeHint;
533}
534
540{
541 bool actualChange = (v != isVisible());
542 QAbstractItemView::setVisible(v);
543 if (actualChange) {
544 QAbstractScrollArea *parent = qobject_cast<QAbstractScrollArea*>(parentWidget());
545 if (parent)
546 parent->updateGeometry();
547 }
548}
549
550
558int QHeaderView::sectionSizeHint(int logicalIndex) const
559{
560 Q_D(const QHeaderView);
562 return 0;
563 if (logicalIndex < 0 || logicalIndex >= count())
564 return -1;
565 QSize size;
566 QVariant value = d->model->headerData(logicalIndex, d->orientation, Qt::SizeHintRole);
567 if (value.isValid())
568 size = qvariant_cast<QSize>(value);
569 else
571 int hint = d->orientation == Qt::Horizontal ? size.width() : size.height();
573}
574
583{
584 Q_D(const QHeaderView);
585 int vposition = position;
586 d->executePostedLayout();
587 d->executePostedResize();
588 const int count = d->sectionCount();
589 if (count < 1)
590 return -1;
591
592 if (d->reverse())
593 vposition = d->viewport->width() - vposition - 1;
594 vposition += d->offset;
595
596 if (vposition > d->length)
597 return -1;
598 int visual = d->headerVisualIndexAt(vposition);
599 if (visual < 0)
600 return -1;
601
602 while (d->isVisualIndexHidden(visual)){
603 ++visual;
604 if (visual >= count)
605 return -1;
606 }
607 return visual;
608}
609
617{
618 const int visual = visualIndexAt(position);
619 if (visual > -1)
620 return logicalIndex(visual);
621 return -1;
622}
623
631int QHeaderView::sectionSize(int logicalIndex) const
632{
633 Q_D(const QHeaderView);
635 return 0;
636 if (logicalIndex < 0 || logicalIndex >= count())
637 return 0;
638 int visual = visualIndex(logicalIndex);
639 if (visual == -1)
640 return 0;
641 d->executePostedResize();
642 return d->headerSectionSize(visual);
643}
644
656int QHeaderView::sectionPosition(int logicalIndex) const
657{
658 Q_D(const QHeaderView);
659 int visual = visualIndex(logicalIndex);
660 // in some cases users may change the selections
661 // before we have a chance to do the layout
662 if (visual == -1)
663 return -1;
664 d->executePostedResize();
665 return d->headerSectionPosition(visual);
666}
667
676int QHeaderView::sectionViewportPosition(int logicalIndex) const
677{
678 Q_D(const QHeaderView);
679 if (logicalIndex >= count())
680 return -1;
682 if (position < 0)
683 return position; // the section was hidden
684 int offsetPosition = position - d->offset;
685 if (d->reverse())
686 return d->viewport->width() - (offsetPosition + sectionSize(logicalIndex));
687 return offsetPosition;
688}
689
708template<typename Container>
709static void qMoveRange(Container& c,
710 typename Container::size_type rangeStart,
711 typename Container::size_type rangeEnd,
712 typename Container::size_type targetPosition)
713{
714 Q_ASSERT(targetPosition <= c.size());
715 Q_ASSERT(targetPosition < rangeStart || targetPosition >= rangeEnd);
716
717 const bool forwardMove = targetPosition > rangeStart;
718 typename Container::size_type first = std::min(rangeStart, targetPosition);
719 typename Container::size_type mid = forwardMove ? rangeEnd : rangeStart;
720 typename Container::size_type last = forwardMove ? targetPosition + 1 : rangeEnd;
721 std::rotate(c.begin() + first, c.begin() + mid, c.begin() + last);
722}
723
730void QHeaderView::moveSection(int from, int to)
731{
732 Q_D(QHeaderView);
733
734 d->executePostedLayout();
735 if (from < 0 || from >= d->sectionCount() || to < 0 || to >= d->sectionCount())
736 return;
737
738 if (from == to) {
739 int logical = logicalIndex(from);
740 Q_ASSERT(logical != -1);
741 updateSection(logical);
742 return;
743 }
744
745 d->initializeIndexMapping();
746
747 int *visualIndices = d->visualIndices.data();
748 int *logicalIndices = d->logicalIndices.data();
749 int logical = logicalIndices[from];
750 int visual = from;
751
752 if (to > from) {
753 while (visual < to) {
754 visualIndices[logicalIndices[visual + 1]] = visual;
755 logicalIndices[visual] = logicalIndices[visual + 1];
756 ++visual;
757 }
758 } else {
759 while (visual > to) {
760 visualIndices[logicalIndices[visual - 1]] = visual;
761 logicalIndices[visual] = logicalIndices[visual - 1];
762 --visual;
763 }
764 }
765 visualIndices[logical] = to;
766 logicalIndices[to] = logical;
767
768 qMoveRange(d->sectionItems, from, from + 1, to);
769
770 d->sectionStartposRecalc = true;
771
772 if (d->hasAutoResizeSections())
773 d->doDelayedResizeSections();
774 d->viewport->update();
775
776 emit sectionMoved(logical, from, to);
777
778 if (stretchLastSection()) {
779 const int lastSectionVisualIdx = visualIndex(d->lastSectionLogicalIdx);
780 if (from >= lastSectionVisualIdx || to >= lastSectionVisualIdx)
781 d->maybeRestorePrevLastSectionAndStretchLast();
782 }
783}
784
792void QHeaderView::swapSections(int first, int second)
793{
794 Q_D(QHeaderView);
795
796 if (first == second)
797 return;
798 d->executePostedLayout();
799 if (first < 0 || first >= d->sectionCount() || second < 0 || second >= d->sectionCount())
800 return;
801
802 int firstSize = d->headerSectionSize(first);
803 ResizeMode firstMode = d->headerSectionResizeMode(first);
804 int firstLogical = d->logicalIndex(first);
805
806 int secondSize = d->headerSectionSize(second);
807 ResizeMode secondMode = d->headerSectionResizeMode(second);
808 int secondLogical = d->logicalIndex(second);
809
811 d->preventCursorChangeInSetOffset = true;
812
813 d->createSectionItems(second, second, firstSize, firstMode);
814 d->createSectionItems(first, first, secondSize, secondMode);
815
816 d->initializeIndexMapping();
817
818 d->visualIndices[firstLogical] = second;
819 d->logicalIndices[second] = firstLogical;
820
821 d->visualIndices[secondLogical] = first;
822 d->logicalIndices[first] = secondLogical;
823
824 if (!d->hiddenSectionSize.isEmpty()) {
825 bool firstHidden = d->isVisualIndexHidden(first);
826 bool secondHidden = d->isVisualIndexHidden(second);
827 d->setVisualIndexHidden(first, secondHidden);
828 d->setVisualIndexHidden(second, firstHidden);
829 }
830
831 d->viewport->update();
832 emit sectionMoved(firstLogical, first, second);
833 emit sectionMoved(secondLogical, second, first);
834
835 if (stretchLastSection()) {
836 const int lastSectionVisualIdx = visualIndex(d->lastSectionLogicalIdx);
837 if (first >= lastSectionVisualIdx || second >= lastSectionVisualIdx)
838 d->maybeRestorePrevLastSectionAndStretchLast();
839 }
840}
841
853void QHeaderView::resizeSection(int logical, int size)
854{
855 Q_D(QHeaderView);
856 if (logical < 0 || logical >= count() || size < 0 || size > maxSizeSection)
857 return;
858
859 // make sure to not exceed bounds when setting size programmatically
860 if (size > 0)
862
863 if (isSectionHidden(logical)) {
864 d->hiddenSectionSize.insert(logical, size);
865 return;
866 }
867
868 int visual = visualIndex(logical);
869 if (visual == -1)
870 return;
871
872 if (d->state == QHeaderViewPrivate::ResizeSection && !d->cascadingResizing && logical != d->section)
873 d->preventCursorChangeInSetOffset = true;
874
875 int oldSize = d->headerSectionSize(visual);
876 if (oldSize == size)
877 return;
878
879 d->executePostedLayout();
880 d->invalidateCachedSizeHint();
881
882 if (stretchLastSection() && logical == d->lastSectionLogicalIdx)
883 d->lastSectionSize = size;
884
885 d->createSectionItems(visual, visual, size, d->headerSectionResizeMode(visual));
886
887 if (!updatesEnabled()) {
888 if (d->hasAutoResizeSections())
889 d->doDelayedResizeSections();
890 emit sectionResized(logical, oldSize, size);
891 return;
892 }
893
894 int w = d->viewport->width();
895 int h = d->viewport->height();
896 int pos = sectionViewportPosition(logical);
897 QRect r;
898 if (d->orientation == Qt::Horizontal)
899 if (isRightToLeft())
900 r.setRect(0, 0, pos + size, h);
901 else
902 r.setRect(pos, 0, w - pos, h);
903 else
904 r.setRect(0, pos, w, h - pos);
905
906 if (d->hasAutoResizeSections()) {
907 d->doDelayedResizeSections();
908 r = d->viewport->rect();
909 }
910
911 // If the parent is a QAbstractScrollArea with QAbstractScrollArea::AdjustToContents
912 // then we want to change the geometry on that widget. Not doing it at once can/will
913 // cause scrollbars flicker as they would be shown at first but then removed.
914 // In the same situation it will also allow shrinking the whole view when stretchLastSection is set
915 // (It is default on QTreeViews - and it wouldn't shrink since the last stretch was made before the
916 // viewport was resized)
917
918 QAbstractScrollArea *parent = qobject_cast<QAbstractScrollArea *>(parentWidget());
919 if (parent && parent->sizeAdjustPolicy() == QAbstractScrollArea::AdjustToContents)
920 parent->updateGeometry();
921
922 d->viewport->update(r.normalized());
923 emit sectionResized(logical, oldSize, size);
924}
925
934{
935 Q_D(QHeaderView);
936 d->resizeSections(mode, true);
937}
938
962bool QHeaderView::isSectionHidden(int logicalIndex) const
963{
964 Q_D(const QHeaderView);
965 d->executePostedLayout();
966 if (d->hiddenSectionSize.isEmpty() || logicalIndex < 0 || logicalIndex >= d->sectionCount())
967 return false;
968 int visual = visualIndex(logicalIndex);
969 Q_ASSERT(visual != -1);
970 return d->isVisualIndexHidden(visual);
971}
972
981{
982 Q_D(const QHeaderView);
983 return d->hiddenSectionSize.size();
984}
985
993void QHeaderView::setSectionHidden(int logicalIndex, bool hide)
994{
995 Q_D(QHeaderView);
996 if (logicalIndex < 0 || logicalIndex >= count())
997 return;
998
999 d->executePostedLayout();
1000 int visual = visualIndex(logicalIndex);
1001 Q_ASSERT(visual != -1);
1002 if (hide == d->isVisualIndexHidden(visual))
1003 return;
1004 if (hide) {
1005 const bool isHidingLastSection = (stretchLastSection() && logicalIndex == d->lastSectionLogicalIdx);
1006 if (isHidingLastSection)
1007 d->restoreSizeOnPrevLastSection(); // Restore here/now to get the right restore size.
1008 int size = d->headerSectionSize(visual);
1009 if (!d->hasAutoResizeSections())
1011 d->hiddenSectionSize.insert(logicalIndex, size);
1012 d->setVisualIndexHidden(visual, true);
1013 if (isHidingLastSection)
1014 d->setNewLastSection(d->lastVisibleVisualIndex());
1015 if (d->hasAutoResizeSections())
1016 d->doDelayedResizeSections();
1017 } else {
1018 int size = d->hiddenSectionSize.value(logicalIndex, d->defaultSectionSize);
1019 d->hiddenSectionSize.remove(logicalIndex);
1020 d->setVisualIndexHidden(visual, false);
1022
1023 const bool newLastSection = (stretchLastSection() && visual > visualIndex(d->lastSectionLogicalIdx));
1024 if (newLastSection) {
1025 d->restoreSizeOnPrevLastSection();
1026 d->setNewLastSection(visual);
1027 }
1028 }
1029}
1030
1038{
1039 Q_D(const QHeaderView);
1040 //Q_ASSERT(d->sectionCount == d->headerSectionCount());
1041 // ### this may affect the lazy layout
1042 d->executePostedLayout();
1043 return d->sectionCount();
1044}
1045
1055int QHeaderView::visualIndex(int logicalIndex) const
1056{
1057 Q_D(const QHeaderView);
1058 if (logicalIndex < 0)
1059 return -1;
1060 d->executePostedLayout();
1061 if (d->visualIndices.isEmpty()) { // nothing has been moved, so we have no mapping
1062 if (logicalIndex < d->sectionCount())
1063 return logicalIndex;
1064 } else if (logicalIndex < d->visualIndices.size()) {
1065 int visual = d->visualIndices.at(logicalIndex);
1066 Q_ASSERT(visual < d->sectionCount());
1067 return visual;
1068 }
1069 return -1;
1070}
1071
1081int QHeaderView::logicalIndex(int visualIndex) const
1082{
1083 Q_D(const QHeaderView);
1084 if (visualIndex < 0 || visualIndex >= d->sectionCount())
1085 return -1;
1086 return d->logicalIndex(visualIndex);
1087}
1088
1104{
1105 Q_D(QHeaderView);
1106 d->movableSections = movable;
1107}
1108
1122{
1123 Q_D(const QHeaderView);
1124 return d->movableSections;
1125}
1126
1152{
1153 Q_D(QHeaderView);
1154 d->allowUserMoveOfSection0 = movable;
1155}
1156
1158{
1159 Q_D(const QHeaderView);
1160 return d->allowUserMoveOfSection0;
1161}
1162
1173{
1174 Q_D(QHeaderView);
1175 d->clickableSections = clickable;
1176}
1177
1189{
1190 Q_D(const QHeaderView);
1191 return d->clickableSections;
1192}
1193
1195{
1196 Q_D(QHeaderView);
1197 d->highlightSelected = highlight;
1198}
1199
1201{
1202 Q_D(const QHeaderView);
1203 return d->highlightSelected;
1204}
1205
1216{
1217 Q_D(QHeaderView);
1219 d->stretchSections = (mode == Stretch ? count() : 0);
1220 d->contentsSections = (mode == ResizeToContents ? count() : 0);
1221 d->setGlobalHeaderResizeMode(mode);
1222 if (d->hasAutoResizeSections())
1223 d->doDelayedResizeSections(); // section sizes may change as a result of the new mode
1224}
1225
1241{
1242 Q_D(QHeaderView);
1243 int visual = visualIndex(logicalIndex);
1244 Q_ASSERT(visual != -1);
1245
1246 ResizeMode old = d->headerSectionResizeMode(visual);
1247 d->setHeaderSectionResizeMode(visual, mode);
1248
1249 if (mode == Stretch && old != Stretch)
1250 ++d->stretchSections;
1251 else if (mode == ResizeToContents && old != ResizeToContents)
1252 ++d->contentsSections;
1253 else if (mode != Stretch && old == Stretch)
1254 --d->stretchSections;
1255 else if (mode != ResizeToContents && old == ResizeToContents)
1256 --d->contentsSections;
1257
1258 if (d->hasAutoResizeSections() && d->state == QHeaderViewPrivate::NoState)
1259 d->doDelayedResizeSections(); // section sizes may change as a result of the new mode
1260}
1261
1272{
1273 Q_D(const QHeaderView);
1274 int visual = visualIndex(logicalIndex);
1275 if (visual == -1)
1276 return Fixed; //the default value
1277 return d->headerSectionResizeMode(visual);
1278}
1279
1303{
1304 Q_D(QHeaderView);
1305 d->resizeContentsPrecision = precision;
1306}
1307
1317{
1318 Q_D(const QHeaderView);
1319 return d->resizeContentsPrecision;
1320}
1321
1333{
1334 Q_D(const QHeaderView);
1335 return d->stretchSections;
1336}
1337
1348{
1349 Q_D(QHeaderView);
1350 if (d->sortIndicatorShown == show)
1351 return;
1352
1353 d->sortIndicatorShown = show;
1354
1356 return;
1357
1358 if (d->headerSectionResizeMode(sortIndicatorSection()) == ResizeToContents)
1360
1361 d->viewport->update();
1362}
1363
1365{
1366 Q_D(const QHeaderView);
1367 return d->sortIndicatorShown;
1368}
1369
1383{
1384 Q_D(QHeaderView);
1385
1386 // This is so that people can set the position of the sort indicator before the fill the model
1387 int old = d->sortIndicatorSection;
1388 if (old == logicalIndex && order == d->sortIndicatorOrder)
1389 return;
1390 d->sortIndicatorSection = logicalIndex;
1391 d->sortIndicatorOrder = order;
1392
1393 if (logicalIndex >= d->sectionCount()) {
1395 return; // nothing to do
1396 }
1397
1398 if (old != logicalIndex
1400 || old >= d->sectionCount() || (old >= 0 && sectionResizeMode(old) == ResizeToContents))) {
1402 d->viewport->update();
1403 } else {
1404 if (old >= 0 && old != logicalIndex)
1405 updateSection(old);
1406 if (logicalIndex >= 0)
1408 }
1409
1411}
1412
1421{
1422 Q_D(const QHeaderView);
1423 return d->sortIndicatorSection;
1424}
1425
1434{
1435 Q_D(const QHeaderView);
1436 return d->sortIndicatorOrder;
1437}
1438
1460{
1461 Q_D(QHeaderView);
1462 if (d->sortIndicatorClearable == clearable)
1463 return;
1464 d->sortIndicatorClearable = clearable;
1466}
1467
1469{
1470 Q_D(const QHeaderView);
1471 return d->sortIndicatorClearable;
1472}
1473
1490{
1491 Q_D(const QHeaderView);
1492 return d->stretchLastSection;
1493}
1494
1496{
1497 Q_D(QHeaderView);
1498 if (d->stretchLastSection == stretch)
1499 return;
1500 d->stretchLastSection = stretch;
1501 if (d->state != QHeaderViewPrivate::NoState)
1502 return;
1503 if (stretch) {
1504 d->setNewLastSection(d->lastVisibleVisualIndex());
1506 } else {
1507 d->restoreSizeOnPrevLastSection();
1508 }
1509}
1510
1526{
1527 Q_D(const QHeaderView);
1528 return d->cascadingResizing;
1529}
1530
1532{
1533 Q_D(QHeaderView);
1534 d->cascadingResizing = enable;
1535}
1536
1552{
1553 Q_D(const QHeaderView);
1554 return d->defaultSectionSize;
1555}
1556
1558{
1559 Q_D(QHeaderView);
1560 if (size < 0 || size > maxSizeSection)
1561 return;
1562 d->setDefaultSectionSize(size);
1563}
1564
1566{
1567 Q_D(QHeaderView);
1568 if (d->customDefaultSectionSize) {
1569 d->updateDefaultSectionSizeFromStyle();
1570 d->customDefaultSectionSize = false;
1571 }
1572}
1573
1588{
1589 Q_D(const QHeaderView);
1590 if (d->minimumSectionSize == -1) {
1591 int margin = 2 * style()->pixelMetric(QStyle::PM_HeaderMargin, nullptr, this);
1592 if (d->orientation == Qt::Horizontal)
1593 return fontMetrics().maxWidth() + margin;
1594 return fontMetrics().height() + margin;
1595 }
1596 return d->minimumSectionSize;
1597}
1598
1600{
1601 Q_D(QHeaderView);
1602 if (size < -1 || size > maxSizeSection)
1603 return;
1604 // larger new min size - check current section sizes
1605 const bool needSizeCheck = size > d->minimumSectionSize;
1606 d->minimumSectionSize = size;
1607 if (d->minimumSectionSize > maximumSectionSize())
1609
1610 if (needSizeCheck) {
1611 if (d->hasAutoResizeSections()) {
1612 d->doDelayedResizeSections();
1613 } else {
1614 for (int visual = 0; visual < d->sectionCount(); ++visual) {
1615 if (d->isVisualIndexHidden(visual))
1616 continue;
1617 if (d->headerSectionSize(visual) < d->minimumSectionSize)
1619 }
1620 }
1621 }
1622
1623}
1624
1640{
1641 Q_D(const QHeaderView);
1642 if (d->maximumSectionSize == -1)
1643 return maxSizeSection;
1644 return d->maximumSectionSize;
1645}
1646
1648{
1649 Q_D(QHeaderView);
1650 if (size == -1) {
1651 d->maximumSectionSize = maxSizeSection;
1652 return;
1653 }
1654 if (size < 0 || size > maxSizeSection)
1655 return;
1656 if (minimumSectionSize() > size)
1657 d->minimumSectionSize = size;
1658
1659 // smaller new max size - check current section sizes
1660 const bool needSizeCheck = size < d->maximumSectionSize;
1661 d->maximumSectionSize = size;
1662
1663 if (needSizeCheck) {
1664 if (d->hasAutoResizeSections()) {
1665 d->doDelayedResizeSections();
1666 } else {
1667 for (int visual = 0; visual < d->sectionCount(); ++visual) {
1668 if (d->isVisualIndexHidden(visual))
1669 continue;
1670 if (d->headerSectionSize(visual) > d->maximumSectionSize)
1672 }
1673 }
1674 }
1675}
1676
1677
1685{
1686 Q_D(const QHeaderView);
1687 return d->defaultAlignment;
1688}
1689
1691{
1692 Q_D(QHeaderView);
1693 if (d->defaultAlignment == alignment)
1694 return;
1695
1696 d->defaultAlignment = alignment;
1697 d->viewport->update();
1698}
1699
1704{
1707}
1708
1716{
1717 Q_D(const QHeaderView);
1718 return !d->visualIndices.isEmpty();
1719}
1720
1730{
1731 Q_D(const QHeaderView);
1732 return !d->hiddenSectionSize.isEmpty();
1733}
1734
1735#ifndef QT_NO_DATASTREAM
1746{
1747 Q_D(const QHeaderView);
1750 stream.setVersion(QDataStream::Qt_5_0);
1752 stream << 0; // current version is 0
1753 d->write(stream);
1754 return data;
1755}
1756
1766{
1767 Q_D(QHeaderView);
1768 if (state.isEmpty())
1769 return false;
1770
1771 for (const auto dataStreamVersion : {QDataStream::Qt_5_0, QDataStream::Qt_6_0}) {
1772
1775 stream.setVersion(dataStreamVersion);
1776 int marker;
1777 int ver;
1778 stream >> marker;
1779 stream >> ver;
1780 if (stream.status() != QDataStream::Ok
1782 || ver != 0) { // current version is 0
1783 return false;
1784 }
1785
1786 if (d->read(stream)) {
1787 emit sortIndicatorChanged(d->sortIndicatorSection, d->sortIndicatorOrder );
1788 d->viewport->update();
1789 return true;
1790 }
1791 }
1792 return false;
1793}
1794#endif // QT_NO_DATASTREAM
1795
1800{
1801 Q_D(QHeaderView);
1803 // it would be correct to call clear, but some apps rely
1804 // on the header keeping the sections, even after calling reset
1805 //d->clear();
1807 d->invalidateCachedSizeHint();
1808}
1809
1814void QHeaderView::headerDataChanged(Qt::Orientation orientation, int logicalFirst, int logicalLast)
1815{
1816 Q_D(QHeaderView);
1817 if (d->orientation != orientation)
1818 return;
1819
1820 if (logicalFirst < 0 || logicalLast < 0 || logicalFirst >= count() || logicalLast >= count())
1821 return;
1822
1823 d->invalidateCachedSizeHint();
1824
1825 int firstVisualIndex = INT_MAX, lastVisualIndex = -1;
1826
1827 for (int section = logicalFirst; section <= logicalLast; ++section) {
1828 const int visual = visualIndex(section);
1829 firstVisualIndex = qMin(firstVisualIndex, visual);
1830 lastVisualIndex = qMax(lastVisualIndex, visual);
1831 }
1832
1833 d->executePostedResize();
1834 const int first = d->headerSectionPosition(firstVisualIndex),
1835 last = d->headerSectionPosition(lastVisualIndex)
1836 + d->headerSectionSize(lastVisualIndex);
1837
1838 if (orientation == Qt::Horizontal) {
1839 d->viewport->update(first, 0, last - first, d->viewport->height());
1840 } else {
1841 d->viewport->update(0, first, d->viewport->width(), last - first);
1842 }
1843}
1844
1852void QHeaderView::updateSection(int logicalIndex)
1853{
1854 Q_D(QHeaderView);
1855 if (d->orientation == Qt::Horizontal)
1856 d->viewport->update(QRect(sectionViewportPosition(logicalIndex),
1857 0, sectionSize(logicalIndex), d->viewport->height()));
1858 else
1859 d->viewport->update(QRect(0, sectionViewportPosition(logicalIndex),
1860 d->viewport->width(), sectionSize(logicalIndex)));
1861}
1862
1869{
1870 Q_D(QHeaderView);
1871 if (d->hasAutoResizeSections())
1872 d->resizeSections(Interactive, false); // no global resize mode
1873}
1874
1885 int logicalFirst, int logicalLast)
1886{
1887 Q_D(QHeaderView);
1888 // only handle root level changes and return on no-op
1889 if (parent != d->root || d->modelSectionCount() == d->sectionCount())
1890 return;
1891 int oldCount = d->sectionCount();
1892
1893 d->invalidateCachedSizeHint();
1894
1896 d->preventCursorChangeInSetOffset = true;
1897
1898 // add the new sections
1899 int insertAt = logicalFirst;
1900 int insertCount = logicalLast - logicalFirst + 1;
1901
1902 bool lastSectionActualChange = false;
1903 if (stretchLastSection()) {
1904
1905 int visualIndexForStretch = d->lastSectionLogicalIdx;
1906 if (d->lastSectionLogicalIdx >= 0 && d->lastSectionLogicalIdx < d->visualIndices.size())
1907 visualIndexForStretch = d->visualIndices[d->lastSectionLogicalIdx]; // We cannot call visualIndex since it executes executePostedLayout()
1908 // and it is likely to bypass initializeSections() and we may end up here again. Doing the insert twice.
1909
1910 if (d->lastSectionLogicalIdx < 0 || insertAt >= visualIndexForStretch)
1911 lastSectionActualChange = true;
1912
1913 if (d->lastSectionLogicalIdx >= logicalFirst)
1914 d->lastSectionLogicalIdx += insertCount; // We do not want to emit resize before we have fixed the count
1915 }
1916
1917 QHeaderViewPrivate::SectionItem section(d->defaultSectionSize, d->globalResizeMode);
1918 d->sectionStartposRecalc = true;
1919
1920 if (d->sectionItems.isEmpty() || insertAt >= d->sectionItems.size()) {
1921 int insertLength = d->defaultSectionSize * insertCount;
1922 d->length += insertLength;
1923 d->sectionItems.insert(d->sectionItems.size(), insertCount, section); // append
1924 } else {
1925 // separate them out into their own sections
1926 int insertLength = d->defaultSectionSize * insertCount;
1927 d->length += insertLength;
1928 d->sectionItems.insert(insertAt, insertCount, section);
1929 }
1930
1931 // update sorting column
1932 if (d->sortIndicatorSection >= logicalFirst)
1933 d->sortIndicatorSection += insertCount;
1934
1935 // update resize mode section counts
1936 if (d->globalResizeMode == Stretch)
1937 d->stretchSections = d->sectionCount();
1938 else if (d->globalResizeMode == ResizeToContents)
1939 d->contentsSections = d->sectionCount();
1940
1941 // clear selection cache
1942 d->sectionSelected.clear();
1943
1944 // update mapping
1945 if (!d->visualIndices.isEmpty() && !d->logicalIndices.isEmpty()) {
1946 Q_ASSERT(d->visualIndices.size() == d->logicalIndices.size());
1947 int mappingCount = d->visualIndices.size();
1948 for (int i = 0; i < mappingCount; ++i) {
1949 if (d->visualIndices.at(i) >= logicalFirst)
1950 d->visualIndices[i] += insertCount;
1951 if (d->logicalIndices.at(i) >= logicalFirst)
1952 d->logicalIndices[i] += insertCount;
1953 }
1954 for (int j = logicalFirst; j <= logicalLast; ++j) {
1955 d->visualIndices.insert(j, j);
1956 d->logicalIndices.insert(j, j);
1957 }
1958 }
1959
1960 // insert sections into hiddenSectionSize
1961 QHash<int, int> newHiddenSectionSize; // from logical index to section size
1962 for (QHash<int, int>::const_iterator it = d->hiddenSectionSize.cbegin(),
1963 end = d->hiddenSectionSize.cend(); it != end; ++it) {
1964 const int oldIndex = it.key();
1965 const int newIndex = (oldIndex < logicalFirst) ? oldIndex : oldIndex + insertCount;
1966 newHiddenSectionSize[newIndex] = it.value();
1967 }
1968 d->hiddenSectionSize.swap(newHiddenSectionSize);
1969
1970 d->doDelayedResizeSections();
1971 emit sectionCountChanged(oldCount, count());
1972
1973 if (lastSectionActualChange)
1974 d->maybeRestorePrevLastSectionAndStretchLast();
1975
1976 // if the new sections were not updated by resizing, we need to update now
1977 if (!d->hasAutoResizeSections())
1978 d->viewport->update();
1979}
1980
1990 int logicalFirst, int logicalLast)
1991{
1993 Q_UNUSED(logicalFirst);
1994 Q_UNUSED(logicalLast);
1995}
1996
1997void QHeaderViewPrivate::updateHiddenSections(int logicalFirst, int logicalLast)
1998{
1999 Q_Q(QHeaderView);
2000 const int changeCount = logicalLast - logicalFirst + 1;
2001
2002 // remove sections from hiddenSectionSize
2003 QHash<int, int> newHiddenSectionSize; // from logical index to section size
2004 for (int i = 0; i < logicalFirst; ++i)
2005 if (q->isSectionHidden(i))
2006 newHiddenSectionSize[i] = hiddenSectionSize[i];
2007 for (int j = logicalLast + 1; j < sectionCount(); ++j)
2008 if (q->isSectionHidden(j))
2009 newHiddenSectionSize[j - changeCount] = hiddenSectionSize[j];
2010 hiddenSectionSize = newHiddenSectionSize;
2011}
2012
2014 int logicalFirst, int logicalLast)
2015{
2016 Q_Q(QHeaderView);
2017 if (parent != root)
2018 return; // we only handle changes in the root level
2019 if (qMin(logicalFirst, logicalLast) < 0
2020 || qMax(logicalLast, logicalFirst) >= sectionCount())
2021 return;
2022 int oldCount = q->count();
2023 int changeCount = logicalLast - logicalFirst + 1;
2024
2027
2028 updateHiddenSections(logicalFirst, logicalLast);
2029
2031 //Q_ASSERT(headerSectionCount() == sectionCount);
2032 removeSectionsFromSectionItems(logicalFirst, logicalLast);
2033 } else {
2034 if (logicalFirst == logicalLast) { // Remove just one index.
2035 int l = logicalFirst;
2036 int visual = visualIndices.at(l);
2038 for (int v = 0; v < sectionCount(); ++v) {
2039 if (v > visual) {
2040 int logical = logicalIndices.at(v);
2041 --(visualIndices[logical]);
2042 }
2043 if (logicalIndex(v) > l) // no need to move the positions before l
2044 --(logicalIndices[v]);
2045 }
2046 logicalIndices.remove(visual);
2048 //Q_ASSERT(headerSectionCount() == sectionCount);
2049 removeSectionsFromSectionItems(visual, visual);
2050 } else {
2051 sectionStartposRecalc = true; // We will need to recalc positions after removing items
2052 for (int u = 0; u < sectionItems.size(); ++u) // Store section info
2053 sectionItems.at(u).tmpLogIdx = logicalIndices.at(u);
2054 for (int v = sectionItems.size() - 1; v >= 0; --v) { // Remove the sections
2055 if (logicalFirst <= sectionItems.at(v).tmpLogIdx && sectionItems.at(v).tmpLogIdx <= logicalLast)
2057 }
2060 int* visual_data = visualIndices.data();
2061 int* logical_data = logicalIndices.data();
2062 for (int w = 0; w < sectionItems.size(); ++w) { // Restore visual and logical indexes
2063 int logindex = sectionItems.at(w).tmpLogIdx;
2064 if (logindex > logicalFirst)
2065 logindex -= changeCount;
2066 visual_data[logindex] = w;
2067 logical_data[w] = logindex;
2068 }
2069 }
2070 // ### handle sectionSelection (sectionHidden is handled by updateHiddenSections)
2071 }
2072
2073 // update sorting column
2074 if (sortIndicatorSection >= logicalFirst) {
2075 if (sortIndicatorSection <= logicalLast)
2077 else
2078 sortIndicatorSection -= changeCount;
2079 }
2080
2081 // if we only have the last section (the "end" position) left, the header is empty
2082 if (sectionCount() <= 0)
2083 clear();
2085 emit q->sectionCountChanged(oldCount, q->count());
2086
2087 if (q->stretchLastSection()) {
2088 const bool lastSectionRemoved = lastSectionLogicalIdx >= logicalFirst && lastSectionLogicalIdx <= logicalLast;
2089 if (lastSectionRemoved)
2091 else
2092 lastSectionLogicalIdx = logicalIndex(lastVisibleVisualIndex()); // Just update the last log index.
2094 }
2095
2096 viewport->update();
2097}
2098
2099void QHeaderViewPrivate::_q_sectionsAboutToBeMoved(const QModelIndex &sourceParent, int logicalStart, int logicalEnd, const QModelIndex &destinationParent, int logicalDestination)
2100{
2101 if (sourceParent != root || destinationParent != root)
2102 return; // we only handle changes in the root level
2103 Q_UNUSED(logicalStart);
2104 Q_UNUSED(logicalEnd);
2105 Q_UNUSED(logicalDestination);
2107}
2108
2109void QHeaderViewPrivate::_q_sectionsMoved(const QModelIndex &sourceParent, int logicalStart, int logicalEnd, const QModelIndex &destinationParent, int logicalDestination)
2110{
2111 if (sourceParent != root || destinationParent != root)
2112 return; // we only handle changes in the root level
2113 Q_UNUSED(logicalStart);
2114 Q_UNUSED(logicalEnd);
2115 Q_UNUSED(logicalDestination);
2117}
2118
2121{
2124 return;
2125
2126 //if there is no row/column we can't have mapping for columns
2127 //because no QModelIndex in the model would be valid
2128 // ### this is far from being bullet-proof and we would need a real system to
2129 // ### map columns or rows persistently
2130 if ((orientation == Qt::Horizontal && model->rowCount(root) == 0)
2131 || model->columnCount(root) == 0)
2132 return;
2133
2135 layoutChangePersistentSections.reserve(std::min(10, int(sectionItems.size())));
2136 // after layoutChanged another section can be last stretched section
2138 const int visual = visualIndex(lastSectionLogicalIdx);
2139 if (visual >= 0 && visual < sectionItems.size()) {
2140 auto &itemRef = sectionItems[visual];
2141 if (itemRef.size != lastSectionSize) {
2142 length += lastSectionSize - itemRef.size;
2143 itemRef.size = lastSectionSize;
2144 }
2145 }
2146 }
2147 for (int i = 0; i < sectionItems.size(); ++i) {
2148 auto s = sectionItems.at(i);
2149 // only add if the section is not default and not visually moved
2150 if (s.size == defaultSectionSize && !s.isHidden && s.resizeMode == globalResizeMode)
2151 continue;
2152
2153 const int logical = logicalIndex(i);
2154 if (s.isHidden)
2155 s.size = hiddenSectionSize.value(logical);
2156
2157 // ### note that we are using column or row 0
2159 ? model->index(0, logical, root)
2160 : model->index(logical, 0, root),
2161 s});
2162 }
2163}
2164
2167{
2170 return;
2171
2172 Q_Q(QHeaderView);
2173 viewport->update();
2174
2175 const auto oldPersistentSections = layoutChangePersistentSections;
2177
2178 const int newCount = modelSectionCount();
2179 const int oldCount = sectionItems.size();
2180 if (newCount == 0) {
2181 clear();
2182 if (oldCount != 0)
2183 emit q->sectionCountChanged(oldCount, 0);
2184 return;
2185 }
2186
2187 bool hasPersistantIndexes = false;
2188 for (const auto &item : oldPersistentSections) {
2189 if (item.index.isValid()) {
2190 hasPersistantIndexes = true;
2191 break;
2192 }
2193 }
2194
2195 // Though far from perfect we here try to retain earlier/existing behavior
2196 // ### See QHeaderViewPrivate::_q_layoutAboutToBeChanged()
2197 // When we don't have valid hasPersistantIndexes it can be due to
2198 // - all sections are default sections
2199 // - the row/column 0 which is used for persistent indexes is gone
2200 // - all non-default sections were removed
2201 // case one is trivial, in case two we assume nothing else changed (it's the best
2202 // guess we can do - everything else can not be handled correctly for now)
2203 // case three can not be handled correctly with layoutChanged - removeSections
2204 // should be used instead for this
2205 if (!hasPersistantIndexes) {
2206 if (oldCount != newCount)
2207 q->initializeSections();
2208 return;
2209 }
2210
2211 // adjust section size
2212 if (newCount != oldCount) {
2213 const int min = qBound(0, oldCount, newCount - 1);
2214 q->initializeSections(min, newCount - 1);
2215 }
2216 // reset sections
2218
2219 // all hidden sections are in oldPersistentSections
2221
2222 for (const auto &item : oldPersistentSections) {
2223 const auto &index = item.index;
2224 if (!index.isValid())
2225 continue;
2226
2227 const int newLogicalIndex = (orientation == Qt::Horizontal
2228 ? index.column()
2229 : index.row());
2230 // the new visualIndices are already adjusted / reset by initializeSections()
2231 const int newVisualIndex = visualIndex(newLogicalIndex);
2232 if (newVisualIndex < sectionItems.size()) {
2233 auto &newSection = sectionItems[newVisualIndex];
2234 newSection = item.section;
2235
2236 if (newSection.isHidden) {
2237 // otherwise setSectionHidden will return without doing anything
2238 newSection.isHidden = false;
2239 q->setSectionHidden(newLogicalIndex, true);
2240 }
2241 }
2242 }
2243
2245 length = headerLength();
2246
2247 if (stretchLastSection) {
2248 // force rebuild of stretched section later on
2251 }
2252}
2253
2259{
2260 Q_D(QHeaderView);
2261 const int oldCount = d->sectionCount();
2262 const int newCount = d->modelSectionCount();
2263 if (newCount <= 0) {
2264 d->clear();
2265 emit sectionCountChanged(oldCount, 0);
2266 } else if (newCount != oldCount) {
2267 const int min = qBound(0, oldCount, newCount - 1);
2268 initializeSections(min, newCount - 1);
2269 if (stretchLastSection()) // we've already gotten the size hint
2270 d->maybeRestorePrevLastSectionAndStretchLast();
2271
2272 // make sure we update the hidden sections
2273 // simulate remove from newCount to oldCount
2274 if (newCount < oldCount)
2275 d->updateHiddenSections(newCount, oldCount);
2276 }
2277}
2278
2284{
2285 Q_D(QHeaderView);
2286
2287 Q_ASSERT(start >= 0);
2288 Q_ASSERT(end >= 0);
2289
2290 d->invalidateCachedSizeHint();
2291 int oldCount = d->sectionCount();
2292
2293 if (end + 1 < d->sectionCount()) {
2294 int newCount = end + 1;
2295 d->removeSectionsFromSectionItems(newCount, d->sectionCount() - 1);
2296 if (!d->hiddenSectionSize.isEmpty()) {
2297 if (oldCount - newCount > d->hiddenSectionSize.size()) {
2298 for (int i = end + 1; i < d->sectionCount(); ++i)
2299 d->hiddenSectionSize.remove(i);
2300 } else {
2301 QHash<int, int>::iterator it = d->hiddenSectionSize.begin();
2302 while (it != d->hiddenSectionSize.end()) {
2303 if (it.key() > end)
2304 it = d->hiddenSectionSize.erase(it);
2305 else
2306 ++it;
2307 }
2308 }
2309 }
2310 }
2311
2312 int newSectionCount = end + 1;
2313
2314 if (!d->logicalIndices.isEmpty()) {
2315 if (oldCount <= newSectionCount) {
2316 d->logicalIndices.resize(newSectionCount);
2317 d->visualIndices.resize(newSectionCount);
2318 for (int i = oldCount; i < newSectionCount; ++i) {
2319 d->logicalIndices[i] = i;
2320 d->visualIndices[i] = i;
2321 }
2322 } else {
2323 int j = 0;
2324 for (int i = 0; i < oldCount; ++i) {
2325 int v = d->logicalIndices.at(i);
2326 if (v < newSectionCount) {
2327 d->logicalIndices[j] = v;
2328 d->visualIndices[v] = j;
2329 j++;
2330 }
2331 }
2332 d->logicalIndices.resize(newSectionCount);
2333 d->visualIndices.resize(newSectionCount);
2334 }
2335 }
2336
2337 if (d->globalResizeMode == Stretch)
2338 d->stretchSections = newSectionCount;
2339 else if (d->globalResizeMode == ResizeToContents)
2340 d->contentsSections = newSectionCount;
2341
2342 if (newSectionCount > oldCount)
2343 d->createSectionItems(start, end, d->defaultSectionSize, d->globalResizeMode);
2344 //Q_ASSERT(d->headerLength() == d->length);
2345
2346 if (d->sectionCount() != oldCount)
2347 emit sectionCountChanged(oldCount, d->sectionCount());
2348 d->viewport->update();
2349}
2350
2356{
2357 Q_D(QHeaderView);
2358
2359 if (d->orientation == Qt::Horizontal && current.column() != old.column()) {
2360 if (old.isValid() && old.parent() == d->root)
2361 d->viewport->update(QRect(sectionViewportPosition(old.column()), 0,
2362 sectionSize(old.column()), d->viewport->height()));
2363 if (current.isValid() && current.parent() == d->root)
2364 d->viewport->update(QRect(sectionViewportPosition(current.column()), 0,
2365 sectionSize(current.column()), d->viewport->height()));
2366 } else if (d->orientation == Qt::Vertical && current.row() != old.row()) {
2367 if (old.isValid() && old.parent() == d->root)
2368 d->viewport->update(QRect(0, sectionViewportPosition(old.row()),
2369 d->viewport->width(), sectionSize(old.row())));
2370 if (current.isValid() && current.parent() == d->root)
2371 d->viewport->update(QRect(0, sectionViewportPosition(current.row()),
2372 d->viewport->width(), sectionSize(current.row())));
2373 }
2374}
2375
2376
2382{
2383 Q_D(QHeaderView);
2384 switch (e->type()) {
2385 case QEvent::HoverEnter: {
2386 QHoverEvent *he = static_cast<QHoverEvent*>(e);
2387 d->hover = logicalIndexAt(he->position().toPoint());
2388 if (d->hover != -1)
2389 updateSection(d->hover);
2390 break; }
2391 case QEvent::Leave:
2392 case QEvent::HoverLeave: {
2393 if (d->hover != -1)
2394 updateSection(d->hover);
2395 d->hover = -1;
2396 break; }
2397 case QEvent::HoverMove: {
2398 QHoverEvent *he = static_cast<QHoverEvent*>(e);
2399 int oldHover = d->hover;
2400 d->hover = logicalIndexAt(he->position().toPoint());
2401 if (d->hover != oldHover) {
2402 if (oldHover != -1)
2403 updateSection(oldHover);
2404 if (d->hover != -1)
2405 updateSection(d->hover);
2406 }
2407 break; }
2408 case QEvent::Timer: {
2409 QTimerEvent *te = static_cast<QTimerEvent*>(e);
2410 if (te->timerId() == d->delayedResize.timerId()) {
2411 d->delayedResize.stop();
2413 }
2414 break; }
2416 if (!d->customDefaultSectionSize)
2417 d->updateDefaultSectionSizeFromStyle();
2418 break;
2419 default:
2420 break;
2421 }
2423}
2424
2430{
2431 Q_D(QHeaderView);
2432
2433 if (count() == 0)
2434 return;
2435
2436 QPainter painter(d->viewport);
2437 const QPoint offset = d->scrollDelayOffset;
2438 QRect translatedEventRect = e->rect();
2439 translatedEventRect.translate(offset);
2440
2441 int start = -1;
2442 int end = -1;
2443 if (d->orientation == Qt::Horizontal) {
2444 start = visualIndexAt(translatedEventRect.left());
2445 end = visualIndexAt(translatedEventRect.right());
2446 } else {
2447 start = visualIndexAt(translatedEventRect.top());
2448 end = visualIndexAt(translatedEventRect.bottom());
2449 }
2450
2451 if (d->reverse()) {
2452 start = (start == -1 ? count() - 1 : start);
2453 end = (end == -1 ? 0 : end);
2454 } else {
2455 start = (start == -1 ? 0 : start);
2456 end = (end == -1 ? count() - 1 : end);
2457 }
2458
2459 int tmp = start;
2460 start = qMin(start, end);
2461 end = qMax(tmp, end);
2462
2463 d->prepareSectionSelected(); // clear and resize the bit array
2464
2465 QRect currentSectionRect;
2466 const int width = d->viewport->width();
2467 const int height = d->viewport->height();
2468 const int rtlHorizontalOffset = d->reverse() ? 1 : 0;
2469 for (int i = start; i <= end; ++i) {
2470 if (d->isVisualIndexHidden(i))
2471 continue;
2472 painter.save();
2473 const int logical = logicalIndex(i);
2474 if (d->orientation == Qt::Horizontal) {
2475 currentSectionRect.setRect(sectionViewportPosition(logical) + rtlHorizontalOffset,
2476 0, sectionSize(logical), height);
2477 } else {
2478 currentSectionRect.setRect(0, sectionViewportPosition(logical),
2479 width, sectionSize(logical));
2480 }
2481 currentSectionRect.translate(offset);
2482
2483 QVariant variant = d->model->headerData(logical, d->orientation,
2484 Qt::FontRole);
2485 if (variant.isValid() && variant.canConvert<QFont>()) {
2486 QFont sectionFont = qvariant_cast<QFont>(variant);
2487 painter.setFont(sectionFont);
2488 }
2489 paintSection(&painter, currentSectionRect, logical);
2490 painter.restore();
2491 }
2492
2494 opt.initFrom(this);
2495 // Paint the area beyond where there are indexes
2496 if (d->reverse()) {
2498 if (currentSectionRect.left() > translatedEventRect.left()) {
2499 opt.rect = QRect(translatedEventRect.left(), 0,
2500 currentSectionRect.left() - translatedEventRect.left(), height);
2501 style()->drawControl(QStyle::CE_HeaderEmptyArea, &opt, &painter, this);
2502 }
2503 } else if (currentSectionRect.right() < translatedEventRect.right()) {
2504 // paint to the right
2506 opt.rect = QRect(currentSectionRect.right() + 1, 0,
2507 translatedEventRect.right() - currentSectionRect.right(), height);
2508 style()->drawControl(QStyle::CE_HeaderEmptyArea, &opt, &painter, this);
2509 } else if (currentSectionRect.bottom() < translatedEventRect.bottom()) {
2510 // paint the bottom section
2511 opt.state &= ~QStyle::State_Horizontal;
2512 opt.rect = QRect(0, currentSectionRect.bottom() + 1,
2513 width, height - currentSectionRect.bottom() - 1);
2514 style()->drawControl(QStyle::CE_HeaderEmptyArea, &opt, &painter, this);
2515 }
2516
2517#if 0
2518 // ### visualize sections
2519 for (int a = 0, i = 0; i < d->sectionItems.count(); ++i) {
2520 QColor color((i & 4 ? 255 : 0), (i & 2 ? 255 : 0), (i & 1 ? 255 : 0));
2521 if (d->orientation == Qt::Horizontal)
2522 painter.fillRect(a - d->offset, 0, d->sectionItems.at(i).size, 4, color);
2523 else
2524 painter.fillRect(0, a - d->offset, 4, d->sectionItems.at(i).size, color);
2525 a += d->sectionItems.at(i).size;
2526 }
2527
2528#endif
2529}
2530
2536{
2537 Q_D(QHeaderView);
2538 if (d->state != QHeaderViewPrivate::NoState || e->button() != Qt::LeftButton)
2539 return;
2540 int pos = d->orientation == Qt::Horizontal ? e->position().toPoint().x() : e->position().toPoint().y();
2541 int handle = d->sectionHandleAt(pos);
2542 d->originalSize = -1; // clear the stored original size
2543 if (handle == -1) {
2544 d->firstPressed = d->pressed = logicalIndexAt(pos);
2545 if (d->clickableSections)
2546 emit sectionPressed(d->pressed);
2547
2548 bool acceptMoveSection = d->movableSections;
2549 if (acceptMoveSection && d->pressed == 0 && !d->allowUserMoveOfSection0)
2550 acceptMoveSection = false; // Do not allow moving the tree nod
2551
2552 if (acceptMoveSection) {
2553 d->target = -1;
2554 d->section = d->pressed;
2555 if (d->section == -1)
2556 return;
2558 d->setupSectionIndicator(d->section, pos);
2559 } else if (d->clickableSections && d->pressed != -1) {
2560 updateSection(d->pressed);
2562 }
2563 } else if (sectionResizeMode(handle) == Interactive) {
2564 d->originalSize = sectionSize(handle);
2566 d->section = handle;
2567 d->preventCursorChangeInSetOffset = false;
2568 }
2569
2570 d->firstPos = pos;
2571 d->lastPos = pos;
2572
2573 d->clearCascadingSections();
2574}
2575
2581{
2582 Q_D(QHeaderView);
2583 const int pos = d->orientation == Qt::Horizontal ? e->position().toPoint().x() : e->position().toPoint().y();
2584 if (pos < 0 && d->state != QHeaderViewPrivate::SelectSections)
2585 return;
2586 if (e->buttons() == Qt::NoButton) {
2587 // Under Cocoa, when the mouse button is released, may include an extra
2588 // simulated mouse moved event. The state of the buttons when this event
2589 // is generated is already "no button" and the code below gets executed
2590 // just before the mouseReleaseEvent and resets the state. This prevents
2591 // column dragging from working. So this code is disabled under Cocoa.
2593 d->firstPressed = d->pressed = -1;
2594 }
2595 switch (d->state) {
2597 Q_ASSERT(d->originalSize != -1);
2598 if (d->cascadingResizing) {
2599 int delta = d->reverse() ? d->lastPos - pos : pos - d->lastPos;
2600 int visual = visualIndex(d->section);
2601 d->cascadingResize(visual, d->headerSectionSize(visual) + delta);
2602 } else {
2603 int delta = d->reverse() ? d->firstPos - pos : pos - d->firstPos;
2604 int newsize = qBound(minimumSectionSize(), d->originalSize + delta, maximumSectionSize());
2605 resizeSection(d->section, newsize);
2606 }
2607 d->lastPos = pos;
2608 return;
2609 }
2611 if (d->shouldAutoScroll(e->position().toPoint())) {
2612 d->draggedPosition = e->pos();
2613 d->startAutoScroll();
2614 }
2615 if (qAbs(pos - d->firstPos) >= QApplication::startDragDistance()
2616#if QT_CONFIG(label)
2617 || !d->sectionIndicator->isHidden()
2618#endif
2619 ) {
2620 int visual = visualIndexAt(pos);
2621 if (visual == -1)
2622 return;
2623 if (visual == 0 && logicalIndex(0) == 0 && !d->allowUserMoveOfSection0)
2624 return;
2625
2626 const int posThreshold = d->headerSectionPosition(visual) - d->offset + d->headerSectionSize(visual) / 2;
2627 const int checkPos = d->reverse() ? d->viewport->width() - pos : pos;
2628 int moving = visualIndex(d->section);
2629 int oldTarget = d->target;
2630 if (visual < moving) {
2631 if (checkPos < posThreshold)
2632 d->target = d->logicalIndex(visual);
2633 else
2634 d->target = d->logicalIndex(visual + 1);
2635 } else if (visual > moving) {
2636 if (checkPos > posThreshold)
2637 d->target = d->logicalIndex(visual);
2638 else
2639 d->target = d->logicalIndex(visual - 1);
2640 } else {
2641 d->target = d->section;
2642 }
2643 if (oldTarget != d->target || oldTarget == -1)
2644 d->updateSectionsBeforeAfter(d->target);
2645 d->updateSectionIndicator(d->section, pos);
2646 }
2647 return;
2648 }
2650 int logical = logicalIndexAt(qMax(-d->offset, pos));
2651 if (logical == -1 && pos > 0)
2652 logical = logicalIndex(d->lastVisibleVisualIndex());
2653 if (logical == d->pressed)
2654 return; // nothing to do
2655 else if (d->pressed != -1)
2656 updateSection(d->pressed);
2657 d->pressed = logical;
2658 if (d->clickableSections && logical != -1) {
2659 emit sectionEntered(d->pressed);
2660 updateSection(d->pressed);
2661 }
2662 return;
2663 }
2665#ifndef QT_NO_CURSOR
2666 int handle = d->sectionHandleAt(pos);
2667 bool hasCursor = testAttribute(Qt::WA_SetCursor);
2668 if (handle != -1 && (sectionResizeMode(handle) == Interactive)) {
2669 if (!hasCursor)
2671 } else {
2672 if (hasCursor)
2673 unsetCursor();
2674#ifndef QT_NO_STATUSTIP
2675 int logical = logicalIndexAt(pos);
2676 QString statusTip;
2677 if (logical != -1)
2678 statusTip = d->model->headerData(logical, d->orientation, Qt::StatusTipRole).toString();
2679 if (d->shouldClearStatusTip || !statusTip.isEmpty()) {
2680 QStatusTipEvent tip(statusTip);
2681 QCoreApplication::sendEvent(d->parent ? d->parent : this, &tip);
2682 d->shouldClearStatusTip = !statusTip.isEmpty();
2683 }
2684#endif // !QT_NO_STATUSTIP
2685 }
2686#endif
2687 return;
2688 }
2689 default:
2690 break;
2691 }
2692}
2693
2699{
2700 Q_D(QHeaderView);
2701 int pos = d->orientation == Qt::Horizontal ? e->position().toPoint().x() : e->position().toPoint().y();
2702 switch (d->state) {
2704 if (true
2705#if QT_CONFIG(label)
2706 && !d->sectionIndicator->isHidden()
2707#endif
2708 ) { // moving
2709 int from = visualIndex(d->section);
2710 Q_ASSERT(from != -1);
2711 int to = visualIndex(d->target);
2712 Q_ASSERT(to != -1);
2713 moveSection(from, to);
2714 d->section = d->target = -1;
2715 d->updateSectionIndicator(d->section, pos);
2716 if (from == to)
2717 d->updateSectionsBeforeAfter(from);
2718 break;
2719 } // not moving
2720 Q_FALLTHROUGH();
2722 if (!d->clickableSections) {
2723 int section = logicalIndexAt(pos);
2724 updateSection(section);
2725 }
2726 Q_FALLTHROUGH();
2728 if (d->clickableSections) {
2729 int section = logicalIndexAt(pos);
2730 if (section != -1 && section == d->firstPressed) {
2731 QRect firstPressedSectionRect;
2732 switch (d->orientation) {
2733 case Qt::Horizontal:
2734 firstPressedSectionRect.setRect(sectionViewportPosition(d->firstPressed),
2735 0,
2736 sectionSize(d->firstPressed),
2737 d->viewport->height());
2738 break;
2739 case Qt::Vertical:
2740 firstPressedSectionRect.setRect(0,
2741 sectionViewportPosition(d->firstPressed),
2742 d->viewport->width(),
2743 sectionSize(d->firstPressed));
2744 break;
2745 };
2746
2747 if (firstPressedSectionRect.contains(e->position().toPoint())) {
2748 d->flipSortIndicator(section);
2749 emit sectionClicked(section);
2750 }
2751 }
2752 if (d->pressed != -1)
2753 updateSection(d->pressed);
2754 }
2755 break;
2757 d->originalSize = -1;
2758 d->clearCascadingSections();
2759 break;
2760 default:
2761 break;
2762 }
2764 d->firstPressed = d->pressed = -1;
2765}
2766
2772{
2773 Q_D(QHeaderView);
2774 int pos = d->orientation == Qt::Horizontal ? e->position().toPoint().x() : e->position().toPoint().y();
2775 int handle = d->sectionHandleAt(pos);
2776 if (handle > -1 && sectionResizeMode(handle) == Interactive) {
2778#ifndef QT_NO_CURSOR
2779 Qt::CursorShape splitCursor = (d->orientation == Qt::Horizontal)
2781 if (cursor().shape() == splitCursor) {
2782 // signal handlers may have changed the section size
2783 handle = d->sectionHandleAt(pos);
2784 if (!(handle > -1 && sectionResizeMode(handle) == Interactive))
2786 }
2787#endif
2788 } else {
2789 emit sectionDoubleClicked(logicalIndexAt(e->position().toPoint()));
2790 }
2791}
2792
2798{
2799 Q_D(QHeaderView);
2800 switch (e->type()) {
2801#if QT_CONFIG(tooltip)
2802 case QEvent::ToolTip: {
2803 QHelpEvent *he = static_cast<QHelpEvent*>(e);
2804 int logical = logicalIndexAt(he->pos());
2805 if (logical != -1) {
2806 QVariant variant = d->model->headerData(logical, d->orientation, Qt::ToolTipRole);
2807 if (variant.isValid()) {
2809 return true;
2810 }
2811 }
2812 break; }
2813#endif
2814#if QT_CONFIG(whatsthis)
2816 QHelpEvent *he = static_cast<QHelpEvent*>(e);
2817 int logical = logicalIndexAt(he->pos());
2818 if (logical != -1
2819 && d->model->headerData(logical, d->orientation, Qt::WhatsThisRole).isValid())
2820 return true;
2821 break; }
2822 case QEvent::WhatsThis: {
2823 QHelpEvent *he = static_cast<QHelpEvent*>(e);
2824 int logical = logicalIndexAt(he->pos());
2825 if (logical != -1) {
2826 QVariant whatsthis = d->model->headerData(logical, d->orientation,
2828 if (whatsthis.isValid()) {
2829 QWhatsThis::showText(he->globalPos(), whatsthis.toString(), this);
2830 return true;
2831 }
2832 }
2833 break; }
2834#endif // QT_CONFIG(whatsthis)
2835#if QT_CONFIG(statustip)
2836 case QEvent::StatusTip: {
2837 QHelpEvent *he = static_cast<QHelpEvent*>(e);
2838 int logical = logicalIndexAt(he->pos());
2839 if (logical != -1) {
2840 QString statustip = d->model->headerData(logical, d->orientation,
2841 Qt::StatusTipRole).toString();
2842 if (!statustip.isEmpty())
2843 setStatusTip(statustip);
2844 }
2845 return true; }
2846#endif // QT_CONFIG(statustip)
2847 case QEvent::Resize:
2848 case QEvent::FontChange:
2850 d->invalidateCachedSizeHint();
2851 Q_FALLTHROUGH();
2852 case QEvent::Hide:
2853 case QEvent::Show: {
2854 QAbstractScrollArea *parent = qobject_cast<QAbstractScrollArea *>(parentWidget());
2855 if (parent && parent->isVisible()) // Only resize if we have a visible parent
2858 break;}
2859 case QEvent::ContextMenu: {
2861 d->pressed = d->section = d->target = -1;
2862 d->updateSectionIndicator(d->section, -1);
2863 break; }
2864 case QEvent::Wheel: {
2865 QAbstractScrollArea *asa = qobject_cast<QAbstractScrollArea *>(parentWidget());
2866 if (asa)
2867 return QCoreApplication::sendEvent(asa->viewport(), e);
2868 break; }
2869 default:
2870 break;
2871 }
2873}
2874
2887{
2888 Q_D(const QHeaderView);
2889
2890 if (!option)
2891 return;
2893 QStyleOptionHeaderV2 *optV2 = qstyleoption_cast<QStyleOptionHeaderV2*>(option);
2894
2895 QStyle::State state = QStyle::State_None;
2896 if (window()->isActiveWindow())
2898 if (d->clickableSections) {
2899 if (logicalIndex == d->hover)
2901 if (logicalIndex == d->pressed)
2903 else if (d->highlightSelected) {
2904 if (d->sectionIntersectsSelection(logicalIndex))
2906 if (d->isSectionSelected(logicalIndex))
2908 }
2909 }
2911 opt.sortIndicator = (sortIndicatorOrder() == Qt::AscendingOrder)
2913
2914 // setup the style options structure
2915 QVariant textAlignment = d->model->headerData(logicalIndex, d->orientation,
2917 opt.section = logicalIndex;
2918 opt.state |= state;
2919 opt.textAlignment = textAlignment.isValid()
2920 ? QtPrivate::legacyFlagValueFromModelData<Qt::Alignment>(textAlignment)
2921 : d->defaultAlignment;
2922
2923 opt.iconAlignment = Qt::AlignVCenter;
2924 opt.text = d->model->headerData(logicalIndex, d->orientation,
2925 Qt::DisplayRole).toString();
2926
2927 const QVariant variant = d->model->headerData(logicalIndex, d->orientation,
2929 opt.icon = qvariant_cast<QIcon>(variant);
2930 if (opt.icon.isNull())
2931 opt.icon = qvariant_cast<QPixmap>(variant);
2932
2933 QVariant var = d->model->headerData(logicalIndex, d->orientation,
2934 Qt::FontRole);
2935 if (var.isValid() && var.canConvert<QFont>())
2936 opt.fontMetrics = QFontMetrics(qvariant_cast<QFont>(var));
2937 if (optV2)
2938 optV2->textElideMode = d->textElideMode;
2939
2940 QVariant foregroundBrush = d->model->headerData(logicalIndex, d->orientation,
2942 if (foregroundBrush.canConvert<QBrush>())
2943 opt.palette.setBrush(QPalette::ButtonText, qvariant_cast<QBrush>(foregroundBrush));
2944
2945 QVariant backgroundBrush = d->model->headerData(logicalIndex, d->orientation,
2947 if (backgroundBrush.canConvert<QBrush>()) {
2948 opt.palette.setBrush(QPalette::Button, qvariant_cast<QBrush>(backgroundBrush));
2949 opt.palette.setBrush(QPalette::Window, qvariant_cast<QBrush>(backgroundBrush));
2950 }
2951
2952 // the section position
2953 int visual = visualIndex(logicalIndex);
2954 Q_ASSERT(visual != -1);
2955 bool first = d->isFirstVisibleSection(visual);
2956 bool last = d->isLastVisibleSection(visual);
2957 if (first && last)
2959 else if (first)
2961 else if (last)
2963 else
2965 opt.orientation = d->orientation;
2966 // the selected position
2967 bool previousSelected = d->isSectionSelected(this->logicalIndex(visual - 1));
2968 bool nextSelected = d->isSectionSelected(this->logicalIndex(visual + 1));
2969 if (previousSelected && nextSelected)
2971 else if (previousSelected)
2973 else if (nextSelected)
2974 opt.selectedPosition = QStyleOptionHeader::NextIsSelected;
2975 else
2976 opt.selectedPosition = QStyleOptionHeader::NotAdjacent;
2977 if (optV2)
2978 optV2->isSectionDragTarget = d->target == logicalIndex;
2979}
2980
2988void QHeaderView::paintSection(QPainter *painter, const QRect &rect, int logicalIndex) const
2989{
2990 if (!rect.isValid())
2991 return;
2992
2994 QPointF oldBO = painter->brushOrigin();
2995
2997
2998 QBrush oBrushButton = opt.palette.brush(QPalette::Button);
2999 QBrush oBrushWindow = opt.palette.brush(QPalette::Window);
3000
3002 // We set rect here. If it needs to be changed it can be changed by overriding this function
3003 opt.rect = rect;
3004
3005 QBrush nBrushButton = opt.palette.brush(QPalette::Button);
3006 QBrush nBrushWindow = opt.palette.brush(QPalette::Window);
3007
3008 // If relevant brushes are not the same as from the regular widgets we set the brush origin
3009 if (oBrushButton != nBrushButton || oBrushWindow != nBrushWindow) {
3011 }
3012
3013 // draw the section.
3014 style()->drawControl(QStyle::CE_Header, &opt, painter, this);
3015 painter->setBrushOrigin(oldBO);
3016}
3017
3026{
3027 Q_D(const QHeaderView);
3028 Q_ASSERT(logicalIndex >= 0);
3029
3030 ensurePolished();
3031
3032 // use SizeHintRole
3033 QVariant variant = d->model->headerData(logicalIndex, d->orientation, Qt::SizeHintRole);
3034 if (variant.isValid())
3035 return qvariant_cast<QSize>(variant);
3036
3037 // otherwise use the contents
3040 opt.section = logicalIndex;
3041 QVariant var = d->model->headerData(logicalIndex, d->orientation,
3042 Qt::FontRole);
3043 QFont fnt;
3044 if (var.isValid() && var.canConvert<QFont>())
3045 fnt = qvariant_cast<QFont>(var);
3046 else
3047 fnt = font();
3048 fnt.setBold(true);
3050 opt.text = d->model->headerData(logicalIndex, d->orientation,
3051 Qt::DisplayRole).toString();
3052 variant = d->model->headerData(logicalIndex, d->orientation, Qt::DecorationRole);
3053 opt.icon = qvariant_cast<QIcon>(variant);
3054 if (opt.icon.isNull())
3055 opt.icon = qvariant_cast<QPixmap>(variant);
3057 opt.sortIndicator = QStyleOptionHeader::SortDown;
3058 return style()->sizeFromContents(QStyle::CT_HeaderSection, &opt, QSize(), this);
3059}
3060
3069{
3070 Q_D(const QHeaderView);
3071 if (d->orientation == Qt::Horizontal)
3072 return d->offset;
3073 return 0;
3074}
3075
3084{
3085 Q_D(const QHeaderView);
3086 if (d->orientation == Qt::Vertical)
3087 return d->offset;
3088 return 0;
3089}
3090
3097{
3098 Q_D(QHeaderView);
3099 d->layoutChildren();
3100 if (d->hasAutoResizeSections())
3101 d->doDelayedResizeSections();
3102}
3103
3110{
3111 Q_D(QHeaderView);
3112 d->scrollDirtyRegion(dx, dy);
3113}
3114
3119void QHeaderView::dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight,
3120 const QList<int> &roles)
3121{
3122 Q_D(QHeaderView);
3123 if (!roles.isEmpty()) {
3124 const auto doesRoleAffectSize = [](int role) -> bool {
3125 switch (role) {
3126 case Qt::DisplayRole:
3127 case Qt::DecorationRole:
3128 case Qt::SizeHintRole:
3129 case Qt::FontRole:
3130 return true;
3131 default:
3132 // who knows what a subclass or custom style might do
3133 return role >= Qt::UserRole;
3134 }
3135 };
3136 if (std::none_of(roles.begin(), roles.end(), doesRoleAffectSize))
3137 return;
3138 }
3139 d->invalidateCachedSizeHint();
3140 if (d->hasAutoResizeSections()) {
3141 bool resizeRequired = d->globalResizeMode == ResizeToContents;
3142 int first = orientation() == Qt::Horizontal ? topLeft.column() : topLeft.row();
3143 int last = orientation() == Qt::Horizontal ? bottomRight.column() : bottomRight.row();
3144 for (int i = first; i <= last && !resizeRequired; ++i)
3145 resizeRequired = (sectionResizeMode(i) == ResizeToContents);
3146 if (resizeRequired)
3147 d->doDelayedResizeSections();
3148 }
3149}
3150
3158{
3159 // do nothing
3160}
3161
3170{
3171 return QRect();
3172}
3173
3182{
3183 // do nothing - the header only displays sections
3184}
3185
3194{
3195 return QModelIndex();
3196}
3197
3206{
3207 return true; // the header view has no items, just sections
3208}
3209
3218{
3219 return QModelIndex();
3220}
3221
3231void QHeaderView::setSelection(const QRect&, QItemSelectionModel::SelectionFlags)
3232{
3233 // do nothing
3234}
3235
3241{
3242 Q_D(const QHeaderView);
3243 const int max = d->modelSectionCount();
3244
3245 if (d->orientation == Qt::Horizontal) {
3246 int logicalLeft = max;
3247 int logicalRight = 0;
3248
3249 if (d->visualIndices.empty()) {
3250 // If no reordered sections, skip redundant visual-to-logical transformations
3251 for (const auto &r : selection) {
3252 if (r.parent().isValid() || !r.isValid())
3253 continue; // we only know about toplevel items and we don't want invalid ranges
3254 if (r.left() < logicalLeft)
3255 logicalLeft = r.left();
3256 if (r.right() > logicalRight)
3257 logicalRight = r.right();
3258 }
3259 } else {
3260 int left = max;
3261 int right = 0;
3262 for (const auto &r : selection) {
3263 if (r.parent().isValid() || !r.isValid())
3264 continue; // we only know about toplevel items and we don't want invalid ranges
3265 for (int k = r.left(); k <= r.right(); ++k) {
3266 int visual = visualIndex(k);
3267 if (visual == -1) // in some cases users may change the selections
3268 continue; // before we have a chance to do the layout
3269 if (visual < left)
3270 left = visual;
3271 if (visual > right)
3272 right = visual;
3273 }
3274 }
3275 logicalLeft = logicalIndex(left);
3276 logicalRight = logicalIndex(right);
3277 }
3278
3279 if (logicalLeft < 0 || logicalLeft >= count() ||
3280 logicalRight < 0 || logicalRight >= count())
3281 return QRegion();
3282
3283 int leftPos = sectionViewportPosition(logicalLeft);
3284 int rightPos = sectionViewportPosition(logicalRight);
3285 rightPos += sectionSize(logicalRight);
3286 return QRect(leftPos, 0, rightPos - leftPos, height());
3287 }
3288 // orientation() == Qt::Vertical
3289 int logicalTop = max;
3290 int logicalBottom = 0;
3291
3292 if (d->visualIndices.empty()) {
3293 // If no reordered sections, skip redundant visual-to-logical transformations
3294 for (const auto &r : selection) {
3295 if (r.parent().isValid() || !r.isValid())
3296 continue; // we only know about toplevel items and we don't want invalid ranges
3297 if (r.top() < logicalTop)
3298 logicalTop = r.top();
3299 if (r.bottom() > logicalBottom)
3300 logicalBottom = r.bottom();
3301 }
3302 } else {
3303 int top = max;
3304 int bottom = 0;
3305
3306 for (const auto &r : selection) {
3307 if (r.parent().isValid() || !r.isValid())
3308 continue; // we only know about toplevel items and we don't want invalid ranges
3309 for (int k = r.top(); k <= r.bottom(); ++k) {
3310 int visual = visualIndex(k);
3311 if (visual == -1) // in some cases users may change the selections
3312 continue; // before we have a chance to do the layout
3313 if (visual < top)
3314 top = visual;
3315 if (visual > bottom)
3316 bottom = visual;
3317 }
3318 }
3319
3320 logicalTop = logicalIndex(top);
3321 logicalBottom = logicalIndex(bottom);
3322 }
3323
3324 if (logicalTop < 0 || logicalTop >= count() ||
3325 logicalBottom < 0 || logicalBottom >= count())
3326 return QRegion();
3327
3328 int topPos = sectionViewportPosition(logicalTop);
3329 int bottomPos = sectionViewportPosition(logicalBottom) + sectionSize(logicalBottom);
3330
3331 return QRect(0, topPos, width(), bottomPos - topPos);
3332}
3333
3334
3335// private implementation
3336
3338{
3339 Q_Q(QHeaderView);
3340 int visual = q->visualIndexAt(position);
3341 if (visual == -1)
3342 return -1;
3343 int log = logicalIndex(visual);
3344 int pos = q->sectionViewportPosition(log);
3345 int grip = q->style()->pixelMetric(QStyle::PM_HeaderGripMargin, nullptr, q);
3346
3347 bool atLeft = position < pos + grip;
3348 bool atRight = (position > pos + q->sectionSize(log) - grip);
3349 if (reverse())
3350 qSwap(atLeft, atRight);
3351
3352 if (atLeft) {
3353 //grip at the beginning of the section
3354 while(visual > -1) {
3355 int logical = q->logicalIndex(--visual);
3356 if (!q->isSectionHidden(logical))
3357 return logical;
3358 }
3359 } else if (atRight) {
3360 //grip at the end of the section
3361 return log;
3362 }
3363 return -1;
3364}
3365
3367{
3368 Q_Q(QHeaderView);
3369#if QT_CONFIG(label)
3370 if (!sectionIndicator) {
3371 sectionIndicator = new QLabel(viewport);
3372 }
3373#endif
3374
3375 int w, h;
3376 int p = q->sectionViewportPosition(section);
3377 if (orientation == Qt::Horizontal) {
3378 w = q->sectionSize(section);
3379 h = viewport->height();
3380 } else {
3381 w = viewport->width();
3382 h = q->sectionSize(section);
3383 }
3384#if QT_CONFIG(label)
3385 sectionIndicator->resize(w, h);
3386#endif
3387
3388 const qreal pixmapDevicePixelRatio = q->devicePixelRatio();
3389 QPixmap pm(QSize(w, h) * pixmapDevicePixelRatio);
3390 pm.setDevicePixelRatio(pixmapDevicePixelRatio);
3391 pm.fill(QColor(0, 0, 0, 45));
3392 QRect rect(0, 0, w, h);
3393
3394 QPainter painter(&pm);
3396 Qt::FontRole);
3397 if (variant.isValid() && variant.canConvert<QFont>()) {
3398 const QFont sectionFont = qvariant_cast<QFont>(variant);
3399 painter.setFont(sectionFont);
3400 } else {
3401 painter.setFont(q->font());
3402 }
3403
3404 painter.setOpacity(0.75);
3405 q->paintSection(&painter, rect, section);
3406 painter.end();
3407
3408#if QT_CONFIG(label)
3409 sectionIndicator->setPixmap(pm);
3410#endif
3412}
3413
3415{
3416#if QT_CONFIG(label)
3417 if (!sectionIndicator)
3418 return;
3419
3420 if (section == -1 || target == -1) {
3421 sectionIndicator->hide();
3422 return;
3423 }
3424
3426 sectionIndicator->move(position - sectionIndicatorOffset, 0);
3427 else
3428 sectionIndicator->move(0, position - sectionIndicatorOffset);
3429
3430 sectionIndicator->show();
3431#endif
3432}
3433
3442{
3443 Q_D(const QHeaderView);
3444 option->initFrom(this);
3446 option->orientation = d->orientation;
3447 if (d->orientation == Qt::Horizontal)
3449 if (isEnabled())
3450 option->state |= QStyle::State_Enabled;
3451 option->section = 0;
3452}
3453
3455{
3456 // The QFrame version is only here to avoid compiler warnings.
3457 // If invoked we just pass it on to the base class.
3459}
3460
3462{
3463 int i = section * 2;
3464 if (i < 0 || i >= sectionSelected.size())
3465 return false;
3466 if (sectionSelected.testBit(i)) // if the value was cached
3467 return sectionSelected.testBit(i + 1);
3468 bool s = false;
3471 else
3473 sectionSelected.setBit(i + 1, s); // selection state
3474 sectionSelected.setBit(i, true); // cache state
3475 return s;
3476}
3477
3479{
3482 const SectionItem &item = sectionItems.at(section);
3483 return item.size > 0 && item.calculated_startpos == 0;
3484}
3485
3487{
3490 const SectionItem &item = sectionItems.at(section);
3491 return item.size > 0 && item.calculatedEndPos() == length;
3492}
3493
3499{
3500 Q_Q(const QHeaderView);
3501 for (int visual = q->count()-1; visual >= 0; --visual) {
3502 if (!q->isSectionHidden(q->logicalIndex(visual)))
3503 return visual;
3504 }
3505
3506 //default value if no section is actually visible
3507 return -1;
3508}
3509
3511{
3512 Q_Q(QHeaderView);
3513 if (lastSectionLogicalIdx < 0)
3514 return;
3515 int resizeLogIdx = lastSectionLogicalIdx;
3516 lastSectionLogicalIdx = -1; // We do not want resize to catch it as the last section.
3517 q->resizeSection(resizeLogIdx, lastSectionSize);
3518}
3519
3520void QHeaderViewPrivate::setNewLastSection(int visualIndexForLastSection)
3521{
3522 Q_Q(QHeaderView);
3523 lastSectionSize = -1;
3524 lastSectionLogicalIdx = q->logicalIndex(visualIndexForLastSection);
3525 lastSectionSize = headerSectionSize(visualIndexForLastSection); // pick size directly since ...
3526 // q->sectionSize(lastSectionLogicalIdx) may do delayed resize and stretch it before we get the value.
3527}
3528
3530{
3531 Q_Q(const QHeaderView);
3532 if (!q->stretchLastSection())
3533 return;
3534
3535 int nowLastVisualSection = lastVisibleVisualIndex();
3536 if (lastSectionLogicalIdx == q->logicalIndex(nowLastVisualSection))
3537 return;
3538
3539 // restore old last section.
3541 setNewLastSection(nowLastVisualSection);
3542 doDelayedResizeSections(); // Do stretch of last section soon (but not now).
3543}
3544
3545
3560{
3561 Q_Q(QHeaderView);
3562 //stop the timer in case it is delayed
3564
3566 if (sectionCount() == 0)
3567 return;
3568
3570 return;
3571 resizeRecursionBlock = true;
3572
3574 const int lastSectionVisualIdx = q->visualIndex(lastSectionLogicalIdx);
3575
3576 // find stretchLastSection if we have it
3577 int stretchSection = -1;
3578 if (stretchLastSection && !useGlobalMode)
3579 stretchSection = lastSectionVisualIdx;
3580
3581 // count up the number of stretched sections and how much space left for them
3582 int lengthToStretch = (orientation == Qt::Horizontal ? viewport->width() : viewport->height());
3583 int numberOfStretchedSections = 0;
3584 QList<int> section_sizes;
3585 for (int i = 0; i < sectionCount(); ++i) {
3587 continue;
3588
3589 QHeaderView::ResizeMode resizeMode;
3590 if (useGlobalMode && (i != stretchSection))
3591 resizeMode = globalMode;
3592 else
3593 resizeMode = (i == stretchSection ? QHeaderView::Stretch : headerSectionResizeMode(i));
3594
3595 if (resizeMode == QHeaderView::Stretch) {
3596 ++numberOfStretchedSections;
3597 section_sizes.append(headerSectionSize(i));
3598 continue;
3599 }
3600
3601 // because it isn't stretch, determine its width and remove that from lengthToStretch
3602 int sectionSize = 0;
3603 if (resizeMode == QHeaderView::Interactive || resizeMode == QHeaderView::Fixed) {
3604 sectionSize = qBound(q->minimumSectionSize(), headerSectionSize(i), q->maximumSectionSize());
3605 } else { // resizeMode == QHeaderView::ResizeToContents
3606 int logicalIndex = q->logicalIndex(i);
3607 sectionSize = qMax(viewSectionSizeHint(logicalIndex),
3608 q->sectionSizeHint(logicalIndex));
3609 }
3610 sectionSize = qBound(q->minimumSectionSize(),
3611 sectionSize,
3612 q->maximumSectionSize());
3613
3614 section_sizes.append(sectionSize);
3615 lengthToStretch -= sectionSize;
3616 }
3617
3618 // calculate the new length for all of the stretched sections
3619 int stretchSectionLength = -1;
3620 int pixelReminder = 0;
3621 if (numberOfStretchedSections > 0 && lengthToStretch > 0) { // we have room to stretch in
3622 int hintLengthForEveryStretchedSection = lengthToStretch / numberOfStretchedSections;
3623 stretchSectionLength = qMax(hintLengthForEveryStretchedSection, q->minimumSectionSize());
3624 pixelReminder = lengthToStretch % numberOfStretchedSections;
3625 }
3626
3627 // ### The code below would be nicer if it was cleaned up a bit (since spans has been replaced with items)
3628 int spanStartSection = 0;
3629 int previousSectionLength = 0;
3630
3631 QHeaderView::ResizeMode previousSectionResizeMode = QHeaderView::Interactive;
3632
3633 // resize each section along the total length
3634 for (int i = 0; i < sectionCount(); ++i) {
3635 int oldSectionLength = headerSectionSize(i);
3636 int newSectionLength = -1;
3637 QHeaderView::ResizeMode newSectionResizeMode = headerSectionResizeMode(i);
3638
3639 if (isVisualIndexHidden(i)) {
3640 newSectionLength = 0;
3641 } else {
3642 QHeaderView::ResizeMode resizeMode;
3643 if (useGlobalMode)
3644 resizeMode = globalMode;
3645 else
3646 resizeMode = (i == stretchSection
3648 : newSectionResizeMode);
3649 if (resizeMode == QHeaderView::Stretch && stretchSectionLength != -1) {
3650 if (i == lastSectionVisualIdx)
3651 newSectionLength = qMax(stretchSectionLength, lastSectionSize);
3652 else
3653 newSectionLength = stretchSectionLength;
3654 if (pixelReminder > 0) {
3655 newSectionLength += 1;
3656 --pixelReminder;
3657 }
3658 section_sizes.removeFirst();
3659 } else {
3660 newSectionLength = section_sizes.takeFirst();
3661 }
3662 }
3663
3664 //Q_ASSERT(newSectionLength > 0);
3665 if ((previousSectionResizeMode != newSectionResizeMode
3666 || previousSectionLength != newSectionLength) && i > 0) {
3667 createSectionItems(spanStartSection, i - 1, previousSectionLength, previousSectionResizeMode);
3668 //Q_ASSERT(headerLength() == length);
3669 spanStartSection = i;
3670 }
3671
3672 if (newSectionLength != oldSectionLength)
3673 emit q->sectionResized(logicalIndex(i), oldSectionLength, newSectionLength);
3674
3675 previousSectionLength = newSectionLength;
3676 previousSectionResizeMode = newSectionResizeMode;
3677 }
3678
3679 createSectionItems(spanStartSection, sectionCount() - 1,
3680 previousSectionLength, previousSectionResizeMode);
3681 //Q_ASSERT(headerLength() == length);
3682 resizeRecursionBlock = false;
3683 viewport->update();
3684}
3685
3687{
3688 if (end >= sectionItems.size()) {
3689 sectionItems.resize(end + 1);
3690 sectionStartposRecalc = true;
3691 }
3692 SectionItem *sectiondata = sectionItems.data();
3693 for (int i = start; i <= end; ++i) {
3694 length += (sizePerSection - sectiondata[i].size);
3695 sectionStartposRecalc |= (sectiondata[i].size != sizePerSection);
3696 sectiondata[i].size = sizePerSection;
3697 sectiondata[i].resizeMode = mode;
3698 }
3699}
3700
3702{
3703 // remove sections
3704 sectionStartposRecalc |= (end != sectionItems.size() - 1);
3705 int removedlength = 0;
3706 for (int u = start; u <= end; ++u)
3707 removedlength += sectionItems.at(u).size;
3708 length -= removedlength;
3709 sectionItems.remove(start, end - start + 1);
3710}
3711
3713{
3714 if (state != NoClear) {
3715 length = 0;
3720 sectionItems.clear();
3723 }
3724}
3725
3727{
3728 switch (order) {
3729 case Qt::AscendingOrder:
3730 return Qt::DescendingOrder;
3732 return Qt::AscendingOrder;
3733 };
3734 Q_UNREACHABLE_RETURN(Qt::AscendingOrder);
3735};
3736
3738{
3739 Q_Q(QHeaderView);
3740 Qt::SortOrder sortOrder;
3743 const Qt::SortOrder defaultSortOrder = defaultSortOrderForSection(section);
3744 if (sortIndicatorOrder == defaultSortOrder) {
3745 sortOrder = flipOrder(sortIndicatorOrder);
3746 } else {
3747 section = -1;
3748 sortOrder = Qt::AscendingOrder;
3749 }
3750 } else {
3751 sortOrder = flipOrder(sortIndicatorOrder);
3752 }
3753 } else {
3755 }
3756 q->setSortIndicator(section, sortOrder);
3757}
3758
3760{
3762 if (value.canConvert<int>())
3763 return static_cast<Qt::SortOrder>(value.toInt());
3764 return Qt::AscendingOrder;
3765}
3766
3767void QHeaderViewPrivate::cascadingResize(int visual, int newSize)
3768{
3769 Q_Q(QHeaderView);
3770 const int minimumSize = q->minimumSectionSize();
3771 const int oldSize = headerSectionSize(visual);
3772 int delta = newSize - oldSize;
3773
3774 if (delta > 0) { // larger
3775 bool sectionResized = false;
3776
3777 // restore old section sizes
3778 for (int i = firstCascadingSection; i < visual; ++i) {
3780 int currentSectionSize = headerSectionSize(i);
3781 int originalSectionSize = cascadingSectionSize.value(i);
3782 if (currentSectionSize < originalSectionSize) {
3783 int newSectionSize = currentSectionSize + delta;
3784 resizeSectionItem(i, currentSectionSize, newSectionSize);
3785 if (newSectionSize >= originalSectionSize && false)
3786 cascadingSectionSize.remove(i); // the section is now restored
3787 sectionResized = true;
3788 break;
3789 }
3790 }
3791
3792 }
3793
3794 // resize the section
3795 if (!sectionResized) {
3796 newSize = qMax(newSize, minimumSize);
3797 if (oldSize != newSize)
3798 resizeSectionItem(visual, oldSize, newSize);
3799 }
3800
3801 // cascade the section size change
3802 for (int i = visual + 1; i < sectionCount(); ++i) {
3804 continue;
3805 if (!sectionIsCascadable(i))
3806 continue;
3807 int currentSectionSize = headerSectionSize(i);
3808 if (currentSectionSize <= minimumSize)
3809 continue;
3810 int newSectionSize = qMax(currentSectionSize - delta, minimumSize);
3811 resizeSectionItem(i, currentSectionSize, newSectionSize);
3812 saveCascadingSectionSize(i, currentSectionSize);
3813 delta = delta - (currentSectionSize - newSectionSize);
3814 if (delta <= 0)
3815 break;
3816 }
3817 } else { // smaller
3818 bool sectionResized = false;
3819
3820 // restore old section sizes
3821 for (int i = lastCascadingSection; i > visual; --i) {
3823 continue;
3824 int currentSectionSize = headerSectionSize(i);
3825 int originalSectionSize = cascadingSectionSize.value(i);
3826 if (currentSectionSize >= originalSectionSize)
3827 continue;
3828 int newSectionSize = currentSectionSize - delta;
3829 resizeSectionItem(i, currentSectionSize, newSectionSize);
3830 if (newSectionSize >= originalSectionSize && false) {
3831 cascadingSectionSize.remove(i); // the section is now restored
3832 }
3833 sectionResized = true;
3834 break;
3835 }
3836
3837 // resize the section
3838 resizeSectionItem(visual, oldSize, qMax(newSize, minimumSize));
3839
3840 // cascade the section size change
3841 if (delta < 0 && newSize < minimumSize) {
3842 for (int i = visual - 1; i >= 0; --i) {
3844 continue;
3845 if (!sectionIsCascadable(i))
3846 continue;
3847 int sectionSize = headerSectionSize(i);
3848 if (sectionSize <= minimumSize)
3849 continue;
3850 resizeSectionItem(i, sectionSize, qMax(sectionSize + delta, minimumSize));
3851 saveCascadingSectionSize(i, sectionSize);
3852 break;
3853 }
3854 }
3855
3856 // let the next section get the space from the resized section
3857 if (!sectionResized) {
3858 for (int i = visual + 1; i < sectionCount(); ++i) {
3860 continue;
3861 if (!sectionIsCascadable(i))
3862 continue;
3863 int currentSectionSize = headerSectionSize(i);
3864 int newSectionSize = qMax(currentSectionSize - delta, minimumSize);
3865 resizeSectionItem(i, currentSectionSize, newSectionSize);
3866 break;
3867 }
3868 }
3869 }
3870
3873
3874 viewport->update();
3875}
3876
3878{
3879 Q_Q(QHeaderView);
3880 size = qBound(q->minimumSectionSize(), size, q->maximumSectionSize());
3887 for (int i = 0; i < sectionItems.size(); ++i) {
3889 if (hiddenSectionSize.isEmpty() || !isVisualIndexHidden(i)) { // resize on not hidden.
3890 const int newSize = size;
3891 if (newSize != section.size) {
3892 length += newSize - section.size; //the whole length is changed
3893 const int oldSectionSize = section.sectionSize();
3894 section.size = size;
3895 emit q->sectionResized(logicalIndex(i), oldSectionSize, size);
3896 }
3897 }
3898 }
3899 sectionStartposRecalc = true;
3902 viewport->update();
3903}
3904
3906{
3907 Q_Q(QHeaderView);
3908 if (orientation == Qt::Horizontal) {
3909 defaultSectionSize = q->style()->pixelMetric(QStyle::PM_HeaderDefaultSectionSizeHorizontal, nullptr, q);
3910 } else {
3911 defaultSectionSize = qMax(q->minimumSectionSize(),
3912 q->style()->pixelMetric(QStyle::PM_HeaderDefaultSectionSizeVertical, nullptr, q));
3913 }
3914}
3915
3916void QHeaderViewPrivate::recalcSectionStartPos() const // linear (but fast)
3917{
3918 int pixelpos = 0;
3919 for (const SectionItem &i : sectionItems) {
3920 i.calculated_startpos = pixelpos; // write into const mutable
3921 pixelpos += i.size;
3922 }
3923 sectionStartposRecalc = false;
3924}
3925
3926void QHeaderViewPrivate::resizeSectionItem(int visualIndex, int oldSize, int newSize)
3927{
3928 Q_Q(QHeaderView);
3931 emit q->sectionResized(logicalIndex(visualIndex), oldSize, newSize);
3932}
3933
3935{
3936 if (visual < sectionCount() && visual >= 0)
3937 return sectionItems.at(visual).sectionSize();
3938 return -1;
3939}
3940
3942{
3943 if (visual < sectionCount() && visual >= 0) {
3946 return sectionItems.at(visual).calculated_startpos;
3947 }
3948 return -1;
3949}
3950
3952{
3955 int startidx = 0;
3956 int endidx = sectionItems.size() - 1;
3957 while (startidx <= endidx) {
3958 int middle = (endidx + startidx) / 2;
3959 if (sectionItems.at(middle).calculated_startpos > position) {
3960 endidx = middle - 1;
3961 } else {
3962 if (sectionItems.at(middle).calculatedEndPos() <= position)
3963 startidx = middle + 1;
3964 else // we found it.
3965 return middle;
3966 }
3967 }
3968 return -1;
3969}
3970
3972{
3973 int size = headerSectionSize(visual);
3974 createSectionItems(visual, visual, size, mode);
3975}
3976
3978{
3979 if (visual < 0 || visual >= sectionItems.size())
3980 return globalResizeMode;
3981 return static_cast<QHeaderView::ResizeMode>(sectionItems.at(visual).resizeMode);
3982}
3983
3985{
3987 for (int i = 0; i < sectionItems.size(); ++i)
3988 sectionItems[i].resizeMode = mode;
3989}
3990
3992{
3993 if (QAbstractItemView *view = qobject_cast<QAbstractItemView*>(parent)) {
3994 return (orientation == Qt::Horizontal
3995 ? view->sizeHintForColumn(logical)
3996 : view->sizeHintForRow(logical));
3997 }
3998 return 0;
3999}
4000
4002{
4003 if (!hiddenSectionSize.isEmpty()) {
4005 int currentVisualIndex = 0;
4006 for (int i = 0; i < sectionItems.size(); ++i) {
4009 else
4010 ++currentVisualIndex;
4011 if (currentVisualIndex >= visualIndex)
4012 break;
4013 }
4015 }
4016 return visualIndex;
4017}
4018
4020{
4021 Q_Q(QHeaderView);
4022 if (scrollMode == QAbstractItemView::ScrollPerItem) {
4023 if (scrollBar->maximum() > 0 && scrollBar->value() == scrollBar->maximum())
4024 q->setOffsetToLastSection();
4025 else
4026 q->setOffsetToSectionPosition(scrollBar->value());
4027 } else {
4028 q->setOffset(scrollBar->value());
4029 }
4030}
4031
4033{
4034 Q_Q(QHeaderView);
4035 const int visual = visualIndex(logical);
4036 int from = logicalIndex(visual > 1 ? visual - 1 : 0);
4037 int to = logicalIndex(visual + 1 >= sectionCount() ? visual : visual + 1);
4038 QRect updateRect;
4039 if (orientation == Qt::Horizontal) {
4040 if (reverse())
4041 std::swap(from, to);
4042 updateRect = QRect(QPoint(q->sectionViewportPosition(from), 0),
4043 QPoint(q->sectionViewportPosition(to) + headerSectionSize(to), viewport->height()));
4044 } else {
4045 updateRect = QRect(QPoint(0, q->sectionViewportPosition(from)),
4046 QPoint(viewport->width(), q->sectionViewportPosition(to) + headerSectionSize(to)));
4047 }
4048 viewport->update(updateRect);
4049}
4050
4051#ifndef QT_NO_DATASTREAM
4053{
4054 out << int(orientation);
4055 out << int(sortIndicatorOrder);
4058
4059 out << visualIndices;
4061
4064
4065 out << length;
4066 out << sectionCount();
4076
4077 out << int(defaultAlignment);
4078 out << int(globalResizeMode);
4079
4080 out << sectionItems;
4085}
4086
4088{
4089 Q_Q(QHeaderView);
4090 int orient, order, align, global;
4091 int sortIndicatorSectionIn;
4092 bool sortIndicatorShownIn;
4093 int lengthIn;
4094 QList<int> visualIndicesIn;
4095 QList<int> logicalIndicesIn;
4096 QHash<int, int> hiddenSectionSizeIn;
4097 bool movableSectionsIn;
4098 bool clickableSectionsIn;
4099 bool highlightSelectedIn;
4100 bool stretchLastSectionIn;
4101 bool cascadingResizingIn;
4102 int stretchSectionsIn;
4103 int contentsSectionsIn;
4104 int defaultSectionSizeIn;
4105 int minimumSectionSizeIn;
4106 QList<SectionItem> sectionItemsIn;
4107
4108 in >> orient;
4109 in >> order;
4110
4111 in >> sortIndicatorSectionIn;
4112 in >> sortIndicatorShownIn;
4113
4114 in >> visualIndicesIn;
4115 in >> logicalIndicesIn;
4116
4117 QBitArray sectionHidden;
4118 in >> sectionHidden;
4119 in >> hiddenSectionSizeIn;
4120 in >> lengthIn;
4121
4122 int unusedSectionCount; // For compatibility
4123 in >> unusedSectionCount;
4124
4125 if (in.status() != QDataStream::Ok || lengthIn < 0)
4126 return false;
4127
4128 in >> movableSectionsIn;
4129 in >> clickableSectionsIn;
4130 in >> highlightSelectedIn;
4131 in >> stretchLastSectionIn;
4132 in >> cascadingResizingIn;
4133 in >> stretchSectionsIn;
4134 in >> contentsSectionsIn;
4135 in >> defaultSectionSizeIn;
4136 in >> minimumSectionSizeIn;
4137
4138 in >> align;
4139
4140 in >> global;
4141
4142 // Check parameter consistency
4143 // Global orientation out of bounds?
4144 if (global < 0 || global > QHeaderView::ResizeToContents)
4145 return false;
4146
4147 // Alignment out of bounds?
4148 if (align < 0 || align > Qt::AlignVertical_Mask)
4149 return false;
4150
4151 in >> sectionItemsIn;
4152 // In Qt4 we had a vector of spans where one span could hold information on more sections.
4153 // Now we have an itemvector where one items contains information about one section
4154 // For backward compatibility with Qt4 we do the following
4155 QList<SectionItem> newSectionItems;
4156 for (int u = 0; u < sectionItemsIn.size(); ++u) {
4157 int count = sectionItemsIn.at(u).tmpDataStreamSectionCount;
4158 if (count > 1)
4159 sectionItemsIn[u].size /= count;
4160 for (int n = 0; n < count; ++n)
4161 newSectionItems.append(sectionItemsIn[u]);
4162 }
4163
4164 int sectionItemsLengthTotal = 0;
4165 for (const SectionItem &section : std::as_const(newSectionItems))
4166 sectionItemsLengthTotal += section.size;
4167 if (sectionItemsLengthTotal != lengthIn)
4168 return false;
4169
4170 const int currentCount = (orient == Qt::Horizontal ? model->columnCount(root) : model->rowCount(root));
4171 if (newSectionItems.size() < currentCount) {
4172 // we have sections not in the saved state, give them default settings
4173 if (!visualIndicesIn.isEmpty() && !logicalIndicesIn.isEmpty()) {
4174 for (int i = newSectionItems.size(); i < currentCount; ++i) {
4175 visualIndicesIn.append(i);
4176 logicalIndicesIn.append(i);
4177 }
4178 }
4179 const int insertCount = currentCount - newSectionItems.size();
4180 const int insertLength = defaultSectionSizeIn * insertCount;
4181 lengthIn += insertLength;
4182 SectionItem section(defaultSectionSizeIn, globalResizeMode);
4183 newSectionItems.insert(newSectionItems.size(), insertCount, section); // append
4184 }
4185
4186 orientation = static_cast<Qt::Orientation>(orient);
4187 sortIndicatorOrder = static_cast<Qt::SortOrder>(order);
4188 sortIndicatorSection = sortIndicatorSectionIn;
4189 sortIndicatorShown = sortIndicatorShownIn;
4190 visualIndices = visualIndicesIn;
4191 logicalIndices = logicalIndicesIn;
4192 hiddenSectionSize = hiddenSectionSizeIn;
4193 length = lengthIn;
4194
4195 movableSections = movableSectionsIn;
4196 clickableSections = clickableSectionsIn;
4197 highlightSelected = highlightSelectedIn;
4198 stretchLastSection = stretchLastSectionIn;
4199 cascadingResizing = cascadingResizingIn;
4200 stretchSections = stretchSectionsIn;
4201 contentsSections = contentsSectionsIn;
4202 defaultSectionSize = defaultSectionSizeIn;
4203 minimumSectionSize = minimumSectionSizeIn;
4204
4205 defaultAlignment = Qt::Alignment(align);
4207
4208 sectionItems = newSectionItems;
4209 setHiddenSectionsFromBitVector(sectionHidden);
4211
4212 int tmpint;
4213 in >> tmpint;
4214 if (in.status() == QDataStream::Ok) // we haven't read past end
4215 resizeContentsPrecision = tmpint;
4216
4217 bool tmpbool;
4218 in >> tmpbool;
4219 if (in.status() == QDataStream::Ok) { // we haven't read past end
4220 customDefaultSectionSize = tmpbool;
4223 }
4224
4225 lastSectionSize = -1;
4226 int inLastSectionSize;
4227 in >> inLastSectionSize;
4228 if (in.status() == QDataStream::Ok)
4229 lastSectionSize = inLastSectionSize;
4230
4232 if (stretchLastSection) {
4235 }
4236
4237 int inSortIndicatorClearable;
4238 in >> inSortIndicatorClearable;
4239 if (in.status() == QDataStream::Ok) // we haven't read past end
4240 sortIndicatorClearable = inSortIndicatorClearable;
4241
4242 return true;
4243}
4244
4245#endif // QT_NO_DATASTREAM
4246
4248
4249#include "moc_qheaderview.cpp"
static QAbstractItemModel * staticEmptyModel()
LayoutChangeHint
This enum describes the way the model changes layout.
virtual Q_INVOKABLE QVariant headerData(int section, Qt::Orientation orientation, int role=Qt::DisplayRole) const
Returns the data for the given role and section in the header with the specified orientation.
virtual Q_INVOKABLE int rowCount(const QModelIndex &parent=QModelIndex()) const =0
Returns the number of rows under the given parent.
virtual Q_INVOKABLE int columnCount(const QModelIndex &parent=QModelIndex()) const =0
Returns the number of columns for the children of the given parent.
virtual Q_INVOKABLE QModelIndex index(int row, int column, const QModelIndex &parent=QModelIndex()) const =0
Returns the index of the item in the model specified by the given row, column and parent index.
QPersistentModelIndex root
The QAbstractItemView class provides the basic functionality for item view classes.
QAbstractItemModel * model() const
Returns the model that this view is presenting.
bool event(QEvent *event) override
\reimp
State state() const
Returns the item view's state.
virtual void reset()
Reset the internal state of the view.
virtual void dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QList< int > &roles=QList< int >())
This slot is called when items with the given roles are changed in the model.
bool viewportEvent(QEvent *event) override
This function is used to handle tool tips, and What's This? mode, if the given event is a QEvent::Too...
virtual void rowsAboutToBeRemoved(const QModelIndex &parent, int start, int end)
This slot is called when rows are about to be removed.
virtual void setModel(QAbstractItemModel *model)
Sets the model for the view to present.
virtual void doItemsLayout()
CursorAction
This enum describes the different ways to navigate between items,.
virtual void currentChanged(const QModelIndex &current, const QModelIndex &previous)
This slot is called when a new item becomes the current item.
ScrollHint
\value EnsureVisible Scroll to ensure that the item is visible.
virtual void rowsInserted(const QModelIndex &parent, int start, int end)
This slot is called when rows are inserted.
int value
the slider's current value
int maximum
the slider's maximum value
int startDragDistance
the minimum distance required for a drag and drop operation to start.
void stop()
Stops the timer.
\inmodule QtCore
Definition qbitarray.h:13
void clear()
Clears the contents of the bit array and makes it empty.
Definition qbitarray.h:42
bool testBit(qsizetype i) const
Returns true if the bit at index position i is 1; otherwise returns false.
Definition qbitarray.h:84
void setBit(qsizetype i)
Sets the bit at index position i to 1.
Definition qbitarray.h:88
qsizetype size() const
Returns the number of bits stored in the bit array.
Definition qbitarray.h:31
\inmodule QtGui
Definition qbrush.h:30
\inmodule QtCore
Definition qbytearray.h:57
The QColor class provides colors based on RGB, HSV or CMYK values.
Definition qcolor.h:31
static bool sendEvent(QObject *receiver, QEvent *event)
Sends event event directly to receiver receiver, using the notify() function.
static void setPos(int x, int y)
Moves the cursor (hot spot) of the primary screen to the global screen position (x,...
Definition qcursor.cpp:240
static QPoint pos()
Returns the position of the cursor (hot spot) of the primary screen in global screen coordinates.
Definition qcursor.cpp:188
\inmodule QtCore\reentrant
Definition qdatastream.h:30
\inmodule QtCore
Definition qcoreevent.h:45
@ QueryWhatsThis
Definition qcoreevent.h:169
@ StatusTip
Definition qcoreevent.h:149
@ StyleChange
Definition qcoreevent.h:136
@ FontChange
Definition qcoreevent.h:133
@ HoverLeave
Definition qcoreevent.h:176
@ HoverEnter
Definition qcoreevent.h:175
@ HoverMove
Definition qcoreevent.h:177
@ WhatsThis
Definition qcoreevent.h:148
@ ContextMenu
Definition qcoreevent.h:119
\reentrant \inmodule QtGui
\reentrant
Definition qfont.h:20
void setBold(bool)
If enable is true sets the font's weight to \l{Weight}{QFont::Bold}; otherwise sets the weight to \l{...
Definition qfont.h:312
virtual void initStyleOption(QStyleOptionFrame *option) const
Definition qframe.cpp:189
\inmodule QtCore
Definition qhash.h:1135
\inmodule QtCore
Definition qhash.h:1093
\inmodule QtCore
Definition qhash.h:818
bool remove(const Key &key)
Removes the item that has the key from the hash.
Definition qhash.h:956
bool contains(const Key &key) const noexcept
Returns true if the hash contains an item with the key; otherwise returns false.
Definition qhash.h:991
T value(const Key &key) const noexcept
Definition qhash.h:1044
void clear() noexcept(std::is_nothrow_destructible< Node >::value)
Removes all items from the hash and frees up all memory used by it.
Definition qhash.h:949
bool isEmpty() const noexcept
Returns true if the hash contains no items; otherwise returns false.
Definition qhash.h:926
int headerSectionSize(int visual) const
void updateDefaultSectionSizeFromStyle()
int headerLength() const
void _q_sectionsRemoved(const QModelIndex &, int, int)
int headerVisualIndexAt(int position) const
void cascadingResize(int visual, int newSize)
Qt::SortOrder defaultSortOrderForSection(int section) const
void saveCascadingSectionSize(int visual, int size)
void setupSectionIndicator(int section, int position)
Qt::Alignment defaultAlignment
int logicalIndex(int visualIndex) const
void _q_sectionsChanged(const QList< QPersistentModelIndex > &parents=QList< QPersistentModelIndex >(), QAbstractItemModel::LayoutChangeHint hint=QAbstractItemModel::NoLayoutChangeHint)
void _q_sectionsMoved(const QModelIndex &sourceParent, int logicalStart, int logicalEnd, const QModelIndex &destinationParent, int logicalDestination)
void recalcSectionStartPos() const
void setNewLastSection(int visualIndexForLastSection)
void updateHiddenSections(int logicalFirst, int logicalLast)
void invalidateCachedSizeHint() const
void removeSectionsFromSectionItems(int start, int end)
Qt::Orientation orientation
QBitArray sectionSelected
void updateSectionIndicator(int section, int position)
int sectionCount() const
void _q_sectionsAboutToBeChanged(const QList< QPersistentModelIndex > &parents=QList< QPersistentModelIndex >(), QAbstractItemModel::LayoutChangeHint hint=QAbstractItemModel::NoLayoutChangeHint)
int lastVisibleVisualIndex() const
void createSectionItems(int start, int end, int sectionSize, QHeaderView::ResizeMode mode)
QHash< int, int > cascadingSectionSize
bool sectionIsCascadable(int visual) const
int modelSectionCount() const
bool read(QDataStream &in)
bool isFirstVisibleSection(int section) const
bool isSectionSelected(int section) const
void restoreSizeOnPrevLastSection()
void setHeaderSectionResizeMode(int visual, QHeaderView::ResizeMode mode)
void resizeSections(QHeaderView::ResizeMode globalMode, bool useGlobalMode=false)
bool reverse() const
int headerSectionPosition(int visual) const
void setGlobalHeaderResizeMode(QHeaderView::ResizeMode mode)
void flipSortIndicator(int section)
bool isColumnSelected(int column) const
void write(QDataStream &out) const
bool preventCursorChangeInSetOffset
void _q_sectionsAboutToBeMoved(const QModelIndex &sourceParent, int logicalStart, int logicalEnd, const QModelIndex &destinationParent, int logicalDestination)
QHeaderView::ResizeMode globalResizeMode
void setHiddenSectionsFromBitVector(const QBitArray &sectionHidden)
int adjustedVisualIndex(int visualIndex) const
bool isRowSelected(int row) const
int visualIndex(int logicalIndex) const
bool isVisualIndexHidden(int visual) const
QList< int > logicalIndices
enum QHeaderViewPrivate::State state
void resizeSectionItem(int visualIndex, int oldSize, int newSize)
bool isLastVisibleSection(int section) const
QHeaderView::ResizeMode headerSectionResizeMode(int visual) const
int sectionHandleAt(int position)
void setScrollOffset(const QScrollBar *scrollBar, QAbstractItemView::ScrollMode scrollMode)
QBasicTimer delayedResize
QList< LayoutChangeItem > layoutChangePersistentSections
QHash< int, int > hiddenSectionSize
Qt::SortOrder sortIndicatorOrder
void setDefaultSectionSize(int size)
void maybeRestorePrevLastSectionAndStretchLast()
QBitArray sectionsHiddenToBitVector() const
void updateSectionsBeforeAfter(int logical)
QList< int > visualIndices
int viewSectionSizeHint(int logical) const
bool hasAutoResizeSections() const
QList< SectionItem > sectionItems
The QHeaderView class provides a header row or header column for item views.
Definition qheaderview.h:18
bool sectionsClickable() const
void resizeSections()
Resizes the sections according to their size hints.
void moveSection(int from, int to)
Moves the section at visual index from to occupy visual index to.
void geometriesChanged()
QRegion visualRegionForSelection(const QItemSelection &selection) const override
QModelIndex moveCursor(CursorAction, Qt::KeyboardModifiers) override
\reimp
void setSortIndicatorShown(bool show)
int sectionPosition(int logicalIndex) const
Returns the section position of the given logicalIndex, or -1 if the section is hidden.
void setHighlightSections(bool highlight)
void setDefaultSectionSize(int size)
void resetDefaultSectionSize()
bool highlightSections
whether the sections containing selected items are highlighted
Definition qheaderview.h:22
bool sectionsHidden() const
void setSectionsClickable(bool clickable)
bool isIndexHidden(const QModelIndex &index) const override
\reimp
void reset() override
\reimp
void sectionClicked(int logicalIndex)
This signal is emitted when a section is clicked.
void initializeSections()
void mouseReleaseEvent(QMouseEvent *e) override
\reimp
QSize sizeHint() const override
Returns a suitable size hint for this header.
int sectionViewportPosition(int logicalIndex) const
Returns the section viewport position of the given logicalIndex.
virtual ~QHeaderView()
Destroys the header.
bool isSectionHidden(int logicalIndex) const
Returns true if the section specified by logicalIndex is explicitly hidden from the user; otherwise r...
void sectionCountChanged(int oldCount, int newCount)
This signal is emitted when the number of sections changes, i.e., when sections are added or deleted.
void headerDataChanged(Qt::Orientation orientation, int logicalFirst, int logicalLast)
Updates the changed header sections with the given orientation, from logicalFirst to logicalLast incl...
void updateGeometries() override
\reimp
void sectionResized(int logicalIndex, int oldSize, int newSize)
This signal is emitted when a section is resized.
bool event(QEvent *e) override
\reimp
void scrollContentsBy(int dx, int dy) override
\reimp
int stretchSectionCount() const
void setSortIndicator(int logicalIndex, Qt::SortOrder order)
Sets the sort indicator for the section specified by the given logicalIndex in the direction specifie...
void setOffsetToSectionPosition(int visualIndex)
int sectionSize(int logicalIndex) const
Returns the width (or height for vertical headers) of the given logicalIndex.
void setMinimumSectionSize(int size)
int horizontalOffset() const override
Returns the horizontal offset of the header.
ResizeMode
The resize mode specifies the behavior of the header sections.
Definition qheaderview.h:37
virtual void initStyleOption(QStyleOptionHeader *option) const
Initialize option with the values from this QHeaderView.
void resizeSection(int logicalIndex, int size)
Resizes the section specified by logicalIndex to size measured in pixels.
void setSortIndicatorClearable(bool clearable)
Qt::SortOrder sortIndicatorOrder() const
Returns the order for the sort indicator.
QByteArray saveState() const
int hiddenSectionCount() const
Qt::Alignment defaultAlignment
the default alignment of the text in each header section
Definition qheaderview.h:30
void setResizeContentsPrecision(int precision)
void setSectionResizeMode(ResizeMode mode)
int minimumSectionSize
the minimum size of the header sections.
Definition qheaderview.h:28
bool sectionsMoved() const
Returns true if sections in the header has been moved; otherwise returns false;.
void setStretchLastSection(bool stretch)
void sectionPressed(int logicalIndex)
This signal is emitted when a section is pressed.
bool isSortIndicatorShown() const
bool viewportEvent(QEvent *e) override
\reimp
void sortIndicatorChanged(int logicalIndex, Qt::SortOrder order)
void setMaximumSectionSize(int size)
void swapSections(int first, int second)
int logicalIndexAt(int position) const
Returns the section that covers the given position in the viewport.
void setModel(QAbstractItemModel *model) override
\reimp
void setDefaultAlignment(Qt::Alignment alignment)
void mouseDoubleClickEvent(QMouseEvent *e) override
\reimp
void setSelection(const QRect &rect, QItemSelectionModel::SelectionFlags flags) override
\reimp
void setSectionHidden(int logicalIndex, bool hide)
If hide is true the section specified by logicalIndex is hidden; otherwise the section is shown.
int logicalIndex(int visualIndex) const
Returns the logicalIndex for the section at the given visualIndex position, or -1 if visualIndex < 0 ...
void sectionsInserted(const QModelIndex &parent, int logicalFirst, int logicalLast)
This slot is called when sections are inserted into the parent.
QRect visualRect(const QModelIndex &index) const override
\reimp
int length() const
Returns the length along the orientation of the header.
bool isFirstSectionMovable() const
void sectionHandleDoubleClicked(int logicalIndex)
This signal is emitted when a section is double-clicked.
int visualIndexAt(int position) const
Returns the visual index of the section that covers the given position in the viewport.
bool cascadingSectionResizes
whether interactive resizing will be cascaded to the following sections once the section being resize...
Definition qheaderview.h:25
void mousePressEvent(QMouseEvent *e) override
\reimp
void sectionEntered(int logicalIndex)
void setOffset(int offset)
Sets the header's offset to offset.
void setOffsetToLastSection()
void scrollTo(const QModelIndex &index, ScrollHint hint) override
\reimp
virtual QSize sectionSizeFromContents(int logicalIndex) const
Returns the size of the contents of the section specified by the given logicalIndex.
void sortIndicatorClearableChanged(bool clearable)
void paintEvent(QPaintEvent *e) override
\reimp
void setFirstSectionMovable(bool movable)
int resizeContentsPrecision() const
void initialize()
virtual void paintSection(QPainter *painter, const QRect &rect, int logicalIndex) const
Paints the section specified by the given logicalIndex, using the given painter and rect.
int visualIndex(int logicalIndex) const
Returns the visual index position of the section specified by the given logicalIndex,...
void doItemsLayout() override
bool stretchLastSection
whether the last visible section in the header takes up all the available space
Definition qheaderview.h:23
int sectionSizeHint(int logicalIndex) const
Returns a suitable size hint for the section specified by logicalIndex.
QModelIndex indexAt(const QPoint &p) const override
\reimp
void setVisible(bool v) override
\reimp
Qt::Orientation orientation() const
Returns the orientation of the header.
QHeaderView(Qt::Orientation orientation, QWidget *parent=nullptr)
Creates a new generic header with the given orientation and parent.
virtual void initStyleOptionForIndex(QStyleOptionHeader *option, int logicalIndex) const
void sectionMoved(int logicalIndex, int oldVisualIndex, int newVisualIndex)
This signal is emitted when a section is moved.
void setSectionsMovable(bool movable)
bool isSortIndicatorClearable() const
int verticalOffset() const override
Returns the vertical offset of the header.
int offset() const
Returns the offset of the header: this is the header's left-most (or top-most for vertical headers) v...
void mouseMoveEvent(QMouseEvent *e) override
\reimp
void updateSection(int logicalIndex)
bool sectionsMovable() const
void sectionDoubleClicked(int logicalIndex)
This signal is emitted when a section is double-clicked.
ResizeMode sectionResizeMode(int logicalIndex) const
int sortIndicatorSection() const
Returns the logical index of the section that has a sort indicator.
int defaultSectionSize
the default size of the header sections before resizing.
Definition qheaderview.h:27
bool restoreState(const QByteArray &state)
void sectionsAboutToBeRemoved(const QModelIndex &parent, int logicalFirst, int logicalLast)
This slot is called when sections are removed from the parent.
int count() const
Returns the number of sections in the header.
int maximumSectionSize
the maximum size of the header sections.
Definition qheaderview.h:29
void setCascadingSectionResizes(bool enable)
The QHelpEvent class provides an event that is used to request helpful information about a particular...
Definition qevent.h:787
const QPoint & globalPos() const
Returns the mouse cursor position when the event was generated in global coordinates.
Definition qevent.h:798
const QPoint & pos() const
Returns the mouse cursor position when the event was generated, relative to the widget to which the e...
Definition qevent.h:797
\inmodule QtGui
Definition qevent.h:245
bool isNull() const
Returns true if the icon is empty; otherwise returns false.
Definition qicon.cpp:973
\inmodule QtCore
The QLabel widget provides a text or image display.
Definition qlabel.h:20
Definition qlist.h:74
qsizetype size() const noexcept
Definition qlist.h:386
void removeFirst() noexcept
Definition qlist.h:800
bool isEmpty() const noexcept
Definition qlist.h:390
iterator insert(qsizetype i, parameter_type t)
Definition qlist.h:471
iterator end()
Definition qlist.h:609
const_reference at(qsizetype i) const noexcept
Definition qlist.h:429
value_type takeFirst()
Definition qlist.h:549
void remove(qsizetype i, qsizetype n=1)
Definition qlist.h:787
iterator begin()
Definition qlist.h:608
pointer data()
Definition qlist.h:414
void resize(qsizetype size)
Definition qlist.h:392
void append(parameter_type t)
Definition qlist.h:441
void clear()
Definition qlist.h:417
\inmodule QtCore
constexpr int row() const noexcept
Returns the row this model index refers to.
QModelIndex parent() const
Returns the parent of the model index, or QModelIndex() if it has no parent.
constexpr int column() const noexcept
Returns the column this model index refers to.
constexpr bool isValid() const noexcept
Returns {true} if this model index is valid; otherwise returns {false}.
\inmodule QtGui
Definition qevent.h:195
static QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *member, Qt::ConnectionType=Qt::AutoConnection)
\threadsafe
Definition qobject.cpp:2823
static bool disconnect(const QObject *sender, const char *signal, const QObject *receiver, const char *member)
\threadsafe
Definition qobject.cpp:3099
The QPaintEvent class contains event parameters for paint events.
Definition qevent.h:485
The QPainter class performs low-level painting on widgets and other paint devices.
Definition qpainter.h:46
void setBrushOrigin(int x, int y)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qpainter.h:698
void restore()
Restores the current painter state (pops a saved state off the stack).
void setOpacity(qreal opacity)
void save()
Saves the current painter state (pushes the state onto a stack).
void setFont(const QFont &f)
Sets the painter's font to the given font.
QPoint brushOrigin() const
Returns the currently set brush origin.
bool end()
Ends painting.
void fillRect(const QRectF &, const QBrush &)
Fills the given rectangle with the brush specified.
const QBrush & brush(ColorGroup cg, ColorRole cr) const
Returns the brush in the specified color group, used for the given color role.
Definition qpalette.cpp:794
void setBrush(ColorRole cr, const QBrush &brush)
Sets the brush for the given color role to the specified brush for all groups in the palette.
Definition qpalette.h:150
@ ButtonText
Definition qpalette.h:51
Returns a copy of the pixmap that is transformed using the given transformation transform and transfo...
Definition qpixmap.h:27
void setDevicePixelRatio(qreal scaleFactor)
Sets the device pixel ratio for the pixmap.
Definition qpixmap.cpp:608
void fill(const QColor &fillColor=Qt::white)
Fills the pixmap with the given color.
Definition qpixmap.cpp:854
\inmodule QtCore\reentrant
Definition qpoint.h:214
constexpr QPoint toPoint() const
Rounds the coordinates of this point to the nearest integer, and returns a QPoint object with the rou...
Definition qpoint.h:394
\inmodule QtCore\reentrant
Definition qpoint.h:23
constexpr int x() const noexcept
Returns the x coordinate of this point.
Definition qpoint.h:127
constexpr int y() const noexcept
Returns the y coordinate of this point.
Definition qpoint.h:132
\inmodule QtCore\reentrant
Definition qrect.h:30
constexpr int bottom() const noexcept
Returns the y-coordinate of the rectangle's bottom edge.
Definition qrect.h:181
constexpr QPoint topLeft() const noexcept
Returns the position of the rectangle's top-left corner.
Definition qrect.h:220
constexpr int top() const noexcept
Returns the y-coordinate of the rectangle's top edge.
Definition qrect.h:175
bool contains(const QRect &r, bool proper=false) const noexcept
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qrect.cpp:851
constexpr int left() const noexcept
Returns the x-coordinate of the rectangle's left edge.
Definition qrect.h:172
constexpr void setRect(int x, int y, int w, int h) noexcept
Sets the coordinates of the rectangle's top-left corner to ({x}, {y}), and its size to the given widt...
Definition qrect.h:345
constexpr void translate(int dx, int dy) noexcept
Moves the rectangle dx along the x axis and dy along the y axis, relative to the current position.
Definition qrect.h:244
constexpr int right() const noexcept
Returns the x-coordinate of the rectangle's right edge.
Definition qrect.h:178
The QRegion class specifies a clip region for a painter.
Definition qregion.h:27
The QScrollBar widget provides a vertical or horizontal scroll bar.
Definition qscrollbar.h:20
QPointF position() const
Returns the position of the point in this event, relative to the widget or item that received the eve...
Definition qevent.h:118
\inmodule QtCore
Definition qsize.h:25
The QStatusTipEvent class provides an event that is used to show messages in a status bar.
Definition qevent.h:807
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:127
bool isEmpty() const
Returns true if the string has no characters; otherwise returns false.
Definition qstring.h:1083
\variable QStyleOptionFocusRect::backgroundColor
The QStyleOptionHeaderV2 class is used to describe the parameters for drawing a header.
Qt::TextElideMode textElideMode
The QStyleOptionHeader class is used to describe the parameters for drawing a header.
The QStyleOption class stores the parameters used by QStyle functions.
QFontMetrics fontMetrics
QStyle::State state
QPalette palette
void initFrom(const QWidget *w)
The QStyle class is an abstract base class that encapsulates the look and feel of a GUI.
Definition qstyle.h:29
@ State_MouseOver
Definition qstyle.h:80
@ State_Sunken
Definition qstyle.h:69
@ State_Active
Definition qstyle.h:83
@ State_Enabled
Definition qstyle.h:67
@ State_Horizontal
Definition qstyle.h:74
@ State_On
Definition qstyle.h:72
@ State_Raised
Definition qstyle.h:68
@ State_None
Definition qstyle.h:66
@ CT_HeaderSection
Definition qstyle.h:564
@ CE_Header
Definition qstyle.h:202
@ CE_HeaderEmptyArea
Definition qstyle.h:226
@ PM_HeaderDefaultSectionSizeHorizontal
Definition qstyle.h:528
@ PM_HeaderMargin
Definition qstyle.h:474
@ PM_HeaderDefaultSectionSizeVertical
Definition qstyle.h:529
@ PM_HeaderGripMargin
Definition qstyle.h:476
\inmodule QtCore
Definition qcoreevent.h:359
int timerId() const
Returns the unique timer identifier, which is the same identifier as returned from QObject::startTime...
Definition qcoreevent.h:363
static void showText(const QPoint &pos, const QString &text, QWidget *w=nullptr, const QRect &rect={}, int msecShowTime=-1)
Shows text as a tool tip, with the global position pos as the point of interest.
Definition qtooltip.cpp:427
\inmodule QtCore
Definition qvariant.h:64
bool isValid() const
Returns true if the storage type of this variant is not QMetaType::UnknownType; otherwise returns fal...
Definition qvariant.h:707
QString toString() const
Returns the variant as a QString if the variant has a userType() including, but not limited to:
bool canConvert(QMetaType targetType) const
Definition qvariant.h:342
static void showText(const QPoint &pos, const QString &text, QWidget *w=nullptr)
Shows text as a "What's This?" window, at global position pos.
The QWidget class is the base class of all user interface objects.
Definition qwidget.h:99
QCursor cursor
qSwap(pi, e)
double e
QSet< QString >::iterator it
rect
[4]
uint alignment
QStyleOptionButton opt
fontMetrics
else opt state
[0]
Combined button and popup list for selecting options.
@ AlignVCenter
Definition qnamespace.h:154
@ AlignVertical_Mask
Definition qnamespace.h:160
@ LeftButton
Definition qnamespace.h:57
@ NoButton
Definition qnamespace.h:56
@ WA_SetCursor
Definition qnamespace.h:304
@ NoFocus
Definition qnamespace.h:106
Orientation
Definition qnamespace.h:97
@ Horizontal
Definition qnamespace.h:98
@ Vertical
Definition qnamespace.h:99
CursorShape
@ ArrowCursor
@ SplitVCursor
@ SplitHCursor
@ WhatsThisRole
@ FontRole
@ TextAlignmentRole
@ ForegroundRole
@ UserRole
@ DecorationRole
@ InitialSortOrderRole
@ BackgroundRole
@ StatusTipRole
@ ToolTipRole
@ DisplayRole
@ SizeHintRole
@ ScrollBarAlwaysOff
SortOrder
Definition qnamespace.h:120
@ DescendingOrder
Definition qnamespace.h:122
@ AscendingOrder
Definition qnamespace.h:121
@ ElideNone
Definition qnamespace.h:191
#define Q_FALLTHROUGH()
EGLStreamKHR stream
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
static void unsetCursor(QWindow *w)
static const int maxSizeSection
static void qMoveRange(Container &c, typename Container::size_type rangeStart, typename Container::size_type rangeEnd, typename Container::size_type targetPosition)
static Qt::SortOrder flipOrder(Qt::SortOrder order)
QDataStream & operator>>(QDataStream &in, QHeaderViewPrivate::SectionItem &section)
QT_BEGIN_NAMESPACE QDataStream & operator<<(QDataStream &out, const QHeaderViewPrivate::SectionItem &section)
constexpr const T & qMin(const T &a, const T &b)
Definition qminmax.h:40
constexpr const T & qBound(const T &min, const T &val, const T &max)
Definition qminmax.h:44
constexpr const T & qMax(const T &a, const T &b)
Definition qminmax.h:42
constexpr T qAbs(const T &t)
Definition qnumeric.h:328
#define SLOT(a)
Definition qobjectdefs.h:51
#define SIGNAL(a)
Definition qobjectdefs.h:52
GLsizei const GLfloat * v
[13]
GLuint64 GLenum void * handle
GLenum mode
GLfloat GLfloat GLfloat w
[0]
GLint GLsizei GLsizei height
GLboolean GLboolean GLboolean GLboolean a
[7]
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLuint index
[2]
GLboolean r
[2]
GLuint GLuint end
GLenum GLuint GLenum GLsizei length
GLdouble GLdouble GLdouble GLdouble top
GLenum GLenum GLsizei count
GLdouble GLdouble right
GLint GLsizei width
GLint left
GLuint GLsizei const GLchar * label
[43]
GLint GLint bottom
GLenum target
GLboolean enable
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLuint start
GLenum GLuint GLintptr offset
const GLchar * marker
GLint first
GLfloat n
GLfloat GLfloat GLfloat GLfloat h
const GLubyte * c
GLuint in
GLdouble GLdouble GLdouble GLdouble q
Definition qopenglext.h:259
GLdouble s
[6]
Definition qopenglext.h:235
GLfloat GLfloat p
[1]
GLuint GLenum option
GLfixed GLfixed GLint GLint order
GLenum GLint GLint * precision
static qreal position(const QQuickItem *item, QQuickAnchors::Anchor anchorLine)
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
static QT_BEGIN_NAMESPACE QVariant hint(QPlatformIntegration::StyleHint h)
#define QT_CONFIG(feature)
#define emit
#define Q_UNUSED(x)
double qreal
Definition qtypes.h:92
QSqlQueryModel * model
[16]
view show()
[18] //! [19]
QTextStream out(stdout)
[7]
QScrollBar * scrollBar
QVariant variant
[1]
item setCursor(Qt::IBeamCursor)
[1]
QGraphicsItem * item
view viewport() -> scroll(dx, dy, deviceRect)
edit hide()
edit isVisible()
QItemSelection * selection
[0]
QPainter painter(this)
[7]
aWidget window() -> setWindowTitle("New Window Title")
[2]
label setFrameStyle(QFrame::Panel|QFrame::Raised)
QQuickView * view
[0]
QJSValue global
void write(QDataStream &out) const
IUIAutomationTreeWalker __RPC__deref_out_opt IUIAutomationElement ** parent