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