File indexing completed on 2024-11-24 04:53:07
0001 /* 0002 Copyright (c) 2009 Stephen Kelly <steveire@gmail.com> 0003 Copyright (C) 2010 Klarälvdalens Datakonsult AB, 0004 a KDAB Group company, info@kdab.net, 0005 author Stephen Kelly <stephen@kdab.com> 0006 0007 This library is free software; you can redistribute it and/or modify it 0008 under the terms of the GNU Library General Public License as published by 0009 the Free Software Foundation; either version 2 of the License, or (at your 0010 option) any later version. 0011 0012 This library is distributed in the hope that it will be useful, but WITHOUT 0013 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 0014 FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public 0015 License for more details. 0016 0017 You should have received a copy of the GNU Library General Public License 0018 along with this library; see the file COPYING.LIB. If not, write to the 0019 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 0020 02110-1301, USA. 0021 */ 0022 0023 #include "kdescendantsproxymodel.h" 0024 0025 #include <QtCore/QStringList> 0026 #include <QtCore/QTimer> 0027 0028 #include "kbihash_p.h" 0029 0030 typedef KHash2Map<QPersistentModelIndex, int> Mapping; 0031 0032 class KDescendantsProxyModelPrivate 0033 { 0034 KDescendantsProxyModelPrivate(KDescendantsProxyModel * qq) 0035 : q_ptr(qq), 0036 m_rowCount(0), 0037 m_ignoreNextLayoutAboutToBeChanged(false), 0038 m_ignoreNextLayoutChanged(false), 0039 m_relayouting(false), 0040 m_displayAncestorData( false ), 0041 m_ancestorSeparator( QStringLiteral( " / " ) ) 0042 { 0043 } 0044 0045 Q_DECLARE_PUBLIC(KDescendantsProxyModel) 0046 KDescendantsProxyModel * const q_ptr; 0047 0048 mutable QVector<QPersistentModelIndex> m_pendingParents; 0049 0050 void scheduleProcessPendingParents() const; 0051 void processPendingParents(); 0052 0053 void synchronousMappingRefresh(); 0054 0055 void updateInternalIndexes(int start, int offset); 0056 0057 void resetInternalData(); 0058 0059 void sourceRowsAboutToBeInserted(const QModelIndex &, int, int); 0060 void sourceRowsInserted(const QModelIndex &, int, int); 0061 void sourceRowsAboutToBeRemoved(const QModelIndex &, int, int); 0062 void sourceRowsRemoved(const QModelIndex &, int, int); 0063 void sourceRowsAboutToBeMoved(const QModelIndex &, int, int, const QModelIndex &, int); 0064 void sourceRowsMoved(const QModelIndex &, int, int, const QModelIndex &, int); 0065 void sourceModelAboutToBeReset(); 0066 void sourceModelReset(); 0067 void sourceLayoutAboutToBeChanged(); 0068 void sourceLayoutChanged(); 0069 void sourceDataChanged(const QModelIndex &, const QModelIndex &); 0070 void sourceModelDestroyed(); 0071 0072 Mapping m_mapping; 0073 int m_rowCount; 0074 QPair<int, int> m_removePair; 0075 QPair<int, int> m_insertPair; 0076 0077 bool m_ignoreNextLayoutAboutToBeChanged; 0078 bool m_ignoreNextLayoutChanged; 0079 bool m_relayouting; 0080 0081 bool m_displayAncestorData; 0082 QString m_ancestorSeparator; 0083 0084 QList<QPersistentModelIndex> m_layoutChangePersistentIndexes; 0085 QModelIndexList m_proxyIndexes; 0086 QHash<int,QByteArray> m_roleNames; 0087 }; 0088 0089 void KDescendantsProxyModelPrivate::resetInternalData() 0090 { 0091 m_rowCount = 0; 0092 m_mapping.clear(); 0093 m_layoutChangePersistentIndexes.clear(); 0094 m_proxyIndexes.clear(); 0095 } 0096 0097 void KDescendantsProxyModelPrivate::synchronousMappingRefresh() 0098 { 0099 m_rowCount = 0; 0100 m_mapping.clear(); 0101 m_pendingParents.clear(); 0102 0103 m_pendingParents.append(QModelIndex()); 0104 0105 m_relayouting = true; 0106 while (!m_pendingParents.isEmpty()) 0107 { 0108 processPendingParents(); 0109 } 0110 m_relayouting = false; 0111 } 0112 0113 void KDescendantsProxyModelPrivate::scheduleProcessPendingParents() const 0114 { 0115 const_cast<KDescendantsProxyModelPrivate*>(this)->processPendingParents(); 0116 } 0117 0118 void KDescendantsProxyModelPrivate::processPendingParents() 0119 { 0120 Q_Q(KDescendantsProxyModel); 0121 const QVector<QPersistentModelIndex>::iterator begin = m_pendingParents.begin(); 0122 QVector<QPersistentModelIndex>::iterator it = begin; 0123 0124 const QVector<QPersistentModelIndex>::iterator end = m_pendingParents.end(); 0125 0126 QVector<QPersistentModelIndex> newPendingParents; 0127 0128 while (it != end && it != m_pendingParents.end()) { 0129 const QModelIndex sourceParent = *it; 0130 if (!sourceParent.isValid() && m_rowCount > 0) 0131 { 0132 // It was removed from the source model before it was inserted. 0133 it = m_pendingParents.erase(it); 0134 continue; 0135 } 0136 const int rowCount = q->sourceModel()->rowCount(sourceParent); 0137 0138 Q_ASSERT(rowCount > 0); 0139 const QPersistentModelIndex sourceIndex = q->sourceModel()->index(rowCount - 1, 0, sourceParent); 0140 0141 Q_ASSERT(sourceIndex.isValid()); 0142 0143 const QModelIndex proxyParent = q->mapFromSource(sourceParent); 0144 0145 Q_ASSERT(sourceParent.isValid() == proxyParent.isValid()); 0146 const int proxyEndRow = proxyParent.row() + rowCount; 0147 const int proxyStartRow = proxyEndRow - rowCount + 1; 0148 0149 if (!m_relayouting) 0150 q->beginInsertRows(QModelIndex(), proxyStartRow, proxyEndRow); 0151 0152 updateInternalIndexes(proxyStartRow, rowCount); 0153 m_mapping.insert(sourceIndex, proxyEndRow); 0154 it = m_pendingParents.erase(it); 0155 m_rowCount += rowCount; 0156 0157 if (!m_relayouting) 0158 q->endInsertRows(); 0159 0160 for (int sourceRow = 0; sourceRow < rowCount; ++sourceRow ) { 0161 static const int column = 0; 0162 const QModelIndex child = q->sourceModel()->index(sourceRow, column, sourceParent); 0163 Q_ASSERT(child.isValid()); 0164 0165 if (q->sourceModel()->hasChildren(child)) 0166 { 0167 Q_ASSERT(q->sourceModel()->rowCount(child) > 0); 0168 newPendingParents.append(child); 0169 } 0170 } 0171 } 0172 m_pendingParents += newPendingParents; 0173 if (!m_pendingParents.isEmpty()) 0174 processPendingParents(); 0175 // scheduleProcessPendingParents(); 0176 } 0177 0178 void KDescendantsProxyModelPrivate::updateInternalIndexes(int start, int offset) 0179 { 0180 // TODO: Make KHash2Map support key updates and do this backwards. 0181 QHash<int, QPersistentModelIndex> updates; 0182 { 0183 Mapping::right_iterator it = m_mapping.rightLowerBound(start); 0184 const Mapping::right_iterator end = m_mapping.rightEnd(); 0185 0186 while (it != end) 0187 { 0188 updates.insert(it.key() + offset, *it); 0189 ++it; 0190 } 0191 } 0192 0193 { 0194 QHash<int, QPersistentModelIndex>::const_iterator it = updates.constBegin(); 0195 const QHash<int, QPersistentModelIndex>::const_iterator end = updates.constEnd(); 0196 0197 for ( ; it != end; ++it) 0198 { 0199 m_mapping.insert(it.value(), it.key()); 0200 } 0201 } 0202 0203 } 0204 0205 KDescendantsProxyModel::KDescendantsProxyModel(QObject *parent) 0206 : QAbstractProxyModel(parent), d_ptr(new KDescendantsProxyModelPrivate(this)) 0207 { 0208 } 0209 0210 KDescendantsProxyModel::~KDescendantsProxyModel() 0211 { 0212 delete d_ptr; 0213 } 0214 0215 void KDescendantsProxyModel::setRootIndex(const QModelIndex &index) 0216 { 0217 Q_UNUSED(index) 0218 } 0219 0220 QModelIndexList KDescendantsProxyModel::match(const QModelIndex &start, int role, const QVariant &value, int hits, Qt::MatchFlags flags) const 0221 { 0222 return QAbstractProxyModel::match(start, role, value, hits, flags); 0223 } 0224 0225 void KDescendantsProxyModel::setDisplayAncestorData( bool display ) 0226 { 0227 Q_D(KDescendantsProxyModel); 0228 d->m_displayAncestorData = display; 0229 } 0230 0231 bool KDescendantsProxyModel::displayAncestorData() const 0232 { 0233 Q_D(const KDescendantsProxyModel ); 0234 return d->m_displayAncestorData; 0235 } 0236 0237 void KDescendantsProxyModel::setAncestorSeparator( const QString &separator ) 0238 { 0239 Q_D(KDescendantsProxyModel); 0240 d->m_ancestorSeparator = separator; 0241 } 0242 0243 QString KDescendantsProxyModel::ancestorSeparator() const 0244 { 0245 Q_D(const KDescendantsProxyModel ); 0246 return d->m_ancestorSeparator; 0247 } 0248 0249 0250 void KDescendantsProxyModel::setSourceModel(QAbstractItemModel *_sourceModel) 0251 { 0252 beginResetModel(); 0253 0254 if (_sourceModel) { 0255 disconnect(_sourceModel, SIGNAL(rowsAboutToBeInserted(const QModelIndex &, int, int)), 0256 this, SLOT(sourceRowsAboutToBeInserted(const QModelIndex &, int, int))); 0257 disconnect(_sourceModel, SIGNAL(rowsInserted(const QModelIndex &, int, int)), 0258 this, SLOT(sourceRowsInserted(const QModelIndex &, int, int))); 0259 disconnect(_sourceModel, SIGNAL(rowsAboutToBeRemoved(const QModelIndex &, int, int)), 0260 this, SLOT(sourceRowsAboutToBeRemoved(const QModelIndex &, int, int))); 0261 disconnect(_sourceModel, SIGNAL(rowsRemoved(const QModelIndex &, int, int)), 0262 this, SLOT(sourceRowsRemoved(const QModelIndex &, int, int))); 0263 // disconnect(_sourceModel, SIGNAL(rowsAboutToBeMoved(const QModelIndex &, int, int, const QModelIndex &, int)), 0264 // this, SLOT(sourceRowsAboutToBeMoved(const QModelIndex &, int, int, const QModelIndex &, int))); 0265 // disconnect(_sourceModel, SIGNAL(rowsMoved(const QModelIndex &, int, int, const QModelIndex &, int)), 0266 // this, SLOT(sourceRowsMoved(const QModelIndex &, int, int, const QModelIndex &, int))); 0267 disconnect(_sourceModel, SIGNAL(modelAboutToBeReset()), 0268 this, SLOT(sourceModelAboutToBeReset())); 0269 disconnect(_sourceModel, SIGNAL(modelReset()), 0270 this, SLOT(sourceModelReset())); 0271 disconnect(_sourceModel, SIGNAL(dataChanged(const QModelIndex &, const QModelIndex &)), 0272 this, SLOT(sourceDataChanged(const QModelIndex &, const QModelIndex &))); 0273 disconnect(_sourceModel, SIGNAL(layoutAboutToBeChanged()), 0274 this, SLOT(sourceLayoutAboutToBeChanged())); 0275 disconnect(_sourceModel, SIGNAL(layoutChanged()), 0276 this, SLOT(sourceLayoutChanged())); 0277 disconnect(_sourceModel, SIGNAL(destroyed()), 0278 this, SLOT(sourceModelDestroyed())); 0279 } 0280 0281 QAbstractProxyModel::setSourceModel(_sourceModel); 0282 0283 if (_sourceModel) { 0284 connect(_sourceModel, SIGNAL(rowsAboutToBeInserted(const QModelIndex &, int, int)), 0285 SLOT(sourceRowsAboutToBeInserted(const QModelIndex &, int, int))); 0286 connect(_sourceModel, SIGNAL(rowsInserted(const QModelIndex &, int, int)), 0287 SLOT(sourceRowsInserted(const QModelIndex &, int, int))); 0288 connect(_sourceModel, SIGNAL(rowsAboutToBeRemoved(const QModelIndex &, int, int)), 0289 SLOT(sourceRowsAboutToBeRemoved(const QModelIndex &, int, int))); 0290 connect(_sourceModel, SIGNAL(rowsRemoved(const QModelIndex &, int, int)), 0291 SLOT(sourceRowsRemoved(const QModelIndex &, int, int))); 0292 // connect(_sourceModel, SIGNAL(rowsAboutToBeMoved(const QModelIndex &, int, int, const QModelIndex &, int)), 0293 // SLOT(sourceRowsAboutToBeMoved(const QModelIndex &, int, int, const QModelIndex &, int))); 0294 // connect(_sourceModel, SIGNAL(rowsMoved(const QModelIndex &, int, int, const QModelIndex &, int)), 0295 // SLOT(sourceRowsMoved(const QModelIndex &, int, int, const QModelIndex &, int))); 0296 connect(_sourceModel, SIGNAL(modelAboutToBeReset()), 0297 SLOT(sourceModelAboutToBeReset())); 0298 connect(_sourceModel, SIGNAL(modelReset()), 0299 SLOT(sourceModelReset())); 0300 connect(_sourceModel, SIGNAL(dataChanged(const QModelIndex &, const QModelIndex &)), 0301 SLOT(sourceDataChanged(const QModelIndex &, const QModelIndex &))); 0302 connect(_sourceModel, SIGNAL(layoutAboutToBeChanged()), 0303 SLOT(sourceLayoutAboutToBeChanged())); 0304 connect(_sourceModel, SIGNAL(layoutChanged()), 0305 SLOT(sourceLayoutChanged())); 0306 connect(_sourceModel, SIGNAL(destroyed()), 0307 SLOT(sourceModelDestroyed())); 0308 } 0309 0310 endResetModel(); 0311 } 0312 0313 QModelIndex KDescendantsProxyModel::parent(const QModelIndex &index) const 0314 { 0315 Q_UNUSED(index) 0316 return QModelIndex(); 0317 } 0318 0319 bool KDescendantsProxyModel::hasChildren(const QModelIndex &parent) const 0320 { 0321 Q_D(const KDescendantsProxyModel); 0322 return !(d->m_mapping.isEmpty() || parent.isValid()); 0323 } 0324 0325 int KDescendantsProxyModel::rowCount(const QModelIndex &parent) const 0326 { 0327 Q_D(const KDescendantsProxyModel); 0328 if (d->m_pendingParents.contains(parent) || parent.isValid() || !sourceModel()) 0329 return 0; 0330 0331 if (d->m_mapping.isEmpty() && sourceModel()->hasChildren()) 0332 { 0333 Q_ASSERT(sourceModel()->rowCount() > 0); 0334 const_cast<KDescendantsProxyModelPrivate*>(d)->synchronousMappingRefresh(); 0335 } 0336 return d->m_rowCount; 0337 } 0338 0339 QModelIndex KDescendantsProxyModel::index(int row, int column, const QModelIndex &parent) const 0340 { 0341 if (parent.isValid()) 0342 return QModelIndex(); 0343 0344 if (!hasIndex(row, column, parent)) 0345 return QModelIndex(); 0346 0347 return createIndex(row, column); 0348 } 0349 0350 QModelIndex KDescendantsProxyModel::mapToSource(const QModelIndex &proxyIndex) const 0351 { 0352 Q_D(const KDescendantsProxyModel); 0353 if (d->m_mapping.isEmpty() || !proxyIndex.isValid() || !sourceModel()) 0354 return QModelIndex(); 0355 0356 const Mapping::right_const_iterator result = d->m_mapping.rightLowerBound(proxyIndex.row()); 0357 Q_ASSERT(result != d->m_mapping.rightEnd()); 0358 0359 const int proxyLastRow = result.key(); 0360 const QModelIndex sourceLastChild = result.value(); 0361 Q_ASSERT(sourceLastChild.isValid()); 0362 0363 // proxyLastRow is greater than proxyIndex.row(). 0364 // sourceLastChild is vertically below the result we're looking for 0365 // and not necessarily in the correct parent. 0366 // We travel up through its parent hierarchy until we are in the 0367 // right parent, then return the correct sibling. 0368 0369 // Source: Proxy: Row 0370 // - A - A - 0 0371 // - B - B - 1 0372 // - C - C - 2 0373 // - D - D - 3 0374 // - - E - E - 4 0375 // - - F - F - 5 0376 // - - G - G - 6 0377 // - - H - H - 7 0378 // - - I - I - 8 0379 // - - - J - J - 9 0380 // - - - K - K - 10 0381 // - - - L - L - 11 0382 // - - M - M - 12 0383 // - - N - N - 13 0384 // - O - O - 14 0385 0386 // Note that L, N and O are lastChildIndexes, and therefore have a mapping. If we 0387 // are trying to map G from the proxy to the source, We at this point have an iterator 0388 // pointing to (L -> 11). The proxy row of G is 6. (proxyIndex.row() == 6). We seek the 0389 // sourceIndex which is vertically above L by the distance proxyLastRow - proxyIndex.row(). 0390 // In this case the verticalDistance is 5. 0391 0392 int verticalDistance = proxyLastRow - proxyIndex.row(); 0393 0394 // We traverse the ancestors of L, until we can index the desired row in the source. 0395 0396 QModelIndex ancestor = sourceLastChild; 0397 while (ancestor.isValid()) 0398 { 0399 const int ancestorRow = ancestor.row(); 0400 if (verticalDistance <= ancestorRow) 0401 { 0402 return ancestor.sibling(ancestorRow - verticalDistance, proxyIndex.column()); 0403 } 0404 verticalDistance -= (ancestorRow + 1); 0405 ancestor = ancestor.parent(); 0406 } 0407 Q_ASSERT(!"Didn't find target row."); 0408 return QModelIndex(); 0409 } 0410 0411 QModelIndex KDescendantsProxyModel::mapFromSource(const QModelIndex &sourceIndex) const 0412 { 0413 Q_D(const KDescendantsProxyModel); 0414 0415 if (!sourceModel()) 0416 return QModelIndex(); 0417 0418 if (d->m_mapping.isEmpty()) 0419 return QModelIndex(); 0420 0421 0422 { 0423 // TODO: Consider a parent Mapping to speed this up. 0424 0425 Mapping::right_const_iterator it = d->m_mapping.rightConstBegin(); 0426 const Mapping::right_const_iterator end = d->m_mapping.rightConstEnd(); 0427 const QModelIndex sourceParent = sourceIndex.parent(); 0428 Mapping::right_const_iterator result = end; 0429 0430 for ( ; it != end; ++it ) 0431 { 0432 QModelIndex index = it.value(); 0433 bool found_block = false; 0434 while (index.isValid()) 0435 { 0436 const QModelIndex ancestor = index.parent(); 0437 if (ancestor == sourceParent && index.row() >= sourceIndex.row()) 0438 { 0439 found_block = true; 0440 if (result == end || it.key() < result.key()) 0441 { 0442 result = it; 0443 break; // Leave the while loop. index is still valid. 0444 } 0445 } 0446 index = ancestor; 0447 } 0448 if (found_block && !index.isValid()) 0449 // Looked through the ascendants of it.key() without finding sourceParent. 0450 // That means we've already got the result we need. 0451 break; 0452 } 0453 Q_ASSERT(result != end); 0454 const QModelIndex sourceLastChild = result.value(); 0455 int proxyRow = result.key(); 0456 QModelIndex index = sourceLastChild; 0457 while (index.isValid()) 0458 { 0459 const QModelIndex ancestor = index.parent(); 0460 if (ancestor == sourceParent) 0461 { 0462 return createIndex(proxyRow - (index.row() - sourceIndex.row()), sourceIndex.column()); 0463 } 0464 proxyRow -= (index.row() + 1); 0465 index = ancestor; 0466 } 0467 Q_ASSERT(!"Didn't find valid proxy mapping."); 0468 return QModelIndex(); 0469 } 0470 0471 } 0472 0473 int KDescendantsProxyModel::columnCount(const QModelIndex &parent) const 0474 { 0475 if (parent.isValid() /* || rowCount(parent) == 0 */ || !sourceModel()) 0476 return 0; 0477 0478 return sourceModel()->columnCount(); 0479 } 0480 0481 QVariant KDescendantsProxyModel::data(const QModelIndex &index, int role) const 0482 { 0483 Q_D(const KDescendantsProxyModel ); 0484 0485 if (!sourceModel()) 0486 return QVariant(); 0487 0488 if (!index.isValid()) 0489 return sourceModel()->data(index, role); 0490 0491 QModelIndex sourceIndex = mapToSource( index ); 0492 0493 if ((d->m_displayAncestorData) && ( role == Qt::DisplayRole ) ) 0494 { 0495 if (!sourceIndex.isValid()) 0496 { 0497 return QVariant(); 0498 } 0499 QString displayData = sourceIndex.data().toString(); 0500 sourceIndex = sourceIndex.parent(); 0501 while (sourceIndex.isValid()) 0502 { 0503 displayData.prepend(d->m_ancestorSeparator); 0504 displayData.prepend(sourceIndex.data().toString()); 0505 sourceIndex = sourceIndex.parent(); 0506 } 0507 return displayData; 0508 } else { 0509 return sourceIndex.data(role); 0510 } 0511 } 0512 0513 QVariant KDescendantsProxyModel::headerData(int section, Qt::Orientation orientation, int role) const 0514 { 0515 if (!sourceModel() || columnCount() <= section) 0516 return QVariant(); 0517 0518 return QAbstractProxyModel::headerData(section, orientation, role); 0519 } 0520 0521 Qt::ItemFlags KDescendantsProxyModel::flags(const QModelIndex &index) const 0522 { 0523 if (!index.isValid() || !sourceModel()) 0524 return QAbstractProxyModel::flags(index); 0525 0526 const QModelIndex srcIndex = mapToSource(index); 0527 Q_ASSERT(srcIndex.isValid()); 0528 return sourceModel()->flags(srcIndex); 0529 } 0530 0531 void KDescendantsProxyModelPrivate::sourceRowsAboutToBeInserted(const QModelIndex &parent, int start, int end) 0532 { 0533 Q_Q(KDescendantsProxyModel); 0534 0535 if (!q->sourceModel()->hasChildren(parent)) 0536 { 0537 Q_ASSERT(q->sourceModel()->rowCount(parent) == 0); 0538 // parent was not a parent before. 0539 return; 0540 } 0541 0542 int proxyStart = -1; 0543 0544 const int rowCount = q->sourceModel()->rowCount(parent); 0545 0546 if (rowCount > start) 0547 { 0548 const QModelIndex belowStart = q->sourceModel()->index(start, 0, parent); 0549 proxyStart = q->mapFromSource(belowStart).row(); 0550 } else if (rowCount == 0) 0551 { 0552 proxyStart = q->mapFromSource(parent).row() + 1; 0553 } else { 0554 Q_ASSERT(rowCount == start); 0555 static const int column = 0; 0556 QModelIndex idx = q->sourceModel()->index(rowCount - 1, column, parent); 0557 while (q->sourceModel()->hasChildren(idx)) 0558 { 0559 Q_ASSERT(q->sourceModel()->rowCount(idx) > 0); 0560 idx = q->sourceModel()->index(q->sourceModel()->rowCount(idx) - 1, column, idx); 0561 } 0562 // The last item in the list is getting a sibling below it. 0563 proxyStart = q->mapFromSource(idx).row() + 1; 0564 } 0565 const int proxyEnd = proxyStart + (end - start); 0566 0567 m_insertPair = qMakePair(proxyStart, proxyEnd); 0568 q->beginInsertRows(QModelIndex(), proxyStart, proxyEnd); 0569 } 0570 0571 void KDescendantsProxyModelPrivate::sourceRowsInserted(const QModelIndex &parent, int start, int end) 0572 { 0573 Q_Q(KDescendantsProxyModel); 0574 0575 Q_ASSERT(q->sourceModel()->index(start, 0, parent).isValid()); 0576 0577 const int rowCount = q->sourceModel()->rowCount(parent); 0578 Q_ASSERT(rowCount > 0); 0579 0580 const int difference = end - start + 1; 0581 0582 if (rowCount == difference) 0583 { 0584 // @p parent was not a parent before. 0585 m_pendingParents.append(parent); 0586 scheduleProcessPendingParents(); 0587 return; 0588 } 0589 0590 const int proxyStart = m_insertPair.first; 0591 0592 Q_ASSERT(proxyStart >= 0); 0593 0594 updateInternalIndexes(proxyStart, difference); 0595 0596 if (rowCount - 1 == end) 0597 { 0598 // The previously last row (the mapped one) is no longer the last. 0599 // For example, 0600 0601 // - A - A 0 0602 // - - B - B 1 0603 // - - C - C 2 0604 // - - - D - D 3 0605 // - - - E -> - E 4 0606 // - - F - F 5 0607 // - - G -> - G 6 0608 // - H - H 7 0609 // - I -> - I 8 0610 0611 // As last children, E, F and G have mappings. 0612 // Consider that 'J' is appended to the children of 'C', below 'E'. 0613 0614 // - A - A 0 0615 // - - B - B 1 0616 // - - C - C 2 0617 // - - - D - D 3 0618 // - - - E -> - E 4 0619 // - - - J - ??? 5 0620 // - - F - F 6 0621 // - - G -> - G 7 0622 // - H - H 8 0623 // - I -> - I 9 0624 0625 // The updateInternalIndexes call above will have updated the F and G mappings correctly because proxyStart is 5. 0626 // That means that E -> 4 was not affected by the updateInternalIndexes call. 0627 // Now the mapping for E -> 4 needs to be updated so that it's a mapping for J -> 5. 0628 0629 Q_ASSERT(!m_mapping.isEmpty()); 0630 static const int column = 0; 0631 const QModelIndex oldIndex = q->sourceModel()->index(rowCount - 1 - difference, column, parent); 0632 Q_ASSERT(m_mapping.leftContains(oldIndex)); 0633 0634 const QModelIndex newIndex = q->sourceModel()->index(rowCount - 1, column, parent); 0635 0636 QModelIndex indexAbove = oldIndex; 0637 0638 if (start > 0) { 0639 // If we have something like this: 0640 // 0641 // - A 0642 // - - B 0643 // - - C 0644 // 0645 // and we then insert D as a sibling of A below it, we need to remove the mapping for A, 0646 // and the row number used for D must take into account the descendants of A. 0647 0648 while (q->sourceModel()->hasChildren(indexAbove)) { 0649 Q_ASSERT(q->sourceModel()->rowCount(indexAbove) > 0); 0650 indexAbove = q->sourceModel()->index(q->sourceModel()->rowCount(indexAbove) - 1, column, indexAbove); 0651 } 0652 Q_ASSERT(q->sourceModel()->rowCount(indexAbove) == 0); 0653 } 0654 0655 Q_ASSERT(m_mapping.leftContains(indexAbove)); 0656 0657 const int newProxyRow = m_mapping.leftToRight(indexAbove) + difference; 0658 0659 // oldIndex is E in the source. proxyRow is 4. 0660 m_mapping.removeLeft(oldIndex); 0661 0662 // newIndex is J. (proxyRow + difference) is 5. 0663 m_mapping.insert(newIndex, newProxyRow); 0664 } 0665 0666 for (int row = start; row <= end; ++row) 0667 { 0668 static const int column = 0; 0669 const QModelIndex idx = q->sourceModel()->index(row, column, parent); 0670 Q_ASSERT(idx.isValid()); 0671 if (q->sourceModel()->hasChildren(idx)) 0672 { 0673 Q_ASSERT(q->sourceModel()->rowCount(idx) > 0); 0674 m_pendingParents.append(idx); 0675 } 0676 } 0677 0678 m_rowCount += difference; 0679 0680 q->endInsertRows(); 0681 scheduleProcessPendingParents(); 0682 } 0683 0684 void KDescendantsProxyModelPrivate::sourceRowsAboutToBeRemoved(const QModelIndex &parent, int start, int end) 0685 { 0686 Q_Q(KDescendantsProxyModel); 0687 0688 const int proxyStart = q->mapFromSource(q->sourceModel()->index(start, 0, parent)).row(); 0689 0690 static const int column = 0; 0691 QModelIndex idx = q->sourceModel()->index(end, column, parent); 0692 while (q->sourceModel()->hasChildren(idx)) 0693 { 0694 Q_ASSERT(q->sourceModel()->rowCount(idx) > 0); 0695 idx = q->sourceModel()->index(q->sourceModel()->rowCount(idx) - 1, column, idx); 0696 } 0697 const int proxyEnd = q->mapFromSource(idx).row(); 0698 0699 m_removePair = qMakePair(proxyStart, proxyEnd); 0700 0701 q->beginRemoveRows(QModelIndex(), proxyStart, proxyEnd); 0702 } 0703 0704 static QModelIndex getFirstDeepest(QAbstractItemModel *model, const QModelIndex &parent, int *count) { 0705 static const int column = 0; 0706 Q_ASSERT(model->hasChildren(parent)); 0707 Q_ASSERT(model->rowCount(parent) > 0); 0708 for (int row = 0; row < model->rowCount(parent); ++row) { 0709 (*count)++; 0710 const QModelIndex child = model->index(row, column, parent); 0711 Q_ASSERT(child.isValid()); 0712 if (model->hasChildren(child)) 0713 return getFirstDeepest(model, child, count); 0714 } 0715 return model->index(model->rowCount(parent) - 1, column, parent); 0716 } 0717 0718 void KDescendantsProxyModelPrivate::sourceRowsRemoved(const QModelIndex &parent, int start, int end) 0719 { 0720 Q_Q(KDescendantsProxyModel); 0721 Q_UNUSED(end) 0722 0723 const int rowCount = q->sourceModel()->rowCount(parent); 0724 0725 0726 const int proxyStart = m_removePair.first; 0727 const int proxyEnd = m_removePair.second; 0728 0729 const int difference = proxyEnd - proxyStart + 1; 0730 { 0731 Mapping::right_iterator it = m_mapping.rightLowerBound(proxyStart); 0732 const Mapping::right_iterator endIt = m_mapping.rightUpperBound(proxyEnd); 0733 0734 if (endIt != m_mapping.rightEnd()) 0735 while (it != endIt) 0736 it = m_mapping.eraseRight(it); 0737 else 0738 while (it != m_mapping.rightUpperBound(proxyEnd)) 0739 it = m_mapping.eraseRight(it); 0740 } 0741 0742 m_removePair = qMakePair(-1, -1); 0743 m_rowCount -= difference; 0744 Q_ASSERT(m_rowCount >= 0); 0745 0746 updateInternalIndexes(proxyStart, -1 * difference); 0747 0748 if (rowCount != start || rowCount == 0) { 0749 q->endRemoveRows(); 0750 return; 0751 } 0752 0753 static const int column = 0; 0754 const QModelIndex newEnd = q->sourceModel()->index(rowCount - 1, column, parent); 0755 Q_ASSERT(newEnd.isValid()); 0756 0757 if (m_mapping.isEmpty()) { 0758 m_mapping.insert(newEnd, newEnd.row()); 0759 q->endRemoveRows(); 0760 return; 0761 } 0762 if (q->sourceModel()->hasChildren(newEnd)) { 0763 int count = 0; 0764 const QModelIndex firstDeepest = getFirstDeepest(q->sourceModel(), newEnd, &count); 0765 Q_ASSERT(firstDeepest.isValid()); 0766 const int firstDeepestProxy = m_mapping.leftToRight(firstDeepest); 0767 0768 m_mapping.insert(newEnd, firstDeepestProxy - count); 0769 q->endRemoveRows(); 0770 return; 0771 } 0772 Mapping::right_iterator lowerBound = m_mapping.rightLowerBound(proxyStart); 0773 if (lowerBound == m_mapping.rightEnd()) { 0774 int proxyRow = (lowerBound - 1).key(); 0775 0776 for (int row = newEnd.row(); row >= 0; --row ) { 0777 const QModelIndex newEndSibling = q->sourceModel()->index(row, column, parent); 0778 if (!q->sourceModel()->hasChildren(newEndSibling)) { 0779 ++proxyRow; 0780 } else { 0781 break; 0782 } 0783 } 0784 m_mapping.insert(newEnd, proxyRow); 0785 q->endRemoveRows(); 0786 return; 0787 } else if (lowerBound == m_mapping.rightBegin()) { 0788 int proxyRow = rowCount - 1; 0789 QModelIndex trackedParent = parent; 0790 while (trackedParent.isValid()) { 0791 proxyRow += (trackedParent.row() + 1); 0792 trackedParent = trackedParent.parent(); 0793 } 0794 m_mapping.insert(newEnd, proxyRow); 0795 q->endRemoveRows(); 0796 return; 0797 } 0798 const Mapping::right_iterator boundAbove = lowerBound - 1; 0799 0800 QVector<QModelIndex> targetParents; 0801 targetParents.push_back(parent); 0802 { 0803 QModelIndex target = parent; 0804 int count = 0; 0805 while (target.isValid()) { 0806 if (target == boundAbove.value()) { 0807 m_mapping.insert(newEnd, count + boundAbove.key() + newEnd.row() + 1); 0808 q->endRemoveRows(); 0809 return; 0810 } 0811 count += (target.row() + 1); 0812 target = target.parent(); 0813 if (target.isValid()) 0814 targetParents.push_back(target); 0815 } 0816 } 0817 0818 QModelIndex boundParent = boundAbove.value().parent(); 0819 QModelIndex prevParent = boundParent; 0820 Q_ASSERT(boundParent.isValid()); 0821 while (boundParent.isValid()) { 0822 prevParent = boundParent; 0823 boundParent = boundParent.parent(); 0824 0825 if (targetParents.contains(prevParent)) 0826 break; 0827 0828 if (!m_mapping.leftContains(prevParent)) 0829 break; 0830 0831 if (m_mapping.leftToRight(prevParent) > boundAbove.key()) 0832 break; 0833 } 0834 0835 QModelIndex trackedParent = parent; 0836 0837 int proxyRow = boundAbove.key(); 0838 0839 Q_ASSERT(prevParent.isValid()); 0840 proxyRow -= prevParent.row(); 0841 while (trackedParent != boundParent) { 0842 proxyRow += (trackedParent.row() + 1); 0843 trackedParent = trackedParent.parent(); 0844 } 0845 m_mapping.insert(newEnd, proxyRow + newEnd.row()); 0846 q->endRemoveRows(); 0847 } 0848 0849 void KDescendantsProxyModelPrivate::sourceRowsAboutToBeMoved(const QModelIndex &srcParent, int srcStart, int srcEnd, const QModelIndex &destParent, int destStart) 0850 { 0851 Q_UNUSED(srcParent) 0852 Q_UNUSED(srcStart) 0853 Q_UNUSED(srcEnd) 0854 Q_UNUSED(destParent) 0855 Q_UNUSED(destStart) 0856 Q_Q(KDescendantsProxyModel); 0857 q->beginResetModel(); 0858 } 0859 0860 void KDescendantsProxyModelPrivate::sourceRowsMoved(const QModelIndex &srcParent, int srcStart, int srcEnd, const QModelIndex &destParent, int destStart) 0861 { 0862 Q_UNUSED(srcParent) 0863 Q_UNUSED(srcStart) 0864 Q_UNUSED(srcEnd) 0865 Q_UNUSED(destParent) 0866 Q_UNUSED(destStart) 0867 Q_Q(KDescendantsProxyModel); 0868 resetInternalData(); 0869 q->endResetModel(); 0870 } 0871 0872 void KDescendantsProxyModelPrivate::sourceModelAboutToBeReset() 0873 { 0874 Q_Q(KDescendantsProxyModel); 0875 q->beginResetModel(); 0876 } 0877 0878 void KDescendantsProxyModelPrivate::sourceModelReset() 0879 { 0880 Q_Q(KDescendantsProxyModel); 0881 resetInternalData(); 0882 if (q->sourceModel()->hasChildren()) 0883 { 0884 Q_ASSERT(q->sourceModel()->rowCount() > 0); 0885 m_pendingParents.append(QModelIndex()); 0886 scheduleProcessPendingParents(); 0887 } 0888 q->endResetModel(); 0889 } 0890 0891 void KDescendantsProxyModelPrivate::sourceLayoutAboutToBeChanged() 0892 { 0893 Q_Q(KDescendantsProxyModel); 0894 0895 if (m_ignoreNextLayoutChanged) { 0896 m_ignoreNextLayoutChanged = false; 0897 return; 0898 } 0899 0900 if (m_mapping.isEmpty()) 0901 return; 0902 0903 QPersistentModelIndex srcPersistentIndex; 0904 foreach(const QPersistentModelIndex &proxyPersistentIndex, q->persistentIndexList()) { 0905 m_proxyIndexes << proxyPersistentIndex; 0906 Q_ASSERT(proxyPersistentIndex.isValid()); 0907 srcPersistentIndex = q->mapToSource(proxyPersistentIndex); 0908 Q_ASSERT(srcPersistentIndex.isValid()); 0909 m_layoutChangePersistentIndexes << srcPersistentIndex; 0910 } 0911 0912 q->layoutAboutToBeChanged(); 0913 } 0914 0915 void KDescendantsProxyModelPrivate::sourceLayoutChanged() 0916 { 0917 Q_Q(KDescendantsProxyModel); 0918 0919 if (m_ignoreNextLayoutAboutToBeChanged) { 0920 m_ignoreNextLayoutAboutToBeChanged = false; 0921 return; 0922 } 0923 0924 if (m_mapping.isEmpty()) 0925 return; 0926 0927 m_rowCount = 0; 0928 0929 synchronousMappingRefresh(); 0930 0931 for (int i = 0; i < m_proxyIndexes.size(); ++i) { 0932 q->changePersistentIndex(m_proxyIndexes.at(i), q->mapFromSource(m_layoutChangePersistentIndexes.at(i))); 0933 } 0934 0935 m_layoutChangePersistentIndexes.clear(); 0936 m_proxyIndexes.clear(); 0937 0938 q->layoutChanged(); 0939 } 0940 0941 void KDescendantsProxyModelPrivate::sourceDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight) 0942 { 0943 Q_Q(KDescendantsProxyModel); 0944 Q_ASSERT(topLeft.model() == q->sourceModel()); 0945 Q_ASSERT(bottomRight.model() == q->sourceModel()); 0946 0947 const int topRow = topLeft.row(); 0948 const int bottomRow = bottomRight.row(); 0949 0950 for(int i = topRow; i <= bottomRow; ++i) 0951 { 0952 const QModelIndex sourceTopLeft = q->sourceModel()->index(i, topLeft.column(), topLeft.parent()); 0953 Q_ASSERT(sourceTopLeft.isValid()); 0954 const QModelIndex proxyTopLeft = q->mapFromSource(sourceTopLeft); 0955 // TODO. If an index does not have any descendants, then we can emit in blocks of rows. 0956 // As it is we emit once for each row. 0957 const QModelIndex sourceBottomRight = q->sourceModel()->index(i, bottomRight.column(), bottomRight.parent()); 0958 Q_ASSERT(sourceBottomRight.isValid()); 0959 const QModelIndex proxyBottomRight = q->mapFromSource(sourceBottomRight); 0960 Q_ASSERT(proxyTopLeft.isValid()); 0961 Q_ASSERT(proxyBottomRight.isValid()); 0962 emit q->dataChanged(proxyTopLeft, proxyBottomRight); 0963 } 0964 } 0965 0966 void KDescendantsProxyModelPrivate::sourceModelDestroyed() 0967 { 0968 resetInternalData(); 0969 } 0970 0971 QMimeData* KDescendantsProxyModel::mimeData( const QModelIndexList & indexes ) const 0972 { 0973 if (!sourceModel()) 0974 return QAbstractProxyModel::mimeData(indexes); 0975 Q_ASSERT(sourceModel()); 0976 QModelIndexList sourceIndexes; 0977 foreach(const QModelIndex& index, indexes) 0978 sourceIndexes << mapToSource(index); 0979 return sourceModel()->mimeData(sourceIndexes); 0980 } 0981 0982 QStringList KDescendantsProxyModel::mimeTypes() const 0983 { 0984 if (!sourceModel()) 0985 return QAbstractProxyModel::mimeTypes(); 0986 Q_ASSERT(sourceModel()); 0987 return sourceModel()->mimeTypes(); 0988 } 0989 0990 Qt::DropActions KDescendantsProxyModel::supportedDropActions() const 0991 { 0992 if (!sourceModel()) 0993 return QAbstractProxyModel::supportedDropActions(); 0994 return sourceModel()->supportedDropActions(); 0995 } 0996 0997 void KDescendantsProxyModel::proxySetRoleNames(const QHash<int, QByteArray> &roleNames) 0998 { 0999 Q_D(KDescendantsProxyModel); 1000 d->m_roleNames = roleNames; 1001 } 1002 1003 QHash<int,QByteArray> KDescendantsProxyModel::roleNames() const 1004 { 1005 Q_D(const KDescendantsProxyModel); 1006 return d->m_roleNames; 1007 } 1008 1009 #include "moc_kdescendantsproxymodel.cpp"