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