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