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 |
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 : public QAbstractItemViewPrivate |
68 | { |
69 | Q_DECLARE_PUBLIC(QHeaderView) |
70 | |
71 | public: |
72 | enum { = 0xff }; |
73 | |
74 | () |
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 () const; |
115 | void (); |
116 | void (int visualIndexForLastSection); |
117 | void maybeRestorePrevLastSectionAndStretchLast(); |
118 | int sectionHandleAt(int position); |
119 | void (int section, int position); |
120 | void (int section, int position); |
121 | void (int logicalFirst, int logicalLast); |
122 | void (QHeaderView::ResizeMode globalMode, bool useGlobalMode = false); |
123 | void (const QModelIndex &,int,int); |
124 | void (const QModelIndex &sourceParent, int logicalStart, int logicalEnd, const QModelIndex &destinationParent, int logicalDestination); |
125 | void (const QModelIndex &sourceParent, int logicalStart, int logicalEnd, const QModelIndex &destinationParent, int logicalDestination); |
126 | void (const QList<QPersistentModelIndex> &parents = QList<QPersistentModelIndex>(), |
127 | QAbstractItemModel::LayoutChangeHint hint = QAbstractItemModel::NoLayoutChangeHint); |
128 | void (const QList<QPersistentModelIndex> &parents = QList<QPersistentModelIndex>(), |
129 | QAbstractItemModel::LayoutChangeHint hint = QAbstractItemModel::NoLayoutChangeHint); |
130 | |
131 | bool (int section) const; |
132 | bool (int section) const; |
133 | bool (int section) const; |
134 | |
135 | inline bool (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 (int logical) const { |
144 | return (orientation == Qt::Horizontal ? columnIntersectsSelection(column: logical) : rowIntersectsSelection(row: logical)); |
145 | } |
146 | |
147 | inline bool (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 () { |
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 () const {return sectionItems.count();} |
164 | |
165 | inline bool () const { |
166 | return orientation == Qt::Horizontal && q_func()->isRightToLeft(); |
167 | } |
168 | |
169 | inline int (int visualIndex) const { |
170 | return logicalIndices.isEmpty() ? visualIndex : logicalIndices.at(i: visualIndex); |
171 | } |
172 | |
173 | inline int (int logicalIndex) const { |
174 | return visualIndices.isEmpty() ? logicalIndex : visualIndices.at(i: logicalIndex); |
175 | } |
176 | |
177 | inline void (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 (int visual) const { |
186 | return sectionItems.at(i: visual).isHidden; |
187 | } |
188 | |
189 | inline void (int visual, bool hidden) { |
190 | sectionItems[visual].isHidden = hidden; |
191 | } |
192 | |
193 | inline bool () const { |
194 | return stretchSections || stretchLastSection || contentsSections; |
195 | } |
196 | |
197 | QStyleOptionHeader () const; |
198 | |
199 | inline void () const { |
200 | cachedSizeHint = QSize(); |
201 | } |
202 | |
203 | inline void () 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 () { |
216 | firstCascadingSection = sectionItems.count(); |
217 | lastCascadingSection = 0; |
218 | cascadingSectionSize.clear(); |
219 | } |
220 | |
221 | inline void (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 (int visual) const { |
230 | return headerSectionResizeMode(visual) == QHeaderView::Interactive; |
231 | } |
232 | |
233 | inline int () const { |
234 | return (orientation == Qt::Horizontal |
235 | ? model->columnCount(parent: root) |
236 | : model->rowCount(parent: root)); |
237 | } |
238 | |
239 | inline void () { |
240 | if (!delayedResize.isActive()) |
241 | delayedResize.start(msec: 0, obj: q_func()); |
242 | } |
243 | |
244 | inline void () const { |
245 | if (delayedResize.isActive() && state == NoState) { |
246 | const_cast<QHeaderView*>(q_func())->resizeSections(); |
247 | } |
248 | } |
249 | |
250 | void (); |
251 | void (int section); |
252 | void (int visual, int newSize); |
253 | |
254 | enum { , , , , } ; |
255 | |
256 | int ; |
257 | Qt::Orientation ; |
258 | Qt::SortOrder ; |
259 | int ; |
260 | bool ; |
261 | |
262 | mutable QVector<int> ; // visualIndex = visualIndices.at(logicalIndex) |
263 | mutable QVector<int> ; // logicalIndex = row or column in the model |
264 | mutable QBitArray ; // from logical index to bit |
265 | mutable QHash<int, int> ; // from logical index to section size |
266 | mutable QHash<int, int> ; // from visual index to section size |
267 | mutable QSize ; |
268 | mutable QBasicTimer ; |
269 | |
270 | int ; |
271 | int ; |
272 | |
273 | int ; |
274 | int ; |
275 | int ; |
276 | int ; // used for resizing and moving sections |
277 | int ; |
278 | int ; |
279 | int ; |
280 | int ; |
281 | |
282 | int ; |
283 | bool ; |
284 | bool ; |
285 | bool ; |
286 | bool ; |
287 | bool ; |
288 | bool ; |
289 | bool ; |
290 | bool ; |
291 | bool ; |
292 | int ; |
293 | int ; |
294 | int ; |
295 | int ; |
296 | int ; |
297 | int ; |
298 | int ; // Only trust if we stretch LastSection |
299 | int ; |
300 | Qt::Alignment ; |
301 | #if QT_CONFIG(label) |
302 | QLabel *; |
303 | #endif |
304 | QHeaderView::ResizeMode ; |
305 | mutable bool ; |
306 | int ; |
307 | // header sections |
308 | |
309 | struct { |
310 | uint : 20; |
311 | uint : 1; |
312 | uint : 5; // (holding QHeaderView::ResizeMode) |
313 | uint : 6; |
314 | |
315 | union { // This union is made in order to save space and ensure good vector performance (on remove) |
316 | mutable int ; // <- this is the primary used member. |
317 | mutable int ; // When one of these 'tmp'-members has been used we call |
318 | int ; // recalcSectionStartPos() or set sectionStartposRecalc to true |
319 | }; // to ensure that calculated_startpos will be calculated afterwards. |
320 | |
321 | inline () : size(0), isHidden(0), resizeMode(QHeaderView::Interactive) {} |
322 | inline (int length, QHeaderView::ResizeMode mode) |
323 | : size(length), isHidden(0), resizeMode(mode), calculated_startpos(-1) {} |
324 | inline int () const { return size; } |
325 | inline int () const { return calculated_startpos + size; } |
326 | #ifndef QT_NO_DATASTREAM |
327 | inline void (QDataStream &out) const |
328 | { out << static_cast<int>(size); out << 1; out << (int)resizeMode; } |
329 | inline void (QDataStream &in) |
330 | { int m; in >> m; size = m; in >> tmpDataStreamSectionCount; in >> m; resizeMode = m; } |
331 | #endif |
332 | }; |
333 | |
334 | QVector<SectionItem> ; |
335 | struct { |
336 | QPersistentModelIndex ; |
337 | SectionItem ; |
338 | }; |
339 | QVector<LayoutChangeItem> ; |
340 | |
341 | void (int start, int end, int size, QHeaderView::ResizeMode mode); |
342 | void (int start, int end); |
343 | void (int visualIndex, int oldSize, int newSize); |
344 | void (int size); |
345 | void (); |
346 | void () const; // not really const |
347 | |
348 | inline int () const { // for debugging |
349 | int len = 0; |
350 | for (const auto §ion : sectionItems) |
351 | len += section.size; |
352 | return len; |
353 | } |
354 | |
355 | QBitArray () 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 (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 (int visual) const; |
373 | int (int visual) const; |
374 | int (int position) const; |
375 | |
376 | // resize mode |
377 | void (int visual, QHeaderView::ResizeMode mode); |
378 | QHeaderView::ResizeMode (int visual) const; |
379 | void (QHeaderView::ResizeMode mode); |
380 | |
381 | // other |
382 | int (int logical) const; |
383 | int (int visualIndex) const; |
384 | void (const QScrollBar *scrollBar, QAbstractItemView::ScrollMode scrollMode); |
385 | |
386 | #ifndef QT_NO_DATASTREAM |
387 | void (QDataStream &out) const; |
388 | bool (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 | |