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 QTABLEVIEW_P_H |
5 | #define QTABLEVIEW_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 "qtableview.h" |
20 | #include "qheaderview.h" |
21 | |
22 | #include <QtCore/QList> |
23 | #include <QtCore/QMap> |
24 | #include <QtCore/QSet> |
25 | #include <QtCore/QDebug> |
26 | #include "private/qabstractitemview_p.h" |
27 | |
28 | #include <array> |
29 | #include <list> |
30 | #include <vector> |
31 | |
32 | QT_REQUIRE_CONFIG(tableview); |
33 | |
34 | QT_BEGIN_NAMESPACE |
35 | |
36 | /** \internal |
37 | * |
38 | * This is a list of span with a binary index to look up quickly a span at a certain index. |
39 | * |
40 | * The index is a map of map. |
41 | * spans are mentaly divided into sub spans so that the start of any subspans doesn't overlap |
42 | * with any other subspans. There is no real representation of the subspans. |
43 | * The key of the first map is the row where the subspan starts, the value of the first map is |
44 | * a list (map) of all subspans that starts at the same row. It is indexed with its row |
45 | */ |
46 | class Q_AUTOTEST_EXPORT QSpanCollection |
47 | { |
48 | public: |
49 | struct Span |
50 | { |
51 | int m_top; |
52 | int m_left; |
53 | int m_bottom; |
54 | int m_right; |
55 | bool will_be_deleted; |
56 | Span() |
57 | : m_top(-1), m_left(-1), m_bottom(-1), m_right(-1), will_be_deleted(false) { } |
58 | Span(int row, int column, int rowCount, int columnCount) |
59 | : m_top(row), m_left(column), m_bottom(row+rowCount-1), m_right(column+columnCount-1), will_be_deleted(false) { } |
60 | inline int top() const { return m_top; } |
61 | inline int left() const { return m_left; } |
62 | inline int bottom() const { return m_bottom; } |
63 | inline int right() const { return m_right; } |
64 | inline int height() const { return m_bottom - m_top + 1; } |
65 | inline int width() const { return m_right - m_left + 1; } |
66 | }; |
67 | |
68 | ~QSpanCollection() |
69 | { |
70 | qDeleteAll(c: spans); |
71 | } |
72 | |
73 | void addSpan(Span *span); |
74 | void updateSpan(Span *span, int old_height); |
75 | Span *spanAt(int x, int y) const; |
76 | void clear(); |
77 | QSet<Span *> spansInRect(int x, int y, int w, int h) const; |
78 | |
79 | void updateInsertedRows(int start, int end); |
80 | void updateInsertedColumns(int start, int end); |
81 | void updateRemovedRows(int start, int end); |
82 | void updateRemovedColumns(int start, int end); |
83 | |
84 | #ifdef QT_BUILD_INTERNAL |
85 | bool checkConsistency() const; |
86 | #endif |
87 | |
88 | typedef std::list<Span *> SpanList; |
89 | SpanList spans; //lists of all spans |
90 | private: |
91 | //the indexes are negative so the QMap::lowerBound do what i need. |
92 | typedef QMap<int, Span *> SubIndex; |
93 | typedef QMap<int, SubIndex> Index; |
94 | Index index; |
95 | |
96 | bool cleanSpanSubIndex(SubIndex &subindex, int end, bool update = false); |
97 | }; |
98 | |
99 | Q_DECLARE_TYPEINFO ( QSpanCollection::Span, Q_RELOCATABLE_TYPE); |
100 | |
101 | #if QT_CONFIG(abstractbutton) |
102 | class QTableCornerButton; |
103 | #endif |
104 | class Q_AUTOTEST_EXPORT QTableViewPrivate : public QAbstractItemViewPrivate |
105 | { |
106 | Q_DECLARE_PUBLIC(QTableView) |
107 | public: |
108 | QTableViewPrivate() |
109 | : showGrid(true), gridStyle(Qt::SolidLine), |
110 | columnResizeTimerID(0), rowResizeTimerID(0), |
111 | horizontalHeader(nullptr), verticalHeader(nullptr), |
112 | sortingEnabled(false), geometryRecursionBlock(false), |
113 | visualCursor(QPoint()) |
114 | { |
115 | wrapItemText = true; |
116 | #if QT_CONFIG(draganddrop) |
117 | overwrite = true; |
118 | #endif |
119 | } |
120 | void init(); |
121 | void clearConnections(); |
122 | void trimHiddenSelections(QItemSelectionRange *range) const; |
123 | QRect intersectedRect(const QRect rect, const QModelIndex &topLeft, const QModelIndex &bottomRight) const override; |
124 | |
125 | inline bool isHidden(int row, int col) const { |
126 | return verticalHeader->isSectionHidden(logicalIndex: row) |
127 | || horizontalHeader->isSectionHidden(logicalIndex: col); |
128 | } |
129 | inline int visualRow(int logicalRow) const { |
130 | return verticalHeader->visualIndex(logicalIndex: logicalRow); |
131 | } |
132 | inline int visualColumn(int logicalCol) const { |
133 | return horizontalHeader->visualIndex(logicalIndex: logicalCol); |
134 | } |
135 | inline int logicalRow(int visualRow) const { |
136 | return verticalHeader->logicalIndex(visualIndex: visualRow); |
137 | } |
138 | inline int logicalColumn(int visualCol) const { |
139 | return horizontalHeader->logicalIndex(visualIndex: visualCol); |
140 | } |
141 | |
142 | inline int accessibleTable2Index(const QModelIndex &index) const { |
143 | const int vHeader = verticalHeader ? 1 : 0; |
144 | return (index.row() + (horizontalHeader ? 1 : 0)) * (index.model()->columnCount() + vHeader) |
145 | + index.column() + vHeader; |
146 | } |
147 | |
148 | int sectionSpanEndLogical(const QHeaderView *header, int logical, int span) const; |
149 | int sectionSpanSize(const QHeaderView *header, int logical, int span) const; |
150 | bool spanContainsSection(const QHeaderView *header, int logical, int spanLogical, int span) const; |
151 | void drawAndClipSpans(const QRegion &area, QPainter *painter, |
152 | const QStyleOptionViewItem &option, QBitArray *drawn, |
153 | int firstVisualRow, int lastVisualRow, int firstVisualColumn, int lastVisualColumn); |
154 | void drawCell(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index); |
155 | int widthHintForIndex(const QModelIndex &index, int hint, const QStyleOptionViewItem &option) const; |
156 | int heightHintForIndex(const QModelIndex &index, int hint, QStyleOptionViewItem &option) const; |
157 | |
158 | bool showGrid; |
159 | Qt::PenStyle gridStyle; |
160 | int columnResizeTimerID; |
161 | int rowResizeTimerID; |
162 | QList<int> columnsToUpdate; |
163 | QList<int> rowsToUpdate; |
164 | QHeaderView *horizontalHeader; |
165 | QHeaderView *verticalHeader; |
166 | #if QT_CONFIG(abstractbutton) |
167 | QTableCornerButton *cornerWidget; |
168 | QMetaObject::Connection cornerWidgetConnection; |
169 | #endif |
170 | QMetaObject::Connection selectionmodelConnection; |
171 | std::array<QMetaObject::Connection, 4> modelConnections; |
172 | std::array<QMetaObject::Connection, 7> verHeaderConnections; |
173 | std::array<QMetaObject::Connection, 5> horHeaderConnections; |
174 | std::vector<QMetaObject::Connection> dynHorHeaderConnections; |
175 | |
176 | bool sortingEnabled; |
177 | bool geometryRecursionBlock; |
178 | QPoint visualCursor; // (Row,column) cell coordinates to track through span navigation. |
179 | |
180 | QSpanCollection spans; |
181 | |
182 | void setSpan(int row, int column, int rowSpan, int columnSpan); |
183 | QSpanCollection::Span span(int row, int column) const; |
184 | inline int rowSpan(int row, int column) const { |
185 | return span(row, column).height(); |
186 | } |
187 | inline int columnSpan(int row, int column) const { |
188 | return span(row, column).width(); |
189 | } |
190 | inline bool hasSpans() const { |
191 | return !spans.spans.empty(); |
192 | } |
193 | inline int rowSpanHeight(int row, int span) const { |
194 | return sectionSpanSize(header: verticalHeader, logical: row, span); |
195 | } |
196 | inline int columnSpanWidth(int column, int span) const { |
197 | return sectionSpanSize(header: horizontalHeader, logical: column, span); |
198 | } |
199 | inline int rowSpanEndLogical(int row, int span) const { |
200 | return sectionSpanEndLogical(header: verticalHeader, logical: row, span); |
201 | } |
202 | inline int columnSpanEndLogical(int column, int span) const { |
203 | return sectionSpanEndLogical(header: horizontalHeader, logical: column, span); |
204 | } |
205 | |
206 | inline bool isRowHidden(int row) const { |
207 | return verticalHeader->isSectionHidden(logicalIndex: row); |
208 | } |
209 | inline bool isColumnHidden(int column) const { |
210 | return horizontalHeader->isSectionHidden(logicalIndex: column); |
211 | } |
212 | inline bool isCellEnabled(int row, int column) const { |
213 | return isIndexEnabled(index: model->index(row, column, parent: root)); |
214 | } |
215 | |
216 | enum class SearchDirection |
217 | { |
218 | Increasing, |
219 | Decreasing |
220 | }; |
221 | int nextActiveVisualRow(int rowToStart, int column, int limit, |
222 | SearchDirection searchDirection) const; |
223 | int nextActiveVisualColumn(int row, int columnToStart, int limit, |
224 | SearchDirection searchDirection) const; |
225 | |
226 | QRect visualSpanRect(const QSpanCollection::Span &span) const; |
227 | |
228 | void selectRow(int row, bool anchor); |
229 | void selectColumn(int column, bool anchor); |
230 | |
231 | void updateSpanInsertedRows(const QModelIndex &parent, int start, int end); |
232 | void updateSpanInsertedColumns(const QModelIndex &parent, int start, int end); |
233 | void updateSpanRemovedRows(const QModelIndex &parent, int start, int end); |
234 | void updateSpanRemovedColumns(const QModelIndex &parent, int start, int end); |
235 | void sortIndicatorChanged(int column, Qt::SortOrder order); |
236 | }; |
237 | |
238 | QT_END_NAMESPACE |
239 | |
240 | #endif // QTABLEVIEW_P_H |
241 |
Definitions
- QSpanCollection
- Span
- Span
- Span
- top
- left
- bottom
- right
- height
- width
- ~QSpanCollection
- QTableViewPrivate
- QTableViewPrivate
- isHidden
- visualRow
- visualColumn
- logicalRow
- logicalColumn
- accessibleTable2Index
- rowSpan
- columnSpan
- hasSpans
- rowSpanHeight
- columnSpanWidth
- rowSpanEndLogical
- columnSpanEndLogical
- isRowHidden
- isColumnHidden
- isCellEnabled
Learn Advanced QML with KDAB
Find out more