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 Qt Data Visualization module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:GPL$
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 General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU
19** General Public License version 3 or (at your option) any later version
20** approved by the KDE Free Qt Foundation. The licenses are as published by
21** the Free Software Foundation and appearing in the file LICENSE.GPL3
22** included in the packaging of this file. Please review the following
23** information to ensure the GNU General Public License requirements will
24** be met: https://www.gnu.org/licenses/gpl-3.0.html.
25**
26** $QT_END_LICENSE$
27**
28****************************************************************************/
29
30#include "abstractitemmodelhandler_p.h"
31
32QT_BEGIN_NAMESPACE_DATAVISUALIZATION
33
34AbstractItemModelHandler::AbstractItemModelHandler(QObject *parent)
35 : QObject(parent),
36 resolvePending(0),
37 m_fullReset(true)
38{
39 m_resolveTimer.setSingleShot(true);
40 QObject::connect(sender: &m_resolveTimer, signal: &QTimer::timeout,
41 receiver: this, slot: &AbstractItemModelHandler::handlePendingResolve);
42}
43
44AbstractItemModelHandler::~AbstractItemModelHandler()
45{
46}
47
48void AbstractItemModelHandler::setItemModel(QAbstractItemModel *itemModel)
49{
50 if (itemModel != m_itemModel.data()) {
51 if (!m_itemModel.isNull())
52 QObject::disconnect(sender: m_itemModel, signal: 0, receiver: this, member: 0);
53
54 m_itemModel = itemModel;
55
56 if (!m_itemModel.isNull()) {
57 QObject::connect(sender: m_itemModel.data(), signal: &QAbstractItemModel::columnsInserted,
58 receiver: this, slot: &AbstractItemModelHandler::handleColumnsInserted);
59 QObject::connect(sender: m_itemModel.data(), signal: &QAbstractItemModel::columnsMoved,
60 receiver: this, slot: &AbstractItemModelHandler::handleColumnsMoved);
61 QObject::connect(sender: m_itemModel.data(), signal: &QAbstractItemModel::columnsRemoved,
62 receiver: this, slot: &AbstractItemModelHandler::handleColumnsRemoved);
63 QObject::connect(sender: m_itemModel.data(), signal: &QAbstractItemModel::dataChanged,
64 receiver: this, slot: &AbstractItemModelHandler::handleDataChanged);
65 QObject::connect(sender: m_itemModel.data(), signal: &QAbstractItemModel::layoutChanged,
66 receiver: this, slot: &AbstractItemModelHandler::handleLayoutChanged);
67 QObject::connect(sender: m_itemModel.data(), signal: &QAbstractItemModel::modelReset,
68 receiver: this, slot: &AbstractItemModelHandler::handleModelReset);
69 QObject::connect(sender: m_itemModel.data(), signal: &QAbstractItemModel::rowsInserted,
70 receiver: this, slot: &AbstractItemModelHandler::handleRowsInserted);
71 QObject::connect(sender: m_itemModel.data(), signal: &QAbstractItemModel::rowsMoved,
72 receiver: this, slot: &AbstractItemModelHandler::handleRowsMoved);
73 QObject::connect(sender: m_itemModel.data(), signal: &QAbstractItemModel::rowsRemoved,
74 receiver: this, slot: &AbstractItemModelHandler::handleRowsRemoved);
75 }
76 if (!m_resolveTimer.isActive())
77 m_resolveTimer.start(msec: 0);
78
79 emit itemModelChanged(itemModel);
80 }
81}
82
83QAbstractItemModel *AbstractItemModelHandler::itemModel() const
84{
85 return m_itemModel.data();
86}
87
88void AbstractItemModelHandler::handleColumnsInserted(const QModelIndex &parent,
89 int start, int end)
90{
91 Q_UNUSED(parent)
92 Q_UNUSED(start)
93 Q_UNUSED(end)
94
95 // Manipulating columns changes all rows in proxies that map rows/columns directly,
96 // and its effects are not clearly defined in others -> always do full reset.
97 if (!m_resolveTimer.isActive()) {
98 m_fullReset = true;
99 m_resolveTimer.start(msec: 0);
100 }
101}
102
103void AbstractItemModelHandler::handleColumnsMoved(const QModelIndex &sourceParent,
104 int sourceStart,
105 int sourceEnd,
106 const QModelIndex &destinationParent,
107 int destinationColumn)
108{
109 Q_UNUSED(sourceParent)
110 Q_UNUSED(sourceStart)
111 Q_UNUSED(sourceEnd)
112 Q_UNUSED(destinationParent)
113 Q_UNUSED(destinationColumn)
114
115 // Manipulating columns changes all rows in proxies that map rows/columns directly,
116 // and its effects are not clearly defined in others -> always do full reset.
117 if (!m_resolveTimer.isActive()) {
118 m_fullReset = true;
119 m_resolveTimer.start(msec: 0);
120 }
121}
122
123void AbstractItemModelHandler::handleColumnsRemoved(const QModelIndex &parent,
124 int start, int end)
125{
126 Q_UNUSED(parent)
127 Q_UNUSED(start)
128 Q_UNUSED(end)
129
130 // Manipulating columns changes all rows in proxies that map rows/columns directly,
131 // and its effects are not clearly defined in others -> always do full reset.
132 if (!m_resolveTimer.isActive()) {
133 m_fullReset = true;
134 m_resolveTimer.start(msec: 0);
135 }
136}
137
138void AbstractItemModelHandler::handleDataChanged(const QModelIndex &topLeft,
139 const QModelIndex &bottomRight,
140 const QVector<int> &roles)
141{
142 Q_UNUSED(topLeft)
143 Q_UNUSED(bottomRight)
144 Q_UNUSED(roles)
145
146 // Default handling for dataChanged is to do full reset, as it cannot be optimized
147 // in a general case, where we do not know which row/column/index the item model item
148 // actually ended up to in the proxy.
149 if (!m_resolveTimer.isActive()) {
150 m_fullReset = true;
151 m_resolveTimer.start(msec: 0);
152 }
153}
154
155void AbstractItemModelHandler::handleLayoutChanged(const QList<QPersistentModelIndex> &parents,
156 QAbstractItemModel::LayoutChangeHint hint)
157{
158 Q_UNUSED(parents)
159 Q_UNUSED(hint)
160
161 // Resolve entire model if layout changes
162 if (!m_resolveTimer.isActive()) {
163 m_fullReset = true;
164 m_resolveTimer.start(msec: 0);
165 }
166}
167
168void AbstractItemModelHandler::handleModelReset()
169{
170 // Data cleared, reset array
171 if (!m_resolveTimer.isActive()) {
172 m_fullReset = true;
173 m_resolveTimer.start(msec: 0);
174 }
175}
176
177void AbstractItemModelHandler::handleRowsInserted(const QModelIndex &parent, int start, int end)
178{
179 Q_UNUSED(parent)
180 Q_UNUSED(start)
181 Q_UNUSED(end)
182
183 // Default handling for rowsInserted is to do full reset, as it cannot be optimized
184 // in a general case, where we do not know which row/column/index the item model item
185 // actually ended up to in the proxy.
186 if (!m_resolveTimer.isActive()) {
187 m_fullReset = true;
188 m_resolveTimer.start(msec: 0);
189 }
190}
191
192void AbstractItemModelHandler::handleRowsMoved(const QModelIndex &sourceParent,
193 int sourceStart,
194 int sourceEnd,
195 const QModelIndex &destinationParent,
196 int destinationRow)
197{
198 Q_UNUSED(sourceParent)
199 Q_UNUSED(sourceStart)
200 Q_UNUSED(sourceEnd)
201 Q_UNUSED(destinationParent)
202 Q_UNUSED(destinationRow)
203
204 // Default handling for rowsMoved is to do full reset, as it cannot be optimized
205 // in a general case, where we do not know which row/column/index the item model item
206 // actually ended up to in the proxy.
207 if (!m_resolveTimer.isActive()) {
208 m_fullReset = true;
209 m_resolveTimer.start(msec: 0);
210 }
211}
212
213void AbstractItemModelHandler::handleRowsRemoved(const QModelIndex &parent, int start, int end)
214{
215 Q_UNUSED(parent)
216 Q_UNUSED(start)
217 Q_UNUSED(end)
218
219 // Default handling for rowsRemoved is to do full reset, as it cannot be optimized
220 // in a general case, where we do not know which row/column/index the item model item
221 // actually ended up to in the proxy.
222 if (!m_resolveTimer.isActive()) {
223 m_fullReset = true;
224 m_resolveTimer.start(msec: 0);
225 }
226}
227
228void AbstractItemModelHandler::handleMappingChanged()
229{
230 if (!m_resolveTimer.isActive())
231 m_resolveTimer.start(msec: 0);
232}
233
234void AbstractItemModelHandler::handlePendingResolve()
235{
236 resolveModel();
237 m_fullReset = false;
238}
239
240QT_END_NAMESPACE_DATAVISUALIZATION
241

source code of qtdatavis3d/src/datavisualization/data/abstractitemmodelhandler.cpp