Branch 'kolab/integration/4.13.0' - 6 commits - akonadi/asyncselectionhandler.cpp akonadi/calendar akonadi/collectionfetchjob.cpp akonadi/collectionfetchscope.cpp akonadi/collectionfetchscope.h akonadi/entitytreemodel.h akonadi/entitytreemodel_p.cpp akonadi/entitytreemodel_p.h akonadi/protocolhelper.cpp akonadi/tests

Christian Mollekopf mollekopf at kolabsys.com
Mon Aug 18 10:23:33 CEST 2014


 akonadi/asyncselectionhandler.cpp     |    6 ++
 akonadi/calendar/etmcalendar.cpp      |   21 ++++++++--
 akonadi/collectionfetchjob.cpp        |   54 ++++++++++++++++++--------
 akonadi/collectionfetchscope.cpp      |   58 ++++++++++++++++++++++++----
 akonadi/collectionfetchscope.h        |   56 +++++++++++++++++++++++++--
 akonadi/entitytreemodel.h             |    1 
 akonadi/entitytreemodel_p.cpp         |   70 ++++++++++++++++------------------
 akonadi/entitytreemodel_p.h           |    2 
 akonadi/protocolhelper.cpp            |    8 ++-
 akonadi/tests/collectionjobtest.cpp   |    3 -
 akonadi/tests/entitytreemodeltest.cpp |    2 
 11 files changed, 208 insertions(+), 73 deletions(-)

New commits:
commit c05631fbbcb0011dae400262fea73aff8db2b6b0
Author: Christian Mollekopf <chrigi_1 at fastmail.fm>
Date:   Mon Aug 18 10:23:14 2014 +0200

    Ancestor collectionfetchscope

diff --git a/akonadi/collectionfetchjob.cpp b/akonadi/collectionfetchjob.cpp
index 4223c90..c2c1261 100644
--- a/akonadi/collectionfetchjob.cpp
+++ b/akonadi/collectionfetchjob.cpp
@@ -288,24 +288,46 @@ void CollectionFetchJob::doStart()
     }
     if (d->mScope.ancestorRetrieval() != CollectionFetchScope::None) {
         options.append("ANCESTORS");
-        switch (d->mScope.ancestorRetrieval()) {
-        case CollectionFetchScope::None:
-            options.append("0");
-            break;
-        case CollectionFetchScope::Parent:
-            options.append("1");
-            break;
-        case CollectionFetchScope::All:
-            options.append("INF");
-            break;
-        default:
-            Q_ASSERT(false);
+
+        if (d->mScope.ancestorFetchScope().fetchIdOnly()) {
+            switch (d->mScope.ancestorRetrieval()) {
+            case CollectionFetchScope::None:
+                options.append("0");
+                break;
+            case CollectionFetchScope::Parent:
+                options.append("1");
+                break;
+            case CollectionFetchScope::All:
+                options.append("INF");
+                break;
+            default:
+                Q_ASSERT(false);
+            }
+        } else {
+            QByteArray ancestorFetchScope = "(";
+            ancestorFetchScope += "DEPTH ";
+            switch (d->mScope.ancestorRetrieval()) {
+            case CollectionFetchScope::None:
+                ancestorFetchScope += "0 ";
+                break;
+            case CollectionFetchScope::Parent:
+                ancestorFetchScope += "1 ";
+                break;
+            case CollectionFetchScope::All:
+                ancestorFetchScope += "INF ";
+                break;
+            default:
+                Q_ASSERT(false);
+            }
+            ancestorFetchScope += "NAME ";
+            ancestorFetchScope += "REMOTEID ";
+            Q_FOREACH (const QByteArray &ancestorAttribute, d->mScope.ancestorFetchScope().attributes()) {
+                ancestorFetchScope += ancestorAttribute + " ";
+            }
+            ancestorFetchScope += ")";
+            options.append(ancestorFetchScope);
         }
     }
-    Q_FOREACH (const QByteArray &ancestorAttributes, d->mScope.ancestorAttributes()) {
-        options.append("ANCESTORATTR");
-        options.append(ancestorAttributes);
-    }
 
     command += ImapParser::join(filter, " ") + ") (" + ImapParser::join(options, " ") + ")\n";
     d->writeData(command);
diff --git a/akonadi/collectionfetchscope.cpp b/akonadi/collectionfetchscope.cpp
index 2b71309..560b31d 100644
--- a/akonadi/collectionfetchscope.cpp
+++ b/akonadi/collectionfetchscope.cpp
@@ -32,6 +32,8 @@ public:
         : ancestorDepth(CollectionFetchScope::None)
         , statistics(false)
         , listFilter(CollectionFetchScope::Enabled)
+        , fetchAllAttributes(false)
+        , fetchIdOnly(true)
     {
     }
 
@@ -43,7 +45,15 @@ public:
         ancestorDepth = other.ancestorDepth;
         statistics = other.statistics;
         listFilter = other.listFilter;
-        ancestorAttributes = other.ancestorAttributes;
+        attributes = other.attributes;
+        if (!ancestorFetchScope && other.ancestorFetchScope) {
+            ancestorFetchScope.reset(new CollectionFetchScope());
+            *ancestorFetchScope = *other.ancestorFetchScope;
+        } else if (ancestorFetchScope && !other.ancestorFetchScope) {
+            ancestorFetchScope.reset(0);
+        }
+        fetchAllAttributes = other.fetchAllAttributes;
+        fetchIdOnly = other.fetchIdOnly;
     }
 
 public:
@@ -52,7 +62,10 @@ public:
     CollectionFetchScope::AncestorRetrieval ancestorDepth;
     bool statistics;
     CollectionFetchScope::ListFilter listFilter;
-    QSet<QByteArray> ancestorAttributes;
+    QSet<QByteArray> attributes;
+    QScopedPointer<CollectionFetchScope> ancestorFetchScope;
+    bool fetchAllAttributes;
+    bool fetchIdOnly;
 };
 
 CollectionFetchScope::CollectionFetchScope()
@@ -152,19 +165,50 @@ void CollectionFetchScope::setListFilter(CollectionFetchScope::ListFilter listFi
     d->listFilter = listFilter;
 }
 
-QSet<QByteArray> CollectionFetchScope::ancestorAttributes() const
+QSet<QByteArray> CollectionFetchScope::attributes() const
 {
-    return d->ancestorAttributes;
+    return d->attributes;
 }
 
-void CollectionFetchScope::fetchAncestorAttribute(const QByteArray &type, bool fetch)
+void CollectionFetchScope::fetchAttribute(const QByteArray &type, bool fetch)
 {
     if (fetch) {
-        d->ancestorAttributes.insert(type);
+        d->attributes.insert(type);
     } else {
-        d->ancestorAttributes.remove(type);
+        d->attributes.remove(type);
     }
 }
 
+void CollectionFetchScope::setFetchIdOnly(bool fetchIdOnly)
+{
+    d->fetchIdOnly = fetchIdOnly;
+}
+
+bool CollectionFetchScope::fetchIdOnly() const
+{
+    return d->fetchIdOnly;
+}
+
+void CollectionFetchScope::setAncestorFetchScope(const CollectionFetchScope &scope)
+{
+    *d->ancestorFetchScope = scope;
+}
+
+CollectionFetchScope CollectionFetchScope::ancestorFetchScope() const
+{
+    if (!d->ancestorFetchScope) {
+        return CollectionFetchScope();
+    }
+    return *d->ancestorFetchScope;
+}
+
+CollectionFetchScope &CollectionFetchScope::ancestorFetchScope()
+{
+    if (!d->ancestorFetchScope) {
+        d->ancestorFetchScope.reset(new CollectionFetchScope());
+    }
+    return *d->ancestorFetchScope;
+}
+
 
 }
diff --git a/akonadi/collectionfetchscope.h b/akonadi/collectionfetchscope.h
index 5acd591..7ab7781 100644
--- a/akonadi/collectionfetchscope.h
+++ b/akonadi/collectionfetchscope.h
@@ -218,13 +218,44 @@ public:
     AncestorRetrieval ancestorRetrieval() const;
 
     /**
+     * Sets the fetch scope for ancestor retrieval.
+     *
+     * @see setAncestorRetrieval()
+     */
+    void setAncestorFetchScope(const CollectionFetchScope &scope);
+
+    /**
+     * Returns the fetch scope for ancestor retrieval.
+     */
+    CollectionFetchScope ancestorFetchScope() const;
+
+    /**
+     * Returns the fetch scope for ancestor retrieval.
+     */
+    CollectionFetchScope &ancestorFetchScope();
+
+    /**
+     * Sets wether all attributes should be retrieved (true by default).
+     * 
+     * This is currently only supported for ancestors.
+     */
+    void setFetchAllAttribute(bool fetchAll = true);
+
+    /**
+     * Returns wether all attributes should be retrieved (true by default).
+     * 
+     * This is currently only supported for ancestors.
+     */
+    bool fetchAllAttributes() const;
+
+    /**
      * Returns all explicitly fetched attributes.
      *
      * Undefined if fetchAllAttributes() returns true.
      *
      * @see fetchAttribute()
      */
-    QSet<QByteArray> ancestorAttributes() const;
+    QSet<QByteArray> attributes() const;
 
     /**
      * Sets whether the attribute of the given @p type should be fetched.
@@ -232,20 +263,37 @@ public:
      * @param type The attribute type to fetch.
      * @param fetch @c true if the attribute should be fetched, @c false otherwise.
      */
-    void fetchAncestorAttribute(const QByteArray &type, bool fetch = true);
+    void fetchAttribute(const QByteArray &type, bool fetch = true);
 
     /**
      * Sets whether the attribute of the requested type should be fetched.
      *
      * @param fetch @c true if the attribute should be fetched, @c false otherwise.
      */
-    template <typename T> inline void fetchAncestorAttribute(bool fetch = true)
+    template <typename T> inline void fetchAttribute(bool fetch = true)
     {
         T dummy;
-        fetchAncestorAttribute(dummy.type(), fetch);
+        fetchAttribute(dummy.type(), fetch);
     }
 
     /**
+     * Sets wether only the id or the complete tag should be fetched.
+     *
+     * The default is @c false.
+     *
+     * @since 4.15
+     */
+    void setFetchIdOnly(bool fetchIdOnly);
+
+    /**
+     * Sets wether only the id of the tags should be retieved or the complete tag.
+     *
+     * @see tagFetchScope()
+     * @since 4.15
+     */
+    bool fetchIdOnly() const;
+
+    /**
      * Returns @c true if there is nothing to fetch.
      */
     bool isEmpty() const;
diff --git a/akonadi/protocolhelper.cpp b/akonadi/protocolhelper.cpp
index 8aacdf5..c8e2f97 100644
--- a/akonadi/protocolhelper.cpp
+++ b/akonadi/protocolhelper.cpp
@@ -126,8 +126,12 @@ void ProtocolHelper::parseAncestors( const QByteArray &data, Entity *entity, int
       break;
     }
 
-    Akonadi::Collection parentCollection;
-    parseCollection( ImapParser::join(parentIds, " "), parentCollection, 0, false );
+    Akonadi::Collection parentCollection(uid);
+    if (parentIds[1].at(0) == '(') {
+        parseCollection( ImapParser::join(parentIds, " "), parentCollection, 0, false );
+    } else {
+        parentCollection.setRemoteId(QString::fromLatin1(parentIds[1]));
+    }
     current->setParentCollection(parentCollection);
 
     current = &current->parentCollection();
diff --git a/akonadi/tests/collectionjobtest.cpp b/akonadi/tests/collectionjobtest.cpp
index b6cb398..7cb0ffb 100644
--- a/akonadi/tests/collectionjobtest.cpp
+++ b/akonadi/tests/collectionjobtest.cpp
@@ -786,7 +786,8 @@ void CollectionJobTest::testAncestorAttributeRetrieval()
 
     CollectionFetchJob *job = new CollectionFetchJob(create->collection(), CollectionFetchJob::Base);
     job->fetchScope().setAncestorRetrieval(CollectionFetchScope::All);
-    job->fetchScope().fetchAncestorAttribute<TestAttribute>(CollectionFetchScope::All);
+    job->fetchScope().ancestorFetchScope().setFetchIdOnly(false);
+    job->fetchScope().ancestorFetchScope().fetchAttribute<TestAttribute>();
     AKVERIFYEXEC(job);
     Akonadi::Collection result = job->collections().first();
     QCOMPARE(result.parentCollection().hasAttribute<TestAttribute>(), true);


commit d80b9966f37da29069e4d572b115ac2dbc2e8488
Author: Christian Mollekopf <chrigi_1 at fastmail.fm>
Date:   Mon Aug 18 10:20:26 2014 +0200

    Abort on invalid child.

diff --git a/akonadi/asyncselectionhandler.cpp b/akonadi/asyncselectionhandler.cpp
index 52c7ee9..8b23577 100644
--- a/akonadi/asyncselectionhandler.cpp
+++ b/akonadi/asyncselectionhandler.cpp
@@ -57,6 +57,12 @@ bool AsyncSelectionHandler::scanSubTree(const QModelIndex &index, bool searchFor
 
     for (int row = 0; row < mModel->rowCount(index); ++row) {
         const QModelIndex childIndex = mModel->index(row, 0, index);
+        //This should not normally happen, but if it does we end up in an endless loop
+        if (!childIndex.isValid()) {
+            kWarning() << "Invalid child detected: " << index.data().toString();
+            Q_ASSERT(false);
+            return false;
+        }
         if (scanSubTree(childIndex, searchForItem)) {
             return true;
         }


commit 7365844bd7223d38f26b1e36aa966a4aca1388fe
Author: Christian Mollekopf <chrigi_1 at fastmail.fm>
Date:   Wed Aug 13 01:59:50 2014 +0200

    Workaround for broken filter model.
    
    The filter should react to the mimetype change and insert the collectoin,
    but it doesn't. We don't actually require the mimetypefiltering and this
    at least works.

diff --git a/akonadi/calendar/etmcalendar.cpp b/akonadi/calendar/etmcalendar.cpp
index 9bb16d4..194091c 100644
--- a/akonadi/calendar/etmcalendar.cpp
+++ b/akonadi/calendar/etmcalendar.cpp
@@ -39,9 +39,25 @@
 #include <QItemSelectionModel>
 #include <QTreeView>
 
+#include <recursivecollectionfilterproxymodel.h>
+#include <mimetypechecker.h>
+
 using namespace Akonadi;
 using namespace KCalCore;
 
+class CollectionFilter : public QSortFilterProxyModel
+{
+public:
+    explicit CollectionFilter(QObject *parent = 0): QSortFilterProxyModel (parent) {};
+
+    virtual bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const
+    {
+        const Collection collection = sourceModel()->index(sourceRow, 0, sourceParent).data(Akonadi::EntityTreeModel::CollectionRole).value<Akonadi::Collection>();
+        return collection.isValid();
+    }
+
+};
+
 //TODO: implement batchAdding
 
 ETMCalendarPrivate::ETMCalendarPrivate(ETMCalendar *qq) : CalendarBasePrivate(qq)
@@ -144,12 +160,9 @@ void ETMCalendarPrivate::setupFilteredETM()
     columnFilterProxy->setVisibleColumn(CalendarModel::CollectionTitle);
     columnFilterProxy->setObjectName("Remove columns");
 
-    mCollectionProxyModel = new Akonadi::CollectionFilterProxyModel(this);
+    CollectionFilter *mCollectionProxyModel = new CollectionFilter(this);
     mCollectionProxyModel->setObjectName("Only show collections");
     mCollectionProxyModel->setDynamicSortFilter(true);
-    mCollectionProxyModel->addMimeTypeFilter(QString::fromLatin1("text/calendar"));
-    mCollectionProxyModel->setExcludeVirtualCollections(true);
-    mCollectionProxyModel->setSortCaseSensitivity(Qt::CaseInsensitive);
     mCollectionProxyModel->setSourceModel(columnFilterProxy);
 
     // Keep track of selected items.


commit 45bfa5dc82c177222f896aaf22b4ae5410298b74
Author: Christian Mollekopf <chrigi_1 at fastmail.fm>
Date:   Thu Aug 14 11:45:40 2014 +0200

    ETM: Keep track of collectionfetchjobs and only emit collectionTreeFetched once all are done.
    
    Because we need at least two fetch jobs when monitoring collectoins (base + recursive),
    the signal was emitted to early, resulting in test continuing before the model
    was fully populated. Additionally this allowed to remove another extra
    codepath.

diff --git a/akonadi/entitytreemodel.h b/akonadi/entitytreemodel.h
index a58668e..1e2a544 100644
--- a/akonadi/entitytreemodel.h
+++ b/akonadi/entitytreemodel.h
@@ -725,7 +725,6 @@ private:
     Q_PRIVATE_SLOT(d_func(), void rootFetchJobDone(KJob *job))
     Q_PRIVATE_SLOT(d_func(), void pasteJobDone(KJob *job))
     Q_PRIVATE_SLOT(d_func(), void updateJobDone(KJob *job))
-    Q_PRIVATE_SLOT(d_func(), void finalCollectionFetchJobDone(KJob *job))
 
     Q_PRIVATE_SLOT(d_func(), void itemsFetched(Akonadi::Item::List))
     Q_PRIVATE_SLOT(d_func(), void collectionsFetched(Akonadi::Collection::List))
diff --git a/akonadi/entitytreemodel_p.cpp b/akonadi/entitytreemodel_p.cpp
index 4eb258b..e45403c 100644
--- a/akonadi/entitytreemodel_p.cpp
+++ b/akonadi/entitytreemodel_p.cpp
@@ -288,6 +288,7 @@ void EntityTreeModelPrivate::fetchCollections(Akonadi::CollectionFetchJob *job)
 
     job->fetchScope().setListFilter(m_listFilter);
     job->fetchScope().setContentMimeTypes(m_monitor->mimeTypesMonitored());
+    m_pendingCollectionFetchJobs.insert(static_cast<KJob*>(job));
 
     if (m_collectionFetchStrategy == EntityTreeModel::InvisibleCollectionFetch) {
         q->connect(job, SIGNAL(collectionsReceived(Akonadi::Collection::List)),
@@ -297,8 +298,6 @@ void EntityTreeModelPrivate::fetchCollections(Akonadi::CollectionFetchJob *job)
         job->fetchScope().setAncestorRetrieval(Akonadi::CollectionFetchScope::All);
         q->connect(job, SIGNAL(collectionsReceived(Akonadi::Collection::List)),
                     q, SLOT(collectionsFetched(Akonadi::Collection::List)));
-        q->connect(job, SIGNAL(result(KJob*)),
-                    q, SLOT(finalCollectionFetchJobDone(KJob*)));
     }
     q->connect(job, SIGNAL(result(KJob*)),
                 q, SLOT(collectionFetchJobDone(KJob*)));
@@ -1355,12 +1354,18 @@ void EntityTreeModelPrivate::monitoredItemUnlinked(const Akonadi::Item &item, co
 
 void EntityTreeModelPrivate::collectionFetchJobDone(KJob *job)
 {
+    m_pendingCollectionFetchJobs.remove(job);
     CollectionFetchJob *cJob = static_cast<CollectionFetchJob *>(job);
     if (job->error()) {
         kWarning() << "Job error: " << job->errorString() << "for collection:" << cJob->collections() << endl;
         return;
     }
 
+    if (!m_collectionTreeFetched && m_pendingCollectionFetchJobs.isEmpty()) {
+        m_collectionTreeFetched = true;
+        emit q_ptr->collectionTreeFetched(m_collections.values());
+    }
+
 #ifdef DBG_TRACK_JOB_TIMES
     kDebug() << "Fetch job took " << jobTimeTracker.take(job).elapsed() << "msec";
     kDebug() << "was collection fetch job: collections:" << cJob->collections().size();
@@ -1544,21 +1549,6 @@ void EntityTreeModelPrivate::startFirstListJob()
     }
 }
 
-void EntityTreeModelPrivate::finalCollectionFetchJobDone(KJob *job)
-{
-    if (job->error()) {
-        kWarning() << job->errorString();
-        return;
-    }
-
-    Akonadi::CollectionFetchJob *fetchJob = static_cast<Akonadi::CollectionFetchJob*>(job);
-    //Can happen when monitoring resources
-    if (!m_collectionTreeFetched) {
-        m_collectionTreeFetched = true;
-        emit q_ptr->collectionTreeFetched(fetchJob->collections());
-    }
-}
-
 void EntityTreeModelPrivate::fetchTopLevelCollections() const
 {
     Q_Q(const EntityTreeModel);
@@ -1866,6 +1856,9 @@ void EntityTreeModelPrivate::endResetModel()
     m_collectionsWithoutItems.clear();
     m_populatedCols.clear();
     m_items.clear();
+    m_pendingCollectionFetchJobs.clear();
+    m_pendingCollectionRetrieveJobs.clear();
+    m_collectionTreeFetched = false;
 
     foreach (const QList<Node *> &list, m_childEntities) {
         qDeleteAll(list);
diff --git a/akonadi/entitytreemodel_p.h b/akonadi/entitytreemodel_p.h
index ba98935..39f4e1c 100644
--- a/akonadi/entitytreemodel_p.h
+++ b/akonadi/entitytreemodel_p.h
@@ -136,6 +136,7 @@ public:
     QVector<Entity::Id> m_pendingCutItems;
     QVector<Entity::Id> m_pendingCutCollections;
     mutable QSet<Collection::Id> m_pendingCollectionRetrieveJobs;
+    mutable QSet<KJob*> m_pendingCollectionFetchJobs;
 
     ChangeRecorder *m_monitor;
     Collection m_rootCollection;
@@ -169,7 +170,6 @@ public:
     void rootFetchJobDone(KJob *job);
     void collectionFetchJobDone(KJob *job);
     void itemFetchJobDone(KJob *job);
-    void finalCollectionFetchJobDone(KJob *job);
     void updateJobDone(KJob *job);
     void pasteJobDone(KJob *job);
 


commit c091c7479e4c8703f29285448089f14e95b01446
Author: Christian Mollekopf <chrigi_1 at fastmail.fm>
Date:   Wed Aug 13 09:00:38 2014 +0200

    ETM: Whenever we insert a new collection we need to populate it.

diff --git a/akonadi/entitytreemodel_p.cpp b/akonadi/entitytreemodel_p.cpp
index ee22660..4eb258b 100644
--- a/akonadi/entitytreemodel_p.cpp
+++ b/akonadi/entitytreemodel_p.cpp
@@ -872,10 +872,16 @@ void EntityTreeModelPrivate::monitoredCollectionAdded(const Akonadi::Collection
         if (collection != Collection::root()) {
             retrieveAncestors(collection);
         }
+        if (m_itemPopulation == EntityTreeModel::ImmediatePopulation) {
+            fetchItems(collection);
+        }
         return;
     }
 
     insertCollection(collection, parent);
+    if (m_itemPopulation == EntityTreeModel::ImmediatePopulation) {
+        fetchItems(collection);
+    }
 }
 
 void EntityTreeModelPrivate::monitoredCollectionRemoved(const Akonadi::Collection &collection)
diff --git a/akonadi/tests/entitytreemodeltest.cpp b/akonadi/tests/entitytreemodeltest.cpp
index fc6e3be..bb93a36 100644
--- a/akonadi/tests/entitytreemodeltest.cpp
+++ b/akonadi/tests/entitytreemodeltest.cpp
@@ -325,6 +325,8 @@ void EntityTreeModelTest::testCollectionAdded()
 
   expectedSignals << getExpectedSignal( RowsAboutToBeInserted, 0, 0, parentCollection, QVariantList() << addedCollection );
   expectedSignals << getExpectedSignal( RowsInserted, 0, 0, parentCollection, QVariantList() << addedCollection );
+  //The data changed signal comes from the item fetch job that is triggered because we have ImmediatePopulation enabled
+  expectedSignals << getExpectedSignal( DataChanged, 0, 0, parentCollection, QVariantList() << addedCollection );
 
   m_modelSpy->setExpectedSignals( expectedSignals );
   serverData->processNotifications();


commit b68da55650880b0fd9666a4c3e325696cfb2ae07
Author: Christian Mollekopf <chrigi_1 at fastmail.fm>
Date:   Tue Aug 12 23:05:35 2014 +0200

    ETM: Fixed inserts.
    
    The previous code seems bogus. It's always one toplevel parent anyways as it seems.
    I introduced the previous code myself in 0dc0c06d74915.

diff --git a/akonadi/entitytreemodel_p.cpp b/akonadi/entitytreemodel_p.cpp
index 3a09ed9..ee22660 100644
--- a/akonadi/entitytreemodel_p.cpp
+++ b/akonadi/entitytreemodel_p.cpp
@@ -676,6 +676,11 @@ void EntityTreeModelPrivate::retrieveAncestors(const Akonadi::Collection &collec
         return;
     }
 
+    if (ancestors.isEmpty() && !insertBaseCollection) {
+        //Nothing to do, avoid emitting insert signals
+        return;
+    }
+
     if (!ancestors.isEmpty()) {
         // Fetch the real ancestors
         CollectionFetchJob *job = new CollectionFetchJob(ancestors, CollectionFetchJob::Base, m_session);
@@ -693,19 +698,10 @@ void EntityTreeModelPrivate::retrieveAncestors(const Akonadi::Collection &collec
     // Still prepending all collections for now.
     int row = 0;
 
+    // Although we insert several Collections here, we only need to notify though the model
+    // about the top-level one. The rest will be found auotmatically by the view.
+    q->beginInsertRows(parent, row, row);
 
-    if (insertBaseCollection) {
-        // Although we insert several Collections here, we only need to notify though the model
-        // about the top-level one. The rest will be found auotmatically by the view.
-        q->beginInsertRows(parent, row, row);
-        m_collections.insert(collection.id(), collection);
-        Node *node = new Node;
-        node->id = collection.id();
-        // Can't just use parentCollection because that doesn't necessarily refer to collection.
-        node->parent = collection.parentCollection().id();
-        node->type = Node::Collection;
-        m_childEntities[node->parent].prepend(node);
-    }
 
     Collection::List::const_iterator it = ancestors.constBegin();
     const Collection::List::const_iterator end = ancestors.constEnd();
@@ -713,10 +709,6 @@ void EntityTreeModelPrivate::retrieveAncestors(const Akonadi::Collection &collec
     for (; it != end; ++it) {
         const Collection ancestor = *it;
         Q_ASSERT(ancestor.parentCollection().isValid());
-        if (!insertBaseCollection) {
-            const QModelIndex ancestorParent = indexForCollection(ancestor.parentCollection());
-            q->beginInsertRows(ancestorParent, 0, 0);
-        }
         m_collections.insert(ancestor.id(), ancestor);
 
         Node *node = new Node;
@@ -724,14 +716,19 @@ void EntityTreeModelPrivate::retrieveAncestors(const Akonadi::Collection &collec
         node->parent = ancestor.parentCollection().id();
         node->type = Node::Collection;
         m_childEntities[node->parent].prepend(node);
-        if (!insertBaseCollection) {
-            q->endInsertRows();
-        }
     }
 
     if (insertBaseCollection) {
-        q->endInsertRows();
+        m_collections.insert(collection.id(), collection);
+        Node *node = new Node;
+        node->id = collection.id();
+        // Can't just use parentCollection because that doesn't necessarily refer to collection.
+        node->parent = collection.parentCollection().id();
+        node->type = Node::Collection;
+        m_childEntities[node->parent].prepend(node);
     }
+
+    q->endInsertRows();
 }
 
 void EntityTreeModelPrivate::ancestorsFetched(const Akonadi::Collection::List &collectionList)




More information about the commits mailing list