1 | // Copyright (C) 2011 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Stephen Kelly <stephen.kelly@kdab.com> |
---|---|
2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only |
3 | |
4 | #include "qidentityproxymodel.h" |
5 | #include "qidentityproxymodel_p.h" |
6 | #include "qitemselectionmodel.h" |
7 | #include <private/qabstractproxymodel_p.h> |
8 | |
9 | QT_BEGIN_NAMESPACE |
10 | |
11 | QIdentityProxyModelPrivate::~QIdentityProxyModelPrivate() |
12 | = default; |
13 | |
14 | /*! |
15 | \since 4.8 |
16 | \class QIdentityProxyModel |
17 | \inmodule QtCore |
18 | \brief The QIdentityProxyModel class proxies its source model unmodified. |
19 | |
20 | \ingroup model-view |
21 | |
22 | QIdentityProxyModel can be used to forward the structure of a source model exactly, with no sorting, filtering or other transformation. |
23 | This is similar in concept to an identity matrix where A.I = A. |
24 | |
25 | Because it does no sorting or filtering, this class is most suitable to proxy models which transform the data() of the source model. |
26 | For example, a proxy model could be created to define the font used, or the background colour, or the tooltip etc. This removes the |
27 | need to implement all data handling in the same class that creates the structure of the model, and can also be used to create |
28 | re-usable components. |
29 | |
30 | This also provides a way to change the data in the case where a source model is supplied by a third party which cannot be modified. |
31 | |
32 | \snippet code/src_gui_itemviews_qidentityproxymodel.cpp 0 |
33 | |
34 | \sa QAbstractProxyModel, {Model/View Programming}, QAbstractItemModel |
35 | |
36 | */ |
37 | |
38 | /*! |
39 | Constructs an identity model with the given \a parent. |
40 | */ |
41 | QIdentityProxyModel::QIdentityProxyModel(QObject* parent) |
42 | : QAbstractProxyModel(*new QIdentityProxyModelPrivate, parent) |
43 | { |
44 | |
45 | } |
46 | |
47 | /*! |
48 | \internal |
49 | */ |
50 | QIdentityProxyModel::QIdentityProxyModel(QIdentityProxyModelPrivate &dd, QObject* parent) |
51 | : QAbstractProxyModel(dd, parent) |
52 | { |
53 | |
54 | } |
55 | |
56 | /*! |
57 | Destroys this identity model. |
58 | */ |
59 | QIdentityProxyModel::~QIdentityProxyModel() |
60 | { |
61 | } |
62 | |
63 | /*! |
64 | \reimp |
65 | */ |
66 | int QIdentityProxyModel::columnCount(const QModelIndex& parent) const |
67 | { |
68 | Q_ASSERT(parent.isValid() ? parent.model() == this : true); |
69 | Q_D(const QIdentityProxyModel); |
70 | return d->model->columnCount(parent: mapToSource(proxyIndex: parent)); |
71 | } |
72 | |
73 | /*! |
74 | \reimp |
75 | */ |
76 | bool QIdentityProxyModel::dropMimeData(const QMimeData* data, Qt::DropAction action, int row, int column, const QModelIndex& parent) |
77 | { |
78 | Q_ASSERT(parent.isValid() ? parent.model() == this : true); |
79 | Q_D(QIdentityProxyModel); |
80 | return d->model->dropMimeData(data, action, row, column, parent: mapToSource(proxyIndex: parent)); |
81 | } |
82 | |
83 | /*! |
84 | \reimp |
85 | */ |
86 | QModelIndex QIdentityProxyModel::index(int row, int column, const QModelIndex& parent) const |
87 | { |
88 | Q_ASSERT(parent.isValid() ? parent.model() == this : true); |
89 | Q_D(const QIdentityProxyModel); |
90 | const QModelIndex sourceParent = mapToSource(proxyIndex: parent); |
91 | const QModelIndex sourceIndex = d->model->index(row, column, parent: sourceParent); |
92 | return mapFromSource(sourceIndex); |
93 | } |
94 | |
95 | /*! |
96 | \reimp |
97 | */ |
98 | QModelIndex QIdentityProxyModel::sibling(int row, int column, const QModelIndex &idx) const |
99 | { |
100 | Q_D(const QIdentityProxyModel); |
101 | return mapFromSource(sourceIndex: d->model->sibling(row, column, idx: mapToSource(proxyIndex: idx))); |
102 | } |
103 | |
104 | /*! |
105 | \reimp |
106 | */ |
107 | bool QIdentityProxyModel::insertColumns(int column, int count, const QModelIndex& parent) |
108 | { |
109 | Q_ASSERT(parent.isValid() ? parent.model() == this : true); |
110 | Q_D(QIdentityProxyModel); |
111 | return d->model->insertColumns(column, count, parent: mapToSource(proxyIndex: parent)); |
112 | } |
113 | |
114 | /*! |
115 | \reimp |
116 | */ |
117 | bool QIdentityProxyModel::insertRows(int row, int count, const QModelIndex& parent) |
118 | { |
119 | Q_ASSERT(parent.isValid() ? parent.model() == this : true); |
120 | Q_D(QIdentityProxyModel); |
121 | return d->model->insertRows(row, count, parent: mapToSource(proxyIndex: parent)); |
122 | } |
123 | |
124 | /*! |
125 | \reimp |
126 | */ |
127 | QModelIndex QIdentityProxyModel::mapFromSource(const QModelIndex& sourceIndex) const |
128 | { |
129 | Q_D(const QIdentityProxyModel); |
130 | if (!d->model || !sourceIndex.isValid()) |
131 | return QModelIndex(); |
132 | |
133 | Q_ASSERT(sourceIndex.model() == d->model); |
134 | return createIndex(arow: sourceIndex.row(), acolumn: sourceIndex.column(), adata: sourceIndex.internalPointer()); |
135 | } |
136 | |
137 | /*! |
138 | \reimp |
139 | */ |
140 | QItemSelection QIdentityProxyModel::mapSelectionFromSource(const QItemSelection& selection) const |
141 | { |
142 | Q_D(const QIdentityProxyModel); |
143 | QItemSelection proxySelection; |
144 | |
145 | if (!d->model) |
146 | return proxySelection; |
147 | |
148 | QItemSelection::const_iterator it = selection.constBegin(); |
149 | const QItemSelection::const_iterator end = selection.constEnd(); |
150 | proxySelection.reserve(asize: selection.size()); |
151 | for ( ; it != end; ++it) { |
152 | Q_ASSERT(it->model() == d->model); |
153 | const QItemSelectionRange range(mapFromSource(sourceIndex: it->topLeft()), mapFromSource(sourceIndex: it->bottomRight())); |
154 | proxySelection.append(t: range); |
155 | } |
156 | |
157 | return proxySelection; |
158 | } |
159 | |
160 | /*! |
161 | \reimp |
162 | */ |
163 | QItemSelection QIdentityProxyModel::mapSelectionToSource(const QItemSelection& selection) const |
164 | { |
165 | Q_D(const QIdentityProxyModel); |
166 | QItemSelection sourceSelection; |
167 | |
168 | if (!d->model) |
169 | return sourceSelection; |
170 | |
171 | QItemSelection::const_iterator it = selection.constBegin(); |
172 | const QItemSelection::const_iterator end = selection.constEnd(); |
173 | sourceSelection.reserve(asize: selection.size()); |
174 | for ( ; it != end; ++it) { |
175 | Q_ASSERT(it->model() == this); |
176 | const QItemSelectionRange range(mapToSource(proxyIndex: it->topLeft()), mapToSource(proxyIndex: it->bottomRight())); |
177 | sourceSelection.append(t: range); |
178 | } |
179 | |
180 | return sourceSelection; |
181 | } |
182 | |
183 | /*! |
184 | \reimp |
185 | */ |
186 | QModelIndex QIdentityProxyModel::mapToSource(const QModelIndex& proxyIndex) const |
187 | { |
188 | Q_D(const QIdentityProxyModel); |
189 | if (!d->model || !proxyIndex.isValid()) |
190 | return QModelIndex(); |
191 | Q_ASSERT(proxyIndex.model() == this); |
192 | return createSourceIndex(row: proxyIndex.row(), col: proxyIndex.column(), internalPtr: proxyIndex.internalPointer()); |
193 | } |
194 | |
195 | /*! |
196 | \reimp |
197 | */ |
198 | QModelIndexList QIdentityProxyModel::match(const QModelIndex& start, int role, const QVariant& value, int hits, Qt::MatchFlags flags) const |
199 | { |
200 | Q_D(const QIdentityProxyModel); |
201 | Q_ASSERT(start.isValid() ? start.model() == this : true); |
202 | if (!d->model) |
203 | return QModelIndexList(); |
204 | |
205 | const QModelIndexList sourceList = d->model->match(start: mapToSource(proxyIndex: start), role, value, hits, flags); |
206 | QModelIndexList::const_iterator it = sourceList.constBegin(); |
207 | const QModelIndexList::const_iterator end = sourceList.constEnd(); |
208 | QModelIndexList proxyList; |
209 | proxyList.reserve(asize: sourceList.size()); |
210 | for ( ; it != end; ++it) |
211 | proxyList.append(t: mapFromSource(sourceIndex: *it)); |
212 | return proxyList; |
213 | } |
214 | |
215 | /*! |
216 | \reimp |
217 | */ |
218 | QModelIndex QIdentityProxyModel::parent(const QModelIndex& child) const |
219 | { |
220 | Q_ASSERT(child.isValid() ? child.model() == this : true); |
221 | const QModelIndex sourceIndex = mapToSource(proxyIndex: child); |
222 | const QModelIndex sourceParent = sourceIndex.parent(); |
223 | return mapFromSource(sourceIndex: sourceParent); |
224 | } |
225 | |
226 | /*! |
227 | \reimp |
228 | */ |
229 | bool QIdentityProxyModel::removeColumns(int column, int count, const QModelIndex& parent) |
230 | { |
231 | Q_ASSERT(parent.isValid() ? parent.model() == this : true); |
232 | Q_D(QIdentityProxyModel); |
233 | return d->model->removeColumns(column, count, parent: mapToSource(proxyIndex: parent)); |
234 | } |
235 | |
236 | /*! |
237 | \reimp |
238 | */ |
239 | bool QIdentityProxyModel::removeRows(int row, int count, const QModelIndex& parent) |
240 | { |
241 | Q_ASSERT(parent.isValid() ? parent.model() == this : true); |
242 | Q_D(QIdentityProxyModel); |
243 | return d->model->removeRows(row, count, parent: mapToSource(proxyIndex: parent)); |
244 | } |
245 | |
246 | /*! |
247 | \reimp |
248 | \since 5.15 |
249 | */ |
250 | bool QIdentityProxyModel::moveRows(const QModelIndex &sourceParent, int sourceRow, int count, const QModelIndex &destinationParent, int destinationChild) |
251 | { |
252 | Q_ASSERT(sourceParent.isValid() ? sourceParent.model() == this : true); |
253 | Q_ASSERT(destinationParent.isValid() ? destinationParent.model() == this : true); |
254 | Q_D(QIdentityProxyModel); |
255 | return d->model->moveRows(sourceParent: mapToSource(proxyIndex: sourceParent), sourceRow, count, destinationParent: mapToSource(proxyIndex: destinationParent), destinationChild); |
256 | } |
257 | |
258 | /*! |
259 | \reimp |
260 | \since 5.15 |
261 | */ |
262 | bool QIdentityProxyModel::moveColumns(const QModelIndex &sourceParent, int sourceColumn, int count, const QModelIndex &destinationParent, int destinationChild) |
263 | { |
264 | Q_ASSERT(sourceParent.isValid() ? sourceParent.model() == this : true); |
265 | Q_ASSERT(destinationParent.isValid() ? destinationParent.model() == this : true); |
266 | Q_D(QIdentityProxyModel); |
267 | return d->model->moveColumns(sourceParent: mapToSource(proxyIndex: sourceParent), sourceColumn, count, destinationParent: mapToSource(proxyIndex: destinationParent), destinationChild); |
268 | } |
269 | |
270 | /*! |
271 | \reimp |
272 | */ |
273 | int QIdentityProxyModel::rowCount(const QModelIndex& parent) const |
274 | { |
275 | Q_ASSERT(parent.isValid() ? parent.model() == this : true); |
276 | Q_D(const QIdentityProxyModel); |
277 | return d->model->rowCount(parent: mapToSource(proxyIndex: parent)); |
278 | } |
279 | |
280 | /*! |
281 | \reimp |
282 | */ |
283 | QVariant QIdentityProxyModel::headerData(int section, Qt::Orientation orientation, int role) const |
284 | { |
285 | Q_D(const QIdentityProxyModel); |
286 | return d->model->headerData(section, orientation, role); |
287 | } |
288 | |
289 | /*! |
290 | \reimp |
291 | */ |
292 | void QIdentityProxyModel::setSourceModel(QAbstractItemModel* newSourceModel) |
293 | { |
294 | beginResetModel(); |
295 | |
296 | Q_D(QIdentityProxyModel); |
297 | |
298 | // Call QObject::disconnect() unconditionally, if there is an existing source |
299 | // model, it's disconnected, and if there isn't, then calling disconnect() on |
300 | // a default-constructed Connection does nothing |
301 | for (const auto &c : d->m_sourceModelConnections) |
302 | QObject::disconnect(c); |
303 | |
304 | QAbstractProxyModel::setSourceModel(newSourceModel); |
305 | |
306 | if (sourceModel()) { |
307 | auto *m = sourceModel(); |
308 | d->m_sourceModelConnections = { |
309 | QObjectPrivate::connect(sender: m, signal: &QAbstractItemModel::rowsAboutToBeInserted, receiverPrivate: d, |
310 | slot: &QIdentityProxyModelPrivate::sourceRowsAboutToBeInserted), |
311 | QObjectPrivate::connect(sender: m, signal: &QAbstractItemModel::rowsInserted, receiverPrivate: d, |
312 | slot: &QIdentityProxyModelPrivate::sourceRowsInserted), |
313 | QObjectPrivate::connect(sender: m, signal: &QAbstractItemModel::rowsAboutToBeRemoved, receiverPrivate: d, |
314 | slot: &QIdentityProxyModelPrivate::sourceRowsAboutToBeRemoved), |
315 | QObjectPrivate::connect(sender: m, signal: &QAbstractItemModel::rowsRemoved, receiverPrivate: d, |
316 | slot: &QIdentityProxyModelPrivate::sourceRowsRemoved), |
317 | QObjectPrivate::connect(sender: m, signal: &QAbstractItemModel::rowsAboutToBeMoved, receiverPrivate: d, |
318 | slot: &QIdentityProxyModelPrivate::sourceRowsAboutToBeMoved), |
319 | QObjectPrivate::connect(sender: m, signal: &QAbstractItemModel::rowsMoved, receiverPrivate: d, |
320 | slot: &QIdentityProxyModelPrivate::sourceRowsMoved), |
321 | QObjectPrivate::connect(sender: m, signal: &QAbstractItemModel::columnsAboutToBeInserted, receiverPrivate: d, |
322 | slot: &QIdentityProxyModelPrivate::sourceColumnsAboutToBeInserted), |
323 | QObjectPrivate::connect(sender: m, signal: &QAbstractItemModel::columnsInserted, receiverPrivate: d, |
324 | slot: &QIdentityProxyModelPrivate::sourceColumnsInserted), |
325 | QObjectPrivate::connect(sender: m, signal: &QAbstractItemModel::columnsAboutToBeRemoved, receiverPrivate: d, |
326 | slot: &QIdentityProxyModelPrivate::sourceColumnsAboutToBeRemoved), |
327 | QObjectPrivate::connect(sender: m, signal: &QAbstractItemModel::columnsRemoved, receiverPrivate: d, |
328 | slot: &QIdentityProxyModelPrivate::sourceColumnsRemoved), |
329 | QObjectPrivate::connect(sender: m, signal: &QAbstractItemModel::columnsAboutToBeMoved, receiverPrivate: d, |
330 | slot: &QIdentityProxyModelPrivate::sourceColumnsAboutToBeMoved), |
331 | QObjectPrivate::connect(sender: m, signal: &QAbstractItemModel::columnsMoved, receiverPrivate: d, |
332 | slot: &QIdentityProxyModelPrivate::sourceColumnsMoved), |
333 | QObjectPrivate::connect(sender: m, signal: &QAbstractItemModel::modelAboutToBeReset, receiverPrivate: d, |
334 | slot: &QIdentityProxyModelPrivate::sourceModelAboutToBeReset), |
335 | QObjectPrivate::connect(sender: m, signal: &QAbstractItemModel::modelReset, receiverPrivate: d, |
336 | slot: &QIdentityProxyModelPrivate::sourceModelReset), |
337 | QObjectPrivate::connect(sender: m, signal: &QAbstractItemModel::headerDataChanged, receiverPrivate: d, |
338 | slot: &QIdentityProxyModelPrivate::sourceHeaderDataChanged), |
339 | }; |
340 | |
341 | if (d->m_handleDataChanges) { |
342 | d->m_sourceModelConnections.emplace_back( |
343 | args: QObjectPrivate::connect(sender: m, signal: &QAbstractItemModel::dataChanged, receiverPrivate: d, |
344 | slot: &QIdentityProxyModelPrivate::sourceDataChanged)); |
345 | } |
346 | if (d->m_handleLayoutChanges) { |
347 | d->m_sourceModelConnections.emplace_back( |
348 | args: QObjectPrivate::connect(sender: m, signal: &QAbstractItemModel::layoutAboutToBeChanged, receiverPrivate: d, |
349 | slot: &QIdentityProxyModelPrivate::sourceLayoutAboutToBeChanged)); |
350 | d->m_sourceModelConnections.emplace_back( |
351 | args: QObjectPrivate::connect(sender: m, signal: &QAbstractItemModel::layoutChanged, receiverPrivate: d, |
352 | slot: &QIdentityProxyModelPrivate::sourceLayoutChanged)); |
353 | } |
354 | } |
355 | |
356 | endResetModel(); |
357 | } |
358 | |
359 | /*! |
360 | \since 6.8 |
361 | |
362 | If \a b is \c true, this proxy model will handle the source model layout |
363 | changes (by connecting to \c QAbstractItemModel::layoutAboutToBeChanged |
364 | and \c QAbstractItemModel::layoutChanged signals). |
365 | |
366 | The default is for this proxy model to handle the source model layout |
367 | changes. |
368 | |
369 | In sub-classes of QIdentityProxyModel, it may be useful to set this to |
370 | \c false if you need to specially handle the source model layout changes. |
371 | |
372 | \note Calling this method will only have an effect after calling setSourceModel(). |
373 | */ |
374 | void QIdentityProxyModel::setHandleSourceLayoutChanges(bool b) |
375 | { |
376 | d_func()->m_handleLayoutChanges = b; |
377 | } |
378 | |
379 | /*! |
380 | \since 6.8 |
381 | |
382 | Returns \c true if this proxy model handles the source model layout |
383 | changes, otherwise returns \c false. |
384 | */ |
385 | bool QIdentityProxyModel::handleSourceLayoutChanges() const |
386 | { |
387 | return d_func()->m_handleLayoutChanges; |
388 | } |
389 | |
390 | /*! |
391 | \since 6.8 |
392 | |
393 | If \a b is \c true, this proxy model will handle the source model data |
394 | changes (by connecting to \c QAbstractItemModel::dataChanged signal). |
395 | |
396 | The default is for this proxy model to handle the source model data |
397 | changes. |
398 | |
399 | In sub-classes of QIdentityProxyModel, it may be useful to set this to |
400 | \c false if you need to specially handle the source model data changes. |
401 | |
402 | \note Calling this method will only have an effect after calling setSourceModel(). |
403 | */ |
404 | void QIdentityProxyModel::setHandleSourceDataChanges(bool b) |
405 | { |
406 | d_func()->m_handleDataChanges = b; |
407 | } |
408 | |
409 | /*! |
410 | \since 6.8 |
411 | |
412 | Returns \c true if this proxy model handles the source model data |
413 | changes, otherwise returns \c false. |
414 | */ |
415 | bool QIdentityProxyModel::handleSourceDataChanges() const |
416 | { |
417 | return d_func()->m_handleDataChanges; |
418 | } |
419 | |
420 | void QIdentityProxyModelPrivate::sourceColumnsAboutToBeInserted(const QModelIndex &parent, int start, int end) |
421 | { |
422 | Q_ASSERT(parent.isValid() ? parent.model() == model : true); |
423 | Q_Q(QIdentityProxyModel); |
424 | q->beginInsertColumns(parent: q->mapFromSource(sourceIndex: parent), first: start, last: end); |
425 | } |
426 | |
427 | void QIdentityProxyModelPrivate::sourceColumnsAboutToBeMoved(const QModelIndex &sourceParent, |
428 | int sourceStart, int sourceEnd, |
429 | const QModelIndex &destParent, |
430 | int dest) |
431 | { |
432 | Q_ASSERT(sourceParent.isValid() ? sourceParent.model() == model : true); |
433 | Q_ASSERT(destParent.isValid() ? destParent.model() == model : true); |
434 | Q_Q(QIdentityProxyModel); |
435 | q->beginMoveColumns(sourceParent: q->mapFromSource(sourceIndex: sourceParent), sourceFirst: sourceStart, sourceLast: sourceEnd, destinationParent: q->mapFromSource(sourceIndex: destParent), destinationColumn: dest); |
436 | } |
437 | |
438 | void QIdentityProxyModelPrivate::sourceColumnsAboutToBeRemoved(const QModelIndex &parent, int start, int end) |
439 | { |
440 | Q_ASSERT(parent.isValid() ? parent.model() == model : true); |
441 | Q_Q(QIdentityProxyModel); |
442 | q->beginRemoveColumns(parent: q->mapFromSource(sourceIndex: parent), first: start, last: end); |
443 | } |
444 | |
445 | void QIdentityProxyModelPrivate::sourceColumnsInserted(const QModelIndex &parent, int start, int end) |
446 | { |
447 | Q_ASSERT(parent.isValid() ? parent.model() == model : true); |
448 | Q_Q(QIdentityProxyModel); |
449 | Q_UNUSED(parent); |
450 | Q_UNUSED(start); |
451 | Q_UNUSED(end); |
452 | q->endInsertColumns(); |
453 | } |
454 | |
455 | void QIdentityProxyModelPrivate::sourceColumnsMoved(const QModelIndex &sourceParent, |
456 | int sourceStart, int sourceEnd, |
457 | const QModelIndex &destParent, int dest) |
458 | { |
459 | Q_ASSERT(sourceParent.isValid() ? sourceParent.model() == model : true); |
460 | Q_ASSERT(destParent.isValid() ? destParent.model() == model : true); |
461 | Q_Q(QIdentityProxyModel); |
462 | Q_UNUSED(sourceParent); |
463 | Q_UNUSED(sourceStart); |
464 | Q_UNUSED(sourceEnd); |
465 | Q_UNUSED(destParent); |
466 | Q_UNUSED(dest); |
467 | q->endMoveColumns(); |
468 | } |
469 | |
470 | void QIdentityProxyModelPrivate::sourceColumnsRemoved(const QModelIndex &parent, int start, int end) |
471 | { |
472 | Q_ASSERT(parent.isValid() ? parent.model() == model : true); |
473 | Q_Q(QIdentityProxyModel); |
474 | Q_UNUSED(parent); |
475 | Q_UNUSED(start); |
476 | Q_UNUSED(end); |
477 | q->endRemoveColumns(); |
478 | } |
479 | |
480 | void QIdentityProxyModelPrivate::sourceDataChanged(const QModelIndex &topLeft, |
481 | const QModelIndex &bottomRight, |
482 | const QList<int> &roles) |
483 | { |
484 | Q_ASSERT(topLeft.isValid() ? topLeft.model() == model : true); |
485 | Q_ASSERT(bottomRight.isValid() ? bottomRight.model() == model : true); |
486 | Q_Q(QIdentityProxyModel); |
487 | emit q->dataChanged(topLeft: q->mapFromSource(sourceIndex: topLeft), bottomRight: q->mapFromSource(sourceIndex: bottomRight), roles); |
488 | } |
489 | |
490 | void QIdentityProxyModelPrivate::sourceHeaderDataChanged(Qt::Orientation orientation, int first, |
491 | int last) |
492 | { |
493 | Q_Q(QIdentityProxyModel); |
494 | emit q->headerDataChanged(orientation, first, last); |
495 | } |
496 | |
497 | void QIdentityProxyModelPrivate::sourceLayoutAboutToBeChanged( |
498 | const QList<QPersistentModelIndex> &sourceParents, QAbstractItemModel::LayoutChangeHint hint) |
499 | { |
500 | Q_Q(QIdentityProxyModel); |
501 | |
502 | QList<QPersistentModelIndex> parents; |
503 | parents.reserve(asize: sourceParents.size()); |
504 | for (const QPersistentModelIndex &parent : sourceParents) { |
505 | if (!parent.isValid()) { |
506 | parents << QPersistentModelIndex(); |
507 | continue; |
508 | } |
509 | const QModelIndex mappedParent = q->mapFromSource(sourceIndex: parent); |
510 | Q_ASSERT(mappedParent.isValid()); |
511 | parents << mappedParent; |
512 | } |
513 | |
514 | emit q->layoutAboutToBeChanged(parents, hint); |
515 | |
516 | const auto proxyPersistentIndexes = q->persistentIndexList(); |
517 | for (const QModelIndex &proxyPersistentIndex : proxyPersistentIndexes) { |
518 | proxyIndexes << proxyPersistentIndex; |
519 | Q_ASSERT(proxyPersistentIndex.isValid()); |
520 | const QPersistentModelIndex srcPersistentIndex = q->mapToSource(proxyIndex: proxyPersistentIndex); |
521 | Q_ASSERT(srcPersistentIndex.isValid()); |
522 | layoutChangePersistentIndexes << srcPersistentIndex; |
523 | } |
524 | } |
525 | |
526 | void QIdentityProxyModelPrivate::sourceLayoutChanged( |
527 | const QList<QPersistentModelIndex> &sourceParents, QAbstractItemModel::LayoutChangeHint hint) |
528 | { |
529 | Q_Q(QIdentityProxyModel); |
530 | |
531 | for (int i = 0; i < proxyIndexes.size(); ++i) { |
532 | q->changePersistentIndex(from: proxyIndexes.at(i), to: q->mapFromSource(sourceIndex: layoutChangePersistentIndexes.at(i))); |
533 | } |
534 | |
535 | layoutChangePersistentIndexes.clear(); |
536 | proxyIndexes.clear(); |
537 | |
538 | QList<QPersistentModelIndex> parents; |
539 | parents.reserve(asize: sourceParents.size()); |
540 | for (const QPersistentModelIndex &parent : sourceParents) { |
541 | if (!parent.isValid()) { |
542 | parents << QPersistentModelIndex(); |
543 | continue; |
544 | } |
545 | const QModelIndex mappedParent = q->mapFromSource(sourceIndex: parent); |
546 | Q_ASSERT(mappedParent.isValid()); |
547 | parents << mappedParent; |
548 | } |
549 | |
550 | emit q->layoutChanged(parents, hint); |
551 | } |
552 | |
553 | void QIdentityProxyModelPrivate::sourceModelAboutToBeReset() |
554 | { |
555 | Q_Q(QIdentityProxyModel); |
556 | q->beginResetModel(); |
557 | } |
558 | |
559 | void QIdentityProxyModelPrivate::sourceModelReset() |
560 | { |
561 | Q_Q(QIdentityProxyModel); |
562 | q->endResetModel(); |
563 | } |
564 | |
565 | void QIdentityProxyModelPrivate::sourceRowsAboutToBeInserted(const QModelIndex &parent, int start, |
566 | int end) |
567 | { |
568 | Q_ASSERT(parent.isValid() ? parent.model() == model : true); |
569 | Q_Q(QIdentityProxyModel); |
570 | q->beginInsertRows(parent: q->mapFromSource(sourceIndex: parent), first: start, last: end); |
571 | } |
572 | |
573 | void QIdentityProxyModelPrivate::sourceRowsAboutToBeMoved(const QModelIndex &sourceParent, |
574 | int sourceStart, int sourceEnd, |
575 | const QModelIndex &destParent, int dest) |
576 | { |
577 | Q_ASSERT(sourceParent.isValid() ? sourceParent.model() == model : true); |
578 | Q_ASSERT(destParent.isValid() ? destParent.model() == model : true); |
579 | Q_Q(QIdentityProxyModel); |
580 | q->beginMoveRows(sourceParent: q->mapFromSource(sourceIndex: sourceParent), sourceFirst: sourceStart, sourceLast: sourceEnd, destinationParent: q->mapFromSource(sourceIndex: destParent), destinationRow: dest); |
581 | } |
582 | |
583 | void QIdentityProxyModelPrivate::sourceRowsAboutToBeRemoved(const QModelIndex &parent, int start, |
584 | int end) |
585 | { |
586 | Q_ASSERT(parent.isValid() ? parent.model() == model : true); |
587 | Q_Q(QIdentityProxyModel); |
588 | q->beginRemoveRows(parent: q->mapFromSource(sourceIndex: parent), first: start, last: end); |
589 | } |
590 | |
591 | void QIdentityProxyModelPrivate::sourceRowsInserted(const QModelIndex &parent, int start, int end) |
592 | { |
593 | Q_ASSERT(parent.isValid() ? parent.model() == model : true); |
594 | Q_Q(QIdentityProxyModel); |
595 | Q_UNUSED(parent); |
596 | Q_UNUSED(start); |
597 | Q_UNUSED(end); |
598 | q->endInsertRows(); |
599 | } |
600 | |
601 | void QIdentityProxyModelPrivate::sourceRowsMoved(const QModelIndex &sourceParent, int sourceStart, |
602 | int sourceEnd, const QModelIndex &destParent, |
603 | int dest) |
604 | { |
605 | Q_ASSERT(sourceParent.isValid() ? sourceParent.model() == model : true); |
606 | Q_ASSERT(destParent.isValid() ? destParent.model() == model : true); |
607 | Q_Q(QIdentityProxyModel); |
608 | Q_UNUSED(sourceParent); |
609 | Q_UNUSED(sourceStart); |
610 | Q_UNUSED(sourceEnd); |
611 | Q_UNUSED(destParent); |
612 | Q_UNUSED(dest); |
613 | q->endMoveRows(); |
614 | } |
615 | |
616 | void QIdentityProxyModelPrivate::sourceRowsRemoved(const QModelIndex &parent, int start, int end) |
617 | { |
618 | Q_ASSERT(parent.isValid() ? parent.model() == model : true); |
619 | Q_Q(QIdentityProxyModel); |
620 | Q_UNUSED(parent); |
621 | Q_UNUSED(start); |
622 | Q_UNUSED(end); |
623 | q->endRemoveRows(); |
624 | } |
625 | |
626 | QT_END_NAMESPACE |
627 | |
628 | #include "moc_qidentityproxymodel.cpp" |
629 |
Definitions
- ~QIdentityProxyModelPrivate
- QIdentityProxyModel
- QIdentityProxyModel
- ~QIdentityProxyModel
- columnCount
- dropMimeData
- index
- sibling
- insertColumns
- insertRows
- mapFromSource
- mapSelectionFromSource
- mapSelectionToSource
- mapToSource
- match
- parent
- removeColumns
- removeRows
- moveRows
- moveColumns
- rowCount
- headerData
- setSourceModel
- setHandleSourceLayoutChanges
- handleSourceLayoutChanges
- setHandleSourceDataChanges
- handleSourceDataChanges
- sourceColumnsAboutToBeInserted
- sourceColumnsAboutToBeMoved
- sourceColumnsAboutToBeRemoved
- sourceColumnsInserted
- sourceColumnsMoved
- sourceColumnsRemoved
- sourceDataChanged
- sourceHeaderDataChanged
- sourceLayoutAboutToBeChanged
- sourceLayoutChanged
- sourceModelAboutToBeReset
- sourceModelReset
- sourceRowsAboutToBeInserted
- sourceRowsAboutToBeMoved
- sourceRowsAboutToBeRemoved
- sourceRowsInserted
- sourceRowsMoved
Learn Advanced QML with KDAB
Find out more