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 | |
63 | QT_REQUIRE_CONFIG(itemviews); |
64 | |
65 | QT_BEGIN_NAMESPACE |
66 | |
67 | class QHeaderViewPrivate: public QAbstractItemViewPrivate |
68 | { |
69 | Q_DECLARE_PUBLIC(QHeaderView) |
70 | |
71 | public: |
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 §ion : 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 §ionHidden) { |
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 | }; |
392 | Q_DECLARE_TYPEINFO(QHeaderViewPrivate::SectionItem, Q_PRIMITIVE_TYPE); |
393 | Q_DECLARE_TYPEINFO(QHeaderViewPrivate::LayoutChangeItem, Q_MOVABLE_TYPE); |
394 | |
395 | QT_END_NAMESPACE |
396 | |
397 | #endif // QHEADERVIEW_P_H |
398 |
Definitions
- QHeaderViewPrivate
- StateVersion
- QHeaderViewPrivate
- rowIntersectsSelection
- columnIntersectsSelection
- sectionIntersectsSelection
- isRowSelected
- isColumnSelected
- prepareSectionSelected
- sectionCount
- reverse
- logicalIndex
- visualIndex
- setDefaultValues
- isVisualIndexHidden
- setVisualIndexHidden
- hasAutoResizeSections
- invalidateCachedSizeHint
- initializeIndexMapping
- clearCascadingSections
- saveCascadingSectionSize
- sectionIsCascadable
- modelSectionCount
- doDelayedResizeSections
- executePostedResize
- State
- SectionItem
- SectionItem
- SectionItem
- sectionSize
- calculatedEndPos
- write
- read
- LayoutChangeItem
- headerLength
- sectionsHiddenToBitVector
Learn to use CMake with our Intro Training
Find out more