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 QtCore 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#include "qabstractproxymodel.h"
41#include "qitemselectionmodel.h"
42#include <private/qabstractproxymodel_p.h>
43#include <QtCore/QSize>
44#include <QtCore/QStringList>
45
46
47QT_BEGIN_NAMESPACE
48
49/*!
50 \since 4.1
51 \class QAbstractProxyModel
52 \brief The QAbstractProxyModel class provides a base class for proxy item
53 models that can do sorting, filtering or other data processing tasks.
54 \ingroup model-view
55 \inmodule QtCore
56
57 This class defines the standard interface that proxy models must use to be
58 able to interoperate correctly with other model/view components. It is not
59 supposed to be instantiated directly.
60
61 All standard proxy models are derived from the QAbstractProxyModel class.
62 If you need to create a new proxy model class, it is usually better to
63 subclass an existing class that provides the closest behavior to the one
64 you want to provide.
65
66 Proxy models that filter or sort items of data from a source model should
67 be created by using or subclassing QSortFilterProxyModel.
68
69 To subclass QAbstractProxyModel, you need to implement mapFromSource() and
70 mapToSource(). The mapSelectionFromSource() and mapSelectionToSource()
71 functions only need to be reimplemented if you need a behavior different
72 from the default behavior.
73
74 \note If the source model is deleted or no source model is specified, the
75 proxy model operates on a empty placeholder model.
76
77 \sa QSortFilterProxyModel, QAbstractItemModel, {Model/View Programming}
78*/
79
80/*!
81 \property QAbstractProxyModel::sourceModel
82
83 \brief the source model of this proxy model.
84*/
85
86//detects the deletion of the source model
87void QAbstractProxyModelPrivate::_q_sourceModelDestroyed()
88{
89 invalidatePersistentIndexes();
90 model = QAbstractItemModelPrivate::staticEmptyModel();
91}
92
93/*!
94 Constructs a proxy model with the given \a parent.
95*/
96
97QAbstractProxyModel::QAbstractProxyModel(QObject *parent)
98 :QAbstractItemModel(*new QAbstractProxyModelPrivate, parent)
99{
100 setSourceModel(QAbstractItemModelPrivate::staticEmptyModel());
101}
102
103/*!
104 \internal
105*/
106
107QAbstractProxyModel::QAbstractProxyModel(QAbstractProxyModelPrivate &dd, QObject *parent)
108 : QAbstractItemModel(dd, parent)
109{
110 setSourceModel(QAbstractItemModelPrivate::staticEmptyModel());
111}
112
113/*!
114 Destroys the proxy model.
115*/
116QAbstractProxyModel::~QAbstractProxyModel()
117{
118
119}
120
121/*!
122 Sets the given \a sourceModel to be processed by the proxy model.
123
124 Subclasses should call beginResetModel() at the beginning of the method,
125 disconnect from the old model, call this method, connect to the new model,
126 and call endResetModel().
127*/
128void QAbstractProxyModel::setSourceModel(QAbstractItemModel *sourceModel)
129{
130 Q_D(QAbstractProxyModel);
131 if (sourceModel != d->model) {
132 if (d->model)
133 disconnect(d->model, SIGNAL(destroyed()), this, SLOT(_q_sourceModelDestroyed()));
134
135 if (sourceModel) {
136 d->model = sourceModel;
137 connect(d->model, SIGNAL(destroyed()), this, SLOT(_q_sourceModelDestroyed()));
138 } else {
139 d->model = QAbstractItemModelPrivate::staticEmptyModel();
140 }
141 emit sourceModelChanged(QPrivateSignal());
142 }
143}
144
145/*!
146 Returns the model that contains the data that is available through the proxy model.
147*/
148QAbstractItemModel *QAbstractProxyModel::sourceModel() const
149{
150 Q_D(const QAbstractProxyModel);
151 if (d->model == QAbstractItemModelPrivate::staticEmptyModel())
152 return nullptr;
153 return d->model;
154}
155
156/*!
157 \reimp
158 */
159bool QAbstractProxyModel::submit()
160{
161 Q_D(QAbstractProxyModel);
162 return d->model->submit();
163}
164
165/*!
166 \reimp
167 */
168void QAbstractProxyModel::revert()
169{
170 Q_D(QAbstractProxyModel);
171 d->model->revert();
172}
173
174
175/*!
176 \fn QModelIndex QAbstractProxyModel::mapToSource(const QModelIndex &proxyIndex) const
177
178 Reimplement this function to return the model index in the source model that
179 corresponds to the \a proxyIndex in the proxy model.
180
181 \sa mapFromSource()
182*/
183
184/*!
185 \fn QModelIndex QAbstractProxyModel::mapFromSource(const QModelIndex &sourceIndex) const
186
187 Reimplement this function to return the model index in the proxy model that
188 corresponds to the \a sourceIndex from the source model.
189
190 \sa mapToSource()
191*/
192
193/*!
194 Returns a source selection mapped from the specified \a proxySelection.
195
196 Reimplement this method to map proxy selections to source selections.
197 */
198QItemSelection QAbstractProxyModel::mapSelectionToSource(const QItemSelection &proxySelection) const
199{
200 QModelIndexList proxyIndexes = proxySelection.indexes();
201 QItemSelection sourceSelection;
202 for (int i = 0; i < proxyIndexes.size(); ++i) {
203 const QModelIndex proxyIdx = mapToSource(proxyIndexes.at(i));
204 if (!proxyIdx.isValid())
205 continue;
206 sourceSelection << QItemSelectionRange(proxyIdx);
207 }
208 return sourceSelection;
209}
210
211/*!
212 Returns a proxy selection mapped from the specified \a sourceSelection.
213
214 Reimplement this method to map source selections to proxy selections.
215*/
216QItemSelection QAbstractProxyModel::mapSelectionFromSource(const QItemSelection &sourceSelection) const
217{
218 QModelIndexList sourceIndexes = sourceSelection.indexes();
219 QItemSelection proxySelection;
220 for (int i = 0; i < sourceIndexes.size(); ++i) {
221 const QModelIndex srcIdx = mapFromSource(sourceIndexes.at(i));
222 if (!srcIdx.isValid())
223 continue;
224 proxySelection << QItemSelectionRange(srcIdx);
225 }
226 return proxySelection;
227}
228
229/*!
230 \reimp
231 */
232QVariant QAbstractProxyModel::data(const QModelIndex &proxyIndex, int role) const
233{
234 Q_D(const QAbstractProxyModel);
235 return d->model->data(mapToSource(proxyIndex), role);
236}
237
238/*!
239 \reimp
240 */
241QVariant QAbstractProxyModel::headerData(int section, Qt::Orientation orientation, int role) const
242{
243 Q_D(const QAbstractProxyModel);
244 int sourceSection;
245 if (orientation == Qt::Horizontal) {
246 const QModelIndex proxyIndex = index(0, section);
247 sourceSection = mapToSource(proxyIndex).column();
248 } else {
249 const QModelIndex proxyIndex = index(section, 0);
250 sourceSection = mapToSource(proxyIndex).row();
251 }
252 return d->model->headerData(sourceSection, orientation, role);
253}
254
255/*!
256 \reimp
257 */
258QMap<int, QVariant> QAbstractProxyModel::itemData(const QModelIndex &proxyIndex) const
259{
260 return QAbstractItemModel::itemData(proxyIndex);
261}
262
263/*!
264 \reimp
265 */
266Qt::ItemFlags QAbstractProxyModel::flags(const QModelIndex &index) const
267{
268 Q_D(const QAbstractProxyModel);
269 return d->model->flags(mapToSource(index));
270}
271
272/*!
273 \reimp
274 */
275bool QAbstractProxyModel::setData(const QModelIndex &index, const QVariant &value, int role)
276{
277 Q_D(QAbstractProxyModel);
278 return d->model->setData(mapToSource(index), value, role);
279}
280
281/*!
282 \reimp
283 */
284bool QAbstractProxyModel::setItemData(const QModelIndex &index, const QMap< int, QVariant >& roles)
285{
286 return QAbstractItemModel::setItemData(index, roles);
287}
288
289/*!
290 \reimp
291 */
292bool QAbstractProxyModel::setHeaderData(int section, Qt::Orientation orientation, const QVariant &value, int role)
293{
294 Q_D(QAbstractProxyModel);
295 int sourceSection;
296 if (orientation == Qt::Horizontal) {
297 const QModelIndex proxyIndex = index(0, section);
298 sourceSection = mapToSource(proxyIndex).column();
299 } else {
300 const QModelIndex proxyIndex = index(section, 0);
301 sourceSection = mapToSource(proxyIndex).row();
302 }
303 return d->model->setHeaderData(sourceSection, orientation, value, role);
304}
305
306/*!
307 \reimp
308 \since 6.0
309 */
310bool QAbstractProxyModel::clearItemData(const QModelIndex &index)
311{
312 Q_D(QAbstractProxyModel);
313 return d->model->clearItemData(mapToSource(index));
314}
315
316/*!
317 \reimp
318 */
319QModelIndex QAbstractProxyModel::buddy(const QModelIndex &index) const
320{
321 Q_D(const QAbstractProxyModel);
322 return mapFromSource(d->model->buddy(mapToSource(index)));
323}
324
325/*!
326 \reimp
327 */
328bool QAbstractProxyModel::canFetchMore(const QModelIndex &parent) const
329{
330 Q_D(const QAbstractProxyModel);
331 return d->model->canFetchMore(mapToSource(parent));
332}
333
334/*!
335 \reimp
336 */
337void QAbstractProxyModel::fetchMore(const QModelIndex &parent)
338{
339 Q_D(QAbstractProxyModel);
340 d->model->fetchMore(mapToSource(parent));
341}
342
343/*!
344 \reimp
345 */
346void QAbstractProxyModel::sort(int column, Qt::SortOrder order)
347{
348 Q_D(QAbstractProxyModel);
349 d->model->sort(column, order);
350}
351
352/*!
353 \reimp
354 */
355QSize QAbstractProxyModel::span(const QModelIndex &index) const
356{
357 Q_D(const QAbstractProxyModel);
358 return d->model->span(mapToSource(index));
359}
360
361/*!
362 \reimp
363 */
364bool QAbstractProxyModel::hasChildren(const QModelIndex &parent) const
365{
366 Q_D(const QAbstractProxyModel);
367 return d->model->hasChildren(mapToSource(parent));
368}
369
370/*!
371 \reimp
372 */
373QModelIndex QAbstractProxyModel::sibling(int row, int column, const QModelIndex &idx) const
374{
375 return index(row, column, idx.parent());
376}
377
378/*!
379 \reimp
380 */
381QMimeData* QAbstractProxyModel::mimeData(const QModelIndexList &indexes) const
382{
383 Q_D(const QAbstractProxyModel);
384 QModelIndexList list;
385 list.reserve(indexes.count());
386 for (const QModelIndex &index : indexes)
387 list << mapToSource(index);
388 return d->model->mimeData(list);
389}
390
391void QAbstractProxyModelPrivate::mapDropCoordinatesToSource(int row, int column, const QModelIndex &parent,
392 int *sourceRow, int *sourceColumn, QModelIndex *sourceParent) const
393{
394 Q_Q(const QAbstractProxyModel);
395 *sourceRow = -1;
396 *sourceColumn = -1;
397 if (row == -1 && column == -1) {
398 *sourceParent = q->mapToSource(parent);
399 } else if (row == q->rowCount(parent)) {
400 *sourceParent = q->mapToSource(parent);
401 *sourceRow = model->rowCount(*sourceParent);
402 } else {
403 QModelIndex proxyIndex = q->index(row, column, parent);
404 QModelIndex sourceIndex = q->mapToSource(proxyIndex);
405 *sourceRow = sourceIndex.row();
406 *sourceColumn = sourceIndex.column();
407 *sourceParent = sourceIndex.parent();
408 }
409}
410
411/*!
412 \reimp
413 \since 5.4
414 */
415bool QAbstractProxyModel::canDropMimeData(const QMimeData *data, Qt::DropAction action,
416 int row, int column, const QModelIndex &parent) const
417{
418 Q_D(const QAbstractProxyModel);
419 int sourceDestinationRow;
420 int sourceDestinationColumn;
421 QModelIndex sourceParent;
422 d->mapDropCoordinatesToSource(row, column, parent, &sourceDestinationRow, &sourceDestinationColumn, &sourceParent);
423 return d->model->canDropMimeData(data, action, sourceDestinationRow, sourceDestinationColumn, sourceParent);
424}
425
426/*!
427 \reimp
428 \since 5.4
429 */
430bool QAbstractProxyModel::dropMimeData(const QMimeData *data, Qt::DropAction action,
431 int row, int column, const QModelIndex &parent)
432{
433 Q_D(QAbstractProxyModel);
434 int sourceDestinationRow;
435 int sourceDestinationColumn;
436 QModelIndex sourceParent;
437 d->mapDropCoordinatesToSource(row, column, parent, &sourceDestinationRow, &sourceDestinationColumn, &sourceParent);
438 return d->model->dropMimeData(data, action, sourceDestinationRow, sourceDestinationColumn, sourceParent);
439}
440
441/*!
442 \reimp
443 */
444QStringList QAbstractProxyModel::mimeTypes() const
445{
446 Q_D(const QAbstractProxyModel);
447 return d->model->mimeTypes();
448}
449
450/*!
451 \reimp
452 */
453Qt::DropActions QAbstractProxyModel::supportedDragActions() const
454{
455 Q_D(const QAbstractProxyModel);
456 return d->model->supportedDragActions();
457}
458
459/*!
460 \reimp
461 */
462Qt::DropActions QAbstractProxyModel::supportedDropActions() const
463{
464 Q_D(const QAbstractProxyModel);
465 return d->model->supportedDropActions();
466}
467
468/*!
469 \reimp
470 */
471QHash<int,QByteArray> QAbstractProxyModel::roleNames() const
472{
473 Q_D(const QAbstractProxyModel);
474 return d->model->roleNames();
475}
476
477
478QT_END_NAMESPACE
479
480#include "moc_qabstractproxymodel.cpp"
481