Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
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)
285 : QAbstractItemView(dd, parent)
286{
287 Q_D(QHeaderView);
288 d->setDefaultValues(orientation);
289 initialize();
290}
291
297{
298 Q_D(QHeaderView);
299 d->disconnectModel();
300}
301
306{
307 Q_D(QHeaderView);
308 setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
309 setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
310 setFrameStyle(NoFrame);
311 setFocusPolicy(Qt::NoFocus);
312 d->viewport->setMouseTracking(true);
313 d->viewport->setBackgroundRole(QPalette::Button);
314 d->textElideMode = Qt::ElideNone;
315 delete d->itemDelegate;
316}
317
322{
323 if (model == this->model())
324 return;
325 Q_D(QHeaderView);
326 d->layoutChangePersistentSections.clear();
327 if (d->model && d->model != QAbstractItemModelPrivate::staticEmptyModel())
328 d->disconnectModel();
329
331 const bool hor = d->orientation == Qt::Horizontal;
332 d->modelConnections = {
348
355 };
356 }
357
361
362 // Users want to set sizes and modes before the widget is shown.
363 // Thus, we have to initialize when the model is set,
364 // and not lazily like we do in the other views.
366}
367
375{
376 Q_D(const QHeaderView);
377 return d->orientation;
378}
379
388{
389 Q_D(const QHeaderView);
390 return d->headerOffset;
391}
392
401void QHeaderView::setOffset(int newOffset)
402{
403 Q_D(QHeaderView);
404 if (d->headerOffset == newOffset)
405 return;
406 int ndelta = d->headerOffset - newOffset;
407 d->headerOffset = newOffset;
408 if (d->orientation == Qt::Horizontal)
409 d->viewport->scroll(isRightToLeft() ? -ndelta : ndelta, 0);
410 else
411 d->viewport->scroll(0, ndelta);
412 if (d->state == QHeaderViewPrivate::ResizeSection && !d->preventCursorChangeInSetOffset) {
413 QPoint cursorPos = QCursor::pos();
414 if (d->orientation == Qt::Horizontal)
415 QCursor::setPos(cursorPos.x() + ndelta, cursorPos.y());
416 else
417 QCursor::setPos(cursorPos.x(), cursorPos.y() + ndelta);
418 d->firstPos += ndelta;
419 d->lastPos += ndelta;
420 }
421}
422
431void QHeaderView::setOffsetToSectionPosition(int visualSectionNumber)
432{
433 Q_D(QHeaderView);
434 if (visualSectionNumber > -1 && visualSectionNumber < d->sectionCount()) {
435 int position = d->headerSectionPosition(d->adjustedVisualIndex(visualSectionNumber));
437 }
438}
439
447{
448 Q_D(const QHeaderView);
449 int size = (d->orientation == Qt::Horizontal ? viewport()->width() : viewport()->height());
450 int position = length() - size;
452}
453
461{
462 Q_D(const QHeaderView);
463 d->executePostedLayout();
464 d->executePostedResize();
465 //Q_ASSERT(d->headerLength() == d->length);
466 return d->length;
467}
468
476{
477 Q_D(const QHeaderView);
478 if (d->cachedSizeHint.isValid())
479 return d->cachedSizeHint;
480 d->cachedSizeHint = QSize(0, 0); //reinitialize the cached size hint
481 const int sectionCount = count();
482
483 // get size hint for the first n sections
484 int i = 0;
485 for (int checked = 0; checked < 100 && i < sectionCount; ++i) {
486 if (isSectionHidden(i))
487 continue;
488 checked++;
490 d->cachedSizeHint = d->cachedSizeHint.expandedTo(hint);
491 }
492 // get size hint for the last n sections
493 i = qMax(i, sectionCount - 100 );
494 for (int j = sectionCount - 1, checked = 0; j >= i && checked < 100; --j) {
495 if (isSectionHidden(j))
496 continue;
497 checked++;
499 d->cachedSizeHint = d->cachedSizeHint.expandedTo(hint);
500 }
501 return d->cachedSizeHint;
502}
503
509{
510 bool actualChange = (v != isVisible());
511 QAbstractItemView::setVisible(v);
512 if (actualChange) {
513 QAbstractScrollArea *parent = qobject_cast<QAbstractScrollArea*>(parentWidget());
514 if (parent)
515 parent->updateGeometry();
516 }
517}
518
519
527int QHeaderView::sectionSizeHint(int logicalIndex) const
528{
529 Q_D(const QHeaderView);
531 return 0;
532 if (logicalIndex < 0 || logicalIndex >= count())
533 return -1;
534 QSize size;
535 QVariant value = d->model->headerData(logicalIndex, d->orientation, Qt::SizeHintRole);
536 if (value.isValid())
537 size = qvariant_cast<QSize>(value);
538 else
540 int hint = d->orientation == Qt::Horizontal ? size.width() : size.height();
542}
543
552{
553 Q_D(const QHeaderView);
554 int vposition = position;
555 d->executePostedLayout();
556 d->executePostedResize();
557 const int count = d->sectionCount();
558 if (count < 1)
559 return -1;
560
561 if (d->reverse())
562 vposition = d->viewport->width() - vposition - 1;
563 vposition += d->headerOffset;
564
565 if (vposition > d->length)
566 return -1;
567 int visual = d->headerVisualIndexAt(vposition);
568 if (visual < 0)
569 return -1;
570
571 while (d->isVisualIndexHidden(visual)){
572 ++visual;
573 if (visual >= count)
574 return -1;
575 }
576 return visual;
577}
578
586{
587 const int visual = visualIndexAt(position);
588 if (visual > -1)
589 return logicalIndex(visual);
590 return -1;
591}
592
600int QHeaderView::sectionSize(int logicalIndex) const
601{
602 Q_D(const QHeaderView);
604 return 0;
605 if (logicalIndex < 0 || logicalIndex >= count())
606 return 0;
607 int visual = visualIndex(logicalIndex);
608 if (visual == -1)
609 return 0;
610 d->executePostedResize();
611 return d->headerSectionSize(visual);
612}
613
625int QHeaderView::sectionPosition(int logicalIndex) const
626{
627 Q_D(const QHeaderView);
628 int visual = visualIndex(logicalIndex);
629 // in some cases users may change the selections
630 // before we have a chance to do the layout
631 if (visual == -1)
632 return -1;
633 d->executePostedResize();
634 return d->headerSectionPosition(visual);
635}
636
645int QHeaderView::sectionViewportPosition(int logicalIndex) const
646{
647 Q_D(const QHeaderView);
648 if (logicalIndex >= count())
649 return -1;
651 if (position < 0)
652 return position; // the section was hidden
653 int offsetPosition = position - d->headerOffset;
654 if (d->reverse())
655 return d->viewport->width() - (offsetPosition + sectionSize(logicalIndex));
656 return offsetPosition;
657}
658
677template<typename Container>
678static void qMoveRange(Container& c,
679 typename Container::size_type rangeStart,
680 typename Container::size_type rangeEnd,
681 typename Container::size_type targetPosition)
682{
683 Q_ASSERT(targetPosition <= c.size());
684 Q_ASSERT(targetPosition < rangeStart || targetPosition >= rangeEnd);
685
686 const bool forwardMove = targetPosition > rangeStart;
687 typename Container::size_type first = std::min(rangeStart, targetPosition);
688 typename Container::size_type mid = forwardMove ? rangeEnd : rangeStart;
689 typename Container::size_type last = forwardMove ? targetPosition + 1 : rangeEnd;
690 std::rotate(c.begin() + first, c.begin() + mid, c.begin() + last);
691}
692
699void QHeaderView::moveSection(int from, int to)
700{
701 Q_D(QHeaderView);
702
703 d->executePostedLayout();
704 if (from < 0 || from >= d->sectionCount() || to < 0 || to >= d->sectionCount())
705 return;
706
707 if (from == to) {
708 int logical = logicalIndex(from);
709 Q_ASSERT(logical != -1);
710 updateSection(logical);
711 return;
712 }
713
714 d->initializeIndexMapping();
715
716 int *visualIndices = d->visualIndices.data();
717 int *logicalIndices = d->logicalIndices.data();
718 int logical = logicalIndices[from];
719 int visual = from;
720
721 if (to > from) {
722 while (visual < to) {
723 visualIndices[logicalIndices[visual + 1]] = visual;
724 logicalIndices[visual] = logicalIndices[visual + 1];
725 ++visual;
726 }
727 } else {
728 while (visual > to) {
729 visualIndices[logicalIndices[visual - 1]] = visual;
730 logicalIndices[visual] = logicalIndices[visual - 1];
731 --visual;
732 }
733 }
734 visualIndices[logical] = to;
735 logicalIndices[to] = logical;
736
737 qMoveRange(d->sectionItems, from, from + 1, to);
738
739 d->sectionStartposRecalc = true;
740
741 if (d->hasAutoResizeSections())
742 d->doDelayedResizeSections();
743 d->viewport->update();
744
745 emit sectionMoved(logical, from, to);
746
747 if (stretchLastSection()) {
748 const int lastSectionVisualIdx = visualIndex(d->lastSectionLogicalIdx);
749 if (from >= lastSectionVisualIdx || to >= lastSectionVisualIdx)
750 d->maybeRestorePrevLastSectionAndStretchLast();
751 }
752}
753
761void QHeaderView::swapSections(int first, int second)
762{
763 Q_D(QHeaderView);
764
765 if (first == second)
766 return;
767 d->executePostedLayout();
768 if (first < 0 || first >= d->sectionCount() || second < 0 || second >= d->sectionCount())
769 return;
770
771 int firstSize = d->headerSectionSize(first);
772 ResizeMode firstMode = d->headerSectionResizeMode(first);
773 int firstLogical = d->logicalIndex(first);
774
775 int secondSize = d->headerSectionSize(second);
776 ResizeMode secondMode = d->headerSectionResizeMode(second);
777 int secondLogical = d->logicalIndex(second);
778
780 d->preventCursorChangeInSetOffset = true;
781
782 d->createSectionItems(second, second, firstSize, firstMode);
783 d->createSectionItems(first, first, secondSize, secondMode);
784
785 d->initializeIndexMapping();
786
787 d->visualIndices[firstLogical] = second;
788 d->logicalIndices[second] = firstLogical;
789
790 d->visualIndices[secondLogical] = first;
791 d->logicalIndices[first] = secondLogical;
792
793 if (!d->hiddenSectionSize.isEmpty()) {
794 bool firstHidden = d->isVisualIndexHidden(first);
795 bool secondHidden = d->isVisualIndexHidden(second);
796 d->setVisualIndexHidden(first, secondHidden);
797 d->setVisualIndexHidden(second, firstHidden);
798 }
799
800 d->viewport->update();
801 emit sectionMoved(firstLogical, first, second);
802 emit sectionMoved(secondLogical, second, first);
803
804 if (stretchLastSection()) {
805 const int lastSectionVisualIdx = visualIndex(d->lastSectionLogicalIdx);
806 if (first >= lastSectionVisualIdx || second >= lastSectionVisualIdx)
807 d->maybeRestorePrevLastSectionAndStretchLast();
808 }
809}
810
822void QHeaderView::resizeSection(int logical, int size)
823{
824 Q_D(QHeaderView);
825 if (logical < 0 || logical >= count() || size < 0 || size > maxSizeSection)
826 return;
827
828 // make sure to not exceed bounds when setting size programmatically
829 if (size > 0)
831
832 if (isSectionHidden(logical)) {
833 d->hiddenSectionSize.insert(logical, size);
834 return;
835 }
836
837 int visual = visualIndex(logical);
838 if (visual == -1)
839 return;
840
841 if (d->state == QHeaderViewPrivate::ResizeSection && !d->cascadingResizing && logical != d->section)
842 d->preventCursorChangeInSetOffset = true;
843
844 int oldSize = d->headerSectionSize(visual);
845 if (oldSize == size)
846 return;
847
848 d->executePostedLayout();
849 d->invalidateCachedSizeHint();
850
851 if (stretchLastSection() && logical == d->lastSectionLogicalIdx)
852 d->lastSectionSize = size;
853
854 d->createSectionItems(visual, visual, size, d->headerSectionResizeMode(visual));
855
856 if (!updatesEnabled()) {
857 if (d->hasAutoResizeSections())
858 d->doDelayedResizeSections();
859 emit sectionResized(logical, oldSize, size);
860 return;
861 }
862
863 int w = d->viewport->width();
864 int h = d->viewport->height();
865 int pos = sectionViewportPosition(logical);
866 QRect r;
867 if (d->orientation == Qt::Horizontal)
868 if (isRightToLeft())
869 r.setRect(0, 0, pos + size, h);
870 else
871 r.setRect(pos, 0, w - pos, h);
872 else
873 r.setRect(0, pos, w, h - pos);
874
875 if (d->hasAutoResizeSections()) {
876 d->doDelayedResizeSections();
877 r = d->viewport->rect();
878 }
879
880 // If the parent is a QAbstractScrollArea with QAbstractScrollArea::AdjustToContents
881 // then we want to change the geometry on that widget. Not doing it at once can/will
882 // cause scrollbars flicker as they would be shown at first but then removed.
883 // In the same situation it will also allow shrinking the whole view when stretchLastSection is set
884 // (It is default on QTreeViews - and it wouldn't shrink since the last stretch was made before the
885 // viewport was resized)
886
887 QAbstractScrollArea *parent = qobject_cast<QAbstractScrollArea *>(parentWidget());
888 if (parent && parent->sizeAdjustPolicy() == QAbstractScrollArea::AdjustToContents)
889 parent->updateGeometry();
890
891 d->viewport->update(r.normalized());
892 emit sectionResized(logical, oldSize, size);
893}
894
903{
904 Q_D(QHeaderView);
905 d->resizeSections(mode, true);
906}
907
931bool QHeaderView::isSectionHidden(int logicalIndex) const
932{
933 Q_D(const QHeaderView);
934 d->executePostedLayout();
935 if (d->hiddenSectionSize.isEmpty() || logicalIndex < 0 || logicalIndex >= d->sectionCount())
936 return false;
937 int visual = visualIndex(logicalIndex);
938 Q_ASSERT(visual != -1);
939 return d->isVisualIndexHidden(visual);
940}
941
950{
951 Q_D(const QHeaderView);
952 return d->hiddenSectionSize.size();
953}
954
962void QHeaderView::setSectionHidden(int logicalIndex, bool hide)
963{
964 Q_D(QHeaderView);
965 if (logicalIndex < 0 || logicalIndex >= count())
966 return;
967
968 d->executePostedLayout();
969 int visual = visualIndex(logicalIndex);
970 Q_ASSERT(visual != -1);
971 if (hide == d->isVisualIndexHidden(visual))
972 return;
973 if (hide) {
974 const bool isHidingLastSection = (stretchLastSection() && logicalIndex == d->lastSectionLogicalIdx);
975 if (isHidingLastSection)
976 d->restoreSizeOnPrevLastSection(); // Restore here/now to get the right restore size.
977 int size = d->headerSectionSize(visual);
978 if (!d->hasAutoResizeSections())
980 d->hiddenSectionSize.insert(logicalIndex, size);
981 d->setVisualIndexHidden(visual, true);
982 if (isHidingLastSection)
983 d->setNewLastSection(d->lastVisibleVisualIndex());
984 if (d->hasAutoResizeSections())
985 d->doDelayedResizeSections();
986 } else {
987 int size = d->hiddenSectionSize.value(logicalIndex, d->defaultSectionSize);
988 d->hiddenSectionSize.remove(logicalIndex);
989 d->setVisualIndexHidden(visual, false);
991
992 const bool newLastSection = (stretchLastSection() && visual > visualIndex(d->lastSectionLogicalIdx));
993 if (newLastSection) {
994 d->restoreSizeOnPrevLastSection();
995 d->setNewLastSection(visual);
996 }
997 }
998}
999
1007{
1008 Q_D(const QHeaderView);
1009 //Q_ASSERT(d->sectionCount == d->headerSectionCount());
1010 // ### this may affect the lazy layout
1011 d->executePostedLayout();
1012 return d->sectionCount();
1013}
1014
1024int QHeaderView::visualIndex(int logicalIndex) const
1025{
1026 Q_D(const QHeaderView);
1027 if (logicalIndex < 0)
1028 return -1;
1029 d->executePostedLayout();
1030 if (d->visualIndices.isEmpty()) { // nothing has been moved, so we have no mapping
1031 if (logicalIndex < d->sectionCount())
1032 return logicalIndex;
1033 } else if (logicalIndex < d->visualIndices.size()) {
1034 int visual = d->visualIndices.at(logicalIndex);
1035 Q_ASSERT(visual < d->sectionCount());
1036 return visual;
1037 }
1038 return -1;
1039}
1040
1050int QHeaderView::logicalIndex(int visualIndex) const
1051{
1052 Q_D(const QHeaderView);
1053 if (visualIndex < 0 || visualIndex >= d->sectionCount())
1054 return -1;
1055 return d->logicalIndex(visualIndex);
1056}
1057
1076{
1077 Q_D(QHeaderView);
1078 d->movableSections = movable;
1079}
1080
1085{
1086 Q_D(const QHeaderView);
1087 return d->movableSections;
1088}
1089
1115{
1116 Q_D(QHeaderView);
1117 d->allowUserMoveOfSection0 = movable;
1118}
1119
1121{
1122 Q_D(const QHeaderView);
1123 return d->allowUserMoveOfSection0;
1124}
1125
1139{
1140 Q_D(QHeaderView);
1141 d->clickableSections = clickable;
1142}
1143
1148{
1149 Q_D(const QHeaderView);
1150 return d->clickableSections;
1151}
1152
1154{
1155 Q_D(QHeaderView);
1156 d->highlightSelected = highlight;
1157}
1158
1160{
1161 Q_D(const QHeaderView);
1162 return d->highlightSelected;
1163}
1164
1175{
1176 Q_D(QHeaderView);
1178 d->stretchSections = (mode == Stretch ? count() : 0);
1179 d->contentsSections = (mode == ResizeToContents ? count() : 0);
1180 d->setGlobalHeaderResizeMode(mode);
1181 if (d->hasAutoResizeSections())
1182 d->doDelayedResizeSections(); // section sizes may change as a result of the new mode
1183}
1184
1200{
1201 Q_D(QHeaderView);
1202 int visual = visualIndex(logicalIndex);
1203 Q_ASSERT(visual != -1);
1204
1205 ResizeMode old = d->headerSectionResizeMode(visual);
1206 d->setHeaderSectionResizeMode(visual, mode);
1207
1208 if (mode == Stretch && old != Stretch)
1209 ++d->stretchSections;
1210 else if (mode == ResizeToContents && old != ResizeToContents)
1211 ++d->contentsSections;
1212 else if (mode != Stretch && old == Stretch)
1213 --d->stretchSections;
1214 else if (mode != ResizeToContents && old == ResizeToContents)
1215 --d->contentsSections;
1216
1217 if (d->hasAutoResizeSections() && d->state == QHeaderViewPrivate::NoState)
1218 d->doDelayedResizeSections(); // section sizes may change as a result of the new mode
1219}
1220
1231{
1232 Q_D(const QHeaderView);
1233 int visual = visualIndex(logicalIndex);
1234 if (visual == -1)
1235 return Fixed; //the default value
1236 return d->headerSectionResizeMode(visual);
1237}
1238
1262{
1263 Q_D(QHeaderView);
1264 d->resizeContentsPrecision = precision;
1265}
1266
1276{
1277 Q_D(const QHeaderView);
1278 return d->resizeContentsPrecision;
1279}
1280
1292{
1293 Q_D(const QHeaderView);
1294 return d->stretchSections;
1295}
1296
1307{
1308 Q_D(QHeaderView);
1309 if (d->sortIndicatorShown == show)
1310 return;
1311
1312 d->sortIndicatorShown = show;
1313
1315 return;
1316
1317 if (d->headerSectionResizeMode(sortIndicatorSection()) == ResizeToContents)
1319
1320 d->viewport->update();
1321}
1322
1324{
1325 Q_D(const QHeaderView);
1326 return d->sortIndicatorShown;
1327}
1328
1342{
1343 Q_D(QHeaderView);
1344
1345 // This is so that people can set the position of the sort indicator before the fill the model
1346 int old = d->sortIndicatorSection;
1347 if (old == logicalIndex && order == d->sortIndicatorOrder)
1348 return;
1349 d->sortIndicatorSection = logicalIndex;
1350 d->sortIndicatorOrder = order;
1351
1352 if (logicalIndex >= d->sectionCount()) {
1354 return; // nothing to do
1355 }
1356
1357 if (old != logicalIndex
1359 || old >= d->sectionCount() || (old >= 0 && sectionResizeMode(old) == ResizeToContents))) {
1361 d->viewport->update();
1362 } else {
1363 if (old >= 0 && old != logicalIndex)
1364 updateSection(old);
1365 if (logicalIndex >= 0)
1367 }
1368
1370}
1371
1380{
1381 Q_D(const QHeaderView);
1382 return d->sortIndicatorSection;
1383}
1384
1393{
1394 Q_D(const QHeaderView);
1395 return d->sortIndicatorOrder;
1396}
1397
1419{
1420 Q_D(QHeaderView);
1421 if (d->sortIndicatorClearable == clearable)
1422 return;
1423 d->sortIndicatorClearable = clearable;
1425}
1426
1428{
1429 Q_D(const QHeaderView);
1430 return d->sortIndicatorClearable;
1431}
1432
1449{
1450 Q_D(const QHeaderView);
1451 return d->stretchLastSection;
1452}
1453
1455{
1456 Q_D(QHeaderView);
1457 if (d->stretchLastSection == stretch)
1458 return;
1459 d->stretchLastSection = stretch;
1460 if (d->state != QHeaderViewPrivate::NoState)
1461 return;
1462 if (stretch) {
1463 d->setNewLastSection(d->lastVisibleVisualIndex());
1465 } else {
1466 d->restoreSizeOnPrevLastSection();
1467 }
1468}
1469
1485{
1486 Q_D(const QHeaderView);
1487 return d->cascadingResizing;
1488}
1489
1491{
1492 Q_D(QHeaderView);
1493 d->cascadingResizing = enable;
1494}
1495
1511{
1512 Q_D(const QHeaderView);
1513 return d->defaultSectionSize;
1514}
1515
1517{
1518 Q_D(QHeaderView);
1519 if (size < 0 || size > maxSizeSection)
1520 return;
1521 d->setDefaultSectionSize(size);
1522}
1523
1525{
1526 Q_D(QHeaderView);
1527 if (d->customDefaultSectionSize) {
1528 d->updateDefaultSectionSizeFromStyle();
1529 d->customDefaultSectionSize = false;
1530 }
1531}
1532
1547{
1548 Q_D(const QHeaderView);
1549 if (d->minimumSectionSize == -1) {
1550 int margin = 2 * style()->pixelMetric(QStyle::PM_HeaderMargin, nullptr, this);
1551 if (d->orientation == Qt::Horizontal)
1552 return fontMetrics().maxWidth() + margin;
1553 return fontMetrics().height() + margin;
1554 }
1555 return d->minimumSectionSize;
1556}
1557
1559{
1560 Q_D(QHeaderView);
1561 if (size < -1 || size > maxSizeSection)
1562 return;
1563 // larger new min size - check current section sizes
1564 const bool needSizeCheck = size > d->minimumSectionSize;
1565 d->minimumSectionSize = size;
1566 if (d->minimumSectionSize > maximumSectionSize())
1568
1569 if (needSizeCheck) {
1570 if (d->hasAutoResizeSections()) {
1571 d->doDelayedResizeSections();
1572 } else {
1573 for (int visual = 0; visual < d->sectionCount(); ++visual) {
1574 if (d->isVisualIndexHidden(visual))
1575 continue;
1576 if (d->headerSectionSize(visual) < d->minimumSectionSize)
1578 }
1579 }
1580 }
1581
1582}
1583
1599{
1600 Q_D(const QHeaderView);
1601 if (d->maximumSectionSize == -1)
1602 return maxSizeSection;
1603 return d->maximumSectionSize;
1604}
1605
1607{
1608 Q_D(QHeaderView);
1609 if (size == -1) {
1610 d->maximumSectionSize = maxSizeSection;
1611 return;
1612 }
1613 if (size < 0 || size > maxSizeSection)
1614 return;
1615 if (minimumSectionSize() > size)
1616 d->minimumSectionSize = size;
1617
1618 // smaller new max size - check current section sizes
1619 const bool needSizeCheck = size < d->maximumSectionSize;
1620 d->maximumSectionSize = size;
1621
1622 if (needSizeCheck) {
1623 if (d->hasAutoResizeSections()) {
1624 d->doDelayedResizeSections();
1625 } else {
1626 for (int visual = 0; visual < d->sectionCount(); ++visual) {
1627 if (d->isVisualIndexHidden(visual))
1628 continue;
1629 if (d->headerSectionSize(visual) > d->maximumSectionSize)
1631 }
1632 }
1633 }
1634}
1635
1636
1644{
1645 Q_D(const QHeaderView);
1646 return d->defaultAlignment;
1647}
1648
1650{
1651 Q_D(QHeaderView);
1652 if (d->defaultAlignment == alignment)
1653 return;
1654
1655 d->defaultAlignment = alignment;
1656 d->viewport->update();
1657}
1658
1667
1675{
1676 Q_D(const QHeaderView);
1677 return !d->visualIndices.isEmpty();
1678}
1679
1689{
1690 Q_D(const QHeaderView);
1691 return !d->hiddenSectionSize.isEmpty();
1692}
1693
1694#ifndef QT_NO_DATASTREAM
1705{
1706 Q_D(const QHeaderView);
1709 stream.setVersion(QDataStream::Qt_5_0);
1711 stream << 0; // current version is 0
1712 d->write(stream);
1713 return data;
1714}
1715
1725{
1726 Q_D(QHeaderView);
1727 if (state.isEmpty())
1728 return false;
1729
1730 for (const auto dataStreamVersion : {QDataStream::Qt_5_0, QDataStream::Qt_6_0}) {
1731
1734 stream.setVersion(dataStreamVersion);
1735 int marker;
1736 int ver;
1737 stream >> marker;
1738 stream >> ver;
1739 if (stream.status() != QDataStream::Ok
1741 || ver != 0) { // current version is 0
1742 return false;
1743 }
1744
1745 if (d->read(stream)) {
1746 emit sortIndicatorChanged(d->sortIndicatorSection, d->sortIndicatorOrder );
1747 d->viewport->update();
1748 return true;
1749 }
1750 }
1751 return false;
1752}
1753#endif // QT_NO_DATASTREAM
1754
1759{
1760 Q_D(QHeaderView);
1762 // it would be correct to call clear, but some apps rely
1763 // on the header keeping the sections, even after calling reset
1764 //d->clear();
1766 d->invalidateCachedSizeHint();
1767}
1768
1773void QHeaderView::headerDataChanged(Qt::Orientation orientation, int logicalFirst, int logicalLast)
1774{
1775 Q_D(QHeaderView);
1776 if (d->orientation != orientation)
1777 return;
1778
1779 if (logicalFirst < 0 || logicalLast < 0 || logicalFirst >= count() || logicalLast >= count())
1780 return;
1781
1782 d->invalidateCachedSizeHint();
1783
1784 int firstVisualIndex = INT_MAX, lastVisualIndex = -1;
1785
1786 for (int section = logicalFirst; section <= logicalLast; ++section) {
1787 const int visual = visualIndex(section);
1788 firstVisualIndex = qMin(firstVisualIndex, visual);
1789 lastVisualIndex = qMax(lastVisualIndex, visual);
1790 }
1791
1792 d->executePostedResize();
1793 const int first = d->headerSectionPosition(firstVisualIndex),
1794 last = d->headerSectionPosition(lastVisualIndex)
1795 + d->headerSectionSize(lastVisualIndex);
1796
1797 if (orientation == Qt::Horizontal) {
1798 d->viewport->update(first, 0, last - first, d->viewport->height());
1799 } else {
1800 d->viewport->update(0, first, d->viewport->width(), last - first);
1801 }
1802}
1803
1811void QHeaderView::updateSection(int logicalIndex)
1812{
1813 Q_D(QHeaderView);
1814 if (d->orientation == Qt::Horizontal)
1815 d->viewport->update(QRect(sectionViewportPosition(logicalIndex),
1816 0, sectionSize(logicalIndex), d->viewport->height()));
1817 else
1818 d->viewport->update(QRect(0, sectionViewportPosition(logicalIndex),
1819 d->viewport->width(), sectionSize(logicalIndex)));
1820}
1821
1828{
1829 Q_D(QHeaderView);
1830 if (d->hasAutoResizeSections())
1831 d->resizeSections(Interactive, false); // no global resize mode
1832}
1833
1844 int logicalFirst, int logicalLast)
1845{
1846 Q_D(QHeaderView);
1847 // only handle root level changes and return on no-op
1848 if (parent != d->root || d->modelSectionCount() == d->sectionCount())
1849 return;
1850 int oldCount = d->sectionCount();
1851
1852 d->invalidateCachedSizeHint();
1853
1855 d->preventCursorChangeInSetOffset = true;
1856
1857 // add the new sections
1858 int insertAt = logicalFirst;
1859 int insertCount = logicalLast - logicalFirst + 1;
1860
1861 bool lastSectionActualChange = false;
1862 if (stretchLastSection()) {
1863
1864 int visualIndexForStretch = d->lastSectionLogicalIdx;
1865 if (d->lastSectionLogicalIdx >= 0 && d->lastSectionLogicalIdx < d->visualIndices.size())
1866 visualIndexForStretch = d->visualIndices[d->lastSectionLogicalIdx]; // We cannot call visualIndex since it executes executePostedLayout()
1867 // and it is likely to bypass initializeSections() and we may end up here again. Doing the insert twice.
1868
1869 if (d->lastSectionLogicalIdx < 0 || insertAt >= visualIndexForStretch)
1870 lastSectionActualChange = true;
1871
1872 if (d->lastSectionLogicalIdx >= logicalFirst)
1873 d->lastSectionLogicalIdx += insertCount; // We do not want to emit resize before we have fixed the count
1874 }
1875
1876 QHeaderViewPrivate::SectionItem section(d->defaultSectionSize, d->globalResizeMode);
1877 d->sectionStartposRecalc = true;
1878
1879 if (d->sectionItems.isEmpty() || insertAt >= d->sectionItems.size()) {
1880 int insertLength = d->defaultSectionSize * insertCount;
1881 d->length += insertLength;
1882 d->sectionItems.insert(d->sectionItems.size(), insertCount, section); // append
1883 } else {
1884 // separate them out into their own sections
1885 int insertLength = d->defaultSectionSize * insertCount;
1886 d->length += insertLength;
1887 d->sectionItems.insert(insertAt, insertCount, section);
1888 }
1889
1890 // update sorting column
1891 if (d->sortIndicatorSection >= logicalFirst)
1892 d->sortIndicatorSection += insertCount;
1893
1894 // update resize mode section counts
1895 if (d->globalResizeMode == Stretch)
1896 d->stretchSections = d->sectionCount();
1897 else if (d->globalResizeMode == ResizeToContents)
1898 d->contentsSections = d->sectionCount();
1899
1900 // clear selection cache
1901 d->sectionSelected.clear();
1902
1903 // update mapping
1904 if (!d->visualIndices.isEmpty() && !d->logicalIndices.isEmpty()) {
1905 Q_ASSERT(d->visualIndices.size() == d->logicalIndices.size());
1906 int mappingCount = d->visualIndices.size();
1907 for (int i = 0; i < mappingCount; ++i) {
1908 if (d->visualIndices.at(i) >= logicalFirst)
1909 d->visualIndices[i] += insertCount;
1910 if (d->logicalIndices.at(i) >= logicalFirst)
1911 d->logicalIndices[i] += insertCount;
1912 }
1913 for (int j = logicalFirst; j <= logicalLast; ++j) {
1914 d->visualIndices.insert(j, j);
1915 d->logicalIndices.insert(j, j);
1916 }
1917 }
1918
1919 // insert sections into hiddenSectionSize
1920 QHash<int, int> newHiddenSectionSize; // from logical index to section size
1921 for (QHash<int, int>::const_iterator it = d->hiddenSectionSize.cbegin(),
1922 end = d->hiddenSectionSize.cend(); it != end; ++it) {
1923 const int oldIndex = it.key();
1924 const int newIndex = (oldIndex < logicalFirst) ? oldIndex : oldIndex + insertCount;
1925 newHiddenSectionSize[newIndex] = it.value();
1926 }
1927 d->hiddenSectionSize.swap(newHiddenSectionSize);
1928
1929 d->doDelayedResizeSections();
1930 emit sectionCountChanged(oldCount, count());
1931
1932 if (lastSectionActualChange)
1933 d->maybeRestorePrevLastSectionAndStretchLast();
1934
1935 // if the new sections were not updated by resizing, we need to update now
1936 if (!d->hasAutoResizeSections())
1937 d->viewport->update();
1938}
1939
1949 int logicalFirst, int logicalLast)
1950{
1951 Q_UNUSED(parent);
1952 Q_UNUSED(logicalFirst);
1953 Q_UNUSED(logicalLast);
1954}
1955
1956void QHeaderViewPrivate::updateHiddenSections(int logicalFirst, int logicalLast)
1957{
1958 Q_Q(QHeaderView);
1959 const int changeCount = logicalLast - logicalFirst + 1;
1960
1961 // remove sections from hiddenSectionSize
1962 QHash<int, int> newHiddenSectionSize; // from logical index to section size
1963 for (int i = 0; i < logicalFirst; ++i)
1964 if (q->isSectionHidden(i))
1965 newHiddenSectionSize[i] = hiddenSectionSize[i];
1966 for (int j = logicalLast + 1; j < sectionCount(); ++j)
1967 if (q->isSectionHidden(j))
1968 newHiddenSectionSize[j - changeCount] = hiddenSectionSize[j];
1969 hiddenSectionSize = newHiddenSectionSize;
1970}
1971
1973 int logicalFirst, int logicalLast)
1974{
1975 Q_Q(QHeaderView);
1976 if (parent != root)
1977 return; // we only handle changes in the root level
1978 if (qMin(logicalFirst, logicalLast) < 0
1979 || qMax(logicalLast, logicalFirst) >= sectionCount())
1980 return;
1981 int oldCount = q->count();
1982 int changeCount = logicalLast - logicalFirst + 1;
1983
1986
1987 updateHiddenSections(logicalFirst, logicalLast);
1988
1990 //Q_ASSERT(headerSectionCount() == sectionCount);
1991 removeSectionsFromSectionItems(logicalFirst, logicalLast);
1992 } else {
1993 if (logicalFirst == logicalLast) { // Remove just one index.
1994 int l = logicalFirst;
1995 int visual = visualIndices.at(l);
1997 for (int v = 0; v < sectionCount(); ++v) {
1998 if (v > visual) {
1999 int logical = logicalIndices.at(v);
2000 --(visualIndices[logical]);
2001 }
2002 if (logicalIndex(v) > l) // no need to move the positions before l
2003 --(logicalIndices[v]);
2004 }
2005 logicalIndices.remove(visual);
2007 //Q_ASSERT(headerSectionCount() == sectionCount);
2008 removeSectionsFromSectionItems(visual, visual);
2009 } else {
2010 sectionStartposRecalc = true; // We will need to recalc positions after removing items
2011 for (int u = 0; u < sectionItems.size(); ++u) // Store section info
2012 sectionItems.at(u).tmpLogIdx = logicalIndices.at(u);
2013 for (int v = sectionItems.size() - 1; v >= 0; --v) { // Remove the sections
2014 if (logicalFirst <= sectionItems.at(v).tmpLogIdx && sectionItems.at(v).tmpLogIdx <= logicalLast)
2016 }
2019 int* visual_data = visualIndices.data();
2020 int* logical_data = logicalIndices.data();
2021 for (int w = 0; w < sectionItems.size(); ++w) { // Restore visual and logical indexes
2022 int logindex = sectionItems.at(w).tmpLogIdx;
2023 if (logindex > logicalFirst)
2024 logindex -= changeCount;
2025 visual_data[logindex] = w;
2026 logical_data[w] = logindex;
2027 }
2028 }
2029 // ### handle sectionSelection (sectionHidden is handled by updateHiddenSections)
2030 }
2031
2032 // update sorting column
2033 if (sortIndicatorSection >= logicalFirst) {
2034 if (sortIndicatorSection <= logicalLast)
2036 else
2037 sortIndicatorSection -= changeCount;
2038 }
2039
2040 // if we only have the last section (the "end" position) left, the header is empty
2041 if (sectionCount() <= 0)
2042 clear();
2044 emit q->sectionCountChanged(oldCount, q->count());
2045
2046 if (q->stretchLastSection()) {
2047 const bool lastSectionRemoved = lastSectionLogicalIdx >= logicalFirst && lastSectionLogicalIdx <= logicalLast;
2048 if (lastSectionRemoved)
2050 else
2051 lastSectionLogicalIdx = logicalIndex(lastVisibleVisualIndex()); // Just update the last log index.
2053 }
2054
2055 viewport->update();
2056}
2057
2058void QHeaderViewPrivate::sectionsAboutToBeMoved(const QModelIndex &sourceParent, int logicalStart,
2059 int logicalEnd, const QModelIndex &destinationParent,
2060 int logicalDestination)
2061{
2062 if (sourceParent != root || destinationParent != root)
2063 return; // we only handle changes in the root level
2064 Q_UNUSED(logicalStart);
2065 Q_UNUSED(logicalEnd);
2066 Q_UNUSED(logicalDestination);
2068}
2069
2070void QHeaderViewPrivate::sectionsMoved(const QModelIndex &sourceParent, int logicalStart,
2071 int logicalEnd, const QModelIndex &destinationParent,
2072 int logicalDestination)
2073{
2074 if (sourceParent != root || destinationParent != root)
2075 return; // we only handle changes in the root level
2076 Q_UNUSED(logicalStart);
2077 Q_UNUSED(logicalEnd);
2078 Q_UNUSED(logicalDestination);
2080}
2081
2082void QHeaderViewPrivate::sectionsAboutToBeChanged(const QList<QPersistentModelIndex> &,
2084{
2087 return;
2088
2089 //if there is no row/column we can't have mapping for columns
2090 //because no QModelIndex in the model would be valid
2091 // ### this is far from being bullet-proof and we would need a real system to
2092 // ### map columns or rows persistently
2093 if ((orientation == Qt::Horizontal && model->rowCount(root) == 0)
2094 || model->columnCount(root) == 0)
2095 return;
2096
2098 layoutChangePersistentSections.reserve(std::min(10, int(sectionItems.size())));
2099 // after layoutChanged another section can be last stretched section
2101 const int visual = visualIndex(lastSectionLogicalIdx);
2102 if (visual >= 0 && visual < sectionItems.size()) {
2103 auto &itemRef = sectionItems[visual];
2104 if (itemRef.size != lastSectionSize) {
2105 length += lastSectionSize - itemRef.size;
2106 itemRef.size = lastSectionSize;
2107 }
2108 }
2109 }
2110 for (int i = 0; i < sectionItems.size(); ++i) {
2111 auto s = sectionItems.at(i);
2112 // only add if the section is not default and not visually moved
2113 if (s.size == defaultSectionSize && !s.isHidden && s.resizeMode == globalResizeMode)
2114 continue;
2115
2116 const int logical = logicalIndex(i);
2117 if (s.isHidden)
2118 s.size = hiddenSectionSize.value(logical);
2119
2120 // ### note that we are using column or row 0
2122 ? model->index(0, logical, root)
2123 : model->index(logical, 0, root),
2124 s});
2125 }
2126}
2127
2128void QHeaderViewPrivate::sectionsChanged(const QList<QPersistentModelIndex> &,
2130{
2133 return;
2134
2135 Q_Q(QHeaderView);
2136 viewport->update();
2137
2138 const auto oldPersistentSections = layoutChangePersistentSections;
2140
2141 const int newCount = modelSectionCount();
2142 const int oldCount = sectionItems.size();
2143 if (newCount == 0) {
2144 clear();
2145 if (oldCount != 0)
2146 emit q->sectionCountChanged(oldCount, 0);
2147 return;
2148 }
2149
2150 bool hasPersistantIndexes = false;
2151 for (const auto &item : oldPersistentSections) {
2152 if (item.index.isValid()) {
2153 hasPersistantIndexes = true;
2154 break;
2155 }
2156 }
2157
2158 // Though far from perfect we here try to retain earlier/existing behavior
2159 // ### See QHeaderViewPrivate::layoutAboutToBeChanged()
2160 // When we don't have valid hasPersistantIndexes it can be due to
2161 // - all sections are default sections
2162 // - the row/column 0 which is used for persistent indexes is gone
2163 // - all non-default sections were removed
2164 // case one is trivial, in case two we assume nothing else changed (it's the best
2165 // guess we can do - everything else can not be handled correctly for now)
2166 // case three can not be handled correctly with layoutChanged - removeSections
2167 // should be used instead for this
2168 if (!hasPersistantIndexes) {
2169 if (oldCount != newCount)
2170 q->initializeSections();
2171 return;
2172 }
2173
2174 // adjust section size
2175 if (newCount != oldCount) {
2176 const int min = qBound(0, oldCount, newCount - 1);
2177 q->initializeSections(min, newCount - 1);
2178 }
2179 // reset sections
2181
2182 // all hidden sections are in oldPersistentSections
2184
2185 for (const auto &item : oldPersistentSections) {
2186 const auto &index = item.index;
2187 if (!index.isValid())
2188 continue;
2189
2190 const int newLogicalIndex = (orientation == Qt::Horizontal
2191 ? index.column()
2192 : index.row());
2193 // the new visualIndices are already adjusted / reset by initializeSections()
2194 const int newVisualIndex = visualIndex(newLogicalIndex);
2195 if (newVisualIndex < sectionItems.size()) {
2196 auto &newSection = sectionItems[newVisualIndex];
2197 newSection = item.section;
2198
2199 if (newSection.isHidden) {
2200 // otherwise setSectionHidden will return without doing anything
2201 newSection.isHidden = false;
2202 q->setSectionHidden(newLogicalIndex, true);
2203 }
2204 }
2205 }
2206
2208 length = headerLength();
2209
2210 if (stretchLastSection) {
2211 // force rebuild of stretched section later on
2214 }
2215}
2216
2222{
2223 Q_D(QHeaderView);
2224 const int oldCount = d->sectionCount();
2225 const int newCount = d->modelSectionCount();
2226 if (newCount <= 0) {
2227 d->clear();
2228 emit sectionCountChanged(oldCount, 0);
2229 } else if (newCount != oldCount) {
2230 const int min = qBound(0, oldCount, newCount - 1);
2231 initializeSections(min, newCount - 1);
2232 if (stretchLastSection()) // we've already gotten the size hint
2233 d->maybeRestorePrevLastSectionAndStretchLast();
2234
2235 // make sure we update the hidden sections
2236 // simulate remove from newCount to oldCount
2237 if (newCount < oldCount)
2238 d->updateHiddenSections(newCount, oldCount);
2239 }
2240}
2241
2247{
2248 Q_D(QHeaderView);
2249
2250 Q_ASSERT(start >= 0);
2251 Q_ASSERT(end >= 0);
2252
2253 d->invalidateCachedSizeHint();
2254 int oldCount = d->sectionCount();
2255
2256 if (end + 1 < d->sectionCount()) {
2257 int newCount = end + 1;
2258 d->removeSectionsFromSectionItems(newCount, d->sectionCount() - 1);
2259 if (!d->hiddenSectionSize.isEmpty()) {
2260 if (oldCount - newCount > d->hiddenSectionSize.size()) {
2261 for (int i = end + 1; i < d->sectionCount(); ++i)
2262 d->hiddenSectionSize.remove(i);
2263 } else {
2264 QHash<int, int>::iterator it = d->hiddenSectionSize.begin();
2265 while (it != d->hiddenSectionSize.end()) {
2266 if (it.key() > end)
2267 it = d->hiddenSectionSize.erase(it);
2268 else
2269 ++it;
2270 }
2271 }
2272 }
2273 }
2274
2275 int newSectionCount = end + 1;
2276
2277 if (!d->logicalIndices.isEmpty()) {
2278 if (oldCount <= newSectionCount) {
2279 d->logicalIndices.resize(newSectionCount);
2280 d->visualIndices.resize(newSectionCount);
2281 for (int i = oldCount; i < newSectionCount; ++i) {
2282 d->logicalIndices[i] = i;
2283 d->visualIndices[i] = i;
2284 }
2285 } else {
2286 int j = 0;
2287 for (int i = 0; i < oldCount; ++i) {
2288 int v = d->logicalIndices.at(i);
2289 if (v < newSectionCount) {
2290 d->logicalIndices[j] = v;
2291 d->visualIndices[v] = j;
2292 j++;
2293 }
2294 }
2295 d->logicalIndices.resize(newSectionCount);
2296 d->visualIndices.resize(newSectionCount);
2297 }
2298 }
2299
2300 if (d->globalResizeMode == Stretch)
2301 d->stretchSections = newSectionCount;
2302 else if (d->globalResizeMode == ResizeToContents)
2303 d->contentsSections = newSectionCount;
2304
2305 if (newSectionCount > oldCount)
2306 d->createSectionItems(start, end, d->defaultSectionSize, d->globalResizeMode);
2307 //Q_ASSERT(d->headerLength() == d->length);
2308
2309 if (d->sectionCount() != oldCount)
2310 emit sectionCountChanged(oldCount, d->sectionCount());
2311 d->viewport->update();
2312}
2313
2319{
2320 Q_D(QHeaderView);
2321
2322 if (d->orientation == Qt::Horizontal && current.column() != old.column()) {
2323 if (old.isValid() && old.parent() == d->root)
2324 d->viewport->update(QRect(sectionViewportPosition(old.column()), 0,
2325 sectionSize(old.column()), d->viewport->height()));
2326 if (current.isValid() && current.parent() == d->root)
2327 d->viewport->update(QRect(sectionViewportPosition(current.column()), 0,
2328 sectionSize(current.column()), d->viewport->height()));
2329 } else if (d->orientation == Qt::Vertical && current.row() != old.row()) {
2330 if (old.isValid() && old.parent() == d->root)
2331 d->viewport->update(QRect(0, sectionViewportPosition(old.row()),
2332 d->viewport->width(), sectionSize(old.row())));
2333 if (current.isValid() && current.parent() == d->root)
2334 d->viewport->update(QRect(0, sectionViewportPosition(current.row()),
2335 d->viewport->width(), sectionSize(current.row())));
2336 }
2337}
2338
2339
2345{
2346 Q_D(QHeaderView);
2347 switch (e->type()) {
2348 case QEvent::HoverEnter: {
2349 QHoverEvent *he = static_cast<QHoverEvent*>(e);
2350 d->hover = logicalIndexAt(he->position().toPoint());
2351 if (d->hover != -1)
2352 updateSection(d->hover);
2353 break; }
2354 case QEvent::Leave:
2355 case QEvent::HoverLeave: {
2356 if (d->hover != -1)
2357 updateSection(d->hover);
2358 d->hover = -1;
2359 break; }
2360 case QEvent::HoverMove: {
2361 QHoverEvent *he = static_cast<QHoverEvent*>(e);
2362 int oldHover = d->hover;
2363 d->hover = logicalIndexAt(he->position().toPoint());
2364 if (d->hover != oldHover) {
2365 if (oldHover != -1)
2366 updateSection(oldHover);
2367 if (d->hover != -1)
2368 updateSection(d->hover);
2369 }
2370 break; }
2371 case QEvent::Timer: {
2372 QTimerEvent *te = static_cast<QTimerEvent*>(e);
2373 if (te->timerId() == d->delayedResize.timerId()) {
2374 d->delayedResize.stop();
2376 }
2377 break; }
2379 if (!d->customDefaultSectionSize)
2380 d->updateDefaultSectionSizeFromStyle();
2381 break;
2382 default:
2383 break;
2384 }
2385 return QAbstractItemView::event(e);
2386}
2387
2393{
2394 Q_D(QHeaderView);
2395
2396 if (count() == 0)
2397 return;
2398
2399 QPainter painter(d->viewport);
2400 const QPoint offset = d->scrollDelayOffset;
2401 QRect translatedEventRect = e->rect();
2402 translatedEventRect.translate(offset);
2403
2404 int start = -1;
2405 int end = -1;
2406 if (d->orientation == Qt::Horizontal) {
2407 start = visualIndexAt(translatedEventRect.left());
2408 end = visualIndexAt(translatedEventRect.right());
2409 } else {
2410 start = visualIndexAt(translatedEventRect.top());
2411 end = visualIndexAt(translatedEventRect.bottom());
2412 }
2413
2414 if (d->reverse()) {
2415 start = (start == -1 ? count() - 1 : start);
2416 end = (end == -1 ? 0 : end);
2417 } else {
2418 start = (start == -1 ? 0 : start);
2419 end = (end == -1 ? count() - 1 : end);
2420 }
2421
2422 int tmp = start;
2423 start = qMin(start, end);
2424 end = qMax(tmp, end);
2425
2426 d->prepareSectionSelected(); // clear and resize the bit array
2427
2428 QRect currentSectionRect;
2429 const int width = d->viewport->width();
2430 const int height = d->viewport->height();
2431 const int rtlHorizontalOffset = d->reverse() ? 1 : 0;
2432 for (int i = start; i <= end; ++i) {
2433 if (d->isVisualIndexHidden(i))
2434 continue;
2435 painter.save();
2436 const int logical = logicalIndex(i);
2437 if (d->orientation == Qt::Horizontal) {
2438 currentSectionRect.setRect(sectionViewportPosition(logical) + rtlHorizontalOffset,
2439 0, sectionSize(logical), height);
2440 } else {
2441 currentSectionRect.setRect(0, sectionViewportPosition(logical),
2442 width, sectionSize(logical));
2443 }
2444 currentSectionRect.translate(offset);
2445
2446 QVariant variant = d->model->headerData(logical, d->orientation,
2447 Qt::FontRole);
2448 if (variant.isValid() && variant.canConvert<QFont>()) {
2449 QFont sectionFont = qvariant_cast<QFont>(variant);
2450 painter.setFont(sectionFont);
2451 }
2452 paintSection(&painter, currentSectionRect, logical);
2453 painter.restore();
2454 }
2455
2457 opt.initFrom(this);
2458 // Paint the area beyond where there are indexes
2459 if (d->reverse()) {
2461 if (currentSectionRect.left() > translatedEventRect.left()) {
2462 opt.rect = QRect(translatedEventRect.left(), 0,
2463 currentSectionRect.left() - translatedEventRect.left(), height);
2464 style()->drawControl(QStyle::CE_HeaderEmptyArea, &opt, &painter, this);
2465 }
2466 } else if (currentSectionRect.right() < translatedEventRect.right()) {
2467 // paint to the right
2469 opt.rect = QRect(currentSectionRect.right() + 1, 0,
2470 translatedEventRect.right() - currentSectionRect.right(), height);
2471 style()->drawControl(QStyle::CE_HeaderEmptyArea, &opt, &painter, this);
2472 } else if (currentSectionRect.bottom() < translatedEventRect.bottom()) {
2473 // paint the bottom section
2474 opt.state &= ~QStyle::State_Horizontal;
2475 opt.rect = QRect(0, currentSectionRect.bottom() + 1,
2476 width, height - currentSectionRect.bottom() - 1);
2477 style()->drawControl(QStyle::CE_HeaderEmptyArea, &opt, &painter, this);
2478 }
2479
2480#if 0
2481 // ### visualize sections
2482 for (int a = 0, i = 0; i < d->sectionItems.count(); ++i) {
2483 QColor color((i & 4 ? 255 : 0), (i & 2 ? 255 : 0), (i & 1 ? 255 : 0));
2484 if (d->orientation == Qt::Horizontal)
2485 painter.fillRect(a - d->headerOffset, 0, d->sectionItems.at(i).size, 4, color);
2486 else
2487 painter.fillRect(0, a - d->headerOffset, 4, d->sectionItems.at(i).size, color);
2488 a += d->sectionItems.at(i).size;
2489 }
2490
2491#endif
2492}
2493
2499{
2500 Q_D(QHeaderView);
2501 if (d->state != QHeaderViewPrivate::NoState || e->button() != Qt::LeftButton)
2502 return;
2503 int pos = d->orientation == Qt::Horizontal ? e->position().toPoint().x() : e->position().toPoint().y();
2504 int handle = d->sectionHandleAt(pos);
2505 d->originalSize = -1; // clear the stored original size
2506 if (handle == -1) {
2507 d->firstPressed = d->pressed = logicalIndexAt(pos);
2508 if (d->clickableSections)
2509 emit sectionPressed(d->pressed);
2510
2511 bool acceptMoveSection = d->movableSections;
2512 if (acceptMoveSection && d->pressed == 0 && !d->allowUserMoveOfSection0)
2513 acceptMoveSection = false; // Do not allow moving the tree nod
2514
2515 if (acceptMoveSection) {
2516 d->target = -1;
2517 d->section = d->pressed;
2518 if (d->section == -1)
2519 return;
2521 d->setupSectionIndicator(d->section, pos);
2522 } else if (d->clickableSections && d->pressed != -1) {
2523 updateSection(d->pressed);
2525 }
2526 } else if (sectionResizeMode(handle) == Interactive) {
2527 d->originalSize = sectionSize(handle);
2529 d->section = handle;
2530 d->preventCursorChangeInSetOffset = false;
2531 }
2532
2533 d->firstPos = pos;
2534 d->lastPos = pos;
2535
2536 d->clearCascadingSections();
2537}
2538
2544{
2545 Q_D(QHeaderView);
2546 const int pos = d->orientation == Qt::Horizontal ? e->position().toPoint().x() : e->position().toPoint().y();
2547 if (pos < 0 && d->state != QHeaderViewPrivate::SelectSections)
2548 return;
2549 if (e->buttons() == Qt::NoButton) {
2550 // Under Cocoa, when the mouse button is released, may include an extra
2551 // simulated mouse moved event. The state of the buttons when this event
2552 // is generated is already "no button" and the code below gets executed
2553 // just before the mouseReleaseEvent and resets the state. This prevents
2554 // column dragging from working. So this code is disabled under Cocoa.
2556 d->firstPressed = d->pressed = -1;
2557 }
2558 switch (d->state) {
2560 Q_ASSERT(d->originalSize != -1);
2561 if (d->cascadingResizing) {
2562 int delta = d->reverse() ? d->lastPos - pos : pos - d->lastPos;
2563 int visual = visualIndex(d->section);
2564 d->cascadingResize(visual, d->headerSectionSize(visual) + delta);
2565 } else {
2566 int delta = d->reverse() ? d->firstPos - pos : pos - d->firstPos;
2567 int newsize = qBound(minimumSectionSize(), d->originalSize + delta, maximumSectionSize());
2568 resizeSection(d->section, newsize);
2569 }
2570 d->lastPos = pos;
2571 return;
2572 }
2574 if (d->shouldAutoScroll(e->position().toPoint())) {
2575 d->draggedPosition = e->pos() + d->offset();
2576 d->startAutoScroll();
2577 }
2578 if (qAbs(pos - d->firstPos) >= QApplication::startDragDistance()
2579#if QT_CONFIG(label)
2580 || !d->sectionIndicator->isHidden()
2581#endif
2582 ) {
2583 int visual = visualIndexAt(pos);
2584 if (visual == -1)
2585 return;
2586 if (visual == 0 && logicalIndex(0) == 0 && !d->allowUserMoveOfSection0)
2587 return;
2588
2589 const int posThreshold = d->headerSectionPosition(visual) - d->headerOffset + d->headerSectionSize(visual) / 2;
2590 const int checkPos = d->reverse() ? d->viewport->width() - pos : pos;
2591 int moving = visualIndex(d->section);
2592 int oldTarget = d->target;
2593 if (visual < moving) {
2594 if (checkPos < posThreshold)
2595 d->target = d->logicalIndex(visual);
2596 else
2597 d->target = d->logicalIndex(visual + 1);
2598 } else if (visual > moving) {
2599 if (checkPos > posThreshold)
2600 d->target = d->logicalIndex(visual);
2601 else
2602 d->target = d->logicalIndex(visual - 1);
2603 } else {
2604 d->target = d->section;
2605 }
2606 if (oldTarget != d->target || oldTarget == -1)
2607 d->updateSectionsBeforeAfter(d->target);
2608 d->updateSectionIndicator(d->section, pos);
2609 }
2610 return;
2611 }
2613 int logical = logicalIndexAt(qMax(-d->headerOffset, pos));
2614 if (logical == -1 && pos > 0)
2615 logical = logicalIndex(d->lastVisibleVisualIndex());
2616 if (logical == d->pressed)
2617 return; // nothing to do
2618 else if (d->pressed != -1)
2619 updateSection(d->pressed);
2620 d->pressed = logical;
2621 if (d->clickableSections && logical != -1) {
2622 emit sectionEntered(d->pressed);
2623 updateSection(d->pressed);
2624 }
2625 return;
2626 }
2628#ifndef QT_NO_CURSOR
2629 int handle = d->sectionHandleAt(pos);
2630 bool hasCursor = testAttribute(Qt::WA_SetCursor);
2631 if (handle != -1 && (sectionResizeMode(handle) == Interactive)) {
2632 if (!hasCursor)
2634 } else {
2635 if (hasCursor)
2636 unsetCursor();
2637#ifndef QT_NO_STATUSTIP
2638 int logical = logicalIndexAt(pos);
2639 QString statusTip;
2640 if (logical != -1)
2641 statusTip = d->model->headerData(logical, d->orientation, Qt::StatusTipRole).toString();
2642 if (d->shouldClearStatusTip || !statusTip.isEmpty()) {
2643 QStatusTipEvent tip(statusTip);
2644 QCoreApplication::sendEvent(d->parent ? d->parent : this, &tip);
2645 d->shouldClearStatusTip = !statusTip.isEmpty();
2646 }
2647#endif // !QT_NO_STATUSTIP
2648 }
2649#endif
2650 return;
2651 }
2652 default:
2653 break;
2654 }
2655}
2656
2662{
2663 Q_D(QHeaderView);
2664 int pos = d->orientation == Qt::Horizontal ? e->position().toPoint().x() : e->position().toPoint().y();
2665 switch (d->state) {
2667 if (true
2668#if QT_CONFIG(label)
2669 && !d->sectionIndicator->isHidden()
2670#endif
2671 ) { // moving
2672 int from = visualIndex(d->section);
2673 Q_ASSERT(from != -1);
2674 int to = visualIndex(d->target);
2675 Q_ASSERT(to != -1);
2676 moveSection(from, to);
2677 d->section = d->target = -1;
2678 d->updateSectionIndicator(d->section, pos);
2679 if (from == to)
2680 d->updateSectionsBeforeAfter(from);
2681 break;
2682 } // not moving
2683 Q_FALLTHROUGH();
2685 if (!d->clickableSections) {
2686 int section = logicalIndexAt(pos);
2687 updateSection(section);
2688 }
2689 Q_FALLTHROUGH();
2691 if (d->clickableSections) {
2692 int section = logicalIndexAt(pos);
2693 if (section != -1 && section == d->firstPressed) {
2694 QRect firstPressedSectionRect;
2695 switch (d->orientation) {
2696 case Qt::Horizontal:
2697 firstPressedSectionRect.setRect(sectionViewportPosition(d->firstPressed),
2698 0,
2699 sectionSize(d->firstPressed),
2700 d->viewport->height());
2701 break;
2702 case Qt::Vertical:
2703 firstPressedSectionRect.setRect(0,
2704 sectionViewportPosition(d->firstPressed),
2705 d->viewport->width(),
2706 sectionSize(d->firstPressed));
2707 break;
2708 };
2709
2710 if (firstPressedSectionRect.contains(e->position().toPoint())) {
2711 d->flipSortIndicator(section);
2712 emit sectionClicked(section);
2713 }
2714 }
2715 if (d->pressed != -1)
2716 updateSection(d->pressed);
2717 }
2718 break;
2720 d->originalSize = -1;
2721 d->clearCascadingSections();
2722 break;
2723 default:
2724 break;
2725 }
2727 d->firstPressed = d->pressed = -1;
2728}
2729
2735{
2736 Q_D(QHeaderView);
2737 int pos = d->orientation == Qt::Horizontal ? e->position().toPoint().x() : e->position().toPoint().y();
2738 int handle = d->sectionHandleAt(pos);
2739 if (handle > -1 && sectionResizeMode(handle) == Interactive) {
2741#ifndef QT_NO_CURSOR
2742 Qt::CursorShape splitCursor = (d->orientation == Qt::Horizontal)
2744 if (cursor().shape() == splitCursor) {
2745 // signal handlers may have changed the section size
2746 handle = d->sectionHandleAt(pos);
2747 if (!(handle > -1 && sectionResizeMode(handle) == Interactive))
2749 }
2750#endif
2751 } else {
2753 }
2754}
2755
2761{
2762 Q_D(QHeaderView);
2763 switch (e->type()) {
2764#if QT_CONFIG(tooltip)
2765 case QEvent::ToolTip: {
2766 QHelpEvent *he = static_cast<QHelpEvent*>(e);
2767 int logical = logicalIndexAt(he->pos());
2768 if (logical != -1) {
2769 QVariant variant = d->model->headerData(logical, d->orientation, Qt::ToolTipRole);
2770 if (variant.isValid()) {
2771 QToolTip::showText(he->globalPos(), variant.toString(), this);
2772 return true;
2773 }
2774 }
2775 break; }
2776#endif
2777#if QT_CONFIG(whatsthis)
2779 QHelpEvent *he = static_cast<QHelpEvent*>(e);
2780 int logical = logicalIndexAt(he->pos());
2781 if (logical != -1
2782 && d->model->headerData(logical, d->orientation, Qt::WhatsThisRole).isValid())
2783 return true;
2784 break; }
2785 case QEvent::WhatsThis: {
2786 QHelpEvent *he = static_cast<QHelpEvent*>(e);
2787 int logical = logicalIndexAt(he->pos());
2788 if (logical != -1) {
2789 QVariant whatsthis = d->model->headerData(logical, d->orientation,
2791 if (whatsthis.isValid()) {
2792 QWhatsThis::showText(he->globalPos(), whatsthis.toString(), this);
2793 return true;
2794 }
2795 }
2796 break; }
2797#endif // QT_CONFIG(whatsthis)
2798#if QT_CONFIG(statustip)
2799 case QEvent::StatusTip: {
2800 QHelpEvent *he = static_cast<QHelpEvent*>(e);
2801 int logical = logicalIndexAt(he->pos());
2802 if (logical != -1) {
2803 QString statustip = d->model->headerData(logical, d->orientation,
2804 Qt::StatusTipRole).toString();
2805 if (!statustip.isEmpty())
2806 setStatusTip(statustip);
2807 }
2808 return true; }
2809#endif // QT_CONFIG(statustip)
2810 case QEvent::Resize:
2811 case QEvent::FontChange:
2813 d->invalidateCachedSizeHint();
2814 Q_FALLTHROUGH();
2815 case QEvent::Hide:
2816 case QEvent::Show: {
2817 QAbstractScrollArea *parent = qobject_cast<QAbstractScrollArea *>(parentWidget());
2818 if (parent && parent->isVisible()) // Only resize if we have a visible parent
2821 break;}
2822 case QEvent::ContextMenu: {
2824 d->pressed = d->section = d->target = -1;
2825 d->updateSectionIndicator(d->section, -1);
2826 break; }
2827 case QEvent::Wheel: {
2828 QAbstractScrollArea *asa = qobject_cast<QAbstractScrollArea *>(parentWidget());
2829 if (asa)
2830 return QCoreApplication::sendEvent(asa->viewport(), e);
2831 break; }
2832 default:
2833 break;
2834 }
2836}
2837
2850{
2851 Q_D(const QHeaderView);
2852
2853 if (!option)
2854 return;
2856 QStyleOptionHeaderV2 *optV2 = qstyleoption_cast<QStyleOptionHeaderV2*>(option);
2857
2858 QStyle::State state = QStyle::State_None;
2859 if (window()->isActiveWindow())
2861 if (d->clickableSections) {
2862 if (logicalIndex == d->hover)
2864 if (logicalIndex == d->pressed)
2866 else if (d->highlightSelected) {
2867 if (d->sectionIntersectsSelection(logicalIndex))
2869 if (d->isSectionSelected(logicalIndex))
2871 }
2872 }
2874 opt.sortIndicator = (sortIndicatorOrder() == Qt::AscendingOrder)
2876
2877 // setup the style options structure
2878 QVariant textAlignment = d->model->headerData(logicalIndex, d->orientation,
2880 opt.section = logicalIndex;
2881 opt.state |= state;
2882 opt.textAlignment = textAlignment.isValid()
2883 ? QtPrivate::legacyFlagValueFromModelData<Qt::Alignment>(textAlignment)
2884 : d->defaultAlignment;
2885
2886 opt.iconAlignment = Qt::AlignVCenter;
2887 opt.text = d->model->headerData(logicalIndex, d->orientation,
2888 Qt::DisplayRole).toString();
2889
2890 const QVariant variant = d->model->headerData(logicalIndex, d->orientation,
2892 opt.icon = qvariant_cast<QIcon>(variant);
2893 if (opt.icon.isNull())
2894 opt.icon = qvariant_cast<QPixmap>(variant);
2895
2896 QVariant var = d->model->headerData(logicalIndex, d->orientation,
2897 Qt::FontRole);
2898 if (var.isValid() && var.canConvert<QFont>())
2899 opt.fontMetrics = QFontMetrics(qvariant_cast<QFont>(var));
2900 if (optV2)
2901 optV2->textElideMode = d->textElideMode;
2902
2903 QVariant foregroundBrush = d->model->headerData(logicalIndex, d->orientation,
2905 if (foregroundBrush.canConvert<QBrush>())
2906 opt.palette.setBrush(QPalette::ButtonText, qvariant_cast<QBrush>(foregroundBrush));
2907
2908 QVariant backgroundBrush = d->model->headerData(logicalIndex, d->orientation,
2910 if (backgroundBrush.canConvert<QBrush>()) {
2911 opt.palette.setBrush(QPalette::Button, qvariant_cast<QBrush>(backgroundBrush));
2912 opt.palette.setBrush(QPalette::Window, qvariant_cast<QBrush>(backgroundBrush));
2913 }
2914
2915 // the section position
2916 int visual = visualIndex(logicalIndex);
2917 Q_ASSERT(visual != -1);
2918 bool first = d->isFirstVisibleSection(visual);
2919 bool last = d->isLastVisibleSection(visual);
2920 if (first && last)
2922 else if (first)
2924 else if (last)
2926 else
2928 opt.orientation = d->orientation;
2929 // the selected position
2930 bool previousSelected = d->isSectionSelected(this->logicalIndex(visual - 1));
2931 bool nextSelected = d->isSectionSelected(this->logicalIndex(visual + 1));
2932 if (previousSelected && nextSelected)
2934 else if (previousSelected)
2936 else if (nextSelected)
2937 opt.selectedPosition = QStyleOptionHeader::NextIsSelected;
2938 else
2939 opt.selectedPosition = QStyleOptionHeader::NotAdjacent;
2940 if (optV2)
2941 optV2->isSectionDragTarget = d->target == logicalIndex;
2942}
2943
2951void QHeaderView::paintSection(QPainter *painter, const QRect &rect, int logicalIndex) const
2952{
2953 if (!rect.isValid())
2954 return;
2955
2957 QPointF oldBO = painter->brushOrigin();
2958
2960
2961 QBrush oBrushButton = opt.palette.brush(QPalette::Button);
2962 QBrush oBrushWindow = opt.palette.brush(QPalette::Window);
2963
2965 // We set rect here. If it needs to be changed it can be changed by overriding this function
2966 opt.rect = rect;
2967
2968 QBrush nBrushButton = opt.palette.brush(QPalette::Button);
2969 QBrush nBrushWindow = opt.palette.brush(QPalette::Window);
2970
2971 // If relevant brushes are not the same as from the regular widgets we set the brush origin
2972 if (oBrushButton != nBrushButton || oBrushWindow != nBrushWindow) {
2974 }
2975
2976 // draw the section.
2977 style()->drawControl(QStyle::CE_Header, &opt, painter, this);
2978 painter->setBrushOrigin(oldBO);
2979}
2980
2989{
2990 Q_D(const QHeaderView);
2991 Q_ASSERT(logicalIndex >= 0);
2992
2993 ensurePolished();
2994
2995 // use SizeHintRole
2996 QVariant variant = d->model->headerData(logicalIndex, d->orientation, Qt::SizeHintRole);
2997 if (variant.isValid())
2998 return qvariant_cast<QSize>(variant);
2999
3000 // otherwise use the contents
3003 opt.section = logicalIndex;
3004 QVariant var = d->model->headerData(logicalIndex, d->orientation,
3005 Qt::FontRole);
3006 QFont fnt;
3007 if (var.isValid() && var.canConvert<QFont>())
3008 fnt = qvariant_cast<QFont>(var);
3009 else
3010 fnt = font();
3011 fnt.setBold(true);
3013 opt.text = d->model->headerData(logicalIndex, d->orientation,
3014 Qt::DisplayRole).toString();
3015 variant = d->model->headerData(logicalIndex, d->orientation, Qt::DecorationRole);
3016 opt.icon = qvariant_cast<QIcon>(variant);
3017 if (opt.icon.isNull())
3018 opt.icon = qvariant_cast<QPixmap>(variant);
3020 opt.sortIndicator = QStyleOptionHeader::SortDown;
3021 return style()->sizeFromContents(QStyle::CT_HeaderSection, &opt, QSize(), this);
3022}
3023
3032{
3033 Q_D(const QHeaderView);
3034 if (d->orientation == Qt::Horizontal)
3035 return d->headerOffset;
3036 return 0;
3037}
3038
3047{
3048 Q_D(const QHeaderView);
3049 if (d->orientation == Qt::Vertical)
3050 return d->headerOffset;
3051 return 0;
3052}
3053
3060{
3061 Q_D(QHeaderView);
3062 d->layoutChildren();
3063 if (d->hasAutoResizeSections())
3064 d->doDelayedResizeSections();
3065}
3066
3073{
3074 Q_D(QHeaderView);
3075 d->scrollDirtyRegion(dx, dy);
3076}
3077
3082void QHeaderView::dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight,
3083 const QList<int> &roles)
3084{
3085 Q_D(QHeaderView);
3086 if (!roles.isEmpty()) {
3087 const auto doesRoleAffectSize = [](int role) -> bool {
3088 switch (role) {
3089 case Qt::DisplayRole:
3090 case Qt::DecorationRole:
3091 case Qt::SizeHintRole:
3092 case Qt::FontRole:
3093 return true;
3094 default:
3095 // who knows what a subclass or custom style might do
3096 return role >= Qt::UserRole;
3097 }
3098 };
3099 if (std::none_of(roles.begin(), roles.end(), doesRoleAffectSize))
3100 return;
3101 }
3102 d->invalidateCachedSizeHint();
3103 if (d->hasAutoResizeSections()) {
3104 bool resizeRequired = d->globalResizeMode == ResizeToContents;
3105 int first = orientation() == Qt::Horizontal ? topLeft.column() : topLeft.row();
3106 int last = orientation() == Qt::Horizontal ? bottomRight.column() : bottomRight.row();
3107 for (int i = first; i <= last && !resizeRequired; ++i)
3108 resizeRequired = (sectionResizeMode(i) == ResizeToContents);
3109 if (resizeRequired)
3110 d->doDelayedResizeSections();
3111 }
3112}
3113
3121{
3122 // do nothing
3123}
3124
3133{
3134 return QRect();
3135}
3136
3145{
3146 // do nothing - the header only displays sections
3147}
3148
3157{
3158 return QModelIndex();
3159}
3160
3169{
3170 return true; // the header view has no items, just sections
3171}
3172
3181{
3182 return QModelIndex();
3183}
3184
3194void QHeaderView::setSelection(const QRect&, QItemSelectionModel::SelectionFlags)
3195{
3196 // do nothing
3197}
3198
3204{
3205 Q_D(const QHeaderView);
3206 const int max = d->modelSectionCount();
3207
3208 if (d->orientation == Qt::Horizontal) {
3209 int logicalLeft = max;
3210 int logicalRight = 0;
3211
3212 if (d->visualIndices.empty()) {
3213 // If no reordered sections, skip redundant visual-to-logical transformations
3214 for (const auto &r : selection) {
3215 if (r.parent().isValid() || !r.isValid())
3216 continue; // we only know about toplevel items and we don't want invalid ranges
3217 if (r.left() < logicalLeft)
3218 logicalLeft = r.left();
3219 if (r.right() > logicalRight)
3220 logicalRight = r.right();
3221 }
3222 } else {
3223 int left = max;
3224 int right = 0;
3225 for (const auto &r : selection) {
3226 if (r.parent().isValid() || !r.isValid())
3227 continue; // we only know about toplevel items and we don't want invalid ranges
3228 for (int k = r.left(); k <= r.right(); ++k) {
3229 int visual = visualIndex(k);
3230 if (visual == -1) // in some cases users may change the selections
3231 continue; // before we have a chance to do the layout
3232 if (visual < left)
3233 left = visual;
3234 if (visual > right)
3235 right = visual;
3236 }
3237 }
3238 logicalLeft = logicalIndex(left);
3239 logicalRight = logicalIndex(right);
3240 }
3241
3242 if (logicalLeft < 0 || logicalLeft >= count() ||
3243 logicalRight < 0 || logicalRight >= count())
3244 return QRegion();
3245
3246 int leftPos = sectionViewportPosition(logicalLeft);
3247 int rightPos = sectionViewportPosition(logicalRight);
3248 rightPos += sectionSize(logicalRight);
3249 return QRect(leftPos, 0, rightPos - leftPos, height());
3250 }
3251 // orientation() == Qt::Vertical
3252 int logicalTop = max;
3253 int logicalBottom = 0;
3254
3255 if (d->visualIndices.empty()) {
3256 // If no reordered sections, skip redundant visual-to-logical transformations
3257 for (const auto &r : selection) {
3258 if (r.parent().isValid() || !r.isValid())
3259 continue; // we only know about toplevel items and we don't want invalid ranges
3260 if (r.top() < logicalTop)
3261 logicalTop = r.top();
3262 if (r.bottom() > logicalBottom)
3263 logicalBottom = r.bottom();
3264 }
3265 } else {
3266 int top = max;
3267 int bottom = 0;
3268
3269 for (const auto &r : selection) {
3270 if (r.parent().isValid() || !r.isValid())
3271 continue; // we only know about toplevel items and we don't want invalid ranges
3272 for (int k = r.top(); k <= r.bottom(); ++k) {
3273 int visual = visualIndex(k);
3274 if (visual == -1) // in some cases users may change the selections
3275 continue; // before we have a chance to do the layout
3276 if (visual < top)
3277 top = visual;
3278 if (visual > bottom)
3279 bottom = visual;
3280 }
3281 }
3282
3283 logicalTop = logicalIndex(top);
3284 logicalBottom = logicalIndex(bottom);
3285 }
3286
3287 if (logicalTop < 0 || logicalTop >= count() ||
3288 logicalBottom < 0 || logicalBottom >= count())
3289 return QRegion();
3290
3291 int topPos = sectionViewportPosition(logicalTop);
3292 int bottomPos = sectionViewportPosition(logicalBottom) + sectionSize(logicalBottom);
3293
3294 return QRect(0, topPos, width(), bottomPos - topPos);
3295}
3296
3297
3298// private implementation
3299
3301{
3302 Q_Q(QHeaderView);
3303 int visual = q->visualIndexAt(position);
3304 if (visual == -1)
3305 return -1;
3306 int log = logicalIndex(visual);
3307 int pos = q->sectionViewportPosition(log);
3308 int grip = q->style()->pixelMetric(QStyle::PM_HeaderGripMargin, nullptr, q);
3309
3310 bool atLeft = position < pos + grip;
3311 bool atRight = (position > pos + q->sectionSize(log) - grip);
3312 if (reverse())
3313 qSwap(atLeft, atRight);
3314
3315 if (atLeft) {
3316 //grip at the beginning of the section
3317 while(visual > -1) {
3318 int logical = q->logicalIndex(--visual);
3319 if (!q->isSectionHidden(logical))
3320 return logical;
3321 }
3322 } else if (atRight) {
3323 //grip at the end of the section
3324 return log;
3325 }
3326 return -1;
3327}
3328
3330{
3331 Q_Q(QHeaderView);
3332#if QT_CONFIG(label)
3333 if (!sectionIndicator) {
3334 sectionIndicator = new QLabel(viewport);
3335 }
3336#endif
3337
3338 int w, h;
3339 int p = q->sectionViewportPosition(section);
3340 if (orientation == Qt::Horizontal) {
3341 w = q->sectionSize(section);
3342 h = viewport->height();
3343 } else {
3344 w = viewport->width();
3345 h = q->sectionSize(section);
3346 }
3347#if QT_CONFIG(label)
3348 sectionIndicator->resize(w, h);
3349#endif
3350
3351 const qreal pixmapDevicePixelRatio = q->devicePixelRatio();
3352 QPixmap pm(QSize(w, h) * pixmapDevicePixelRatio);
3353 pm.setDevicePixelRatio(pixmapDevicePixelRatio);
3354 pm.fill(QColor(0, 0, 0, 45));
3355 QRect rect(0, 0, w, h);
3356
3357 QPainter painter(&pm);
3359 Qt::FontRole);
3360 if (variant.isValid() && variant.canConvert<QFont>()) {
3361 const QFont sectionFont = qvariant_cast<QFont>(variant);
3362 painter.setFont(sectionFont);
3363 } else {
3364 painter.setFont(q->font());
3365 }
3366
3367 painter.setOpacity(0.75);
3368 q->paintSection(&painter, rect, section);
3369 painter.end();
3370
3371#if QT_CONFIG(label)
3372 sectionIndicator->setPixmap(pm);
3373#endif
3375}
3376
3378{
3379#if QT_CONFIG(label)
3380 if (!sectionIndicator)
3381 return;
3382
3383 if (section == -1 || target == -1) {
3384 sectionIndicator->hide();
3385 return;
3386 }
3387
3389 sectionIndicator->move(position - sectionIndicatorOffset, 0);
3390 else
3391 sectionIndicator->move(0, position - sectionIndicatorOffset);
3392
3393 sectionIndicator->show();
3394#endif
3395}
3396
3405{
3406 Q_D(const QHeaderView);
3407 option->initFrom(this);
3409 option->orientation = d->orientation;
3410 if (d->orientation == Qt::Horizontal)
3412 if (isEnabled())
3413 option->state |= QStyle::State_Enabled;
3414 option->section = 0;
3415}
3416
3418{
3419 // The QFrame version is only here to avoid compiler warnings.
3420 // If invoked we just pass it on to the base class.
3422}
3423
3425{
3426 int i = section * 2;
3427 if (i < 0 || i >= sectionSelected.size())
3428 return false;
3429 if (sectionSelected.testBit(i)) // if the value was cached
3430 return sectionSelected.testBit(i + 1);
3431 bool s = false;
3434 else
3436 sectionSelected.setBit(i + 1, s); // selection state
3437 sectionSelected.setBit(i, true); // cache state
3438 return s;
3439}
3440
3442{
3445 const SectionItem &item = sectionItems.at(section);
3446 return item.size > 0 && item.calculated_startpos == 0;
3447}
3448
3450{
3453 const SectionItem &item = sectionItems.at(section);
3454 return item.size > 0 && item.calculatedEndPos() == length;
3455}
3456
3462{
3463 Q_Q(const QHeaderView);
3464 for (int visual = q->count()-1; visual >= 0; --visual) {
3465 if (!q->isSectionHidden(q->logicalIndex(visual)))
3466 return visual;
3467 }
3468
3469 //default value if no section is actually visible
3470 return -1;
3471}
3472
3474{
3475 Q_Q(QHeaderView);
3476 if (lastSectionLogicalIdx < 0)
3477 return;
3478 int resizeLogIdx = lastSectionLogicalIdx;
3479 lastSectionLogicalIdx = -1; // We do not want resize to catch it as the last section.
3480 q->resizeSection(resizeLogIdx, lastSectionSize);
3481}
3482
3483void QHeaderViewPrivate::setNewLastSection(int visualIndexForLastSection)
3484{
3485 Q_Q(QHeaderView);
3486 lastSectionSize = -1;
3487 lastSectionLogicalIdx = q->logicalIndex(visualIndexForLastSection);
3488 lastSectionSize = headerSectionSize(visualIndexForLastSection); // pick size directly since ...
3489 // q->sectionSize(lastSectionLogicalIdx) may do delayed resize and stretch it before we get the value.
3490}
3491
3493{
3494 Q_Q(const QHeaderView);
3495 if (!q->stretchLastSection())
3496 return;
3497
3498 int nowLastVisualSection = lastVisibleVisualIndex();
3499 if (lastSectionLogicalIdx == q->logicalIndex(nowLastVisualSection))
3500 return;
3501
3502 // restore old last section.
3504 setNewLastSection(nowLastVisualSection);
3505 doDelayedResizeSections(); // Do stretch of last section soon (but not now).
3506}
3507
3508
3523{
3524 Q_Q(QHeaderView);
3525 //stop the timer in case it is delayed
3527
3529 if (sectionCount() == 0)
3530 return;
3531
3533 return;
3534 resizeRecursionBlock = true;
3535
3537 const int lastSectionVisualIdx = q->visualIndex(lastSectionLogicalIdx);
3538
3539 // find stretchLastSection if we have it
3540 int stretchSection = -1;
3541 if (stretchLastSection && !useGlobalMode)
3542 stretchSection = lastSectionVisualIdx;
3543
3544 // count up the number of stretched sections and how much space left for them
3545 int lengthToStretch = (orientation == Qt::Horizontal ? viewport->width() : viewport->height());
3546 int numberOfStretchedSections = 0;
3547 QList<int> section_sizes;
3548 for (int i = 0; i < sectionCount(); ++i) {
3550 continue;
3551
3552 QHeaderView::ResizeMode resizeMode;
3553 if (useGlobalMode && (i != stretchSection))
3554 resizeMode = globalMode;
3555 else
3556 resizeMode = (i == stretchSection ? QHeaderView::Stretch : headerSectionResizeMode(i));
3557
3558 if (resizeMode == QHeaderView::Stretch) {
3559 ++numberOfStretchedSections;
3560 section_sizes.append(headerSectionSize(i));
3561 continue;
3562 }
3563
3564 // because it isn't stretch, determine its width and remove that from lengthToStretch
3565 int sectionSize = 0;
3566 if (resizeMode == QHeaderView::Interactive || resizeMode == QHeaderView::Fixed) {
3567 sectionSize = qBound(q->minimumSectionSize(), headerSectionSize(i), q->maximumSectionSize());
3568 } else { // resizeMode == QHeaderView::ResizeToContents
3569 int logicalIndex = q->logicalIndex(i);
3570 sectionSize = qMax(viewSectionSizeHint(logicalIndex),
3571 q->sectionSizeHint(logicalIndex));
3572 }
3573 sectionSize = qBound(q->minimumSectionSize(),
3574 sectionSize,
3575 q->maximumSectionSize());
3576
3577 section_sizes.append(sectionSize);
3578 lengthToStretch -= sectionSize;
3579 }
3580
3581 // calculate the new length for all of the stretched sections
3582 int stretchSectionLength = -1;
3583 int pixelReminder = 0;
3584 if (numberOfStretchedSections > 0 && lengthToStretch > 0) { // we have room to stretch in
3585 int hintLengthForEveryStretchedSection = lengthToStretch / numberOfStretchedSections;
3586 stretchSectionLength = qMax(hintLengthForEveryStretchedSection, q->minimumSectionSize());
3587 pixelReminder = lengthToStretch % numberOfStretchedSections;
3588 }
3589
3590 // ### The code below would be nicer if it was cleaned up a bit (since spans has been replaced with items)
3591 int spanStartSection = 0;
3592 int previousSectionLength = 0;
3593
3594 QHeaderView::ResizeMode previousSectionResizeMode = QHeaderView::Interactive;
3595
3596 // resize each section along the total length
3597 for (int i = 0; i < sectionCount(); ++i) {
3598 int oldSectionLength = headerSectionSize(i);
3599 int newSectionLength = -1;
3600 QHeaderView::ResizeMode newSectionResizeMode = headerSectionResizeMode(i);
3601
3602 if (isVisualIndexHidden(i)) {
3603 newSectionLength = 0;
3604 } else {
3605 QHeaderView::ResizeMode resizeMode;
3606 if (useGlobalMode)
3607 resizeMode = globalMode;
3608 else
3609 resizeMode = (i == stretchSection
3611 : newSectionResizeMode);
3612 if (resizeMode == QHeaderView::Stretch && stretchSectionLength != -1) {
3613 if (i == lastSectionVisualIdx)
3614 newSectionLength = qMax(stretchSectionLength, lastSectionSize);
3615 else
3616 newSectionLength = stretchSectionLength;
3617 if (pixelReminder > 0) {
3618 newSectionLength += 1;
3619 --pixelReminder;
3620 }
3621 section_sizes.removeFirst();
3622 } else {
3623 newSectionLength = section_sizes.takeFirst();
3624 }
3625 }
3626
3627 //Q_ASSERT(newSectionLength > 0);
3628 if ((previousSectionResizeMode != newSectionResizeMode
3629 || previousSectionLength != newSectionLength) && i > 0) {
3630 createSectionItems(spanStartSection, i - 1, previousSectionLength, previousSectionResizeMode);
3631 //Q_ASSERT(headerLength() == length);
3632 spanStartSection = i;
3633 }
3634
3635 if (newSectionLength != oldSectionLength)
3636 emit q->sectionResized(logicalIndex(i), oldSectionLength, newSectionLength);
3637
3638 previousSectionLength = newSectionLength;
3639 previousSectionResizeMode = newSectionResizeMode;
3640 }
3641
3642 createSectionItems(spanStartSection, sectionCount() - 1,
3643 previousSectionLength, previousSectionResizeMode);
3644 //Q_ASSERT(headerLength() == length);
3645 resizeRecursionBlock = false;
3646 viewport->update();
3647}
3648
3650{
3651 if (end >= sectionItems.size()) {
3652 sectionItems.resize(end + 1);
3653 sectionStartposRecalc = true;
3654 }
3655 SectionItem *sectiondata = sectionItems.data();
3656 for (int i = start; i <= end; ++i) {
3657 length += (sizePerSection - sectiondata[i].size);
3658 sectionStartposRecalc |= (sectiondata[i].size != sizePerSection);
3659 sectiondata[i].size = sizePerSection;
3660 sectiondata[i].resizeMode = mode;
3661 }
3662}
3663
3665{
3666 // remove sections
3667 sectionStartposRecalc |= (end != sectionItems.size() - 1);
3668 int removedlength = 0;
3669 for (int u = start; u <= end; ++u)
3670 removedlength += sectionItems.at(u).size;
3671 length -= removedlength;
3672 sectionItems.remove(start, end - start + 1);
3673}
3674
3676{
3677 if (state != NoClear) {
3678 length = 0;
3683 sectionItems.clear();
3686 }
3687}
3688
3690{
3691 switch (order) {
3692 case Qt::AscendingOrder:
3693 return Qt::DescendingOrder;
3695 return Qt::AscendingOrder;
3696 };
3697 Q_UNREACHABLE_RETURN(Qt::AscendingOrder);
3698};
3699
3701{
3702 Q_Q(QHeaderView);
3703 Qt::SortOrder sortOrder;
3706 const Qt::SortOrder defaultSortOrder = defaultSortOrderForSection(section);
3707 if (sortIndicatorOrder == defaultSortOrder) {
3708 sortOrder = flipOrder(sortIndicatorOrder);
3709 } else {
3710 section = -1;
3711 sortOrder = Qt::AscendingOrder;
3712 }
3713 } else {
3714 sortOrder = flipOrder(sortIndicatorOrder);
3715 }
3716 } else {
3718 }
3719 q->setSortIndicator(section, sortOrder);
3720}
3721
3723{
3725 if (value.canConvert<int>())
3726 return static_cast<Qt::SortOrder>(value.toInt());
3727 return Qt::AscendingOrder;
3728}
3729
3730void QHeaderViewPrivate::cascadingResize(int visual, int newSize)
3731{
3732 Q_Q(QHeaderView);
3733 const int minimumSize = q->minimumSectionSize();
3734 const int oldSize = headerSectionSize(visual);
3735 int delta = newSize - oldSize;
3736
3737 if (delta > 0) { // larger
3738 bool sectionResized = false;
3739
3740 // restore old section sizes
3741 for (int i = firstCascadingSection; i < visual; ++i) {
3743 int currentSectionSize = headerSectionSize(i);
3744 int originalSectionSize = cascadingSectionSize.value(i);
3745 if (currentSectionSize < originalSectionSize) {
3746 int newSectionSize = currentSectionSize + delta;
3747 resizeSectionItem(i, currentSectionSize, newSectionSize);
3748 if (newSectionSize >= originalSectionSize && false)
3749 cascadingSectionSize.remove(i); // the section is now restored
3750 sectionResized = true;
3751 break;
3752 }
3753 }
3754
3755 }
3756
3757 // resize the section
3758 if (!sectionResized) {
3759 newSize = qMax(newSize, minimumSize);
3760 if (oldSize != newSize)
3761 resizeSectionItem(visual, oldSize, newSize);
3762 }
3763
3764 // cascade the section size change
3765 for (int i = visual + 1; i < sectionCount(); ++i) {
3767 continue;
3768 if (!sectionIsCascadable(i))
3769 continue;
3770 int currentSectionSize = headerSectionSize(i);
3771 if (currentSectionSize <= minimumSize)
3772 continue;
3773 int newSectionSize = qMax(currentSectionSize - delta, minimumSize);
3774 resizeSectionItem(i, currentSectionSize, newSectionSize);
3775 saveCascadingSectionSize(i, currentSectionSize);
3776 delta = delta - (currentSectionSize - newSectionSize);
3777 if (delta <= 0)
3778 break;
3779 }
3780 } else { // smaller
3781 bool sectionResized = false;
3782
3783 // restore old section sizes
3784 for (int i = lastCascadingSection; i > visual; --i) {
3786 continue;
3787 int currentSectionSize = headerSectionSize(i);
3788 int originalSectionSize = cascadingSectionSize.value(i);
3789 if (currentSectionSize >= originalSectionSize)
3790 continue;
3791 int newSectionSize = currentSectionSize - delta;
3792 resizeSectionItem(i, currentSectionSize, newSectionSize);
3793 if (newSectionSize >= originalSectionSize && false) {
3794 cascadingSectionSize.remove(i); // the section is now restored
3795 }
3796 sectionResized = true;
3797 break;
3798 }
3799
3800 // resize the section
3801 resizeSectionItem(visual, oldSize, qMax(newSize, minimumSize));
3802
3803 // cascade the section size change
3804 if (delta < 0 && newSize < minimumSize) {
3805 for (int i = visual - 1; i >= 0; --i) {
3807 continue;
3808 if (!sectionIsCascadable(i))
3809 continue;
3810 int sectionSize = headerSectionSize(i);
3811 if (sectionSize <= minimumSize)
3812 continue;
3813 resizeSectionItem(i, sectionSize, qMax(sectionSize + delta, minimumSize));
3814 saveCascadingSectionSize(i, sectionSize);
3815 break;
3816 }
3817 }
3818
3819 // let the next section get the space from the resized section
3820 if (!sectionResized) {
3821 for (int i = visual + 1; i < sectionCount(); ++i) {
3823 continue;
3824 if (!sectionIsCascadable(i))
3825 continue;
3826 int currentSectionSize = headerSectionSize(i);
3827 int newSectionSize = qMax(currentSectionSize - delta, minimumSize);
3828 resizeSectionItem(i, currentSectionSize, newSectionSize);
3829 break;
3830 }
3831 }
3832 }
3833
3836
3837 viewport->update();
3838}
3839
3841{
3842 Q_Q(QHeaderView);
3843 size = qBound(q->minimumSectionSize(), size, q->maximumSectionSize());
3850 for (int i = 0; i < sectionItems.size(); ++i) {
3852 if (hiddenSectionSize.isEmpty() || !isVisualIndexHidden(i)) { // resize on not hidden.
3853 const int newSize = size;
3854 if (newSize != section.size) {
3855 length += newSize - section.size; //the whole length is changed
3856 const int oldSectionSize = section.sectionSize();
3857 section.size = size;
3858 emit q->sectionResized(logicalIndex(i), oldSectionSize, size);
3859 }
3860 }
3861 }
3862 sectionStartposRecalc = true;
3865 viewport->update();
3866}
3867
3869{
3870 Q_Q(QHeaderView);
3871 if (orientation == Qt::Horizontal) {
3872 defaultSectionSize = q->style()->pixelMetric(QStyle::PM_HeaderDefaultSectionSizeHorizontal, nullptr, q);
3873 } else {
3874 defaultSectionSize = qMax(q->minimumSectionSize(),
3875 q->style()->pixelMetric(QStyle::PM_HeaderDefaultSectionSizeVertical, nullptr, q));
3876 }
3877}
3878
3879void QHeaderViewPrivate::recalcSectionStartPos() const // linear (but fast)
3880{
3881 int pixelpos = 0;
3882 for (const SectionItem &i : sectionItems) {
3883 i.calculated_startpos = pixelpos; // write into const mutable
3884 pixelpos += i.size;
3885 }
3886 sectionStartposRecalc = false;
3887}
3888
3889void QHeaderViewPrivate::resizeSectionItem(int visualIndex, int oldSize, int newSize)
3890{
3891 Q_Q(QHeaderView);
3894 emit q->sectionResized(logicalIndex(visualIndex), oldSize, newSize);
3895}
3896
3898{
3899 if (visual < sectionCount() && visual >= 0)
3900 return sectionItems.at(visual).sectionSize();
3901 return -1;
3902}
3903
3905{
3906 if (visual < sectionCount() && visual >= 0) {
3909 return sectionItems.at(visual).calculated_startpos;
3910 }
3911 return -1;
3912}
3913
3915{
3918 int startidx = 0;
3919 int endidx = sectionItems.size() - 1;
3920 while (startidx <= endidx) {
3921 int middle = (endidx + startidx) / 2;
3922 if (sectionItems.at(middle).calculated_startpos > position) {
3923 endidx = middle - 1;
3924 } else {
3925 if (sectionItems.at(middle).calculatedEndPos() <= position)
3926 startidx = middle + 1;
3927 else // we found it.
3928 return middle;
3929 }
3930 }
3931 return -1;
3932}
3933
3939
3941{
3942 if (visual < 0 || visual >= sectionItems.size())
3943 return globalResizeMode;
3944 return static_cast<QHeaderView::ResizeMode>(sectionItems.at(visual).resizeMode);
3945}
3946
3948{
3950 for (int i = 0; i < sectionItems.size(); ++i)
3951 sectionItems[i].resizeMode = mode;
3952}
3953
3955{
3956 if (QAbstractItemView *view = qobject_cast<QAbstractItemView*>(parent)) {
3957 return (orientation == Qt::Horizontal
3958 ? view->sizeHintForColumn(logical)
3959 : view->sizeHintForRow(logical));
3960 }
3961 return 0;
3962}
3963
3965{
3966 if (!hiddenSectionSize.isEmpty()) {
3968 int currentVisualIndex = 0;
3969 for (int i = 0; i < sectionItems.size(); ++i) {
3972 else
3973 ++currentVisualIndex;
3974 if (currentVisualIndex >= visualIndex)
3975 break;
3976 }
3978 }
3979 return visualIndex;
3980}
3981
3983{
3984 Q_Q(QHeaderView);
3985 if (scrollMode == QAbstractItemView::ScrollPerItem) {
3986 if (scrollBar->maximum() > 0 && scrollBar->value() == scrollBar->maximum())
3987 q->setOffsetToLastSection();
3988 else
3989 q->setOffsetToSectionPosition(scrollBar->value());
3990 } else {
3991 q->setOffset(scrollBar->value());
3992 }
3993}
3994
3996{
3997 Q_Q(QHeaderView);
3998 const int visual = visualIndex(logical);
3999 int from = logicalIndex(visual > 1 ? visual - 1 : 0);
4000 int to = logicalIndex(visual + 1 >= sectionCount() ? visual : visual + 1);
4001 QRect updateRect;
4002 if (orientation == Qt::Horizontal) {
4003 if (reverse())
4004 std::swap(from, to);
4005 updateRect = QRect(QPoint(q->sectionViewportPosition(from), 0),
4006 QPoint(q->sectionViewportPosition(to) + headerSectionSize(to), viewport->height()));
4007 } else {
4008 updateRect = QRect(QPoint(0, q->sectionViewportPosition(from)),
4009 QPoint(viewport->width(), q->sectionViewportPosition(to) + headerSectionSize(to)));
4010 }
4011 viewport->update(updateRect);
4012}
4013
4014#ifndef QT_NO_DATASTREAM
4049
4051{
4052 Q_Q(QHeaderView);
4053 int orient, order, align, global;
4054 int sortIndicatorSectionIn;
4055 bool sortIndicatorShownIn;
4056 int lengthIn;
4057 QList<int> visualIndicesIn;
4058 QList<int> logicalIndicesIn;
4059 QHash<int, int> hiddenSectionSizeIn;
4060 bool movableSectionsIn;
4061 bool clickableSectionsIn;
4062 bool highlightSelectedIn;
4063 bool stretchLastSectionIn;
4064 bool cascadingResizingIn;
4065 int stretchSectionsIn;
4066 int contentsSectionsIn;
4067 int defaultSectionSizeIn;
4068 int minimumSectionSizeIn;
4069 QList<SectionItem> sectionItemsIn;
4070
4071 in >> orient;
4072 in >> order;
4073
4074 in >> sortIndicatorSectionIn;
4075 in >> sortIndicatorShownIn;
4076
4077 in >> visualIndicesIn;
4078 in >> logicalIndicesIn;
4079
4080 QBitArray sectionHidden;
4081 in >> sectionHidden;
4082 in >> hiddenSectionSizeIn;
4083 in >> lengthIn;
4084
4085 int unusedSectionCount; // For compatibility
4086 in >> unusedSectionCount;
4087
4088 if (in.status() != QDataStream::Ok || lengthIn < 0)
4089 return false;
4090
4091 in >> movableSectionsIn;
4092 in >> clickableSectionsIn;
4093 in >> highlightSelectedIn;
4094 in >> stretchLastSectionIn;
4095 in >> cascadingResizingIn;
4096 in >> stretchSectionsIn;
4097 in >> contentsSectionsIn;
4098 in >> defaultSectionSizeIn;
4099 in >> minimumSectionSizeIn;
4100
4101 in >> align;
4102
4103 in >> global;
4104
4105 // Check parameter consistency
4106 // Global orientation out of bounds?
4107 if (global < 0 || global > QHeaderView::ResizeToContents)
4108 return false;
4109
4110 // Alignment out of bounds?
4111 if (align < 0 || align > Qt::AlignVertical_Mask)
4112 return false;
4113
4114 in >> sectionItemsIn;
4115 // In Qt4 we had a vector of spans where one span could hold information on more sections.
4116 // Now we have an itemvector where one items contains information about one section
4117 // For backward compatibility with Qt4 we do the following
4118 QList<SectionItem> newSectionItems;
4119 for (int u = 0; u < sectionItemsIn.size(); ++u) {
4120 int count = sectionItemsIn.at(u).tmpDataStreamSectionCount;
4121 if (count > 1)
4122 sectionItemsIn[u].size /= count;
4123 for (int n = 0; n < count; ++n)
4124 newSectionItems.append(sectionItemsIn[u]);
4125 }
4126
4127 int sectionItemsLengthTotal = 0;
4128 for (const SectionItem &section : std::as_const(newSectionItems))
4129 sectionItemsLengthTotal += section.size;
4130 if (sectionItemsLengthTotal != lengthIn)
4131 return false;
4132
4133 const int currentCount = (orient == Qt::Horizontal ? model->columnCount(root) : model->rowCount(root));
4134 if (newSectionItems.size() < currentCount) {
4135 // we have sections not in the saved state, give them default settings
4136 if (!visualIndicesIn.isEmpty() && !logicalIndicesIn.isEmpty()) {
4137 for (int i = newSectionItems.size(); i < currentCount; ++i) {
4138 visualIndicesIn.append(i);
4139 logicalIndicesIn.append(i);
4140 }
4141 }
4142 const int insertCount = currentCount - newSectionItems.size();
4143 const int insertLength = defaultSectionSizeIn * insertCount;
4144 lengthIn += insertLength;
4145 SectionItem section(defaultSectionSizeIn, globalResizeMode);
4146 newSectionItems.insert(newSectionItems.size(), insertCount, section); // append
4147 }
4148
4149 orientation = static_cast<Qt::Orientation>(orient);
4150 sortIndicatorOrder = static_cast<Qt::SortOrder>(order);
4151 sortIndicatorSection = sortIndicatorSectionIn;
4152 sortIndicatorShown = sortIndicatorShownIn;
4153 visualIndices = visualIndicesIn;
4154 logicalIndices = logicalIndicesIn;
4155 hiddenSectionSize = hiddenSectionSizeIn;
4156 length = lengthIn;
4157
4158 movableSections = movableSectionsIn;
4159 clickableSections = clickableSectionsIn;
4160 highlightSelected = highlightSelectedIn;
4161 stretchLastSection = stretchLastSectionIn;
4162 cascadingResizing = cascadingResizingIn;
4163 stretchSections = stretchSectionsIn;
4164 contentsSections = contentsSectionsIn;
4165 defaultSectionSize = defaultSectionSizeIn;
4166 minimumSectionSize = minimumSectionSizeIn;
4167
4168 defaultAlignment = Qt::Alignment(align);
4170
4171 sectionItems = newSectionItems;
4172 setHiddenSectionsFromBitVector(sectionHidden);
4174
4175 int tmpint;
4176 in >> tmpint;
4177 if (in.status() == QDataStream::Ok) // we haven't read past end
4178 resizeContentsPrecision = tmpint;
4179
4180 bool tmpbool;
4181 in >> tmpbool;
4182 if (in.status() == QDataStream::Ok) { // we haven't read past end
4183 customDefaultSectionSize = tmpbool;
4186 }
4187
4188 lastSectionSize = -1;
4189 int inLastSectionSize;
4190 in >> inLastSectionSize;
4191 if (in.status() == QDataStream::Ok)
4192 lastSectionSize = inLastSectionSize;
4193
4195 if (stretchLastSection) {
4198 }
4199
4200 int inSortIndicatorClearable;
4201 in >> inSortIndicatorClearable;
4202 if (in.status() == QDataStream::Ok) // we haven't read past end
4203 sortIndicatorClearable = inSortIndicatorClearable;
4204
4205 return true;
4206}
4207
4208#endif // QT_NO_DATASTREAM
4209
4211
4212#include "moc_qheaderview.cpp"
static QAbstractItemModel * staticEmptyModel()
void rowsMoved(const QModelIndex &sourceParent, int sourceStart, int sourceEnd, const QModelIndex &destinationParent, int destinationRow, QPrivateSignal)
void columnsRemoved(const QModelIndex &parent, int first, int last, QPrivateSignal)
This signal is emitted after columns have been removed from the model.
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.
void layoutAboutToBeChanged(const QList< QPersistentModelIndex > &parents=QList< QPersistentModelIndex >(), QAbstractItemModel::LayoutChangeHint hint=QAbstractItemModel::NoLayoutChangeHint)
virtual Q_INVOKABLE int rowCount(const QModelIndex &parent=QModelIndex()) const =0
Returns the number of rows under the given parent.
void columnsAboutToBeMoved(const QModelIndex &sourceParent, int sourceStart, int sourceEnd, const QModelIndex &destinationParent, int destinationColumn, QPrivateSignal)
void columnsAboutToBeRemoved(const QModelIndex &parent, int first, int last, QPrivateSignal)
This signal is emitted just before columns are removed from the model.
void layoutChanged(const QList< QPersistentModelIndex > &parents=QList< QPersistentModelIndex >(), QAbstractItemModel::LayoutChangeHint hint=QAbstractItemModel::NoLayoutChangeHint)
void headerDataChanged(Qt::Orientation orientation, int first, int last)
This signal is emitted whenever a header is changed.
void rowsAboutToBeRemoved(const QModelIndex &parent, int first, int last, QPrivateSignal)
This signal is emitted just before rows are removed from the model.
void rowsAboutToBeMoved(const QModelIndex &sourceParent, int sourceStart, int sourceEnd, const QModelIndex &destinationParent, int destinationRow, QPrivateSignal)
virtual Q_INVOKABLE int columnCount(const QModelIndex &parent=QModelIndex()) const =0
Returns the number of columns for the children of the given parent.
void rowsInserted(const QModelIndex &parent, int first, int last, QPrivateSignal)
This signal is emitted after rows have been inserted into the model.
void columnsMoved(const QModelIndex &sourceParent, int sourceStart, int sourceEnd, const QModelIndex &destinationParent, int destinationColumn, QPrivateSignal)
void columnsInserted(const QModelIndex &parent, int first, int last, QPrivateSignal)
This signal is emitted after columns have been inserted into the model.
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.
void rowsRemoved(const QModelIndex &parent, int first, int last, QPrivateSignal)
This signal is emitted after rows have been removed from the model.
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.
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 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,.
ScrollHint
\value EnsureVisible Scroll to ensure that the item is visible.
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:87
bool testBit(qsizetype i) const
Returns true if the bit at index position i is 1; otherwise returns false.
Definition qbitarray.h:89
void setBit(qsizetype i)
Sets the bit at index position i to 1.
Definition qbitarray.h:91
qsizetype size() const
Returns the number of bits stored in the bit array.
Definition qbitarray.h:76
\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:46
\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
Type type() const
Returns the event type.
Definition qcoreevent.h:304
\reentrant \inmodule QtGui
\reentrant
Definition qfont.h:22
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:373
virtual void initStyleOption(QStyleOptionFrame *option) const
Definition qframe.cpp:189
\inmodule QtCore
Definition qhash.h:1145
\inmodule QtCore
Definition qhash.h:1103
bool remove(const Key &key)
Removes the item that has the key from the hash.
Definition qhash.h:958
bool contains(const Key &key) const noexcept
Returns true if the hash contains an item with the key; otherwise returns false.
Definition qhash.h:1007
T value(const Key &key) const noexcept
Definition qhash.h:1054
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:951
bool isEmpty() const noexcept
Returns true if the hash contains no items; otherwise returns false.
Definition qhash.h:928
int headerSectionSize(int visual) const
void updateDefaultSectionSizeFromStyle()
void sectionsAboutToBeMoved(const QModelIndex &sourceParent, int logicalStart, int logicalEnd, const QModelIndex &destinationParent, int logicalDestination)
int headerLength() const
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 recalcSectionStartPos() const
void setNewLastSection(int visualIndexForLastSection)
void sectionsRemoved(const QModelIndex &, int, int)
void sectionsAboutToBeChanged(const QList< QPersistentModelIndex > &parents=QList< QPersistentModelIndex >(), QAbstractItemModel::LayoutChangeHint hint=QAbstractItemModel::NoLayoutChangeHint)
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
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
QHeaderView::ResizeMode globalResizeMode
void setHiddenSectionsFromBitVector(const QBitArray &sectionHidden)
void sectionsMoved(const QModelIndex &sourceParent, int logicalStart, int logicalEnd, const QModelIndex &destinationParent, int logicalDestination)
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)
void sectionsChanged(const QList< QPersistentModelIndex > &parents=QList< QPersistentModelIndex >(), QAbstractItemModel::LayoutChangeHint hint=QAbstractItemModel::NoLayoutChangeHint)
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
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:24
bool sectionsHidden() const
void setSectionsClickable(bool clickable)
Set \l sectionsClickable to 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 currentChanged(const QModelIndex &current, const QModelIndex &old) override
\reimp
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:39
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:32
void setResizeContentsPrecision(int precision)
void setSectionResizeMode(ResizeMode mode)
int minimumSectionSize
the minimum size of the header sections.
Definition qheaderview.h:30
void rowsInserted(const QModelIndex &parent, int start, int end) override
\reimp
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)
bool sectionsClickable
Holds true if the header is clickable; otherwise false.
Definition qheaderview.h:23
void swapSections(int first, int second)
int logicalIndexAt(int position) const
Returns the section that covers the given position in the viewport.
bool sectionsMovable
If sectionsMovable is true, the header sections may be moved by the user; otherwise they are fixed in...
Definition qheaderview.h:22
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:27
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 dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QList< int > &roles=QList< int >()) override
\reimp
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:25
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)
Sets \l sectionsMovable to 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)
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:29
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:31
void setCascadingSectionResizes(bool enable)
The QHelpEvent class provides an event that is used to request helpful information about a particular...
Definition qevent.h:788
\inmodule QtGui
Definition qevent.h:246
bool isNull() const
Returns true if the icon is empty; otherwise returns false.
Definition qicon.cpp:1019
\inmodule QtCore
The QLabel widget provides a text or image display.
Definition qlabel.h:20
qsizetype size() const noexcept
Definition qlist.h:397
bool isEmpty() const noexcept
Definition qlist.h:401
const_reference at(qsizetype i) const noexcept
Definition qlist.h:446
void remove(qsizetype i, qsizetype n=1)
Definition qlist.h:794
pointer data()
Definition qlist.h:431
void resize(qsizetype size)
Definition qlist.h:403
void clear()
Definition qlist.h:434
\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:196
QPoint pos() const
Definition qevent.h:219
static QMetaObject::Connection connect(const typename QtPrivate::FunctionPointer< Func1 >::Object *sender, Func1 signal, const typename QtPrivate::FunctionPointer< Func2 >::Object *receiverPrivate, Func2 slot, Qt::ConnectionType type=Qt::AutoConnection)
Definition qobject_p.h:299
static QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *member, Qt::ConnectionType=Qt::AutoConnection)
\threadsafe
Definition qobject.cpp:2960
The QPaintEvent class contains event parameters for paint events.
Definition qevent.h:486
const QRect & rect() const
Returns the rectangle that needs to be updated.
Definition qevent.h:492
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:748
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:151
@ ButtonText
Definition qpalette.h:52
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:604
void fill(const QColor &fillColor=Qt::white)
Fills the pixmap with the given color.
Definition qpixmap.cpp:850
\inmodule QtCore\reentrant
Definition qpoint.h:217
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:404
\inmodule QtCore\reentrant
Definition qpoint.h:25
constexpr int x() const noexcept
Returns the x coordinate of this point.
Definition qpoint.h:130
constexpr int y() const noexcept
Returns the y coordinate of this point.
Definition qpoint.h:135
\inmodule QtCore\reentrant
Definition qrect.h:30
constexpr QPoint topLeft() const noexcept
Returns the position of the rectangle's top-left corner.
Definition qrect.h:221
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:346
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:245
constexpr int width() const noexcept
Returns the width of the rectangle.
Definition qrect.h:236
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
void swap(QSet< T > &other) noexcept
Definition qset.h:36
iterator begin()
Definition qset.h:136
iterator end()
Definition qset.h:140
iterator erase(const_iterator i)
Definition qset.h:145
const_iterator cbegin() const noexcept
Definition qset.h:138
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:119
Qt::MouseButton button() const
Returns the button that caused the event.
Definition qevent.h:116
Qt::MouseButtons buttons() const
Returns the button state when the event was generated.
Definition qevent.h:117
\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:808
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:129
bool isEmpty() const noexcept
Returns true if the string has no characters; otherwise returns false.
Definition qstring.h:192
\variable QStyleOptionFocusRect::backgroundColor
The QStyleOptionHeaderV2 class is used to describe the parameters for drawing a header.
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:566
@ CE_Header
Definition qstyle.h:202
@ CE_HeaderEmptyArea
Definition qstyle.h:226
@ PM_HeaderDefaultSectionSizeHorizontal
Definition qstyle.h:530
@ PM_HeaderMargin
Definition qstyle.h:476
@ PM_HeaderDefaultSectionSizeVertical
Definition qstyle.h:531
@ PM_HeaderGripMargin
Definition qstyle.h:478
\inmodule QtCore
Definition qcoreevent.h:366
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:439
\inmodule QtCore
Definition qvariant.h:65
bool isValid() const
Returns true if the storage type of this variant is not QMetaType::UnknownType; otherwise returns fal...
Definition qvariant.h:714
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:345
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
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:155
@ AlignVertical_Mask
Definition qnamespace.h:161
@ LeftButton
Definition qnamespace.h:58
@ NoButton
Definition qnamespace.h:57
@ WA_SetCursor
Definition qnamespace.h:305
@ NoFocus
Definition qnamespace.h:107
Orientation
Definition qnamespace.h:98
@ Horizontal
Definition qnamespace.h:99
@ Vertical
Definition qnamespace.h:100
CursorShape
@ ArrowCursor
@ SplitVCursor
@ SplitHCursor
@ WhatsThisRole
@ FontRole
@ TextAlignmentRole
@ ForegroundRole
@ UserRole
@ DecorationRole
@ InitialSortOrderRole
@ BackgroundRole
@ StatusTipRole
@ ToolTipRole
@ DisplayRole
@ SizeHintRole
@ ScrollBarAlwaysOff
SortOrder
Definition qnamespace.h:121
@ DescendingOrder
Definition qnamespace.h:123
@ AscendingOrder
Definition qnamespace.h:122
@ ElideNone
Definition qnamespace.h:192
#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
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 GLsizei GLenum GLenum GLsizei void * data
GLint GLsizei width
GLuint color
[2]
GLint left
GLuint GLsizei const GLchar * label
[43]
GLint GLint bottom
GLenum target
GLboolean enable
GLuint start
GLenum GLuint GLintptr offset
const GLchar * marker
GLint first
GLfloat n
GLfloat GLfloat GLfloat GLfloat h
GLdouble s
[6]
Definition qopenglext.h:235
const GLubyte * c
GLuint in
GLdouble GLdouble GLdouble GLdouble q
Definition qopenglext.h:259
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)
QT_BEGIN_NAMESPACE constexpr void qSwap(T &value1, T &value2) noexcept(std::is_nothrow_swappable_v< T >)
Definition qswap.h:20
#define QT_CONFIG(feature)
#define emit
#define Q_UNUSED(x)
double qreal
Definition qtypes.h:187
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