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#ifndef QHEADERVIEW_P_H
5#define QHEADERVIEW_P_H
6
7//
8// W A R N I N G
9// -------------
10//
11// This file is not part of the Qt API. It exists purely as an
12// implementation detail. This header file may change from version to
13// version without notice, or even be removed.
14//
15// We mean it.
16//
17
18#include <QtWidgets/private/qtwidgetsglobal_p.h>
19#include "qheaderview.h"
20#include "private/qabstractitemview_p.h"
21
22#include "QtCore/qbitarray.h"
23#include "QtWidgets/qapplication.h"
24#if QT_CONFIG(label)
25#include "QtWidgets/qlabel.h"
26#endif
27
28#include <array>
29
30QT_REQUIRE_CONFIG(itemviews);
31
32QT_BEGIN_NAMESPACE
33
34class QHeaderViewPrivate: public QAbstractItemViewPrivate
35{
36 Q_DECLARE_PUBLIC(QHeaderView)
37
38public:
39 enum StateVersion { VersionMarker = 0xff };
40
41 QHeaderViewPrivate()
42 : state(NoState),
43 headerOffset(0),
44 sortIndicatorOrder(Qt::DescendingOrder),
45 sortIndicatorSection(0),
46 sortIndicatorShown(false),
47 sortIndicatorClearable(false),
48 lastPos(-1),
49 firstPos(-1),
50 originalSize(-1),
51 section(-1),
52 target(-1),
53 firstPressed(-1),
54 pressed(-1),
55 hover(-1),
56 length(0),
57 preventCursorChangeInSetOffset(false),
58 movableSections(false),
59 clickableSections(false),
60 highlightSelected(false),
61 stretchLastSection(false),
62 cascadingResizing(false),
63 resizeRecursionBlock(false),
64 allowUserMoveOfSection0(true), // will be false for QTreeView and true for QTableView
65 customDefaultSectionSize(false),
66 stretchSections(0),
67 contentsSections(0),
68 minimumSectionSize(-1),
69 maximumSectionSize(-1),
70 lastSectionSize(0),
71 lastSectionLogicalIdx(-1), // Only trust when we stretch last section
72 sectionIndicatorOffset(0),
73#if QT_CONFIG(label)
74 sectionIndicator(nullptr),
75#endif
76 globalResizeMode(QHeaderView::Interactive),
77 sectionStartposRecalc(true),
78 resizeContentsPrecision(1000)
79 {}
80
81
82 int lastVisibleVisualIndex() const;
83 void restoreSizeOnPrevLastSection();
84 void setNewLastSection(int visualIndexForLastSection);
85 void maybeRestorePrevLastSectionAndStretchLast();
86 int sectionHandleAt(int position);
87 void setupSectionIndicator(int section, int position);
88 void updateSectionIndicator(int section, int position);
89 void updateHiddenSections(int logicalFirst, int logicalLast);
90 void resizeSections(QHeaderView::ResizeMode globalMode, bool useGlobalMode = false);
91 void sectionsRemoved(const QModelIndex &,int,int);
92 void sectionsAboutToBeMoved(const QModelIndex &sourceParent, int logicalStart,
93 int logicalEnd, const QModelIndex &destinationParent,
94 int logicalDestination);
95 void sectionsMoved(const QModelIndex &sourceParent, int logicalStart,
96 int logicalEnd, const QModelIndex &destinationParent,
97 int logicalDestination);
98 void sectionsAboutToBeChanged(const QList<QPersistentModelIndex> &parents = QList<QPersistentModelIndex>(),
99 QAbstractItemModel::LayoutChangeHint hint = QAbstractItemModel::NoLayoutChangeHint);
100 void sectionsChanged(const QList<QPersistentModelIndex> &parents = QList<QPersistentModelIndex>(),
101 QAbstractItemModel::LayoutChangeHint hint = QAbstractItemModel::NoLayoutChangeHint);
102
103 bool isSectionSelected(int section) const;
104 bool isFirstVisibleSection(int section) const;
105 bool isLastVisibleSection(int section) const;
106
107 inline bool rowIntersectsSelection(int row) const {
108 return (selectionModel ? selectionModel->rowIntersectsSelection(row, parent: root) : false);
109 }
110
111 inline bool columnIntersectsSelection(int column) const {
112 return (selectionModel ? selectionModel->columnIntersectsSelection(column, parent: root) : false);
113 }
114
115 inline bool sectionIntersectsSelection(int logical) const {
116 return (orientation == Qt::Horizontal ? columnIntersectsSelection(column: logical) : rowIntersectsSelection(row: logical));
117 }
118
119 inline bool isRowSelected(int row) const {
120 return (selectionModel ? selectionModel->isRowSelected(row, parent: root) : false);
121 }
122
123 inline bool isColumnSelected(int column) const {
124 return (selectionModel ? selectionModel->isColumnSelected(column, parent: root) : false);
125 }
126
127 inline void prepareSectionSelected() {
128 if (!selectionModel || !selectionModel->hasSelection())
129 sectionSelected.clear();
130 else if (sectionSelected.size() != sectionCount() * 2)
131 sectionSelected.fill(aval: false, asize: sectionCount() * 2);
132 else sectionSelected.fill(aval: false);
133 }
134
135 inline int sectionCount() const {return sectionItems.size();}
136
137 inline bool reverse() const {
138 return orientation == Qt::Horizontal && q_func()->isRightToLeft();
139 }
140
141 inline int logicalIndex(int visualIndex) const {
142 return logicalIndices.isEmpty() ? visualIndex : logicalIndices.at(i: visualIndex);
143 }
144
145 inline int visualIndex(int logicalIndex) const {
146 return visualIndices.isEmpty() ? logicalIndex : visualIndices.at(i: logicalIndex);
147 }
148
149 inline void setDefaultValues(Qt::Orientation o) {
150 orientation = o;
151 updateDefaultSectionSizeFromStyle();
152 defaultAlignment = (o == Qt::Horizontal
153 ? Qt::Alignment(Qt::AlignCenter)
154 : Qt::AlignLeft|Qt::AlignVCenter);
155 }
156
157 inline bool isVisualIndexHidden(int visual) const {
158 return sectionItems.at(i: visual).isHidden;
159 }
160
161 inline void setVisualIndexHidden(int visual, bool hidden) {
162 sectionItems[visual].isHidden = hidden;
163 }
164
165 inline bool hasAutoResizeSections() const {
166 return stretchSections || stretchLastSection || contentsSections;
167 }
168
169 QStyleOptionHeader getStyleOption() const;
170
171 inline void invalidateCachedSizeHint() const {
172 cachedSizeHint = QSize();
173 }
174
175 inline void initializeIndexMapping() const {
176 if (visualIndices.size() != sectionCount()
177 || logicalIndices.size() != sectionCount()) {
178 visualIndices.resize(size: sectionCount());
179 logicalIndices.resize(size: sectionCount());
180 for (int s = 0; s < sectionCount(); ++s) {
181 visualIndices[s] = s;
182 logicalIndices[s] = s;
183 }
184 }
185 }
186
187 inline void clearCascadingSections() {
188 firstCascadingSection = sectionItems.size();
189 lastCascadingSection = 0;
190 cascadingSectionSize.clear();
191 }
192
193 inline void saveCascadingSectionSize(int visual, int size) {
194 if (!cascadingSectionSize.contains(key: visual)) {
195 cascadingSectionSize.insert(key: visual, value: size);
196 firstCascadingSection = qMin(a: firstCascadingSection, b: visual);
197 lastCascadingSection = qMax(a: lastCascadingSection, b: visual);
198 }
199 }
200
201 inline bool sectionIsCascadable(int visual) const {
202 return headerSectionResizeMode(visual) == QHeaderView::Interactive;
203 }
204
205 inline int modelSectionCount() const {
206 return (orientation == Qt::Horizontal
207 ? model->columnCount(parent: root)
208 : model->rowCount(parent: root));
209 }
210
211 inline void doDelayedResizeSections() {
212 if (!delayedResize.isActive())
213 delayedResize.start(msec: 0, obj: q_func());
214 }
215
216 inline void executePostedResize() const {
217 if (delayedResize.isActive() && state == NoState) {
218 const_cast<QHeaderView*>(q_func())->resizeSections();
219 }
220 }
221
222 inline void disconnectModel()
223 {
224 for (const QMetaObject::Connection &connection : modelConnections)
225 QObject::disconnect(connection);
226 }
227
228 void clear();
229 void flipSortIndicator(int section);
230 Qt::SortOrder defaultSortOrderForSection(int section) const;
231 void cascadingResize(int visual, int newSize);
232
233 enum State { NoState, ResizeSection, MoveSection, SelectSections, NoClear } state;
234
235 int headerOffset;
236 Qt::Orientation orientation;
237 Qt::SortOrder sortIndicatorOrder;
238 int sortIndicatorSection;
239 bool sortIndicatorShown;
240 bool sortIndicatorClearable;
241
242 mutable QList<int> visualIndices; // visualIndex = visualIndices.at(logicalIndex)
243 mutable QList<int> logicalIndices; // logicalIndex = row or column in the model
244 mutable QBitArray sectionSelected; // from logical index to bit
245 mutable QHash<int, int> hiddenSectionSize; // from logical index to section size
246 mutable QHash<int, int> cascadingSectionSize; // from visual index to section size
247 mutable QSize cachedSizeHint;
248 mutable QBasicTimer delayedResize;
249
250 int firstCascadingSection;
251 int lastCascadingSection;
252
253 int lastPos;
254 int firstPos;
255 int originalSize;
256 int section; // used for resizing and moving sections
257 int target;
258 int firstPressed;
259 int pressed;
260 int hover;
261
262 int length;
263 bool preventCursorChangeInSetOffset;
264 bool movableSections;
265 bool clickableSections;
266 bool highlightSelected;
267 bool stretchLastSection;
268 bool cascadingResizing;
269 bool resizeRecursionBlock;
270 bool allowUserMoveOfSection0;
271 bool customDefaultSectionSize;
272 int stretchSections;
273 int contentsSections;
274 int defaultSectionSize;
275 int oldDefaultSectionSize = -1;
276 int minimumSectionSize;
277 int maximumSectionSize;
278 int lastSectionSize;
279 int lastSectionLogicalIdx; // Only trust if we stretch LastSection
280 int sectionIndicatorOffset;
281 Qt::Alignment defaultAlignment;
282#if QT_CONFIG(label)
283 QLabel *sectionIndicator;
284#endif
285 QHeaderView::ResizeMode globalResizeMode;
286 mutable bool sectionStartposRecalc;
287 int resizeContentsPrecision;
288 // header sections
289
290 struct SectionItem {
291 uint size : 20;
292 uint isHidden : 1;
293 uint resizeMode : 5; // (holding QHeaderView::ResizeMode)
294 uint currentlyUnusedPadding : 6;
295
296 union { // This union is made in order to save space and ensure good vector performance (on remove)
297 mutable int calculated_startpos; // <- this is the primary used member.
298 mutable int tmpLogIdx; // When one of these 'tmp'-members has been used we call
299 int tmpDataStreamSectionCount; // recalcSectionStartPos() or set sectionStartposRecalc to true
300 }; // to ensure that calculated_startpos will be calculated afterwards.
301
302 inline SectionItem() : size(0), isHidden(0), resizeMode(QHeaderView::Interactive) {}
303 inline SectionItem(int length, QHeaderView::ResizeMode mode)
304 : size(length), isHidden(0), resizeMode(mode), calculated_startpos(-1) {}
305 inline int sectionSize() const { return size; }
306 inline int calculatedEndPos() const { return calculated_startpos + size; }
307#ifndef QT_NO_DATASTREAM
308 inline void write(QDataStream &out) const
309 { out << static_cast<int>(size); out << 1; out << (int)resizeMode; }
310 inline void read(QDataStream &in)
311 { int m; in >> m; size = m; in >> tmpDataStreamSectionCount; in >> m; resizeMode = m; }
312#endif
313 };
314
315 QList<SectionItem> sectionItems;
316 struct LayoutChangeItem {
317 QPersistentModelIndex index;
318 SectionItem section;
319 };
320 QList<LayoutChangeItem> layoutChangePersistentSections;
321 std::array<QMetaObject::Connection, 8> modelConnections;
322
323 void createSectionItems(int start, int end, int sectionSize, QHeaderView::ResizeMode mode);
324 void removeSectionsFromSectionItems(int start, int end);
325 void resizeSectionItem(int visualIndex, int oldSize, int newSize);
326 void setDefaultSectionSize(int size);
327 void updateDefaultSectionSizeFromStyle();
328 void recalcSectionStartPos() const; // not really const
329
330 inline int headerLength() const { // for debugging
331 int len = 0;
332 for (const auto &section : sectionItems)
333 len += section.size;
334 return len;
335 }
336
337 QBitArray sectionsHiddenToBitVector() const
338 {
339 QBitArray sectionHidden;
340 if (!hiddenSectionSize.isEmpty()) {
341 sectionHidden.resize(size: sectionItems.size());
342 for (int u = 0; u < sectionItems.size(); ++u)
343 sectionHidden[u] = sectionItems.at(i: u).isHidden;
344 }
345 return sectionHidden;
346 }
347
348 void setHiddenSectionsFromBitVector(const QBitArray &sectionHidden) {
349 SectionItem *sectionData = sectionItems.data();
350 for (int i = 0; i < sectionHidden.size(); ++i)
351 sectionData[i].isHidden = sectionHidden.at(i);
352 }
353
354 int headerSectionSize(int visual) const;
355 int headerSectionPosition(int visual) const;
356 int headerVisualIndexAt(int position) const;
357
358 // resize mode
359 void setHeaderSectionResizeMode(int visual, QHeaderView::ResizeMode mode);
360 QHeaderView::ResizeMode headerSectionResizeMode(int visual) const;
361 void setGlobalHeaderResizeMode(QHeaderView::ResizeMode mode);
362
363 // other
364 int viewSectionSizeHint(int logical) const;
365 int adjustedVisualIndex(int visualIndex) const;
366 void setScrollOffset(const QScrollBar *scrollBar, QAbstractItemView::ScrollMode scrollMode);
367 void updateSectionsBeforeAfter(int logical);
368
369#ifndef QT_NO_DATASTREAM
370 void write(QDataStream &out) const;
371 bool read(QDataStream &in);
372#endif
373
374};
375Q_DECLARE_TYPEINFO(QHeaderViewPrivate::SectionItem, Q_PRIMITIVE_TYPE);
376Q_DECLARE_TYPEINFO(QHeaderViewPrivate::LayoutChangeItem, Q_RELOCATABLE_TYPE);
377
378QT_END_NAMESPACE
379
380#endif // QHEADERVIEW_P_H
381

Provided by KDAB

Privacy Policy
Start learning QML with our Intro Training
Find out more

source code of qtbase/src/widgets/itemviews/qheaderview_p.h