tkdescendantsproxymodel.cpp - sailfish-safe - Sailfish frontend for safe(1)
 (HTM) git clone git://git.z3bra.org/sailfish-safe.git
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) LICENSE
       ---
       tkdescendantsproxymodel.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"