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 | pressed(-1), |
86 | hover(-1), |
87 | length(0), |
88 | preventCursorChangeInSetOffset(false), |
89 | movableSections(false), |
90 | clickableSections(false), |
91 | highlightSelected(false), |
92 | stretchLastSection(false), |
93 | cascadingResizing(false), |
94 | resizeRecursionBlock(false), |
95 | allowUserMoveOfSection0(true), // will be false for QTreeView and true for QTableView |
96 | customDefaultSectionSize(false), |
97 | stretchSections(0), |
98 | contentsSections(0), |
99 | minimumSectionSize(-1), |
100 | maximumSectionSize(-1), |
101 | lastSectionSize(0), |
102 | lastSectionLogicalIdx(-1), // Only trust when we stretch last section |
103 | sectionIndicatorOffset(0), |
104 | #if QT_CONFIG(label) |
105 | sectionIndicator(nullptr), |
106 | #endif |
107 | globalResizeMode(QHeaderView::Interactive), |
108 | sectionStartposRecalc(true), |
109 | resizeContentsPrecision(1000) |
110 | {} |
111 | |
112 | |
113 | int () const; |
114 | void (); |
115 | void (int visualIndexForLastSection); |
116 | void maybeRestorePrevLastSectionAndStretchLast(); |
117 | int sectionHandleAt(int position); |
118 | void (int section, int position); |
119 | void (int section, int position); |
120 | void (int logicalFirst, int logicalLast); |
121 | void (QHeaderView::ResizeMode globalMode, bool useGlobalMode = false); |
122 | void (const QModelIndex &,int,int); |
123 | void (const QModelIndex &sourceParent, int logicalStart, int logicalEnd, const QModelIndex &destinationParent, int logicalDestination); |
124 | void (const QModelIndex &sourceParent, int logicalStart, int logicalEnd, const QModelIndex &destinationParent, int logicalDestination); |
125 | void (const QList<QPersistentModelIndex> &parents = QList<QPersistentModelIndex>(), |
126 | QAbstractItemModel::LayoutChangeHint hint = QAbstractItemModel::NoLayoutChangeHint); |
127 | void (const QList<QPersistentModelIndex> &parents = QList<QPersistentModelIndex>(), |
128 | QAbstractItemModel::LayoutChangeHint hint = QAbstractItemModel::NoLayoutChangeHint); |
129 | |
130 | bool (int section) const; |
131 | bool (int section) const; |
132 | bool (int section) const; |
133 | |
134 | inline bool (int row) const { |
135 | return (selectionModel ? selectionModel->rowIntersectsSelection(row, root) : false); |
136 | } |
137 | |
138 | inline bool columnIntersectsSelection(int column) const { |
139 | return (selectionModel ? selectionModel->columnIntersectsSelection(column, root) : false); |
140 | } |
141 | |
142 | inline bool (int logical) const { |
143 | return (orientation == Qt::Horizontal ? columnIntersectsSelection(logical) : rowIntersectsSelection(logical)); |
144 | } |
145 | |
146 | inline bool (int row) const { |
147 | return (selectionModel ? selectionModel->isRowSelected(row, root) : false); |
148 | } |
149 | |
150 | inline bool isColumnSelected(int column) const { |
151 | return (selectionModel ? selectionModel->isColumnSelected(column, root) : false); |
152 | } |
153 | |
154 | inline void () { |
155 | if (!selectionModel || !selectionModel->hasSelection()) |
156 | sectionSelected.clear(); |
157 | else if (sectionSelected.count() != sectionCount() * 2) |
158 | sectionSelected.fill(false, sectionCount() * 2); |
159 | else sectionSelected.fill(false); |
160 | } |
161 | |
162 | inline int () const {return sectionItems.count();} |
163 | |
164 | inline bool () const { |
165 | return orientation == Qt::Horizontal && q_func()->isRightToLeft(); |
166 | } |
167 | |
168 | inline int (int visualIndex) const { |
169 | return logicalIndices.isEmpty() ? visualIndex : logicalIndices.at(visualIndex); |
170 | } |
171 | |
172 | inline int (int logicalIndex) const { |
173 | return visualIndices.isEmpty() ? logicalIndex : visualIndices.at(logicalIndex); |
174 | } |
175 | |
176 | inline void (Qt::Orientation o) { |
177 | orientation = o; |
178 | updateDefaultSectionSizeFromStyle(); |
179 | defaultAlignment = (o == Qt::Horizontal |
180 | ? Qt::Alignment(Qt::AlignCenter) |
181 | : Qt::AlignLeft|Qt::AlignVCenter); |
182 | } |
183 | |
184 | inline bool (int visual) const { |
185 | return sectionItems.at(visual).isHidden; |
186 | } |
187 | |
188 | inline void (int visual, bool hidden) { |
189 | sectionItems[visual].isHidden = hidden; |
190 | } |
191 | |
192 | inline bool () const { |
193 | return stretchSections || stretchLastSection || contentsSections; |
194 | } |
195 | |
196 | QStyleOptionHeader () const; |
197 | |
198 | inline void () const { |
199 | cachedSizeHint = QSize(); |
200 | } |
201 | |
202 | inline void () const { |
203 | if (visualIndices.count() != sectionCount() |
204 | || logicalIndices.count() != sectionCount()) { |
205 | visualIndices.resize(sectionCount()); |
206 | logicalIndices.resize(sectionCount()); |
207 | for (int s = 0; s < sectionCount(); ++s) { |
208 | visualIndices[s] = s; |
209 | logicalIndices[s] = s; |
210 | } |
211 | } |
212 | } |
213 | |
214 | inline void () { |
215 | firstCascadingSection = sectionItems.count(); |
216 | lastCascadingSection = 0; |
217 | cascadingSectionSize.clear(); |
218 | } |
219 | |
220 | inline void (int visual, int size) { |
221 | if (!cascadingSectionSize.contains(visual)) { |
222 | cascadingSectionSize.insert(visual, size); |
223 | firstCascadingSection = qMin(firstCascadingSection, visual); |
224 | lastCascadingSection = qMax(lastCascadingSection, visual); |
225 | } |
226 | } |
227 | |
228 | inline bool (int visual) const { |
229 | return headerSectionResizeMode(visual) == QHeaderView::Interactive; |
230 | } |
231 | |
232 | inline int () const { |
233 | return (orientation == Qt::Horizontal |
234 | ? model->columnCount(root) |
235 | : model->rowCount(root)); |
236 | } |
237 | |
238 | inline void () { |
239 | if (!delayedResize.isActive()) |
240 | delayedResize.start(0, q_func()); |
241 | } |
242 | |
243 | inline void () const { |
244 | if (delayedResize.isActive() && state == NoState) { |
245 | const_cast<QHeaderView*>(q_func())->resizeSections(); |
246 | } |
247 | } |
248 | |
249 | void (); |
250 | void (int section); |
251 | void (int visual, int newSize); |
252 | |
253 | enum { , , , , } ; |
254 | |
255 | int ; |
256 | Qt::Orientation ; |
257 | Qt::SortOrder ; |
258 | int ; |
259 | bool ; |
260 | |
261 | mutable QList<int> ; // visualIndex = visualIndices.at(logicalIndex) |
262 | mutable QList<int> ; // logicalIndex = row or column in the model |
263 | mutable QBitArray ; // from logical index to bit |
264 | mutable QHash<int, int> ; // from logical index to section size |
265 | mutable QHash<int, int> ; // from visual index to section size |
266 | mutable QSize ; |
267 | mutable QBasicTimer ; |
268 | |
269 | int ; |
270 | int ; |
271 | |
272 | int ; |
273 | int ; |
274 | int ; |
275 | int ; // used for resizing and moving sections |
276 | int ; |
277 | int ; |
278 | int ; |
279 | |
280 | int ; |
281 | bool ; |
282 | bool ; |
283 | bool ; |
284 | bool ; |
285 | bool ; |
286 | bool ; |
287 | bool ; |
288 | bool ; |
289 | bool ; |
290 | int ; |
291 | int ; |
292 | int ; |
293 | int ; |
294 | int ; |
295 | int ; |
296 | int ; // Only trust if we stretch LastSection |
297 | int ; |
298 | Qt::Alignment ; |
299 | #if QT_CONFIG(label) |
300 | QLabel *; |
301 | #endif |
302 | QHeaderView::ResizeMode ; |
303 | mutable bool ; |
304 | int ; |
305 | // header sections |
306 | |
307 | struct { |
308 | uint : 20; |
309 | uint : 1; |
310 | uint : 5; // (holding QHeaderView::ResizeMode) |
311 | uint : 6; |
312 | |
313 | union { // This union is made in order to save space and ensure good vector performance (on remove) |
314 | mutable int ; // <- this is the primary used member. |
315 | mutable int ; // When one of these 'tmp'-members has been used we call |
316 | int ; // recalcSectionStartPos() or set sectionStartposRecalc to true |
317 | }; // to ensure that calculated_startpos will be calculated afterwards. |
318 | |
319 | inline () : size(0), isHidden(0), resizeMode(QHeaderView::Interactive) {} |
320 | inline (int length, QHeaderView::ResizeMode mode) |
321 | : size(length), isHidden(0), resizeMode(mode), calculated_startpos(-1) {} |
322 | inline int () const { return size; } |
323 | inline int () const { return calculated_startpos + size; } |
324 | #ifndef QT_NO_DATASTREAM |
325 | inline void (QDataStream &out) const |
326 | { out << static_cast<int>(size); out << 1; out << (int)resizeMode; } |
327 | inline void (QDataStream &in) |
328 | { int m; in >> m; size = m; in >> tmpDataStreamSectionCount; in >> m; resizeMode = m; } |
329 | #endif |
330 | }; |
331 | |
332 | QList<SectionItem> ; |
333 | struct { |
334 | QPersistentModelIndex ; |
335 | SectionItem ; |
336 | }; |
337 | QList<LayoutChangeItem> ; |
338 | |
339 | void (int start, int end, int size, QHeaderView::ResizeMode mode); |
340 | void (int start, int end); |
341 | void (int visualIndex, int oldSize, int newSize); |
342 | void (int size); |
343 | void (); |
344 | void () const; // not really const |
345 | |
346 | inline int () const { // for debugging |
347 | int len = 0; |
348 | for (const auto §ion : sectionItems) |
349 | len += section.size; |
350 | return len; |
351 | } |
352 | |
353 | QBitArray () const |
354 | { |
355 | QBitArray sectionHidden; |
356 | if (!hiddenSectionSize.isEmpty()) { |
357 | sectionHidden.resize(sectionItems.size()); |
358 | for (int u = 0; u < sectionItems.size(); ++u) |
359 | sectionHidden[u] = sectionItems.at(u).isHidden; |
360 | } |
361 | return sectionHidden; |
362 | } |
363 | |
364 | void (const QBitArray §ionHidden) { |
365 | SectionItem *sectionData = sectionItems.data(); |
366 | for (int i = 0; i < sectionHidden.count(); ++i) |
367 | sectionData[i].isHidden = sectionHidden.at(i); |
368 | } |
369 | |
370 | int (int visual) const; |
371 | int (int visual) const; |
372 | int (int position) const; |
373 | |
374 | // resize mode |
375 | void (int visual, QHeaderView::ResizeMode mode); |
376 | QHeaderView::ResizeMode (int visual) const; |
377 | void (QHeaderView::ResizeMode mode); |
378 | |
379 | // other |
380 | int (int logical) const; |
381 | int (int visualIndex) const; |
382 | void (const QScrollBar *scrollBar, QAbstractItemView::ScrollMode scrollMode); |
383 | |
384 | #ifndef QT_NO_DATASTREAM |
385 | void (QDataStream &out) const; |
386 | bool (QDataStream &in); |
387 | #endif |
388 | |
389 | }; |
390 | Q_DECLARE_TYPEINFO(QHeaderViewPrivate::SectionItem, Q_PRIMITIVE_TYPE); |
391 | Q_DECLARE_TYPEINFO(QHeaderViewPrivate::LayoutChangeItem, Q_MOVABLE_TYPE); |
392 | |
393 | QT_END_NAMESPACE |
394 | |
395 | #endif // QHEADERVIEW_P_H |
396 | |