1 | // Copyright (C) 2016 The Qt Company Ltd. |
---|---|
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 "qabstractproxymodel.h" |
5 | #include "qitemselectionmodel.h" |
6 | #include <private/qabstractproxymodel_p.h> |
7 | #include <QtCore/QSize> |
8 | #include <QtCore/QStringList> |
9 | #include <QtCore/QMap> |
10 | |
11 | |
12 | QT_BEGIN_NAMESPACE |
13 | |
14 | /*! |
15 | \since 4.1 |
16 | \class QAbstractProxyModel |
17 | \brief The QAbstractProxyModel class provides a base class for proxy item |
18 | models that can do sorting, filtering or other data processing tasks. |
19 | \ingroup model-view |
20 | \inmodule QtCore |
21 | |
22 | This class defines the standard interface that proxy models must use to be |
23 | able to interoperate correctly with other model/view components. It is not |
24 | supposed to be instantiated directly. |
25 | |
26 | All standard proxy models are derived from the QAbstractProxyModel class. |
27 | If you need to create a new proxy model class, it is usually better to |
28 | subclass an existing class that provides the closest behavior to the one |
29 | you want to provide. |
30 | |
31 | Proxy models that filter or sort items of data from a source model should |
32 | be created by using or subclassing QSortFilterProxyModel. |
33 | |
34 | To subclass QAbstractProxyModel, you need to implement mapFromSource() and |
35 | mapToSource(). The mapSelectionFromSource() and mapSelectionToSource() |
36 | functions only need to be reimplemented if you need a behavior different |
37 | from the default behavior. |
38 | |
39 | \note If the source model is deleted or no source model is specified, the |
40 | proxy model operates on a empty placeholder model. |
41 | |
42 | \sa QSortFilterProxyModel, QAbstractItemModel, {Model/View Programming} |
43 | */ |
44 | |
45 | /*! |
46 | \property QAbstractProxyModel::sourceModel |
47 | |
48 | \brief the source model of this proxy model. |
49 | */ |
50 | |
51 | //detects the deletion of the source model |
52 | void QAbstractProxyModelPrivate::_q_sourceModelDestroyed() |
53 | { |
54 | invalidatePersistentIndexes(); |
55 | model = QAbstractItemModelPrivate::staticEmptyModel(); |
56 | } |
57 | |
58 | void QAbstractProxyModelPrivate::emitHeaderDataChanged() |
59 | { |
60 | Q_Q(QAbstractProxyModel); |
61 | |
62 | if (updateHorizontalHeader) { |
63 | if (auto columnCount = q->columnCount(); columnCount > 0) |
64 | emit q->headerDataChanged(orientation: Qt::Horizontal, first: 0, last: columnCount - 1); |
65 | } |
66 | |
67 | if (updateVerticalHeader) { |
68 | if (auto rowCount = q->rowCount(); rowCount > 0) |
69 | emit q->headerDataChanged(orientation: Qt::Vertical, first: 0, last: rowCount - 1); |
70 | } |
71 | |
72 | updateHorizontalHeader = false; |
73 | updateVerticalHeader = false; |
74 | } |
75 | |
76 | void QAbstractProxyModelPrivate::scheduleHeaderUpdate(Qt::Orientation orientation) |
77 | { |
78 | const bool isUpdateScheduled = updateHorizontalHeader || updateVerticalHeader; |
79 | |
80 | if (orientation == Qt::Horizontal && !updateHorizontalHeader) |
81 | updateHorizontalHeader = true; |
82 | else if (orientation == Qt::Vertical && !updateVerticalHeader) |
83 | updateVerticalHeader = true; |
84 | else |
85 | return; |
86 | |
87 | if (!isUpdateScheduled) { |
88 | Q_Q(QAbstractProxyModel); |
89 | QMetaObject::invokeMethod(object: q, function: [this]() { emitHeaderDataChanged(); }, type: Qt::QueuedConnection); |
90 | } |
91 | } |
92 | |
93 | void QAbstractProxyModelPrivate::_q_sourceModelRowsAboutToBeInserted(const QModelIndex &parent, int, int) |
94 | { |
95 | if (parent.isValid()) |
96 | return; |
97 | sourceHadZeroRows = model->rowCount() == 0; |
98 | } |
99 | |
100 | void QAbstractProxyModelPrivate::_q_sourceModelRowsInserted(const QModelIndex &parent, int, int) |
101 | { |
102 | if (parent.isValid()) |
103 | return; |
104 | if (sourceHadZeroRows) |
105 | scheduleHeaderUpdate(orientation: Qt::Horizontal); |
106 | } |
107 | |
108 | void QAbstractProxyModelPrivate::_q_sourceModelRowsRemoved(const QModelIndex &parent, int, int) |
109 | { |
110 | if (parent.isValid()) |
111 | return; |
112 | if (model->rowCount() == 0) |
113 | scheduleHeaderUpdate(orientation: Qt::Horizontal); |
114 | } |
115 | |
116 | void QAbstractProxyModelPrivate::_q_sourceModelColumnsAboutToBeInserted(const QModelIndex &parent, int, int) |
117 | { |
118 | if (parent.isValid()) |
119 | return; |
120 | sourceHadZeroColumns = model->columnCount() == 0; |
121 | } |
122 | |
123 | void QAbstractProxyModelPrivate::_q_sourceModelColumnsInserted(const QModelIndex &parent, int, int) |
124 | { |
125 | if (parent.isValid()) |
126 | return; |
127 | if (sourceHadZeroColumns) |
128 | scheduleHeaderUpdate(orientation: Qt::Vertical); |
129 | } |
130 | |
131 | void QAbstractProxyModelPrivate::_q_sourceModelColumnsRemoved(const QModelIndex &parent, int, int) |
132 | { |
133 | if (parent.isValid()) |
134 | return; |
135 | if (model->columnCount() == 0) |
136 | scheduleHeaderUpdate(orientation: Qt::Vertical); |
137 | } |
138 | |
139 | /*! |
140 | Constructs a proxy model with the given \a parent. |
141 | */ |
142 | |
143 | QAbstractProxyModel::QAbstractProxyModel(QObject *parent) |
144 | :QAbstractItemModel(*new QAbstractProxyModelPrivate, parent) |
145 | { |
146 | setSourceModel(QAbstractItemModelPrivate::staticEmptyModel()); |
147 | } |
148 | |
149 | /*! |
150 | \internal |
151 | */ |
152 | |
153 | QAbstractProxyModel::QAbstractProxyModel(QAbstractProxyModelPrivate &dd, QObject *parent) |
154 | : QAbstractItemModel(dd, parent) |
155 | { |
156 | setSourceModel(QAbstractItemModelPrivate::staticEmptyModel()); |
157 | } |
158 | |
159 | /*! |
160 | Destroys the proxy model. |
161 | */ |
162 | QAbstractProxyModel::~QAbstractProxyModel() |
163 | { |
164 | |
165 | } |
166 | |
167 | /*! |
168 | Sets the given \a sourceModel to be processed by the proxy model. |
169 | |
170 | Subclasses should call beginResetModel() at the beginning of the method, |
171 | disconnect from the old model, call this method, connect to the new model, |
172 | and call endResetModel(). |
173 | */ |
174 | void QAbstractProxyModel::setSourceModel(QAbstractItemModel *sourceModel) |
175 | { |
176 | Q_D(QAbstractProxyModel); |
177 | d->model.removeBindingUnlessInWrapper(); |
178 | // Special case to handle nullptr models. Otherwise we will have unwanted |
179 | // notifications. |
180 | const QAbstractItemModel *currentModel = d->model.valueBypassingBindings(); |
181 | if (!sourceModel && currentModel == QAbstractItemModelPrivate::staticEmptyModel()) |
182 | return; |
183 | static const struct { |
184 | const char *signalName; |
185 | const char *slotName; |
186 | } connectionTable[] = { |
187 | // clang-format off |
188 | { SIGNAL(destroyed()), SLOT(_q_sourceModelDestroyed()) }, |
189 | { SIGNAL(rowsAboutToBeInserted(QModelIndex,int,int)), SLOT(_q_sourceModelRowsAboutToBeInserted(QModelIndex,int,int)) }, |
190 | { SIGNAL(rowsInserted(QModelIndex,int,int)), SLOT(_q_sourceModelRowsInserted(QModelIndex,int,int)) }, |
191 | { SIGNAL(rowsRemoved(QModelIndex,int,int)), SLOT(_q_sourceModelRowsRemoved(QModelIndex,int,int)) }, |
192 | { SIGNAL(columnsAboutToBeInserted(QModelIndex,int,int)), SLOT(_q_sourceModelColumnsAboutToBeInserted(QModelIndex,int,int)) }, |
193 | { SIGNAL(columnsInserted(QModelIndex,int,int)), SLOT(_q_sourceModelColumnsInserted(QModelIndex,int,int)) }, |
194 | { SIGNAL(columnsRemoved(QModelIndex,int,int)), SLOT(_q_sourceModelColumnsRemoved(QModelIndex,int,int)) } |
195 | // clang-format on |
196 | }; |
197 | |
198 | if (sourceModel != currentModel) { |
199 | if (currentModel) { |
200 | for (const auto &c : connectionTable) |
201 | disconnect(sender: currentModel, signal: c.signalName, receiver: this, member: c.slotName); |
202 | } |
203 | |
204 | if (sourceModel) { |
205 | d->model.setValueBypassingBindings(sourceModel); |
206 | for (const auto &c : connectionTable) |
207 | connect(sender: sourceModel, signal: c.signalName, receiver: this, member: c.slotName); |
208 | } else { |
209 | d->model.setValueBypassingBindings(QAbstractItemModelPrivate::staticEmptyModel()); |
210 | } |
211 | d->model.notify(); |
212 | } |
213 | } |
214 | |
215 | /*! |
216 | Returns the model that contains the data that is available through the proxy model. |
217 | */ |
218 | QAbstractItemModel *QAbstractProxyModel::sourceModel() const |
219 | { |
220 | Q_D(const QAbstractProxyModel); |
221 | if (d->model == QAbstractItemModelPrivate::staticEmptyModel()) |
222 | return nullptr; |
223 | return d->model; |
224 | } |
225 | |
226 | QBindable<QAbstractItemModel *> QAbstractProxyModel::bindableSourceModel() |
227 | { |
228 | Q_D(QAbstractProxyModel); |
229 | return QBindable<QAbstractItemModel *>(&d->model); |
230 | } |
231 | |
232 | /*! |
233 | \reimp |
234 | */ |
235 | bool QAbstractProxyModel::submit() |
236 | { |
237 | Q_D(QAbstractProxyModel); |
238 | return d->model->submit(); |
239 | } |
240 | |
241 | /*! |
242 | \reimp |
243 | */ |
244 | void QAbstractProxyModel::revert() |
245 | { |
246 | Q_D(QAbstractProxyModel); |
247 | d->model->revert(); |
248 | } |
249 | |
250 | |
251 | /*! |
252 | \fn QModelIndex QAbstractProxyModel::mapToSource(const QModelIndex &proxyIndex) const |
253 | |
254 | Reimplement this function to return the model index in the source model that |
255 | corresponds to the \a proxyIndex in the proxy model. |
256 | |
257 | \sa mapFromSource() |
258 | */ |
259 | |
260 | /*! |
261 | \fn QModelIndex QAbstractProxyModel::mapFromSource(const QModelIndex &sourceIndex) const |
262 | |
263 | Reimplement this function to return the model index in the proxy model that |
264 | corresponds to the \a sourceIndex from the source model. |
265 | |
266 | \sa mapToSource() |
267 | */ |
268 | |
269 | /*! |
270 | Returns a source selection mapped from the specified \a proxySelection. |
271 | |
272 | Reimplement this method to map proxy selections to source selections. |
273 | */ |
274 | QItemSelection QAbstractProxyModel::mapSelectionToSource(const QItemSelection &proxySelection) const |
275 | { |
276 | QModelIndexList proxyIndexes = proxySelection.indexes(); |
277 | QItemSelection sourceSelection; |
278 | for (int i = 0; i < proxyIndexes.size(); ++i) { |
279 | const QModelIndex proxyIdx = mapToSource(proxyIndex: proxyIndexes.at(i)); |
280 | if (!proxyIdx.isValid()) |
281 | continue; |
282 | sourceSelection << QItemSelectionRange(proxyIdx); |
283 | } |
284 | return sourceSelection; |
285 | } |
286 | |
287 | /*! |
288 | Returns a proxy selection mapped from the specified \a sourceSelection. |
289 | |
290 | Reimplement this method to map source selections to proxy selections. |
291 | */ |
292 | QItemSelection QAbstractProxyModel::mapSelectionFromSource(const QItemSelection &sourceSelection) const |
293 | { |
294 | QModelIndexList sourceIndexes = sourceSelection.indexes(); |
295 | QItemSelection proxySelection; |
296 | for (int i = 0; i < sourceIndexes.size(); ++i) { |
297 | const QModelIndex srcIdx = mapFromSource(sourceIndex: sourceIndexes.at(i)); |
298 | if (!srcIdx.isValid()) |
299 | continue; |
300 | proxySelection << QItemSelectionRange(srcIdx); |
301 | } |
302 | return proxySelection; |
303 | } |
304 | |
305 | /*! |
306 | \reimp |
307 | */ |
308 | QVariant QAbstractProxyModel::data(const QModelIndex &proxyIndex, int role) const |
309 | { |
310 | Q_D(const QAbstractProxyModel); |
311 | return d->model->data(index: mapToSource(proxyIndex), role); |
312 | } |
313 | |
314 | /*! |
315 | \reimp |
316 | */ |
317 | QVariant QAbstractProxyModel::headerData(int section, Qt::Orientation orientation, int role) const |
318 | { |
319 | Q_D(const QAbstractProxyModel); |
320 | int sourceSection = section; |
321 | if (orientation == Qt::Horizontal) { |
322 | if (rowCount() > 0) { |
323 | const QModelIndex proxyIndex = index(row: 0, column: section); |
324 | sourceSection = mapToSource(proxyIndex).column(); |
325 | } |
326 | } else { |
327 | if (columnCount() > 0) { |
328 | const QModelIndex proxyIndex = index(row: section, column: 0); |
329 | sourceSection = mapToSource(proxyIndex).row(); |
330 | } |
331 | } |
332 | return d->model->headerData(section: sourceSection, orientation, role); |
333 | } |
334 | |
335 | /*! |
336 | \reimp |
337 | */ |
338 | QMap<int, QVariant> QAbstractProxyModel::itemData(const QModelIndex &proxyIndex) const |
339 | { |
340 | Q_D(const QAbstractProxyModel); |
341 | return d->model->itemData(index: mapToSource(proxyIndex)); |
342 | } |
343 | |
344 | /*! |
345 | \reimp |
346 | */ |
347 | Qt::ItemFlags QAbstractProxyModel::flags(const QModelIndex &index) const |
348 | { |
349 | Q_D(const QAbstractProxyModel); |
350 | return d->model->flags(index: mapToSource(proxyIndex: index)); |
351 | } |
352 | |
353 | /*! |
354 | \reimp |
355 | */ |
356 | bool QAbstractProxyModel::setData(const QModelIndex &index, const QVariant &value, int role) |
357 | { |
358 | Q_D(QAbstractProxyModel); |
359 | return d->model->setData(index: mapToSource(proxyIndex: index), value, role); |
360 | } |
361 | |
362 | /*! |
363 | \reimp |
364 | */ |
365 | bool QAbstractProxyModel::setItemData(const QModelIndex &index, const QMap< int, QVariant >& roles) |
366 | { |
367 | Q_D(QAbstractProxyModel); |
368 | return d->model->setItemData(index: mapToSource(proxyIndex: index), roles); |
369 | } |
370 | |
371 | /*! |
372 | \reimp |
373 | */ |
374 | bool QAbstractProxyModel::setHeaderData(int section, Qt::Orientation orientation, const QVariant &value, int role) |
375 | { |
376 | Q_D(QAbstractProxyModel); |
377 | int sourceSection; |
378 | if (orientation == Qt::Horizontal) { |
379 | const QModelIndex proxyIndex = index(row: 0, column: section); |
380 | sourceSection = mapToSource(proxyIndex).column(); |
381 | } else { |
382 | const QModelIndex proxyIndex = index(row: section, column: 0); |
383 | sourceSection = mapToSource(proxyIndex).row(); |
384 | } |
385 | return d->model->setHeaderData(section: sourceSection, orientation, value, role); |
386 | } |
387 | |
388 | /*! |
389 | \reimp |
390 | \since 6.0 |
391 | */ |
392 | bool QAbstractProxyModel::clearItemData(const QModelIndex &index) |
393 | { |
394 | Q_D(QAbstractProxyModel); |
395 | return d->model->clearItemData(index: mapToSource(proxyIndex: index)); |
396 | } |
397 | |
398 | /*! |
399 | \reimp |
400 | */ |
401 | QModelIndex QAbstractProxyModel::buddy(const QModelIndex &index) const |
402 | { |
403 | Q_D(const QAbstractProxyModel); |
404 | return mapFromSource(sourceIndex: d->model->buddy(index: mapToSource(proxyIndex: index))); |
405 | } |
406 | |
407 | /*! |
408 | \reimp |
409 | */ |
410 | bool QAbstractProxyModel::canFetchMore(const QModelIndex &parent) const |
411 | { |
412 | Q_D(const QAbstractProxyModel); |
413 | return d->model->canFetchMore(parent: mapToSource(proxyIndex: parent)); |
414 | } |
415 | |
416 | /*! |
417 | \reimp |
418 | */ |
419 | void QAbstractProxyModel::fetchMore(const QModelIndex &parent) |
420 | { |
421 | Q_D(QAbstractProxyModel); |
422 | d->model->fetchMore(parent: mapToSource(proxyIndex: parent)); |
423 | } |
424 | |
425 | /*! |
426 | \reimp |
427 | */ |
428 | void QAbstractProxyModel::sort(int column, Qt::SortOrder order) |
429 | { |
430 | Q_D(QAbstractProxyModel); |
431 | d->model->sort(column, order); |
432 | } |
433 | |
434 | /*! |
435 | \reimp |
436 | */ |
437 | QSize QAbstractProxyModel::span(const QModelIndex &index) const |
438 | { |
439 | Q_D(const QAbstractProxyModel); |
440 | return d->model->span(index: mapToSource(proxyIndex: index)); |
441 | } |
442 | |
443 | /*! |
444 | \reimp |
445 | */ |
446 | bool QAbstractProxyModel::hasChildren(const QModelIndex &parent) const |
447 | { |
448 | Q_D(const QAbstractProxyModel); |
449 | return d->model->hasChildren(parent: mapToSource(proxyIndex: parent)); |
450 | } |
451 | |
452 | /*! |
453 | \reimp |
454 | */ |
455 | QModelIndex QAbstractProxyModel::sibling(int row, int column, const QModelIndex &idx) const |
456 | { |
457 | return index(row, column, parent: idx.parent()); |
458 | } |
459 | |
460 | /*! |
461 | \reimp |
462 | */ |
463 | QMimeData* QAbstractProxyModel::mimeData(const QModelIndexList &indexes) const |
464 | { |
465 | Q_D(const QAbstractProxyModel); |
466 | QModelIndexList list; |
467 | list.reserve(asize: indexes.size()); |
468 | for (const QModelIndex &index : indexes) |
469 | list << mapToSource(proxyIndex: index); |
470 | return d->model->mimeData(indexes: list); |
471 | } |
472 | |
473 | void QAbstractProxyModelPrivate::mapDropCoordinatesToSource(int row, int column, const QModelIndex &parent, |
474 | int *sourceRow, int *sourceColumn, QModelIndex *sourceParent) const |
475 | { |
476 | Q_Q(const QAbstractProxyModel); |
477 | *sourceRow = -1; |
478 | *sourceColumn = -1; |
479 | if (row == -1 && column == -1) { |
480 | *sourceParent = q->mapToSource(proxyIndex: parent); |
481 | } else if (row == q->rowCount(parent)) { |
482 | *sourceParent = q->mapToSource(proxyIndex: parent); |
483 | *sourceRow = model->rowCount(parent: *sourceParent); |
484 | } else { |
485 | QModelIndex proxyIndex = q->index(row, column, parent); |
486 | QModelIndex sourceIndex = q->mapToSource(proxyIndex); |
487 | *sourceRow = sourceIndex.row(); |
488 | *sourceColumn = sourceIndex.column(); |
489 | *sourceParent = sourceIndex.parent(); |
490 | } |
491 | } |
492 | |
493 | /*! |
494 | \reimp |
495 | \since 5.4 |
496 | */ |
497 | bool QAbstractProxyModel::canDropMimeData(const QMimeData *data, Qt::DropAction action, |
498 | int row, int column, const QModelIndex &parent) const |
499 | { |
500 | Q_D(const QAbstractProxyModel); |
501 | int sourceDestinationRow; |
502 | int sourceDestinationColumn; |
503 | QModelIndex sourceParent; |
504 | d->mapDropCoordinatesToSource(row, column, parent, sourceRow: &sourceDestinationRow, sourceColumn: &sourceDestinationColumn, sourceParent: &sourceParent); |
505 | return d->model->canDropMimeData(data, action, row: sourceDestinationRow, column: sourceDestinationColumn, parent: sourceParent); |
506 | } |
507 | |
508 | /*! |
509 | \reimp |
510 | \since 5.4 |
511 | */ |
512 | bool QAbstractProxyModel::dropMimeData(const QMimeData *data, Qt::DropAction action, |
513 | int row, int column, const QModelIndex &parent) |
514 | { |
515 | Q_D(QAbstractProxyModel); |
516 | int sourceDestinationRow; |
517 | int sourceDestinationColumn; |
518 | QModelIndex sourceParent; |
519 | d->mapDropCoordinatesToSource(row, column, parent, sourceRow: &sourceDestinationRow, sourceColumn: &sourceDestinationColumn, sourceParent: &sourceParent); |
520 | return d->model->dropMimeData(data, action, row: sourceDestinationRow, column: sourceDestinationColumn, parent: sourceParent); |
521 | } |
522 | |
523 | /*! |
524 | \reimp |
525 | */ |
526 | QStringList QAbstractProxyModel::mimeTypes() const |
527 | { |
528 | Q_D(const QAbstractProxyModel); |
529 | return d->model->mimeTypes(); |
530 | } |
531 | |
532 | /*! |
533 | \reimp |
534 | */ |
535 | Qt::DropActions QAbstractProxyModel::supportedDragActions() const |
536 | { |
537 | Q_D(const QAbstractProxyModel); |
538 | return d->model->supportedDragActions(); |
539 | } |
540 | |
541 | /*! |
542 | \reimp |
543 | */ |
544 | Qt::DropActions QAbstractProxyModel::supportedDropActions() const |
545 | { |
546 | Q_D(const QAbstractProxyModel); |
547 | return d->model->supportedDropActions(); |
548 | } |
549 | |
550 | /*! |
551 | \reimp |
552 | */ |
553 | QHash<int,QByteArray> QAbstractProxyModel::roleNames() const |
554 | { |
555 | Q_D(const QAbstractProxyModel); |
556 | return d->model->roleNames(); |
557 | } |
558 | |
559 | /*! |
560 | Equivalent to calling createIndex on the source model. |
561 | |
562 | This method is useful if your proxy model wants to maintain the |
563 | parent-child relationship of items in the source model. |
564 | When reimplementing mapToSource(), you can call this method to |
565 | create an index for row \a row and column \a col of the source model. |
566 | |
567 | A typical use would be to save the internal pointer coming from the source model |
568 | in the proxy index when reimplementing mapFromSource() and use the same internal |
569 | pointer as \a internalPtr to recover the original source index when |
570 | reimplementing mapToSource(). |
571 | \since 6.2 |
572 | */ |
573 | QModelIndex QAbstractProxyModel::createSourceIndex(int row, int col, void *internalPtr) const |
574 | { |
575 | if (sourceModel()) |
576 | return sourceModel()->createIndex(arow: row, acolumn: col, adata: internalPtr); |
577 | return QModelIndex(); |
578 | } |
579 | |
580 | QT_END_NAMESPACE |
581 | |
582 | #include "moc_qabstractproxymodel.cpp" |
583 |
Definitions
- _q_sourceModelDestroyed
- emitHeaderDataChanged
- scheduleHeaderUpdate
- _q_sourceModelRowsAboutToBeInserted
- _q_sourceModelRowsInserted
- _q_sourceModelRowsRemoved
- _q_sourceModelColumnsAboutToBeInserted
- _q_sourceModelColumnsInserted
- _q_sourceModelColumnsRemoved
- QAbstractProxyModel
- QAbstractProxyModel
- ~QAbstractProxyModel
- setSourceModel
- sourceModel
- bindableSourceModel
- submit
- revert
- mapSelectionToSource
- mapSelectionFromSource
- data
- headerData
- itemData
- flags
- setData
- setItemData
- setHeaderData
- clearItemData
- buddy
- canFetchMore
- fetchMore
- sort
- span
- hasChildren
- sibling
- mimeData
- mapDropCoordinatesToSource
- canDropMimeData
- dropMimeData
- mimeTypes
- supportedDragActions
- supportedDropActions
- roleNames
Learn Advanced QML with KDAB
Find out more