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

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