1 /****************************************************************************
2 **
3 ** Copyright (C) 2015 The Qt Company Ltd.
4 ** Contact: http://www.qt.io/licensing/
5 **
6 ** This file is part of the QtGui 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 http://www.qt.io/terms-conditions. For further
15 ** information use the contact form at http://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 2.1 or version 3 as published by the Free
20 ** Software Foundation and appearing in the file LICENSE.LGPLv21 and
21 ** LICENSE.LGPLv3 included in the packaging of this file. Please review the
22 ** following information to ensure the GNU Lesser General Public License
23 ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
24 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25 **
26 ** As a special exception, The Qt Company gives you certain additional
27 ** rights. These rights are described in The Qt Company LGPL Exception
28 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
29 **
30 ** GNU General Public License Usage
31 ** Alternatively, this file may be used under the terms of the GNU
32 ** General Public License version 3.0 as published by the Free Software
33 ** Foundation and appearing in the file LICENSE.GPL included in the
34 ** packaging of this file.  Please review the following information to
35 ** ensure the GNU General Public License version 3.0 requirements will be
36 ** met: http://www.gnu.org/copyleft/gpl.html.
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41 
42 #ifndef QHEADERVIEW_P_H
43 #define QHEADERVIEW_P_H
44 
45 //
46 //  W A R N I N G
47 //  -------------
48 //
49 // This file is not part of the Qt API.  It exists purely as an
50 // implementation detail.  This header file may change from version to
51 // version without notice, or even be removed.
52 //
53 // We mean it.
54 //
55 
56 #include "private/qabstractitemview_p.h"
57 
58 #ifndef QT_NO_ITEMVIEWS
59 
60 #include "QtCore/qbitarray.h"
61 #include "QtGui/qapplication.h"
62 #include "QtGui/qlabel.h"
63 
64 QT_BEGIN_NAMESPACE
65 
66 class QHeaderViewPrivate: public QAbstractItemViewPrivate
67 {
68     Q_DECLARE_PUBLIC(QHeaderView)
69 
70 public:
71     enum StateVersion { VersionMarker = 0xff };
72 
QHeaderViewPrivate()73     QHeaderViewPrivate()
74         : state(NoState),
75           offset(0),
76           sortIndicatorOrder(Qt::DescendingOrder),
77           sortIndicatorSection(0),
78           sortIndicatorShown(false),
79           lastPos(-1),
80           firstPos(-1),
81           originalSize(-1),
82           section(-1),
83           target(-1),
84           pressed(-1),
85           hover(-1),
86           length(0),
87           sectionCount(0),
88           movableSections(false),
89           clickableSections(false),
90           highlightSelected(false),
91           stretchLastSection(false),
92           cascadingResizing(false),
93           resizeRecursionBlock(false),
94           stretchSections(0),
95           contentsSections(0),
96           minimumSectionSize(-1),
97           lastSectionSize(0),
98           sectionIndicatorOffset(0),
99           sectionIndicator(0),
100           globalResizeMode(QHeaderView::Interactive)
101     {}
102 
103 
104     int lastVisibleVisualIndex() const;
105     int sectionHandleAt(int position);
106     void setupSectionIndicator(int section, int position);
107     void updateSectionIndicator(int section, int position);
108     void updateHiddenSections(int logicalFirst, int logicalLast);
109     void resizeSections(QHeaderView::ResizeMode globalMode, bool useGlobalMode = false);
110     void _q_sectionsRemoved(const QModelIndex &,int,int);
111     void _q_layoutAboutToBeChanged();
112     void _q_layoutChanged();
113 
114     bool isSectionSelected(int section) const;
115 
rowIntersectsSelection(int row)116     inline bool rowIntersectsSelection(int row) const {
117         return (selectionModel ? selectionModel->rowIntersectsSelection(row, root) : false);
118     }
119 
columnIntersectsSelection(int column)120     inline bool columnIntersectsSelection(int column) const {
121         return (selectionModel ? selectionModel->columnIntersectsSelection(column, root) : false);
122     }
123 
sectionIntersectsSelection(int logical)124     inline bool sectionIntersectsSelection(int logical) const {
125         return (orientation == Qt::Horizontal ? columnIntersectsSelection(logical) : rowIntersectsSelection(logical));
126     }
127 
isRowSelected(int row)128     inline bool isRowSelected(int row) const {
129         return (selectionModel ? selectionModel->isRowSelected(row, root) : false);
130     }
131 
isColumnSelected(int column)132     inline bool isColumnSelected(int column) const {
133         return (selectionModel ? selectionModel->isColumnSelected(column, root) : false);
134     }
135 
prepareSectionSelected()136     inline void prepareSectionSelected() {
137         if (!selectionModel || !selectionModel->hasSelection())
138             sectionSelected.clear();
139         else if (sectionSelected.count() != sectionCount * 2)
140             sectionSelected.fill(false, sectionCount * 2);
141         else sectionSelected.fill(false);
142     }
143 
reverse()144     inline bool reverse() const {
145         return orientation == Qt::Horizontal && q_func()->isRightToLeft();
146     }
147 
logicalIndex(int visualIndex)148     inline int logicalIndex(int visualIndex) const {
149         return logicalIndices.isEmpty() ? visualIndex : logicalIndices.at(visualIndex);
150     }
151 
visualIndex(int logicalIndex)152     inline int visualIndex(int logicalIndex) const {
153         return visualIndices.isEmpty() ? logicalIndex : visualIndices.at(logicalIndex);
154     }
155 
setDefaultValues(Qt::Orientation o)156     inline void setDefaultValues(Qt::Orientation o) {
157         orientation = o;
158         defaultSectionSize = (o == Qt::Horizontal ? 100
159                               : qMax(q_func()->minimumSectionSize(), 30));
160         defaultAlignment = (o == Qt::Horizontal
161                             ? Qt::Alignment(Qt::AlignCenter)
162                             : Qt::AlignLeft|Qt::AlignVCenter);
163     }
164 
isVisualIndexHidden(int visual)165     inline bool isVisualIndexHidden(int visual) const {
166         return !sectionHidden.isEmpty() && sectionHidden.at(visual);
167     }
168 
setVisualIndexHidden(int visual,bool hidden)169     inline void setVisualIndexHidden(int visual, bool hidden) {
170         if (!sectionHidden.isEmpty()) sectionHidden.setBit(visual, hidden);
171     }
172 
hasAutoResizeSections()173     inline bool hasAutoResizeSections() const {
174         return stretchSections || stretchLastSection || contentsSections;
175     }
176 
177     QStyleOptionHeader getStyleOption() const;
178 
invalidateCachedSizeHint()179     inline void invalidateCachedSizeHint() const {
180         cachedSizeHint = QSize();
181     }
182 
initializeIndexMapping()183     inline void initializeIndexMapping() const {
184         if (visualIndices.count() != sectionCount
185             || logicalIndices.count() != sectionCount) {
186             visualIndices.resize(sectionCount);
187             logicalIndices.resize(sectionCount);
188             for (int s = 0; s < sectionCount; ++s) {
189                 visualIndices[s] = s;
190                 logicalIndices[s] = s;
191             }
192         }
193     }
194 
clearCascadingSections()195     inline void clearCascadingSections() {
196         firstCascadingSection = sectionCount;
197         lastCascadingSection = 0;
198         cascadingSectionSize.clear();
199     }
200 
saveCascadingSectionSize(int visual,int size)201     inline void saveCascadingSectionSize(int visual, int size) {
202         if (!cascadingSectionSize.contains(visual)) {
203             cascadingSectionSize.insert(visual, size);
204             firstCascadingSection = qMin(firstCascadingSection, visual);
205             lastCascadingSection = qMax(lastCascadingSection, visual);
206         }
207     }
208 
sectionIsCascadable(int visual)209     inline bool sectionIsCascadable(int visual) const {
210         return headerSectionResizeMode(visual) == QHeaderView::Interactive;
211     }
212 
modelSectionCount()213     inline int modelSectionCount() const {
214         return (orientation == Qt::Horizontal
215                 ? model->columnCount(root)
216                 : model->rowCount(root));
217     }
218 
modelIsEmpty()219     inline bool modelIsEmpty() const {
220         return (model->rowCount(root) == 0 || model->columnCount(root) == 0);
221     }
222 
doDelayedResizeSections()223     inline void doDelayedResizeSections() {
224         if (!delayedResize.isActive())
225             delayedResize.start(0, q_func());
226     }
227 
executePostedResize()228     inline void executePostedResize() const {
229         if (delayedResize.isActive() && state == NoState) {
230             const_cast<QHeaderView*>(q_func())->resizeSections();
231         }
232     }
233 
234     void clear();
235     void flipSortIndicator(int section);
236     void cascadingResize(int visual, int newSize);
237 
238     enum State { NoState, ResizeSection, MoveSection, SelectSections, NoClear } state;
239 
240     int offset;
241     Qt::Orientation orientation;
242     Qt::SortOrder sortIndicatorOrder;
243     int sortIndicatorSection;
244     bool sortIndicatorShown;
245 
246     mutable QVector<int> visualIndices; // visualIndex = visualIndices.at(logicalIndex)
247     mutable QVector<int> logicalIndices; // logicalIndex = row or column in the model
248     mutable QBitArray sectionSelected; // from logical index to bit
249     mutable QBitArray sectionHidden; // from visual index to bit
250     mutable QHash<int, int> hiddenSectionSize; // from logical index to section size
251     mutable QHash<int, int> cascadingSectionSize; // from visual index to section size
252     mutable QSize cachedSizeHint;
253     mutable QBasicTimer delayedResize;
254 
255     int firstCascadingSection;
256     int lastCascadingSection;
257 
258     int lastPos;
259     int firstPos;
260     int originalSize;
261     int section; // used for resizing and moving sections
262     int target;
263     int pressed;
264     int hover;
265 
266     int length;
267     int sectionCount;
268     bool movableSections;
269     bool clickableSections;
270     bool highlightSelected;
271     bool stretchLastSection;
272     bool cascadingResizing;
273     bool resizeRecursionBlock;
274     int stretchSections;
275     int contentsSections;
276     int defaultSectionSize;
277     int minimumSectionSize;
278     int lastSectionSize; // $$$
279     int sectionIndicatorOffset;
280     Qt::Alignment defaultAlignment;
281     QLabel *sectionIndicator;
282     QHeaderView::ResizeMode globalResizeMode;
283     QList<QPersistentModelIndex> persistentHiddenSections;
284 
285     // header section spans
286 
287     struct SectionSpan {
288         int size;
289         int count;
290         QHeaderView::ResizeMode resizeMode;
SectionSpanSectionSpan291         inline SectionSpan() : size(0), count(0), resizeMode(QHeaderView::Interactive) {}
SectionSpanSectionSpan292         inline SectionSpan(int length, int sections, QHeaderView::ResizeMode mode)
293             : size(length), count(sections), resizeMode(mode) {}
sectionSizeSectionSpan294         inline int sectionSize() const { return (count > 0 ? size / count : 0); }
295 #ifndef QT_NO_DATASTREAM
writeSectionSpan296         inline void write(QDataStream &out) const
297         { out << size; out << count; out << (int)resizeMode; }
readSectionSpan298         inline void read(QDataStream &in)
299         { in >> size; in >> count; int m; in >> m; resizeMode = (QHeaderView::ResizeMode)m; }
300 #endif
301     };
302 
303     QVector<SectionSpan> sectionSpans;
304 
305     void createSectionSpan(int start, int end, int size, QHeaderView::ResizeMode mode);
306     void removeSectionsFromSpans(int start, int end);
307     void resizeSectionSpan(int visualIndex, int oldSize, int newSize);
308     void setDefaultSectionSize(int size);
309 
headerSectionCount()310     inline int headerSectionCount() const { // for debugging
311         int count = 0;
312         for (int i = 0; i < sectionSpans.count(); ++i)
313             count += sectionSpans.at(i).count;
314         return count;
315     }
316 
headerLength()317     inline int headerLength() const { // for debugging
318         int len = 0;
319         for (int i = 0; i < sectionSpans.count(); ++i)
320             len += sectionSpans.at(i).size;
321         return len;
322     }
323 
removeSpans(const QList<int> & spans)324     inline void removeSpans(const QList<int> &spans) {
325         for (int i = spans.count() - 1; i >= 0; --i) {
326             length -= sectionSpans.at(spans.at(i)).size;
327             sectionSpans.remove(spans.at(i));
328         }
329     }
330 
sectionSpanIndex(int visual)331     inline int sectionSpanIndex(int visual) const {
332         int section_start = 0;
333         for (int i = 0; i < sectionSpans.count(); ++i) {
334             int section_end = section_start + sectionSpans.at(i).count - 1;
335             if (visual >= section_start && visual <= section_end)
336                 return i;
337             section_start = section_end + 1;
338         }
339         return -1;
340     }
341 
342     int headerSectionSize(int visual) const;
343     int headerSectionPosition(int visual) const;
344     int headerVisualIndexAt(int position) const;
345 
346     // resize mode
347     void setHeaderSectionResizeMode(int visual, QHeaderView::ResizeMode mode);
348     QHeaderView::ResizeMode headerSectionResizeMode(int visual) const;
349     void setGlobalHeaderResizeMode(QHeaderView::ResizeMode mode);
350 
351     // other
352     int viewSectionSizeHint(int logical) const;
353     int adjustedVisualIndex(int visualIndex) const;
354 
355 #ifndef QT_NO_DATASTREAM
356     void write(QDataStream &out) const;
357     bool read(QDataStream &in);
358 #endif
359 
360 };
361 
362 QT_END_NAMESPACE
363 
364 #endif // QT_NO_ITEMVIEWS
365 
366 #endif // QHEADERVIEW_P_H
367