kdescendantsproxymodel.cpp (32926B)
1 /* 2 Copyright (c) 2009 Stephen Kelly <steveire@gmail.com> 3 Copyright (C) 2010 Klarälvdalens Datakonsult AB, 4 a KDAB Group company, info@kdab.net, 5 author Stephen Kelly <stephen@kdab.com> 6 7 This library is free software; you can redistribute it and/or modify it 8 under the terms of the GNU Library General Public License as published by 9 the Free Software Foundation; either version 2 of the License, or (at your 10 option) any later version. 11 12 This library is distributed in the hope that it will be useful, but WITHOUT 13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public 15 License for more details. 16 17 You should have received a copy of the GNU Library General Public License 18 along with this library; see the file COPYING.LIB. If not, write to the 19 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 20 02110-1301, USA. 21 */ 22 23 #include "kdescendantsproxymodel.h" 24 25 #include <QStringList> 26 #include <QTimer> 27 #include <QDebug> 28 29 #include "kbihash_p.h" 30 31 typedef KHash2Map<QPersistentModelIndex, int> Mapping; 32 33 class KDescendantsProxyModelPrivate 34 { 35 KDescendantsProxyModelPrivate(KDescendantsProxyModel *qq) 36 : q_ptr(qq), 37 m_rowCount(0), 38 m_ignoreNextLayoutAboutToBeChanged(false), 39 m_ignoreNextLayoutChanged(false), 40 m_relayouting(false), 41 m_displayAncestorData(false), 42 m_ancestorSeparator(QStringLiteral(" / ")) 43 { 44 } 45 46 Q_DECLARE_PUBLIC(KDescendantsProxyModel) 47 KDescendantsProxyModel *const q_ptr; 48 49 mutable QVector<QPersistentModelIndex> m_pendingParents; 50 51 void scheduleProcessPendingParents() const; 52 void processPendingParents(); 53 54 void synchronousMappingRefresh(); 55 56 void updateInternalIndexes(int start, int offset); 57 58 void resetInternalData(); 59 60 void sourceRowsAboutToBeInserted(const QModelIndex &, int, int); 61 void sourceRowsInserted(const QModelIndex &, int, int); 62 void sourceRowsAboutToBeRemoved(const QModelIndex &, int, int); 63 void sourceRowsRemoved(const QModelIndex &, int, int); 64 void sourceRowsAboutToBeMoved(const QModelIndex &, int, int, const QModelIndex &, int); 65 void sourceRowsMoved(const QModelIndex &, int, int, const QModelIndex &, int); 66 void sourceModelAboutToBeReset(); 67 void sourceModelReset(); 68 void sourceLayoutAboutToBeChanged(); 69 void sourceLayoutChanged(); 70 void sourceDataChanged(const QModelIndex &, const QModelIndex &); 71 void sourceModelDestroyed(); 72 73 Mapping m_mapping; 74 int m_rowCount; 75 QPair<int, int> m_removePair; 76 QPair<int, int> m_insertPair; 77 78 bool m_ignoreNextLayoutAboutToBeChanged; 79 bool m_ignoreNextLayoutChanged; 80 bool m_relayouting; 81 82 bool m_displayAncestorData; 83 QString m_ancestorSeparator; 84 85 QList<QPersistentModelIndex> m_layoutChangePersistentIndexes; 86 QModelIndexList m_proxyIndexes; 87 }; 88 89 void KDescendantsProxyModelPrivate::resetInternalData() 90 { 91 m_rowCount = 0; 92 m_mapping.clear(); 93 m_layoutChangePersistentIndexes.clear(); 94 m_proxyIndexes.clear(); 95 } 96 97 void KDescendantsProxyModelPrivate::synchronousMappingRefresh() 98 { 99 m_rowCount = 0; 100 m_mapping.clear(); 101 m_pendingParents.clear(); 102 103 m_pendingParents.append(QModelIndex()); 104 105 m_relayouting = true; 106 while (!m_pendingParents.isEmpty()) { 107 processPendingParents(); 108 } 109 m_relayouting = false; 110 } 111 112 void KDescendantsProxyModelPrivate::scheduleProcessPendingParents() const 113 { 114 const_cast<KDescendantsProxyModelPrivate *>(this)->processPendingParents(); 115 } 116 117 void KDescendantsProxyModelPrivate::processPendingParents() 118 { 119 Q_Q(KDescendantsProxyModel); 120 const QVector<QPersistentModelIndex>::iterator begin = m_pendingParents.begin(); 121 QVector<QPersistentModelIndex>::iterator it = begin; 122 123 const QVector<QPersistentModelIndex>::iterator end = m_pendingParents.end(); 124 125 QVector<QPersistentModelIndex> newPendingParents; 126 127 while (it != end && it != m_pendingParents.end()) { 128 const QModelIndex sourceParent = *it; 129 if (!sourceParent.isValid() && m_rowCount > 0) { 130 // It was removed from the source model before it was inserted. 131 it = m_pendingParents.erase(it); 132 continue; 133 } 134 const int rowCount = q->sourceModel()->rowCount(sourceParent); 135 136 Q_ASSERT(rowCount > 0); 137 const QPersistentModelIndex sourceIndex = q->sourceModel()->index(rowCount - 1, 0, sourceParent); 138 139 Q_ASSERT(sourceIndex.isValid()); 140 141 const QModelIndex proxyParent = q->mapFromSource(sourceParent); 142 143 Q_ASSERT(sourceParent.isValid() == proxyParent.isValid()); 144 const int proxyEndRow = proxyParent.row() + rowCount; 145 const int proxyStartRow = proxyEndRow - rowCount + 1; 146 147 if (!m_relayouting) { 148 q->beginInsertRows(QModelIndex(), proxyStartRow, proxyEndRow); 149 } 150 151 updateInternalIndexes(proxyStartRow, rowCount); 152 m_mapping.insert(sourceIndex, proxyEndRow); 153 it = m_pendingParents.erase(it); 154 m_rowCount += rowCount; 155 156 if (!m_relayouting) { 157 q->endInsertRows(); 158 } 159 160 for (int sourceRow = 0; sourceRow < rowCount; ++sourceRow) { 161 static const int column = 0; 162 const QModelIndex child = q->sourceModel()->index(sourceRow, column, sourceParent); 163 Q_ASSERT(child.isValid()); 164 165 if (q->sourceModel()->hasChildren(child)) { 166 Q_ASSERT(q->sourceModel()->rowCount(child) > 0); 167 newPendingParents.append(child); 168 } 169 } 170 } 171 m_pendingParents += newPendingParents; 172 if (!m_pendingParents.isEmpty()) { 173 processPendingParents(); 174 } 175 // scheduleProcessPendingParents(); 176 } 177 178 void KDescendantsProxyModelPrivate::updateInternalIndexes(int start, int offset) 179 { 180 // TODO: Make KHash2Map support key updates and do this backwards. 181 QHash<int, QPersistentModelIndex> updates; 182 { 183 Mapping::right_iterator it = m_mapping.rightLowerBound(start); 184 const Mapping::right_iterator end = m_mapping.rightEnd(); 185 186 while (it != end) { 187 updates.insert(it.key() + offset, *it); 188 ++it; 189 } 190 } 191 192 { 193 QHash<int, QPersistentModelIndex>::const_iterator it = updates.constBegin(); 194 const QHash<int, QPersistentModelIndex>::const_iterator end = updates.constEnd(); 195 196 for (; it != end; ++it) { 197 m_mapping.insert(it.value(), it.key()); 198 } 199 } 200 201 } 202 203 KDescendantsProxyModel::KDescendantsProxyModel(QObject *parent) 204 : QAbstractProxyModel(parent), d_ptr(new KDescendantsProxyModelPrivate(this)) 205 { 206 } 207 208 KDescendantsProxyModel::~KDescendantsProxyModel() 209 { 210 delete d_ptr; 211 } 212 213 void KDescendantsProxyModel::setRootIndex(const QModelIndex &index) 214 { 215 Q_UNUSED(index) 216 } 217 218 QModelIndexList KDescendantsProxyModel::match(const QModelIndex &start, int role, const QVariant &value, int hits, Qt::MatchFlags flags) const 219 { 220 return QAbstractProxyModel::match(start, role, value, hits, flags); 221 } 222 223 namespace { 224 // we only work on DisplayRole for now 225 static const QVector<int> changedRoles = {Qt::DisplayRole}; 226 } 227 228 void KDescendantsProxyModel::setDisplayAncestorData(bool display) 229 { 230 Q_D(KDescendantsProxyModel); 231 bool displayChanged = (display != d->m_displayAncestorData); 232 d->m_displayAncestorData = display; 233 if (displayChanged) { 234 // send out big hammer. Everything needs to be updated. 235 emit dataChanged(index(0,0),index(rowCount()-1,columnCount()-1), changedRoles); 236 } 237 } 238 239 bool KDescendantsProxyModel::displayAncestorData() const 240 { 241 Q_D(const KDescendantsProxyModel); 242 return d->m_displayAncestorData; 243 } 244 245 void KDescendantsProxyModel::setAncestorSeparator(const QString &separator) 246 { 247 Q_D(KDescendantsProxyModel); 248 bool separatorChanged = (separator != d->m_ancestorSeparator); 249 d->m_ancestorSeparator = separator; 250 if (separatorChanged && d->m_displayAncestorData) { 251 // send out big hammer. Everything needs to be updated. 252 emit dataChanged(index(0,0),index(rowCount()-1,columnCount()-1), changedRoles); 253 } 254 } 255 256 QString KDescendantsProxyModel::ancestorSeparator() const 257 { 258 Q_D(const KDescendantsProxyModel); 259 return d->m_ancestorSeparator; 260 } 261 262 void KDescendantsProxyModel::setSourceModel(QAbstractItemModel *_sourceModel) 263 { 264 Q_D(KDescendantsProxyModel); 265 266 beginResetModel(); 267 268 static const char *const modelSignals[] = { 269 SIGNAL(rowsAboutToBeInserted(QModelIndex,int,int)), 270 SIGNAL(rowsInserted(QModelIndex,int,int)), 271 SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)), 272 SIGNAL(rowsRemoved(QModelIndex,int,int)), 273 SIGNAL(rowsAboutToBeMoved(QModelIndex,int,int,QModelIndex,int)), 274 SIGNAL(rowsMoved(QModelIndex,int,int,QModelIndex,int)), 275 SIGNAL(modelAboutToBeReset()), 276 SIGNAL(modelReset()), 277 SIGNAL(dataChanged(QModelIndex,QModelIndex)), 278 SIGNAL(layoutAboutToBeChanged()), 279 SIGNAL(layoutChanged()), 280 SIGNAL(destroyed()) 281 }; 282 static const char *const proxySlots[] = { 283 SLOT(sourceRowsAboutToBeInserted(QModelIndex,int,int)), 284 SLOT(sourceRowsInserted(QModelIndex,int,int)), 285 SLOT(sourceRowsAboutToBeRemoved(QModelIndex,int,int)), 286 SLOT(sourceRowsRemoved(QModelIndex,int,int)), 287 SLOT(sourceRowsAboutToBeMoved(QModelIndex,int,int,QModelIndex,int)), 288 SLOT(sourceRowsMoved(QModelIndex,int,int,QModelIndex,int)), 289 SLOT(sourceModelAboutToBeReset()), 290 SLOT(sourceModelReset()), 291 SLOT(sourceDataChanged(QModelIndex,QModelIndex)), 292 SLOT(sourceLayoutAboutToBeChanged()), 293 SLOT(sourceLayoutChanged()), 294 SLOT(sourceModelDestroyed()) 295 }; 296 297 if (sourceModel()) { 298 for (int i = 0; i < int(sizeof modelSignals / sizeof * modelSignals); ++i) { 299 disconnect(sourceModel(), modelSignals[i], this, proxySlots[i]); 300 } 301 } 302 303 QAbstractProxyModel::setSourceModel(_sourceModel); 304 305 if (_sourceModel) { 306 for (int i = 0; i < int(sizeof modelSignals / sizeof * modelSignals); ++i) { 307 connect(_sourceModel, modelSignals[i], this, proxySlots[i]); 308 } 309 } 310 311 resetInternalData(); 312 if (_sourceModel && _sourceModel->hasChildren()) { 313 d->synchronousMappingRefresh(); 314 } 315 316 endResetModel(); 317 } 318 319 QModelIndex KDescendantsProxyModel::parent(const QModelIndex &index) const 320 { 321 Q_UNUSED(index) 322 return QModelIndex(); 323 } 324 325 bool KDescendantsProxyModel::hasChildren(const QModelIndex &parent) const 326 { 327 Q_D(const KDescendantsProxyModel); 328 return !(d->m_mapping.isEmpty() || parent.isValid()); 329 } 330 331 int KDescendantsProxyModel::rowCount(const QModelIndex &parent) const 332 { 333 Q_D(const KDescendantsProxyModel); 334 if (d->m_pendingParents.contains(parent) || parent.isValid() || !sourceModel()) { 335 return 0; 336 } 337 338 if (d->m_mapping.isEmpty() && sourceModel()->hasChildren()) { 339 Q_ASSERT(sourceModel()->rowCount() > 0); 340 const_cast<KDescendantsProxyModelPrivate *>(d)->synchronousMappingRefresh(); 341 } 342 return d->m_rowCount; 343 } 344 345 QModelIndex KDescendantsProxyModel::index(int row, int column, const QModelIndex &parent) const 346 { 347 if (parent.isValid()) { 348 return QModelIndex(); 349 } 350 351 if (!hasIndex(row, column, parent)) { 352 return QModelIndex(); 353 } 354 355 return createIndex(row, column); 356 } 357 358 QModelIndex KDescendantsProxyModel::mapToSource(const QModelIndex &proxyIndex) const 359 { 360 Q_D(const KDescendantsProxyModel); 361 if (d->m_mapping.isEmpty() || !proxyIndex.isValid() || !sourceModel()) { 362 return QModelIndex(); 363 } 364 365 const Mapping::right_const_iterator result = d->m_mapping.rightLowerBound(proxyIndex.row()); 366 Q_ASSERT(result != d->m_mapping.rightEnd()); 367 368 const int proxyLastRow = result.key(); 369 const QModelIndex sourceLastChild = result.value(); 370 Q_ASSERT(sourceLastChild.isValid()); 371 372 // proxyLastRow is greater than proxyIndex.row(). 373 // sourceLastChild is vertically below the result we're looking for 374 // and not necessarily in the correct parent. 375 // We travel up through its parent hierarchy until we are in the 376 // right parent, then return the correct sibling. 377 378 // Source: Proxy: Row 379 // - A - A - 0 380 // - B - B - 1 381 // - C - C - 2 382 // - D - D - 3 383 // - - E - E - 4 384 // - - F - F - 5 385 // - - G - G - 6 386 // - - H - H - 7 387 // - - I - I - 8 388 // - - - J - J - 9 389 // - - - K - K - 10 390 // - - - L - L - 11 391 // - - M - M - 12 392 // - - N - N - 13 393 // - O - O - 14 394 395 // Note that L, N and O are lastChildIndexes, and therefore have a mapping. If we 396 // are trying to map G from the proxy to the source, We at this point have an iterator 397 // pointing to (L -> 11). The proxy row of G is 6. (proxyIndex.row() == 6). We seek the 398 // sourceIndex which is vertically above L by the distance proxyLastRow - proxyIndex.row(). 399 // In this case the verticalDistance is 5. 400 401 int verticalDistance = proxyLastRow - proxyIndex.row(); 402 403 // We traverse the ancestors of L, until we can index the desired row in the source. 404 405 QModelIndex ancestor = sourceLastChild; 406 while (ancestor.isValid()) { 407 const int ancestorRow = ancestor.row(); 408 if (verticalDistance <= ancestorRow) { 409 return ancestor.sibling(ancestorRow - verticalDistance, proxyIndex.column()); 410 } 411 verticalDistance -= (ancestorRow + 1); 412 ancestor = ancestor.parent(); 413 } 414 Q_ASSERT(!"Didn't find target row."); 415 return QModelIndex(); 416 } 417 418 QModelIndex KDescendantsProxyModel::mapFromSource(const QModelIndex &sourceIndex) const 419 { 420 Q_D(const KDescendantsProxyModel); 421 422 if (!sourceModel()) { 423 return QModelIndex(); 424 } 425 426 if (d->m_mapping.isEmpty()) { 427 return QModelIndex(); 428 } 429 430 { 431 // TODO: Consider a parent Mapping to speed this up. 432 433 Mapping::right_const_iterator it = d->m_mapping.rightConstBegin(); 434 const Mapping::right_const_iterator end = d->m_mapping.rightConstEnd(); 435 const QModelIndex sourceParent = sourceIndex.parent(); 436 Mapping::right_const_iterator result = end; 437 438 for (; it != end; ++it) { 439 QModelIndex index = it.value(); 440 bool found_block = false; 441 while (index.isValid()) { 442 const QModelIndex ancestor = index.parent(); 443 if (ancestor == sourceParent && index.row() >= sourceIndex.row()) { 444 found_block = true; 445 if (result == end || it.key() < result.key()) { 446 result = it; 447 break; // Leave the while loop. index is still valid. 448 } 449 } 450 index = ancestor; 451 } 452 if (found_block && !index.isValid()) 453 // Looked through the ascendants of it.key() without finding sourceParent. 454 // That means we've already got the result we need. 455 { 456 break; 457 } 458 } 459 Q_ASSERT(result != end); 460 const QModelIndex sourceLastChild = result.value(); 461 int proxyRow = result.key(); 462 QModelIndex index = sourceLastChild; 463 while (index.isValid()) { 464 const QModelIndex ancestor = index.parent(); 465 if (ancestor == sourceParent) { 466 return createIndex(proxyRow - (index.row() - sourceIndex.row()), sourceIndex.column()); 467 } 468 proxyRow -= (index.row() + 1); 469 index = ancestor; 470 } 471 Q_ASSERT(!"Didn't find valid proxy mapping."); 472 return QModelIndex(); 473 } 474 475 } 476 477 int KDescendantsProxyModel::columnCount(const QModelIndex &parent) const 478 { 479 if (parent.isValid() /* || rowCount(parent) == 0 */ || !sourceModel()) { 480 return 0; 481 } 482 483 return sourceModel()->columnCount(); 484 } 485 486 QVariant KDescendantsProxyModel::data(const QModelIndex &index, int role) const 487 { 488 Q_D(const KDescendantsProxyModel); 489 490 if (!sourceModel()) { 491 return QVariant(); 492 } 493 494 if (!index.isValid()) { 495 return sourceModel()->data(index, role); 496 } 497 498 QModelIndex sourceIndex = mapToSource(index); 499 500 if ((d->m_displayAncestorData) && (role == Qt::DisplayRole)) { 501 if (!sourceIndex.isValid()) { 502 return QVariant(); 503 } 504 QString displayData = sourceIndex.data().toString(); 505 sourceIndex = sourceIndex.parent(); 506 while (sourceIndex.isValid()) { 507 displayData.prepend(d->m_ancestorSeparator); 508 displayData.prepend(sourceIndex.data().toString()); 509 sourceIndex = sourceIndex.parent(); 510 } 511 return displayData; 512 } else { 513 return sourceIndex.data(role); 514 } 515 } 516 517 QVariant KDescendantsProxyModel::headerData(int section, Qt::Orientation orientation, int role) const 518 { 519 if (!sourceModel() || columnCount() <= section) { 520 return QVariant(); 521 } 522 523 return QAbstractProxyModel::headerData(section, orientation, role); 524 } 525 526 Qt::ItemFlags KDescendantsProxyModel::flags(const QModelIndex &index) const 527 { 528 if (!index.isValid() || !sourceModel()) { 529 return QAbstractProxyModel::flags(index); 530 } 531 532 const QModelIndex srcIndex = mapToSource(index); 533 Q_ASSERT(srcIndex.isValid()); 534 return sourceModel()->flags(srcIndex); 535 } 536 537 void KDescendantsProxyModelPrivate::sourceRowsAboutToBeInserted(const QModelIndex &parent, int start, int end) 538 { 539 Q_Q(KDescendantsProxyModel); 540 541 if (!q->sourceModel()->hasChildren(parent)) { 542 Q_ASSERT(q->sourceModel()->rowCount(parent) == 0); 543 // parent was not a parent before. 544 return; 545 } 546 547 int proxyStart = -1; 548 549 const int rowCount = q->sourceModel()->rowCount(parent); 550 551 if (rowCount > start) { 552 const QModelIndex belowStart = q->sourceModel()->index(start, 0, parent); 553 proxyStart = q->mapFromSource(belowStart).row(); 554 } else if (rowCount == 0) { 555 proxyStart = q->mapFromSource(parent).row() + 1; 556 } else { 557 Q_ASSERT(rowCount == start); 558 static const int column = 0; 559 QModelIndex idx = q->sourceModel()->index(rowCount - 1, column, parent); 560 while (q->sourceModel()->hasChildren(idx)) { 561 Q_ASSERT(q->sourceModel()->rowCount(idx) > 0); 562 idx = q->sourceModel()->index(q->sourceModel()->rowCount(idx) - 1, column, idx); 563 } 564 // The last item in the list is getting a sibling below it. 565 proxyStart = q->mapFromSource(idx).row() + 1; 566 } 567 const int proxyEnd = proxyStart + (end - start); 568 569 m_insertPair = qMakePair(proxyStart, proxyEnd); 570 q->beginInsertRows(QModelIndex(), proxyStart, proxyEnd); 571 } 572 573 void KDescendantsProxyModelPrivate::sourceRowsInserted(const QModelIndex &parent, int start, int end) 574 { 575 Q_Q(KDescendantsProxyModel); 576 577 Q_ASSERT(q->sourceModel()->index(start, 0, parent).isValid()); 578 579 const int rowCount = q->sourceModel()->rowCount(parent); 580 Q_ASSERT(rowCount > 0); 581 582 const int difference = end - start + 1; 583 584 if (rowCount == difference) { 585 // @p parent was not a parent before. 586 m_pendingParents.append(parent); 587 scheduleProcessPendingParents(); 588 return; 589 } 590 591 const int proxyStart = m_insertPair.first; 592 593 Q_ASSERT(proxyStart >= 0); 594 595 updateInternalIndexes(proxyStart, difference); 596 597 if (rowCount - 1 == end) { 598 // The previously last row (the mapped one) is no longer the last. 599 // For example, 600 601 // - A - A 0 602 // - - B - B 1 603 // - - C - C 2 604 // - - - D - D 3 605 // - - - E -> - E 4 606 // - - F - F 5 607 // - - G -> - G 6 608 // - H - H 7 609 // - I -> - I 8 610 611 // As last children, E, F and G have mappings. 612 // Consider that 'J' is appended to the children of 'C', below 'E'. 613 614 // - A - A 0 615 // - - B - B 1 616 // - - C - C 2 617 // - - - D - D 3 618 // - - - E -> - E 4 619 // - - - J - ??? 5 620 // - - F - F 6 621 // - - G -> - G 7 622 // - H - H 8 623 // - I -> - I 9 624 625 // The updateInternalIndexes call above will have updated the F and G mappings correctly because proxyStart is 5. 626 // That means that E -> 4 was not affected by the updateInternalIndexes call. 627 // Now the mapping for E -> 4 needs to be updated so that it's a mapping for J -> 5. 628 629 Q_ASSERT(!m_mapping.isEmpty()); 630 static const int column = 0; 631 const QModelIndex oldIndex = q->sourceModel()->index(rowCount - 1 - difference, column, parent); 632 Q_ASSERT(m_mapping.leftContains(oldIndex)); 633 634 const QModelIndex newIndex = q->sourceModel()->index(rowCount - 1, column, parent); 635 636 QModelIndex indexAbove = oldIndex; 637 638 if (start > 0) { 639 // If we have something like this: 640 // 641 // - A 642 // - - B 643 // - - C 644 // 645 // and we then insert D as a sibling of A below it, we need to remove the mapping for A, 646 // and the row number used for D must take into account the descendants of A. 647 648 while (q->sourceModel()->hasChildren(indexAbove)) { 649 Q_ASSERT(q->sourceModel()->rowCount(indexAbove) > 0); 650 indexAbove = q->sourceModel()->index(q->sourceModel()->rowCount(indexAbove) - 1, column, indexAbove); 651 } 652 Q_ASSERT(q->sourceModel()->rowCount(indexAbove) == 0); 653 } 654 655 Q_ASSERT(m_mapping.leftContains(indexAbove)); 656 657 const int newProxyRow = m_mapping.leftToRight(indexAbove) + difference; 658 659 // oldIndex is E in the source. proxyRow is 4. 660 m_mapping.removeLeft(oldIndex); 661 662 // newIndex is J. (proxyRow + difference) is 5. 663 m_mapping.insert(newIndex, newProxyRow); 664 } 665 666 for (int row = start; row <= end; ++row) { 667 static const int column = 0; 668 const QModelIndex idx = q->sourceModel()->index(row, column, parent); 669 Q_ASSERT(idx.isValid()); 670 if (q->sourceModel()->hasChildren(idx)) { 671 Q_ASSERT(q->sourceModel()->rowCount(idx) > 0); 672 m_pendingParents.append(idx); 673 } 674 } 675 676 m_rowCount += difference; 677 678 q->endInsertRows(); 679 scheduleProcessPendingParents(); 680 } 681 682 void KDescendantsProxyModelPrivate::sourceRowsAboutToBeRemoved(const QModelIndex &parent, int start, int end) 683 { 684 Q_Q(KDescendantsProxyModel); 685 686 const int proxyStart = q->mapFromSource(q->sourceModel()->index(start, 0, parent)).row(); 687 688 static const int column = 0; 689 QModelIndex idx = q->sourceModel()->index(end, column, parent); 690 while (q->sourceModel()->hasChildren(idx)) { 691 Q_ASSERT(q->sourceModel()->rowCount(idx) > 0); 692 idx = q->sourceModel()->index(q->sourceModel()->rowCount(idx) - 1, column, idx); 693 } 694 const int proxyEnd = q->mapFromSource(idx).row(); 695 696 m_removePair = qMakePair(proxyStart, proxyEnd); 697 698 q->beginRemoveRows(QModelIndex(), proxyStart, proxyEnd); 699 } 700 701 static QModelIndex getFirstDeepest(QAbstractItemModel *model, const QModelIndex &parent, int *count) 702 { 703 static const int column = 0; 704 Q_ASSERT(model->hasChildren(parent)); 705 Q_ASSERT(model->rowCount(parent) > 0); 706 for (int row = 0; row < model->rowCount(parent); ++row) { 707 (*count)++; 708 const QModelIndex child = model->index(row, column, parent); 709 Q_ASSERT(child.isValid()); 710 if (model->hasChildren(child)) { 711 return getFirstDeepest(model, child, count); 712 } 713 } 714 return model->index(model->rowCount(parent) - 1, column, parent); 715 } 716 717 void KDescendantsProxyModelPrivate::sourceRowsRemoved(const QModelIndex &parent, int start, int end) 718 { 719 Q_Q(KDescendantsProxyModel); 720 Q_UNUSED(end) 721 722 const int rowCount = q->sourceModel()->rowCount(parent); 723 724 const int proxyStart = m_removePair.first; 725 const int proxyEnd = m_removePair.second; 726 727 const int difference = proxyEnd - proxyStart + 1; 728 { 729 Mapping::right_iterator it = m_mapping.rightLowerBound(proxyStart); 730 const Mapping::right_iterator endIt = m_mapping.rightUpperBound(proxyEnd); 731 732 if (endIt != m_mapping.rightEnd()) 733 while (it != endIt) { 734 it = m_mapping.eraseRight(it); 735 } 736 else 737 while (it != m_mapping.rightUpperBound(proxyEnd)) { 738 it = m_mapping.eraseRight(it); 739 } 740 } 741 742 m_removePair = qMakePair(-1, -1); 743 m_rowCount -= difference; 744 Q_ASSERT(m_rowCount >= 0); 745 746 updateInternalIndexes(proxyStart, -1 * difference); 747 748 if (rowCount != start || rowCount == 0) { 749 q->endRemoveRows(); 750 return; 751 } 752 753 static const int column = 0; 754 const QModelIndex newEnd = q->sourceModel()->index(rowCount - 1, column, parent); 755 Q_ASSERT(newEnd.isValid()); 756 757 if (m_mapping.isEmpty()) { 758 m_mapping.insert(newEnd, newEnd.row()); 759 q->endRemoveRows(); 760 return; 761 } 762 if (q->sourceModel()->hasChildren(newEnd)) { 763 int count = 0; 764 const QModelIndex firstDeepest = getFirstDeepest(q->sourceModel(), newEnd, &count); 765 Q_ASSERT(firstDeepest.isValid()); 766 const int firstDeepestProxy = m_mapping.leftToRight(firstDeepest); 767 768 m_mapping.insert(newEnd, firstDeepestProxy - count); 769 q->endRemoveRows(); 770 return; 771 } 772 Mapping::right_iterator lowerBound = m_mapping.rightLowerBound(proxyStart); 773 if (lowerBound == m_mapping.rightEnd()) { 774 int proxyRow = (lowerBound - 1).key(); 775 776 for (int row = newEnd.row(); row >= 0; --row) { 777 const QModelIndex newEndSibling = q->sourceModel()->index(row, column, parent); 778 if (!q->sourceModel()->hasChildren(newEndSibling)) { 779 ++proxyRow; 780 } else { 781 break; 782 } 783 } 784 m_mapping.insert(newEnd, proxyRow); 785 q->endRemoveRows(); 786 return; 787 } else if (lowerBound == m_mapping.rightBegin()) { 788 int proxyRow = rowCount - 1; 789 QModelIndex trackedParent = parent; 790 while (trackedParent.isValid()) { 791 proxyRow += (trackedParent.row() + 1); 792 trackedParent = trackedParent.parent(); 793 } 794 m_mapping.insert(newEnd, proxyRow); 795 q->endRemoveRows(); 796 return; 797 } 798 const Mapping::right_iterator boundAbove = lowerBound - 1; 799 800 QVector<QModelIndex> targetParents; 801 targetParents.push_back(parent); 802 { 803 QModelIndex target = parent; 804 int count = 0; 805 while (target.isValid()) { 806 if (target == boundAbove.value()) { 807 m_mapping.insert(newEnd, count + boundAbove.key() + newEnd.row() + 1); 808 q->endRemoveRows(); 809 return; 810 } 811 count += (target.row() + 1); 812 target = target.parent(); 813 if (target.isValid()) { 814 targetParents.push_back(target); 815 } 816 } 817 } 818 819 QModelIndex boundParent = boundAbove.value().parent(); 820 QModelIndex prevParent = boundParent; 821 Q_ASSERT(boundParent.isValid()); 822 while (boundParent.isValid()) { 823 prevParent = boundParent; 824 boundParent = boundParent.parent(); 825 826 if (targetParents.contains(prevParent)) { 827 break; 828 } 829 830 if (!m_mapping.leftContains(prevParent)) { 831 break; 832 } 833 834 if (m_mapping.leftToRight(prevParent) > boundAbove.key()) { 835 break; 836 } 837 } 838 839 QModelIndex trackedParent = parent; 840 841 int proxyRow = boundAbove.key(); 842 843 Q_ASSERT(prevParent.isValid()); 844 proxyRow -= prevParent.row(); 845 while (trackedParent != boundParent) { 846 proxyRow += (trackedParent.row() + 1); 847 trackedParent = trackedParent.parent(); 848 } 849 m_mapping.insert(newEnd, proxyRow + newEnd.row()); 850 q->endRemoveRows(); 851 } 852 853 void KDescendantsProxyModelPrivate::sourceRowsAboutToBeMoved(const QModelIndex &srcParent, int srcStart, int srcEnd, const QModelIndex &destParent, int destStart) 854 { 855 Q_UNUSED(srcParent) 856 Q_UNUSED(srcStart) 857 Q_UNUSED(srcEnd) 858 Q_UNUSED(destParent) 859 Q_UNUSED(destStart) 860 sourceLayoutAboutToBeChanged(); 861 } 862 863 void KDescendantsProxyModelPrivate::sourceRowsMoved(const QModelIndex &srcParent, int srcStart, int srcEnd, const QModelIndex &destParent, int destStart) 864 { 865 Q_UNUSED(srcParent) 866 Q_UNUSED(srcStart) 867 Q_UNUSED(srcEnd) 868 Q_UNUSED(destParent) 869 Q_UNUSED(destStart) 870 sourceLayoutChanged(); 871 } 872 873 void KDescendantsProxyModelPrivate::sourceModelAboutToBeReset() 874 { 875 Q_Q(KDescendantsProxyModel); 876 q->beginResetModel(); 877 } 878 879 void KDescendantsProxyModelPrivate::sourceModelReset() 880 { 881 Q_Q(KDescendantsProxyModel); 882 resetInternalData(); 883 if (q->sourceModel()->hasChildren()) { 884 Q_ASSERT(q->sourceModel()->rowCount() > 0); 885 m_pendingParents.append(QModelIndex()); 886 scheduleProcessPendingParents(); 887 } 888 q->endResetModel(); 889 } 890 891 void KDescendantsProxyModelPrivate::sourceLayoutAboutToBeChanged() 892 { 893 Q_Q(KDescendantsProxyModel); 894 895 if (m_ignoreNextLayoutChanged) { 896 m_ignoreNextLayoutChanged = false; 897 return; 898 } 899 900 if (m_mapping.isEmpty()) { 901 return; 902 } 903 904 emit q->layoutAboutToBeChanged(); 905 906 QPersistentModelIndex srcPersistentIndex; 907 Q_FOREACH (const QPersistentModelIndex &proxyPersistentIndex, q->persistentIndexList()) { 908 m_proxyIndexes << proxyPersistentIndex; 909 Q_ASSERT(proxyPersistentIndex.isValid()); 910 srcPersistentIndex = q->mapToSource(proxyPersistentIndex); 911 Q_ASSERT(srcPersistentIndex.isValid()); 912 m_layoutChangePersistentIndexes << srcPersistentIndex; 913 } 914 } 915 916 void KDescendantsProxyModelPrivate::sourceLayoutChanged() 917 { 918 Q_Q(KDescendantsProxyModel); 919 920 if (m_ignoreNextLayoutAboutToBeChanged) { 921 m_ignoreNextLayoutAboutToBeChanged = false; 922 return; 923 } 924 925 if (m_mapping.isEmpty()) { 926 return; 927 } 928 929 m_rowCount = 0; 930 931 synchronousMappingRefresh(); 932 933 for (int i = 0; i < m_proxyIndexes.size(); ++i) { 934 q->changePersistentIndex(m_proxyIndexes.at(i), q->mapFromSource(m_layoutChangePersistentIndexes.at(i))); 935 } 936 937 m_layoutChangePersistentIndexes.clear(); 938 m_proxyIndexes.clear(); 939 940 emit q->layoutChanged(); 941 } 942 943 void KDescendantsProxyModelPrivate::sourceDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight) 944 { 945 Q_Q(KDescendantsProxyModel); 946 Q_ASSERT(topLeft.model() == q->sourceModel()); 947 Q_ASSERT(bottomRight.model() == q->sourceModel()); 948 949 const int topRow = topLeft.row(); 950 const int bottomRow = bottomRight.row(); 951 952 for (int i = topRow; i <= bottomRow; ++i) { 953 const QModelIndex sourceTopLeft = q->sourceModel()->index(i, topLeft.column(), topLeft.parent()); 954 Q_ASSERT(sourceTopLeft.isValid()); 955 const QModelIndex proxyTopLeft = q->mapFromSource(sourceTopLeft); 956 // TODO. If an index does not have any descendants, then we can emit in blocks of rows. 957 // As it is we emit once for each row. 958 const QModelIndex sourceBottomRight = q->sourceModel()->index(i, bottomRight.column(), bottomRight.parent()); 959 const QModelIndex proxyBottomRight = q->mapFromSource(sourceBottomRight); 960 Q_ASSERT(proxyTopLeft.isValid()); 961 Q_ASSERT(proxyBottomRight.isValid()); 962 emit q->dataChanged(proxyTopLeft, proxyBottomRight); 963 } 964 } 965 966 void KDescendantsProxyModelPrivate::sourceModelDestroyed() 967 { 968 resetInternalData(); 969 } 970 971 QMimeData *KDescendantsProxyModel::mimeData(const QModelIndexList &indexes) const 972 { 973 if (!sourceModel()) { 974 return QAbstractProxyModel::mimeData(indexes); 975 } 976 Q_ASSERT(sourceModel()); 977 QModelIndexList sourceIndexes; 978 Q_FOREACH (const QModelIndex &index, indexes) { 979 sourceIndexes << mapToSource(index); 980 } 981 return sourceModel()->mimeData(sourceIndexes); 982 } 983 984 QStringList KDescendantsProxyModel::mimeTypes() const 985 { 986 if (!sourceModel()) { 987 return QAbstractProxyModel::mimeTypes(); 988 } 989 Q_ASSERT(sourceModel()); 990 return sourceModel()->mimeTypes(); 991 } 992 993 Qt::DropActions KDescendantsProxyModel::supportedDropActions() const 994 { 995 if (!sourceModel()) { 996 return QAbstractProxyModel::supportedDropActions(); 997 } 998 return sourceModel()->supportedDropActions(); 999 } 1000 1001 #include "moc_kdescendantsproxymodel.cpp"