sailfish-safe

Sailfish frontend for safe(1)
git clone git://git.z3bra.org/sailfish-safe.git
Log | Files | Refs | README | LICENSE

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"