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; SpanSpan87 Span() 88 : m_top(-1), m_left(-1), m_bottom(-1), m_right(-1), will_be_deleted(false) { } SpanSpan89 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) { } topSpan91 inline int top() const { return m_top; } leftSpan92 inline int left() const { return m_left; } bottomSpan93 inline int bottom() const { return m_bottom; } rightSpan94 inline int right() const { return m_right; } heightSpan95 inline int height() const { return m_bottom - m_top + 1; } widthSpan96 inline int width() const { return m_right - m_left + 1; } 97 }; 98 ~QSpanCollection()99 ~QSpanCollection() 100 { 101 qDeleteAll(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 { Q_DECLARE_PUBLIC(QTableView)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 isHidden(int row,int col)153 inline bool isHidden(int row, int col) const { 154 return verticalHeader->isSectionHidden(row) 155 || horizontalHeader->isSectionHidden(col); 156 } visualRow(int logicalRow)157 inline int visualRow(int logicalRow) const { 158 return verticalHeader->visualIndex(logicalRow); 159 } visualColumn(int logicalCol)160 inline int visualColumn(int logicalCol) const { 161 return horizontalHeader->visualIndex(logicalCol); 162 } logicalRow(int visualRow)163 inline int logicalRow(int visualRow) const { 164 return verticalHeader->logicalIndex(visualRow); 165 } logicalColumn(int visualCol)166 inline int logicalColumn(int visualCol) const { 167 return horizontalHeader->logicalIndex(visualCol); 168 } 169 accessibleTable2Index(const QModelIndex & index)170 inline int accessibleTable2Index(const QModelIndex &index) const { 171 const int vHeader = verticalHeader ? 1 : 0; 172 return (index.row() + (horizontalHeader ? 1 : 0)) * (index.model()->columnCount() + vHeader) 173 + index.column() + vHeader; 174 } 175 176 int sectionSpanEndLogical(const QHeaderView *header, int logical, int span) const; 177 int sectionSpanSize(const QHeaderView *header, int logical, int span) const; 178 bool spanContainsSection(const QHeaderView *header, 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 *horizontalHeader; 195 QHeaderView *verticalHeader; 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; rowSpan(int row,int column)207 inline int rowSpan(int row, int column) const { 208 return span(row, column).height(); 209 } columnSpan(int row,int column)210 inline int columnSpan(int row, int column) const { 211 return span(row, column).width(); 212 } hasSpans()213 inline bool hasSpans() const { 214 return !spans.spans.empty(); 215 } rowSpanHeight(int row,int span)216 inline int rowSpanHeight(int row, int span) const { 217 return sectionSpanSize(verticalHeader, row, span); 218 } columnSpanWidth(int column,int span)219 inline int columnSpanWidth(int column, int span) const { 220 return sectionSpanSize(horizontalHeader, column, span); 221 } rowSpanEndLogical(int row,int span)222 inline int rowSpanEndLogical(int row, int span) const { 223 return sectionSpanEndLogical(verticalHeader, row, span); 224 } columnSpanEndLogical(int column,int span)225 inline int columnSpanEndLogical(int column, int span) const { 226 return sectionSpanEndLogical(horizontalHeader, column, span); 227 } 228 isRowHidden(int row)229 inline bool isRowHidden(int row) const { 230 return verticalHeader->isSectionHidden(row); 231 } isColumnHidden(int column)232 inline bool isColumnHidden(int column) const { 233 return horizontalHeader->isSectionHidden(column); 234 } isCellEnabled(int row,int column)235 inline bool isCellEnabled(int row, int column) const { 236 return isIndexEnabled(model->index(row, column, 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