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 QtGui 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 QSTANDARDITEMMODEL_P_H
41#define QSTANDARDITEMMODEL_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 for the convenience
48// of other Qt classes. 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 <QtGui/private/qtguiglobal_p.h>
55#include "private/qabstractitemmodel_p.h"
56
57#include <QtCore/qlist.h>
58#include <QtCore/qpair.h>
59#include <QtCore/qstack.h>
60#include <QtCore/qvariant.h>
61#include <QtCore/qvector.h>
62#include <QtCore/qdebug.h>
63
64QT_REQUIRE_CONFIG(standarditemmodel);
65
66QT_BEGIN_NAMESPACE
67
68class QStandardItemData
69{
70public:
71 inline QStandardItemData() : role(-1) {}
72 inline QStandardItemData(int r, const QVariant &v) : role(r), value(v) {}
73 inline QStandardItemData(const std::pair<const int&, const QVariant&> &p) : role(p.first), value(p.second) {}
74 int role;
75 QVariant value;
76 inline bool operator==(const QStandardItemData &other) const { return role == other.role && value == other.value; }
77};
78Q_DECLARE_TYPEINFO(QStandardItemData, Q_MOVABLE_TYPE);
79
80#ifndef QT_NO_DATASTREAM
81
82inline QDataStream &operator>>(QDataStream &in, QStandardItemData &data)
83{
84 in >> data.role;
85 in >> data.value;
86 return in;
87}
88
89inline QDataStream &operator<<(QDataStream &out, const QStandardItemData &data)
90{
91 out << data.role;
92 out << data.value;
93 return out;
94}
95
96inline QDebug &operator<<(QDebug &debug, const QStandardItemData &data)
97{
98 QDebugStateSaver saver(debug);
99 debug.nospace() << data.role
100 << " "
101 << data.value;
102 return debug.space();
103}
104
105#endif // QT_NO_DATASTREAM
106
107class QStandardItemPrivate
108{
109 Q_DECLARE_PUBLIC(QStandardItem)
110public:
111 inline QStandardItemPrivate()
112 : model(nullptr),
113 parent(nullptr),
114 rows(0),
115 columns(0),
116 q_ptr(nullptr),
117 lastKnownIndex(-1)
118 { }
119
120 inline int childIndex(int row, int column) const {
121 if ((row < 0) || (column < 0)
122 || (row >= rowCount()) || (column >= columnCount())) {
123 return -1;
124 }
125 return (row * columnCount()) + column;
126 }
127 inline int childIndex(const QStandardItem *child) const {
128 const int lastChild = children.size() - 1;
129 int &childsLastIndexInParent = child->d_func()->lastKnownIndex;
130 if (childsLastIndexInParent != -1 && childsLastIndexInParent <= lastChild) {
131 if (children.at(childsLastIndexInParent) == child)
132 return childsLastIndexInParent;
133 } else {
134 childsLastIndexInParent = lastChild / 2;
135 }
136
137 // assuming the item is in the vicinity of the previous index, iterate forwards and
138 // backwards through the children
139 int backwardIter = childsLastIndexInParent - 1;
140 int forwardIter = childsLastIndexInParent;
141 Q_FOREVER {
142 if (forwardIter <= lastChild) {
143 if (children.at(forwardIter) == child) {
144 childsLastIndexInParent = forwardIter;
145 break;
146 }
147 ++forwardIter;
148 } else if (backwardIter < 0) {
149 childsLastIndexInParent = -1;
150 break;
151 }
152 if (backwardIter >= 0) {
153 if (children.at(backwardIter) == child) {
154 childsLastIndexInParent = backwardIter;
155 break;
156 }
157 --backwardIter;
158 }
159 }
160 return childsLastIndexInParent;
161 }
162 QPair<int, int> position() const;
163 void setChild(int row, int column, QStandardItem *item,
164 bool emitChanged = false);
165 inline int rowCount() const {
166 return rows;
167 }
168 inline int columnCount() const {
169 return columns;
170 }
171 void childDeleted(QStandardItem *child);
172
173 void setModel(QStandardItemModel *mod);
174
175 inline void setParentAndModel(
176 QStandardItem *par,
177 QStandardItemModel *mod) {
178 setModel(mod);
179 parent = par;
180 }
181
182 void changeFlags(bool enable, Qt::ItemFlags f);
183 void setItemData(const QMap<int, QVariant> &roles);
184 const QMap<int, QVariant> itemData() const;
185
186 bool insertRows(int row, int count, const QList<QStandardItem*> &items);
187 bool insertRows(int row, const QList<QStandardItem*> &items);
188 bool insertColumns(int column, int count, const QList<QStandardItem*> &items);
189
190 void sortChildren(int column, Qt::SortOrder order);
191
192 QStandardItemModel *model;
193 QStandardItem *parent;
194 QVector<QStandardItemData> values;
195 QVector<QStandardItem*> children;
196 int rows;
197 int columns;
198
199 QStandardItem *q_ptr;
200
201 mutable int lastKnownIndex; // this is a cached value
202};
203
204class QStandardItemModelPrivate : public QAbstractItemModelPrivate
205{
206 Q_DECLARE_PUBLIC(QStandardItemModel)
207
208public:
209 QStandardItemModelPrivate();
210 ~QStandardItemModelPrivate();
211
212 void init();
213
214 inline QStandardItem *createItem() const {
215 return itemPrototype ? itemPrototype->clone() : new QStandardItem;
216 }
217
218 inline QStandardItem *itemFromIndex(const QModelIndex &index) const {
219 Q_Q(const QStandardItemModel);
220 if (!index.isValid())
221 return root.data();
222 if (index.model() != q)
223 return nullptr;
224 QStandardItem *parent = static_cast<QStandardItem*>(index.internalPointer());
225 if (parent == nullptr)
226 return nullptr;
227 return parent->child(index.row(), index.column());
228 }
229
230 void sort(QStandardItem *parent, int column, Qt::SortOrder order);
231 void itemChanged(QStandardItem *item, const QVector<int> &roles = QVector<int>());
232 void rowsAboutToBeInserted(QStandardItem *parent, int start, int end);
233 void columnsAboutToBeInserted(QStandardItem *parent, int start, int end);
234 void rowsAboutToBeRemoved(QStandardItem *parent, int start, int end);
235 void columnsAboutToBeRemoved(QStandardItem *parent, int start, int end);
236 void rowsInserted(QStandardItem *parent, int row, int count);
237 void columnsInserted(QStandardItem *parent, int column, int count);
238 void rowsRemoved(QStandardItem *parent, int row, int count);
239 void columnsRemoved(QStandardItem *parent, int column, int count);
240
241 void _q_emitItemChanged(const QModelIndex &topLeft,
242 const QModelIndex &bottomRight);
243
244 void decodeDataRecursive(QDataStream &stream, QStandardItem *item);
245
246 QVector<QStandardItem*> columnHeaderItems;
247 QVector<QStandardItem*> rowHeaderItems;
248 QScopedPointer<QStandardItem> root;
249 const QStandardItem *itemPrototype;
250 int sortRole;
251};
252
253QT_END_NAMESPACE
254
255#endif // QSTANDARDITEMMODEL_P_H
256