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"