| 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 QTREEVIEW_P_H | 
| 41 | #define QTREEVIEW_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 "private/qabstractitemview_p.h" | 
| 56 | #if QT_CONFIG(animation) | 
| 57 | #include <QtCore/qvariantanimation.h> | 
| 58 | #endif | 
| 59 | #include <QtCore/qabstractitemmodel.h> | 
| 60 | #include <QtCore/qvector.h> | 
| 61 |  | 
| 62 | QT_REQUIRE_CONFIG(treeview); | 
| 63 |  | 
| 64 | QT_BEGIN_NAMESPACE | 
| 65 |  | 
| 66 | struct QTreeViewItem | 
| 67 | { | 
| 68 |     QTreeViewItem() : parentItem(-1), expanded(false), spanning(false), hasChildren(false), | 
| 69 |                       hasMoreSiblings(false), total(0), level(0), height(0) {} | 
| 70 |     QModelIndex index; // we remove items whenever the indexes are invalidated | 
| 71 |     int parentItem; // parent item index in viewItems | 
| 72 |     uint expanded : 1; | 
| 73 |     uint spanning : 1; | 
| 74 |     uint hasChildren : 1; // if the item has visible children (even if collapsed) | 
| 75 |     uint hasMoreSiblings : 1; | 
| 76 |     uint total : 28; // total number of children visible | 
| 77 |     uint level : 16; // indentation | 
| 78 |     int height : 16; // row height | 
| 79 | }; | 
| 80 |  | 
| 81 | Q_DECLARE_TYPEINFO(QTreeViewItem, Q_MOVABLE_TYPE); | 
| 82 |  | 
| 83 | class Q_WIDGETS_EXPORT QTreeViewPrivate : public QAbstractItemViewPrivate | 
| 84 | { | 
| 85 |     Q_DECLARE_PUBLIC(QTreeView) | 
| 86 | public: | 
| 87 |  | 
| 88 |     QTreeViewPrivate() | 
| 89 |         : QAbstractItemViewPrivate(), | 
| 90 |           header(nullptr), indent(20), lastViewedItem(0), defaultItemHeight(-1), | 
| 91 |           uniformRowHeights(false), rootDecoration(true), | 
| 92 |           itemsExpandable(true), sortingEnabled(false), | 
| 93 |           expandsOnDoubleClick(true), | 
| 94 |           allColumnsShowFocus(false), customIndent(false), current(0), spanning(false), | 
| 95 |           animationsEnabled(false), columnResizeTimerID(0), | 
| 96 |           autoExpandDelay(-1), hoverBranch(-1), geometryRecursionBlock(false), hasRemovedItems(false), | 
| 97 |           treePosition(0) {} | 
| 98 |  | 
| 99 |     ~QTreeViewPrivate() {} | 
| 100 |     void initialize(); | 
| 101 |     int logicalIndexForTree() const; | 
| 102 |     inline bool isTreePosition(int logicalIndex) const | 
| 103 |     { | 
| 104 |         return logicalIndex == logicalIndexForTree(); | 
| 105 |     } | 
| 106 |  | 
| 107 |     QItemViewPaintPairs draggablePaintPairs(const QModelIndexList &indexes, QRect *r) const override; | 
| 108 |     void adjustViewOptionsForIndex(QStyleOptionViewItem *option, const QModelIndex ¤t) const override; | 
| 109 |  | 
| 110 | #if QT_CONFIG(animation) | 
| 111 |     struct AnimatedOperation : public QVariantAnimation | 
| 112 |     { | 
| 113 |         int item; | 
| 114 |         QPixmap before; | 
| 115 |         QPixmap after; | 
| 116 |         QWidget *viewport; | 
| 117 |         AnimatedOperation() : item(0) { setEasingCurve(QEasingCurve::InOutQuad); } | 
| 118 |         int top() const { return startValue().toInt(); } | 
| 119 |         QRect rect() const { QRect rect = viewport->rect(); rect.moveTop(pos: top()); return rect; } | 
| 120 |         void updateCurrentValue(const QVariant &) override { viewport->update(rect()); } | 
| 121 |         void updateState(State state, State) override { if (state == Stopped) before = after = QPixmap(); } | 
| 122 |     } animatedOperation; | 
| 123 |     void prepareAnimatedOperation(int item, QVariantAnimation::Direction d); | 
| 124 |     void beginAnimatedOperation(); | 
| 125 |     void drawAnimatedOperation(QPainter *painter) const; | 
| 126 |     QPixmap renderTreeToPixmapForAnimation(const QRect &rect) const; | 
| 127 |     void _q_endAnimatedOperation(); | 
| 128 | #endif // animation | 
| 129 |  | 
| 130 |     void expand(int item, bool emitSignal); | 
| 131 |     void collapse(int item, bool emitSignal); | 
| 132 |  | 
| 133 |     void _q_columnsAboutToBeRemoved(const QModelIndex &, int, int) override; | 
| 134 |     void _q_columnsRemoved(const QModelIndex &, int, int) override; | 
| 135 |     void _q_modelAboutToBeReset(); | 
| 136 |     void _q_sortIndicatorChanged(int column, Qt::SortOrder order); | 
| 137 |     void _q_modelDestroyed() override; | 
| 138 |  | 
| 139 |     void layout(int item, bool recusiveExpanding = false, bool afterIsUninitialized = false); | 
| 140 |  | 
| 141 |     int pageUp(int item) const; | 
| 142 |     int pageDown(int item) const; | 
| 143 |     int itemForKeyHome() const; | 
| 144 |     int itemForKeyEnd() const; | 
| 145 |  | 
| 146 |     int itemHeight(int item) const; | 
| 147 |     int indentationForItem(int item) const; | 
| 148 |     int coordinateForItem(int item) const; | 
| 149 |     int itemAtCoordinate(int coordinate) const; | 
| 150 |  | 
| 151 |     int viewIndex(const QModelIndex &index) const; | 
| 152 |     QModelIndex modelIndex(int i, int column = 0) const; | 
| 153 |  | 
| 154 |     void insertViewItems(int pos, int count, const QTreeViewItem &viewItem); | 
| 155 |     void removeViewItems(int pos, int count); | 
| 156 | #if 0 | 
| 157 |     bool checkViewItems() const; | 
| 158 | #endif | 
| 159 |  | 
| 160 |     int firstVisibleItem(int *offset = nullptr) const; | 
| 161 |     int lastVisibleItem(int firstVisual = -1, int offset = -1) const; | 
| 162 |     int columnAt(int x) const; | 
| 163 |     bool hasVisibleChildren( const QModelIndex& parent) const; | 
| 164 |  | 
| 165 |     bool expandOrCollapseItemAtPos(const QPoint &pos); | 
| 166 |  | 
| 167 |     void updateScrollBars(); | 
| 168 |  | 
| 169 |     int itemDecorationAt(const QPoint &pos) const; | 
| 170 |     QRect itemDecorationRect(const QModelIndex &index) const; | 
| 171 |  | 
| 172 |  | 
| 173 |     QVector<QPair<int, int> > columnRanges(const QModelIndex &topIndex, const QModelIndex &bottomIndex) const; | 
| 174 |     void select(const QModelIndex &start, const QModelIndex &stop, QItemSelectionModel::SelectionFlags command); | 
| 175 |  | 
| 176 |     QPair<int,int> startAndEndColumns(const QRect &rect) const; | 
| 177 |  | 
| 178 |     void updateChildCount(const int parentItem, const int delta); | 
| 179 |  | 
| 180 |     void paintAlternatingRowColors(QPainter *painter, QStyleOptionViewItem *option, int y, int bottom) const; | 
| 181 |  | 
| 182 |     // logicalIndices: vector of currently visibly logical indices | 
| 183 |     // itemPositions: vector of view item positions (beginning/middle/end/onlyone) | 
| 184 |     void calcLogicalIndices(QVector<int> *logicalIndices, QVector<QStyleOptionViewItem::ViewItemPosition> *itemPositions, int left, int right) const; | 
| 185 |     int widthHintForIndex(const QModelIndex &index, int hint, const QStyleOptionViewItem &option, int i) const; | 
| 186 |     QHeaderView *; | 
| 187 |     int indent; | 
| 188 |  | 
| 189 |     mutable QVector<QTreeViewItem> viewItems; | 
| 190 |     mutable int lastViewedItem; | 
| 191 |     int defaultItemHeight; // this is just a number; contentsHeight() / numItems | 
| 192 |     bool uniformRowHeights; // used when all rows have the same height | 
| 193 |     bool rootDecoration; | 
| 194 |     bool itemsExpandable; | 
| 195 |     bool sortingEnabled; | 
| 196 |     bool expandsOnDoubleClick; | 
| 197 |     bool allColumnsShowFocus; | 
| 198 |     bool customIndent; | 
| 199 |  | 
| 200 |     // used for drawing | 
| 201 |     mutable QPair<int,int> leftAndRight; | 
| 202 |     mutable int current; | 
| 203 |     mutable bool spanning; | 
| 204 |  | 
| 205 |     // used when expanding and collapsing items | 
| 206 |     QSet<QPersistentModelIndex> expandedIndexes; | 
| 207 |     bool animationsEnabled; | 
| 208 |  | 
| 209 |     inline bool storeExpanded(const QPersistentModelIndex &idx) { | 
| 210 |         if (expandedIndexes.contains(value: idx)) | 
| 211 |             return false; | 
| 212 |         expandedIndexes.insert(value: idx); | 
| 213 |         return true; | 
| 214 |     } | 
| 215 |  | 
| 216 |     inline bool isIndexExpanded(const QModelIndex &idx) const { | 
| 217 |         //We first check if the idx is a QPersistentModelIndex, because creating QPersistentModelIndex is slow | 
| 218 |         return !(idx.flags() & Qt::ItemNeverHasChildren) && isPersistent(index: idx) && expandedIndexes.contains(value: idx); | 
| 219 |     } | 
| 220 |  | 
| 221 |     // used when hiding and showing items | 
| 222 |     QSet<QPersistentModelIndex> hiddenIndexes; | 
| 223 |  | 
| 224 |     inline bool isRowHidden(const QModelIndex &idx) const { | 
| 225 |         if (hiddenIndexes.isEmpty()) | 
| 226 |             return false; | 
| 227 |         //We first check if the idx is a QPersistentModelIndex, because creating QPersistentModelIndex is slow | 
| 228 |         return isPersistent(index: idx) && hiddenIndexes.contains(value: idx); | 
| 229 |     } | 
| 230 |  | 
| 231 |     inline bool isItemHiddenOrDisabled(int i) const { | 
| 232 |         if (i < 0 || i >= viewItems.count()) | 
| 233 |             return false; | 
| 234 |         const QModelIndex index = viewItems.at(i).index; | 
| 235 |         return isRowHidden(idx: index) || !isIndexEnabled(index); | 
| 236 |     } | 
| 237 |  | 
| 238 |     inline int above(int item) const | 
| 239 |         { int i = item; while (isItemHiddenOrDisabled(i: --item)){} return item < 0 ? i : item; } | 
| 240 |     inline int below(int item) const | 
| 241 |         { int i = item; while (isItemHiddenOrDisabled(i: ++item)){} return item >= viewItems.count() ? i : item; } | 
| 242 |     inline void invalidateHeightCache(int item) const | 
| 243 |         { viewItems[item].height = 0; } | 
| 244 |  | 
| 245 |     inline int accessibleTable2Index(const QModelIndex &index) const { | 
| 246 |         return (viewIndex(index) + (header ? 1 : 0)) * model->columnCount()+index.column(); | 
| 247 |     } | 
| 248 |  | 
| 249 |     int accessibleTree2Index(const QModelIndex &index) const; | 
| 250 |  | 
| 251 |     void updateIndentationFromStyle(); | 
| 252 |  | 
| 253 |     // used for spanning rows | 
| 254 |     QSet<QPersistentModelIndex> spanningIndexes; | 
| 255 |  | 
| 256 |     // used for updating resized columns | 
| 257 |     int columnResizeTimerID; | 
| 258 |     QList<int> columnsToUpdate; | 
| 259 |  | 
| 260 |     // used for the automatic opening of nodes during DND | 
| 261 |     int autoExpandDelay; | 
| 262 |     QBasicTimer openTimer; | 
| 263 |  | 
| 264 |     // used for drawing hilighted expand/collapse indicators | 
| 265 |     mutable int hoverBranch; | 
| 266 |  | 
| 267 |     // used for blocking recursion when calling setViewportMargins from updateGeometries | 
| 268 |     bool geometryRecursionBlock; | 
| 269 |  | 
| 270 |     // If we should clean the set | 
| 271 |     bool hasRemovedItems; | 
| 272 |  | 
| 273 |     // tree position | 
| 274 |     int treePosition; | 
| 275 | }; | 
| 276 |  | 
| 277 | QT_END_NAMESPACE | 
| 278 |  | 
| 279 | #endif // QTREEVIEW_P_H | 
| 280 |  |