1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#ifndef QTREEVIEW_P_H
5#define QTREEVIEW_P_H
6
7//
8// W A R N I N G
9// -------------
10//
11// This file is not part of the Qt API. It exists purely as an
12// implementation detail. This header file may change from version to
13// version without notice, or even be removed.
14//
15// We mean it.
16//
17
18#include <QtWidgets/private/qtwidgetsglobal_p.h>
19#include "qtreeview.h"
20#include "private/qabstractitemview_p.h"
21#include <QtCore/qabstractitemmodel.h>
22#include <QtCore/qbasictimer.h>
23#include <QtCore/qlist.h>
24#if QT_CONFIG(animation)
25#include <QtCore/qvariantanimation.h>
26#endif
27
28#include <array>
29
30QT_REQUIRE_CONFIG(treeview);
31
32QT_BEGIN_NAMESPACE
33
34struct QTreeViewItem
35{
36 QTreeViewItem() : parentItem(-1), expanded(false), spanning(false), hasChildren(false),
37 hasMoreSiblings(false), total(0), level(0), height(0) {}
38 QModelIndex index; // we remove items whenever the indexes are invalidated
39 int parentItem; // parent item index in viewItems
40 uint expanded : 1;
41 uint spanning : 1;
42 uint hasChildren : 1; // if the item has visible children (even if collapsed)
43 uint hasMoreSiblings : 1;
44 uint total : 28; // total number of children visible
45 uint level : 16; // indentation
46 int height : 16; // row height
47};
48
49Q_DECLARE_TYPEINFO(QTreeViewItem, Q_RELOCATABLE_TYPE);
50
51class Q_WIDGETS_EXPORT QTreeViewPrivate : public QAbstractItemViewPrivate
52{
53 Q_DECLARE_PUBLIC(QTreeView)
54public:
55
56 QTreeViewPrivate()
57 : QAbstractItemViewPrivate(),
58 header(nullptr), indent(20), lastViewedItem(0), defaultItemHeight(-1),
59 uniformRowHeights(false), rootDecoration(true),
60 itemsExpandable(true), sortingEnabled(false),
61 expandsOnDoubleClick(true),
62 allColumnsShowFocus(false), customIndent(false), current(0), spanning(false),
63 animationsEnabled(false),
64 autoExpandDelay(-1), hoverBranch(-1), geometryRecursionBlock(false), hasRemovedItems(false),
65 treePosition(0) {}
66
67 ~QTreeViewPrivate() {}
68 void initialize();
69 void clearConnections();
70 int logicalIndexForTree() const;
71 inline bool isTreePosition(int logicalIndex) const
72 {
73 return logicalIndex == logicalIndexForTree();
74 }
75
76 QItemViewPaintPairs draggablePaintPairs(const QModelIndexList &indexes, QRect *r) const override;
77 void adjustViewOptionsForIndex(QStyleOptionViewItem *option, const QModelIndex &current) const override;
78
79#if QT_CONFIG(animation)
80 struct AnimatedOperation : public QVariantAnimation
81 {
82 int item;
83 QPixmap before;
84 QPixmap after;
85 QWidget *viewport;
86 AnimatedOperation() : item(0) { setEasingCurve(QEasingCurve::InOutQuad); }
87 int top() const { return startValue().toInt(); }
88 QRect rect() const { QRect rect = viewport->rect(); rect.moveTop(pos: top()); return rect; }
89 void updateCurrentValue(const QVariant &) override { viewport->update(rect()); }
90 void updateState(State state, State) override { if (state == Stopped) before = after = QPixmap(); }
91 } animatedOperation;
92 void prepareAnimatedOperation(int item, QVariantAnimation::Direction d);
93 void beginAnimatedOperation();
94 void drawAnimatedOperation(QPainter *painter) const;
95 QPixmap renderTreeToPixmapForAnimation(const QRect &rect) const;
96 void endAnimatedOperation();
97#endif // animation
98
99 void expand(int item, bool emitSignal);
100 void collapse(int item, bool emitSignal);
101
102 void columnsAboutToBeRemoved(const QModelIndex &, int, int) override;
103 void columnsRemoved(const QModelIndex &, int, int) override;
104 void modelAboutToBeReset();
105 void sortIndicatorChanged(int column, Qt::SortOrder order);
106 void modelDestroyed() override;
107 QRect intersectedRect(const QRect rect, const QModelIndex &topLeft, const QModelIndex &bottomRight) const override;
108
109 void layout(int item, bool recusiveExpanding = false, bool afterIsUninitialized = false);
110
111 int pageUp(int item) const;
112 int pageDown(int item) const;
113 int itemForKeyHome() const;
114 int itemForKeyEnd() const;
115
116 int itemHeight(int item) const;
117 int indentationForItem(int item) const;
118 int coordinateForItem(int item) const;
119 int itemAtCoordinate(int coordinate) const;
120
121 int viewIndex(const QModelIndex &index) const;
122 QModelIndex modelIndex(int i, int column = 0) const;
123
124 void insertViewItems(int pos, int count, const QTreeViewItem &viewItem);
125 void removeViewItems(int pos, int count);
126#if 0
127 bool checkViewItems() const;
128#endif
129
130 int firstVisibleItem(int *offset = nullptr) const;
131 int lastVisibleItem(int firstVisual = -1, int offset = -1) const;
132 int columnAt(int x) const;
133 bool hasVisibleChildren( const QModelIndex& parent) const;
134
135 bool expandOrCollapseItemAtPos(const QPoint &pos);
136
137 void updateScrollBars();
138
139 int itemDecorationAt(const QPoint &pos) const;
140 QRect itemDecorationRect(const QModelIndex &index) const;
141
142 QList<std::pair<int, int>> columnRanges(const QModelIndex &topIndex,
143 const QModelIndex &bottomIndex) const;
144 void select(const QModelIndex &start, const QModelIndex &stop, QItemSelectionModel::SelectionFlags command);
145
146 std::pair<int,int> startAndEndColumns(const QRect &rect) const;
147
148 void updateChildCount(const int parentItem, const int delta);
149
150 void paintAlternatingRowColors(QPainter *painter, QStyleOptionViewItem *option, int y, int bottom) const;
151
152 // logicalIndices: vector of currently visibly logical indices
153 // itemPositions: vector of view item positions (beginning/middle/end/onlyone)
154 void calcLogicalIndices(QList<int> *logicalIndices,
155 QList<QStyleOptionViewItem::ViewItemPosition> *itemPositions, int left,
156 int right) const;
157 int widthHintForIndex(const QModelIndex &index, int hint, const QStyleOptionViewItem &option, int i) const;
158
159 enum RectRule {
160 FullRow,
161 SingleSection,
162 AddRowIndicatorToFirstSection
163 };
164
165 // Base class will get the first visual rect including row indicator
166 QRect visualRect(const QModelIndex &index) const override
167 {
168 return visualRect(index, rule: AddRowIndicatorToFirstSection);
169 }
170
171 QRect visualRect(const QModelIndex &index, RectRule rule) const;
172
173 QHeaderView *header;
174 int indent;
175
176 mutable QList<QTreeViewItem> viewItems;
177 mutable int lastViewedItem;
178 int defaultItemHeight; // this is just a number; contentsHeight() / numItems
179 bool uniformRowHeights; // used when all rows have the same height
180 bool rootDecoration;
181 bool itemsExpandable;
182 bool sortingEnabled;
183 bool expandsOnDoubleClick;
184 bool allColumnsShowFocus;
185 bool customIndent;
186
187 // used for drawing
188 mutable std::pair<int,int> leftAndRight;
189 mutable int current;
190 mutable bool spanning;
191
192 // used when expanding and collapsing items
193 QSet<QPersistentModelIndex> expandedIndexes;
194 bool animationsEnabled;
195
196 inline bool storeExpanded(const QPersistentModelIndex &idx) {
197 if (expandedIndexes.contains(value: idx))
198 return false;
199 expandedIndexes.insert(value: idx);
200 return true;
201 }
202
203 inline bool isIndexExpanded(const QModelIndex &idx) const {
204 //We first check if the idx is a QPersistentModelIndex, because creating QPersistentModelIndex is slow
205 return !(idx.flags() & Qt::ItemNeverHasChildren) && isPersistent(index: idx) && expandedIndexes.contains(value: idx);
206 }
207
208 // used when hiding and showing items
209 QSet<QPersistentModelIndex> hiddenIndexes;
210
211 inline bool isRowHidden(const QModelIndex &idx) const {
212 if (hiddenIndexes.isEmpty())
213 return false;
214 //We first check if the idx is a QPersistentModelIndex, because creating QPersistentModelIndex is slow
215 return isPersistent(index: idx) && hiddenIndexes.contains(value: idx);
216 }
217
218 inline bool isItemHiddenOrDisabled(int i) const {
219 if (i < 0 || i >= viewItems.size())
220 return false;
221 const QModelIndex index = viewItems.at(i).index;
222 return isRowHidden(idx: index) || !isIndexEnabled(index);
223 }
224
225 inline int above(int item) const
226 { int i = item; while (isItemHiddenOrDisabled(i: --item)){} return item < 0 ? i : item; }
227 inline int below(int item) const
228 { int i = item; while (isItemHiddenOrDisabled(i: ++item)){} return item >= viewItems.size() ? i : item; }
229 inline void invalidateHeightCache(int item) const
230 { viewItems[item].height = 0; }
231
232 inline int accessibleTable2Index(const QModelIndex &index) const {
233 return (viewIndex(index) + (header ? 1 : 0)) * model->columnCount()+index.column();
234 }
235
236 int accessibleTree2Index(const QModelIndex &index) const;
237
238 void updateIndentationFromStyle();
239
240 // used for spanning rows
241 QSet<QPersistentModelIndex> spanningIndexes;
242
243 // used for updating resized columns
244 QBasicTimer columnResizeTimer;
245 QList<int> columnsToUpdate;
246
247 // used for the automatic opening of nodes during DND
248 int autoExpandDelay;
249 QBasicTimer openTimer;
250
251 // used for drawing highlighted expand/collapse indicators
252 mutable int hoverBranch;
253
254 // used for blocking recursion when calling setViewportMargins from updateGeometries
255 bool geometryRecursionBlock;
256
257 // If we should clean the set
258 bool hasRemovedItems;
259
260 // tree position
261 int treePosition;
262
263 // pending accessibility update
264#if QT_CONFIG(accessibility)
265 bool pendingAccessibilityUpdate = false;
266#endif
267 void updateAccessibility();
268
269 QMetaObject::Connection animationConnection;
270 QMetaObject::Connection selectionmodelConnection;
271 std::array<QMetaObject::Connection, 2> modelConnections;
272 std::array<QMetaObject::Connection, 5> headerConnections;
273 QMetaObject::Connection sortHeaderConnection;
274};
275
276QT_END_NAMESPACE
277
278#endif // QTREEVIEW_P_H
279

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