| 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::() | 
| 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::(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::(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::(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 |  |