Branch 'kolab/integration/4.13.0' - 9 commits - resources/imap resources/kolab

Christian Mollekopf mollekopf at kolabsys.com
Wed Nov 12 14:06:18 CET 2014


 resources/imap/CMakeLists.txt                               |    1 
 resources/imap/collectionmetadatahelper.cpp                 |    7 
 resources/imap/imapresourcebase.cpp                         |    2 
 resources/imap/resourcestate.cpp                            |   69 -----
 resources/imap/resourcestate.h                              |    1 
 resources/imap/resourcestateinterface.h                     |    1 
 resources/imap/retrievecollectionmetadatatask.cpp           |    7 
 resources/imap/tests/dummyresourcestate.cpp                 |    5 
 resources/imap/tests/dummyresourcestate.h                   |    1 
 resources/imap/tests/testretrievecollectionmetadatatask.cpp |   12 -
 resources/imap/timestampattribute.cpp                       |   61 -----
 resources/imap/timestampattribute.h                         |   42 ---
 resources/kolab/kolabchangeitemsrelationstask.cpp           |   10 
 resources/kolab/kolabhelpers.cpp                            |   32 ++
 resources/kolab/kolabhelpers.h                              |    2 
 resources/kolab/kolabrelationresourcetask.cpp               |    2 
 resources/kolab/kolabresource.cpp                           |   10 
 resources/kolab/kolabresource.h                             |    1 
 resources/kolab/kolabretrievetagstask.cpp                   |  140 ++++++++----
 resources/kolab/kolabretrievetagstask.h                     |   23 +
 resources/kolab/tagchangehelper.cpp                         |   36 ---
 resources/kolab/tagchangehelper.h                           |    1 
 resources/kolab/tests/testchangeitemstagstask.cpp           |    4 
 resources/kolab/tests/testretrievetagstask.cpp              |    2 
 24 files changed, 190 insertions(+), 282 deletions(-)

New commits:
commit d8cb2db505aa7a7acc89d49dba758b0e26f53a57
Author: Christian Mollekopf <chrigi_1 at fastmail.fm>
Date:   Wed Nov 12 14:05:58 2014 +0100

    KolabResource: Not finding a configuration folder is not an error.

diff --git a/resources/kolab/kolabrelationresourcetask.cpp b/resources/kolab/kolabrelationresourcetask.cpp
index aa57b79..3485bf4 100644
--- a/resources/kolab/kolabrelationresourcetask.cpp
+++ b/resources/kolab/kolabrelationresourcetask.cpp
@@ -73,6 +73,6 @@ void KolabRelationResourceTask::onCollectionFetchResult(KJob *job)
         }
     }
 
-    kWarning() << "Couldn't find collection for relations";
+    kDebug() << "Couldn't find collection for relations";
     cancelTask(i18n("No mailbox for storing relations available, cancelling tag operation."));
 }


commit 694d2ec33c8c34a00f16f92024aefaa30a880f05
Author: Christian Mollekopf <chrigi_1 at fastmail.fm>
Date:   Wed Nov 12 14:04:35 2014 +0100

    KolabResource: Extract relation members just like tag members.
    
    We cannot simply store the item id.

diff --git a/resources/kolab/kolabchangeitemsrelationstask.cpp b/resources/kolab/kolabchangeitemsrelationstask.cpp
index 5348497..8133cea 100644
--- a/resources/kolab/kolabchangeitemsrelationstask.cpp
+++ b/resources/kolab/kolabchangeitemsrelationstask.cpp
@@ -32,6 +32,8 @@
 
 #include <akonadi/relationfetchjob.h>
 
+#include "kolabhelpers.h"
+
 KolabChangeItemsRelationsTask::KolabChangeItemsRelationsTask(ResourceStateInterface::Ptr resource, QObject *parent)
     : KolabRelationResourceTask(resource, parent)
 {
@@ -92,8 +94,14 @@ void KolabChangeItemsRelationsTask::onRelationFetchDone(KJob *job)
 
 void KolabChangeItemsRelationsTask::addRelation(const Akonadi::Relation &relation)
 {
+    //FIXME fetch items first?
+    QStringList members;
+    members.reserve(2);
+    members << KolabHelpers::createMemberUrl(relation.left(), QLatin1String("user at example.org"));
+    members << KolabHelpers::createMemberUrl(relation.right(), QLatin1String("user at example.org"));
+
     const QLatin1String productId("Akonadi-Kolab-Resource");
-    const KMime::Message::Ptr message = Kolab::KolabObjectWriter::writeRelation(relation, Kolab::KolabV3, productId);
+    const KMime::Message::Ptr message = Kolab::KolabObjectWriter::writeRelation(relation, members, Kolab::KolabV3, productId);
 
     KIMAP::AppendJob *job = new KIMAP::AppendJob(mSession);
     job->setMailBox(mailBoxForCollection(relationCollection()));
diff --git a/resources/kolab/kolabhelpers.cpp b/resources/kolab/kolabhelpers.cpp
index c72e790..839fc1f 100644
--- a/resources/kolab/kolabhelpers.cpp
+++ b/resources/kolab/kolabhelpers.cpp
@@ -465,3 +465,35 @@ bool KolabHelpers::isHandledType(Kolab::FolderType type)
     return false;
 }
 
+QList<QByteArray> KolabHelpers::ancestorChain(const Akonadi::Collection &col)
+{
+    Q_ASSERT(col.isValid());
+    if (col.parentCollection() == Akonadi::Collection::root() || col == Akonadi::Collection::root() || !col.isValid()) {
+        return QList<QByteArray>();
+    }
+    QList<QByteArray> ancestors = ancestorChain(col.parentCollection());
+    Q_ASSERT(!col.remoteId().isEmpty());
+    ancestors << col.remoteId().toLatin1().mid(1); //We strip the first character which is always the separator
+    return ancestors;
+}
+
+QString KolabHelpers::createMemberUrl(const Akonadi::Item &item, const QString &user)
+{
+    Kolab::RelationMember member;
+    if (item.mimeType() == KMime::Message::mimeType()) {
+        KMime::Message::Ptr msg = item.payload<KMime::Message::Ptr>();
+        member.uid = item.remoteId().toLong();
+        member.user = user;
+        member.subject = msg->subject()->asUnicodeString();
+        member.messageId = msg->messageID()->asUnicodeString();
+        member.mailbox = ancestorChain(item.parentCollection());
+    } else {
+        if (item.gid().isEmpty()) {
+            kWarning() << "Groupware object without GID, failed to add to tag: " << item.id() << item.remoteId();
+            return QString();
+        }
+        member.gid = item.gid();
+    }
+    return Kolab::generateMemberUrl(member);
+}
+
diff --git a/resources/kolab/kolabhelpers.h b/resources/kolab/kolabhelpers.h
index 28162a4..dbd909a 100644
--- a/resources/kolab/kolabhelpers.h
+++ b/resources/kolab/kolabhelpers.h
@@ -40,6 +40,8 @@ public:
     static QString getIcon(Kolab::FolderType type);
     //Returns true if the folder type shouldn't be ignored
     static bool isHandledType(Kolab::FolderType type);
+    static QList<QByteArray> ancestorChain(const Akonadi::Collection &col);
+    static QString createMemberUrl(const Akonadi::Item &item, const QString &user);
 };
 
 #endif
diff --git a/resources/kolab/kolabretrievetagstask.cpp b/resources/kolab/kolabretrievetagstask.cpp
index 1783867..5aa07a2 100644
--- a/resources/kolab/kolabretrievetagstask.cpp
+++ b/resources/kolab/kolabretrievetagstask.cpp
@@ -116,6 +116,39 @@ void KolabRetrieveTagTask::onHeadersReceived(const QString &mailBox,
     }
 }
 
+Akonadi::Item KolabRetrieveTagTask::extractMember(const Kolab::RelationMember &member)
+{
+    //TODO should we create a dummy item if it isn't yet available?
+    Akonadi::Item i;
+    if (!member.gid.isEmpty()) {
+        //Reference by GID
+        i.setGid(member.gid);
+    } else {
+        //Reference by imap uid
+        if (member.uid < 0) {
+            return Akonadi::Item();
+        }
+        i.setRemoteId(QString::number(member.uid));
+        kDebug() << "got member: " << member.uid << member.mailbox;
+        Akonadi::Collection parent;
+        {
+            //The root collection is not part of the mailbox path
+            Akonadi::Collection col;
+            col.setRemoteId(rootRemoteId());
+            col.setParentCollection(Akonadi::Collection::root());
+            parent = col;
+        }
+        Q_FOREACH(const QByteArray part, member.mailbox) {
+            Akonadi::Collection col;
+            col.setRemoteId(separatorCharacter() + QString::fromLatin1(part));
+            col.setParentCollection(parent);
+            parent = col;
+        }
+        i.setParentCollection(parent);
+    }
+    return i;
+}
+
 void KolabRetrieveTagTask::extractTag(const Kolab::KolabObjectReader &reader, qint64 remoteUid)
 {
     Akonadi::Tag tag = reader.getTag();
@@ -125,45 +158,40 @@ void KolabRetrieveTagTask::extractTag(const Kolab::KolabObjectReader &reader, qi
     Akonadi::Item::List members;
     Q_FOREACH (const QString &memberUrl, reader.getTagMembers()) {
         Kolab::RelationMember member = Kolab::parseMemberUrl(memberUrl);
-        //TODO should we create a dummy item if it isn't yet available?
-        Akonadi::Item i;
-        if (!member.gid.isEmpty()) {
-            //Reference by GID
-            i.setGid(member.gid);
+        const Akonadi::Item i = extractMember(member);
+        //TODO implement fallback to search if uid is not available
+        if (!i.remoteId().isEmpty() || !i.gid().isEmpty()) {
+            members << i;
         } else {
-            //Reference by imap uid
-            if (member.uid < 0) {
-                kWarning() << "Failed to parse uid: " << memberUrl;
-                continue;
-            }
-            i.setRemoteId(QString::number(member.uid));
-            kDebug() << "got member: " << member.uid << member.mailbox;
-            Akonadi::Collection parent;
-            {
-                //The root collection is not part of the mailbox path
-                Akonadi::Collection col;
-                col.setRemoteId(rootRemoteId());
-                col.setParentCollection(Akonadi::Collection::root());
-                parent = col;
-            }
-            Q_FOREACH(const QByteArray part, member.mailbox) {
-                Akonadi::Collection col;
-                col.setRemoteId(separatorCharacter() + QString::fromLatin1(part));
-                col.setParentCollection(parent);
-                parent = col;
-            }
-            i.setParentCollection(parent);
+            kWarning() << "Failed to parse member: " << memberUrl;
         }
-        //TODO implement fallback to search if uid is not available
-        members << i;
     }
     mTagMembers.insert(QString::fromLatin1(tag.remoteId()), members);
 }
 
 void KolabRetrieveTagTask::extractRelation(const Kolab::KolabObjectReader &reader, qint64 remoteUid)
 {
+    Akonadi::Item::List members;
+    Q_FOREACH (const QString &memberUrl, reader.getTagMembers()) {
+        Kolab::RelationMember member = Kolab::parseMemberUrl(memberUrl);
+        const Akonadi::Item i = extractMember(member);
+        //TODO implement fallback to search if uid is not available
+        if (!i.remoteId().isEmpty() || !i.gid().isEmpty()) {
+            members << i;
+        } else {
+            kWarning() << "Failed to parse member: " << memberUrl;
+        }
+    }
+    if (members.size() != 2) {
+        kWarning() << "Wrong numbers of members for a relation, expected 2: " << members.size();
+        return;
+    }
+
     Akonadi::Relation relation = reader.getRelation();
+    relation.setType(Akonadi::Relation::GENERIC);
     relation.setRemoteId(QByteArray::number(remoteUid));
+    relation.setLeft(members.at(0));
+    relation.setRight(members.at(1));
     mRelations << relation;
 }
 
diff --git a/resources/kolab/kolabretrievetagstask.h b/resources/kolab/kolabretrievetagstask.h
index 8ea371f..eb63743 100644
--- a/resources/kolab/kolabretrievetagstask.h
+++ b/resources/kolab/kolabretrievetagstask.h
@@ -26,6 +26,7 @@
 namespace Kolab
 {
     class KolabObjectReader;
+    class RelationMember;
 } // namespace Kolab
 
 class KolabRetrieveTagTask : public KolabRelationResourceTask
@@ -50,7 +51,6 @@ private:
     RetrieveType mRetrieveType;
 
 private Q_SLOTS:
-    // void onItemsFetchDone(KJob *job);
     void onFinalSelectDone(KJob *job);
     void onHeadersReceived(const QString &mailBox,
                             const QMap<qint64, qint64> &uids,
@@ -63,10 +63,7 @@ private Q_SLOTS:
 private:
     void extractTag(const Kolab::KolabObjectReader &reader, qint64 remoteUid);
     void extractRelation(const Kolab::KolabObjectReader &reader, qint64 remoteUid);
-
-    // void onApplyCollectionChanged(const Akonadi::Collection &collection);
-    // void onCancelTask(const QString &errorText);
-    // void onChangeCommitted();
+    Akonadi::Item extractMember(const Kolab::RelationMember &member);
 };
 
 #endif // KOLABCHANGETAGTASK_H
diff --git a/resources/kolab/tagchangehelper.cpp b/resources/kolab/tagchangehelper.cpp
index 8d8e9d2..c41445e 100644
--- a/resources/kolab/tagchangehelper.cpp
+++ b/resources/kolab/tagchangehelper.cpp
@@ -22,6 +22,7 @@
 #include "tagchangehelper.h"
 
 #include "kolabrelationresourcetask.h"
+#include "kolabhelpers.h"
 
 #include <imapflags.h>
 #include <uidnextattribute.h>
@@ -44,45 +45,12 @@ TagChangeHelper::TagChangeHelper(KolabRelationResourceTask *parent)
 {
 }
 
-static QList<QByteArray> ancestorChain(const Akonadi::Collection &col)
-{
-    Q_ASSERT(col.isValid());
-    if (col.parentCollection() == Akonadi::Collection::root() || col == Akonadi::Collection::root() || !col.isValid()) {
-        return QList<QByteArray>();
-    }
-    QList<QByteArray> ancestors = ancestorChain(col.parentCollection());
-    Q_ASSERT(!col.remoteId().isEmpty());
-    ancestors << col.remoteId().toLatin1().mid(1); //We strip the first character which is always the separator
-    return ancestors;
-}
-
-QString TagConverter::createMemberUrl(const Akonadi::Item &item)
-{
-    Kolab::RelationMember member;
-    if (item.mimeType() == KMime::Message::mimeType()) {
-        KMime::Message::Ptr msg = item.payload<KMime::Message::Ptr>();
-        member.uid = item.remoteId().toLong();
-        //FIXME get the user from somewhere
-        member.user = QLatin1String("user at example.org");
-        member.subject = msg->subject()->asUnicodeString();
-        member.messageId = msg->messageID()->asUnicodeString();
-        member.mailbox = ancestorChain(item.parentCollection());
-    } else {
-        if (item.gid().isEmpty()) {
-            kWarning() << "Groupware object without GID, failed to add to tag: " << item.id() << item.remoteId();
-            return QString();
-        }
-        member.gid = item.gid();
-    }
-    return Kolab::generateMemberUrl(member);
-}
-
 KMime::Message::Ptr TagConverter::createMessage(const Akonadi::Tag &tag, const Akonadi::Item::List &items)
 {
     QStringList itemRemoteIds;
     itemRemoteIds.reserve(items.count());
     Q_FOREACH (const Akonadi::Item &item, items) {
-        const QString memberUrl = createMemberUrl(item);
+        const QString memberUrl = KolabHelpers::createMemberUrl(item, QLatin1String("user at test.org"));
         if (!memberUrl.isEmpty()) {
             itemRemoteIds << memberUrl;
         }
diff --git a/resources/kolab/tagchangehelper.h b/resources/kolab/tagchangehelper.h
index 5280cf6..ee1b7d6 100644
--- a/resources/kolab/tagchangehelper.h
+++ b/resources/kolab/tagchangehelper.h
@@ -40,7 +40,6 @@ class KolabRelationResourceTask;
 
 struct TagConverter
 {
-    static QString createMemberUrl(const Akonadi::Item &item);
     virtual KMime::Message::Ptr createMessage(const Akonadi::Tag &tag, const Akonadi::Item::List &items);
 };
 
diff --git a/resources/kolab/tests/testchangeitemstagstask.cpp b/resources/kolab/tests/testchangeitemstagstask.cpp
index 23bda44..0687b06 100644
--- a/resources/kolab/tests/testchangeitemstagstask.cpp
+++ b/resources/kolab/tests/testchangeitemstagstask.cpp
@@ -32,10 +32,10 @@ unsigned int qHash(const Akonadi::Tag &tag);
 #include <akonadi/collectioncreatejob.h>
 #include <akonadi/virtualresource.h>
 #include <akonadi/tagcreatejob.h>
-#include "kolabhelpers.h"
 #include <kolab/kolabobject.h>
 
 #include "kolabchangeitemstagstask.h"
+#include "kolabhelpers.h"
 
 using namespace Akonadi;
 
@@ -218,7 +218,7 @@ private slots:
         Akonadi::Item item;
         item.setRemoteId(QLatin1String("20"));
         item.setParentCollection(createCollectionChain("/INBOX"));
-        const QString member = TagConverter::createMemberUrl(item);
+        const QString member = KolabHelpers::createMemberUrl(item, QLatin1String("localuser at localhost"));
         const QString expected = QLatin1String("imap:/user/localuser at localhost/INBOX/20?message-id=messageid&subject=subject&date=");
         QCOMPARE(member, expected);
     }


commit 8462124fde4df47174ee3cac8871afc3c70ef7e9
Merge: 3fbb4b8 a5d3abf
Author: Christian Mollekopf <chrigi_1 at fastmail.fm>
Date:   Tue Nov 11 15:05:42 2014 +0100

    Merge remote-tracking branch 'kolab/feature/remoterelationsyc' into kolab/integration/4.13.0



commit a5d3abff423c66b3a705592741779d6b0e910a06
Author: Aaron Seigo <aseigo at kde.org>
Date:   Tue Nov 11 12:32:42 2014 +0100

    split retrieval of tags and relations

diff --git a/resources/kolab/kolabresource.cpp b/resources/kolab/kolabresource.cpp
index 7c7576e..704d998 100644
--- a/resources/kolab/kolabresource.cpp
+++ b/resources/kolab/kolabresource.cpp
@@ -98,6 +98,7 @@ void KolabResource::retrieveCollections()
 
     startTask(new KolabRetrieveCollectionsTask(createResourceState(TaskArguments()), this));
     synchronizeTags();
+    synchronizeRelations();
 }
 
 void KolabResource::itemAdded(const Akonadi::Item& item, const Akonadi::Collection& collection)
@@ -197,7 +198,13 @@ void KolabResource::itemsTagsChanged(const Akonadi::Item::List &items, const QSe
 
 void KolabResource::retrieveTags()
 {
-    KolabRetrieveTagTask *task = new KolabRetrieveTagTask(createResourceState(TaskArguments()), this);
+    KolabRetrieveTagTask *task = new KolabRetrieveTagTask(createResourceState(TaskArguments()), KolabRetrieveTagTask::RetrieveTags, this);
+    startTask(task);
+}
+
+void KolabResource::retrieveRelations()
+{
+    KolabRetrieveTagTask *task = new KolabRetrieveTagTask(createResourceState(TaskArguments()), KolabRetrieveTagTask::RetrieveRelations, this);
     startTask(task);
 }
 
diff --git a/resources/kolab/kolabresource.h b/resources/kolab/kolabresource.h
index 44fb725..72fea8f 100644
--- a/resources/kolab/kolabresource.h
+++ b/resources/kolab/kolabresource.h
@@ -66,6 +66,7 @@ protected:
 
 private Q_SLOTS:
     void retrieveTags();
+    void retrieveRelations();
 };
 
 #endif
diff --git a/resources/kolab/kolabretrievetagstask.cpp b/resources/kolab/kolabretrievetagstask.cpp
index 43e540d..1783867 100644
--- a/resources/kolab/kolabretrievetagstask.cpp
+++ b/resources/kolab/kolabretrievetagstask.cpp
@@ -25,9 +25,10 @@
 #include <kimap/fetchjob.h>
 #include <kolabobject.h>
 
-KolabRetrieveTagTask::KolabRetrieveTagTask(ResourceStateInterface::Ptr resource, QObject *parent)
+KolabRetrieveTagTask::KolabRetrieveTagTask(ResourceStateInterface::Ptr resource, RetrieveType type, QObject *parent)
     : KolabRelationResourceTask(resource, parent)
     , mSession(0)
+    , mRetrieveType(type)
 {
 }
 
@@ -102,9 +103,9 @@ void KolabRetrieveTagTask::onHeadersReceived(const QString &mailBox,
         const Kolab::KolabObjectReader reader(msg);
         switch (reader.getType()) {
             case Kolab::RelationConfigurationObject:
-                if (reader.isTag()) {
+                if (mRetrieveType == RetrieveTags && reader.isTag()) {
                     extractTag(reader, uids[number]);
-                } else if (reader.isRelation()) {
+                } else if (mRetrieveType == RetrieveRelations && reader.isRelation()) {
                     extractRelation(reader, uids[number]);
                 }
                 break;
@@ -174,12 +175,10 @@ void KolabRetrieveTagTask::onHeadersFetchDone(KJob *job)
         return;
     }
 
-    if (!mTags.isEmpty() || !mTagMembers.isEmpty()) {
+    if (mRetrieveType == RetrieveTags) {
         kDebug() << "Fetched tags: " << mTags.size() << mTagMembers.keys().size();
         resourceState()->tagsRetrieved(mTags, mTagMembers);
-    }
-
-    if (!mRelations.isEmpty()) {
+    } else if (mRetrieveType == RetrieveRelations) {
         kDebug() << "Fetched relations:" << mRelations.size();
         resourceState()->relationsRetrieved(mRelations);
     }
diff --git a/resources/kolab/kolabretrievetagstask.h b/resources/kolab/kolabretrievetagstask.h
index 0dab163..8ea371f 100644
--- a/resources/kolab/kolabretrievetagstask.h
+++ b/resources/kolab/kolabretrievetagstask.h
@@ -32,7 +32,12 @@ class KolabRetrieveTagTask : public KolabRelationResourceTask
 {
     Q_OBJECT
 public:
-    explicit KolabRetrieveTagTask(ResourceStateInterface::Ptr resource, QObject *parent = 0);
+    enum RetrieveType {
+        RetrieveTags,
+        RetrieveRelations
+    };
+
+    explicit KolabRetrieveTagTask(ResourceStateInterface::Ptr resource, RetrieveType type, QObject *parent = 0);
 
 protected:
     virtual void startRelationTask(KIMAP::Session *session);
@@ -42,6 +47,7 @@ private:
     Akonadi::Tag::List mTags;
     QHash<QString, Akonadi::Item::List> mTagMembers;
     Akonadi::Relation::List mRelations;
+    RetrieveType mRetrieveType;
 
 private Q_SLOTS:
     // void onItemsFetchDone(KJob *job);
diff --git a/resources/kolab/tests/testretrievetagstask.cpp b/resources/kolab/tests/testretrievetagstask.cpp
index 6ae2609..767c737 100644
--- a/resources/kolab/tests/testretrievetagstask.cpp
+++ b/resources/kolab/tests/testretrievetagstask.cpp
@@ -133,7 +133,7 @@ private slots:
         DummyResourceState::Ptr state = DummyResourceState::Ptr(new DummyResourceState);
         state->setServerCapabilities(QStringList() << "METADATA" << "ACL");
         state->setUserName("Hans");
-        KolabRetrieveTagTask *task = new KolabRetrieveTagTask(state);
+        KolabRetrieveTagTask *task = new KolabRetrieveTagTask(state, KolabRetrieveTagTask::RetrieveTags);
 
         task->start(&pool);
 


commit 3fbb4b862e5fe7c153e08e8db8e69473142437a7
Merge: 9d2920f 0d296bb
Author: Christian Mollekopf <chrigi_1 at fastmail.fm>
Date:   Tue Nov 11 10:33:45 2014 +0100

    Merge remote-tracking branch 'remotes/kolab/feature/remoterelationsyc' into kolab/integration/4.13.0



commit 0d296bb92ee2f06cd24b96d2ee04d29cf3cf09c9
Author: Aaron Seigo <aseigo at kde.org>
Date:   Wed Nov 5 15:57:51 2014 +0100

    refactor out tag extraction and add relation extraction

diff --git a/resources/kolab/kolabretrievetagstask.cpp b/resources/kolab/kolabretrievetagstask.cpp
index c2ab6fb..43e540d 100644
--- a/resources/kolab/kolabretrievetagstask.cpp
+++ b/resources/kolab/kolabretrievetagstask.cpp
@@ -101,55 +101,71 @@ void KolabRetrieveTagTask::onHeadersReceived(const QString &mailBox,
         const KMime::Message::Ptr msg = messages[number];
         const Kolab::KolabObjectReader reader(msg);
         switch (reader.getType()) {
-            case Kolab::RelationConfigurationObject: {
-                Akonadi::Tag tag = reader.getTag();
-                tag.setRemoteId(QByteArray::number(uids[number]));
-                mTags << tag;
-
-                Akonadi::Item::List members;
-                Q_FOREACH (const QString &memberUrl, reader.getTagMembers()) {
-                    Kolab::RelationMember member = Kolab::parseMemberUrl(memberUrl);
-                    //TODO should we create a dummy item if it isn't yet available?
-                    Akonadi::Item i;
-                    if (!member.gid.isEmpty()) {
-                        //Reference by GID
-                        i.setGid(member.gid);
-                    } else {
-                        //Reference by imap uid
-                        if (member.uid < 0) {
-                            kWarning() << "Failed to parse uid: " << memberUrl;
-                            continue;
-                        }
-                        i.setRemoteId(QString::number(member.uid));
-                        kDebug() << "got member: " << member.uid << member.mailbox;
-                        Akonadi::Collection parent;
-                        {
-                            //The root collection is not part of the mailbox path
-                            Akonadi::Collection col;
-                            col.setRemoteId(rootRemoteId());
-                            col.setParentCollection(Akonadi::Collection::root());
-                            parent = col;
-                        }
-                        Q_FOREACH(const QByteArray part, member.mailbox) {
-                            Akonadi::Collection col;
-                            col.setRemoteId(separatorCharacter() + QString::fromLatin1(part));
-                            col.setParentCollection(parent);
-                            parent = col;
-                        }
-                        i.setParentCollection(parent);
-                    }
-                    //TODO implement fallback to search if uid is not available
-                    members << i;
+            case Kolab::RelationConfigurationObject:
+                if (reader.isTag()) {
+                    extractTag(reader, uids[number]);
+                } else if (reader.isRelation()) {
+                    extractRelation(reader, uids[number]);
                 }
-                mTagMembers.insert(QString::fromLatin1(tag.remoteId()), members);
-            }
                 break;
+
             default:
                 break;
         }
     }
 }
 
+void KolabRetrieveTagTask::extractTag(const Kolab::KolabObjectReader &reader, qint64 remoteUid)
+{
+    Akonadi::Tag tag = reader.getTag();
+    tag.setRemoteId(QByteArray::number(remoteUid));
+    mTags << tag;
+
+    Akonadi::Item::List members;
+    Q_FOREACH (const QString &memberUrl, reader.getTagMembers()) {
+        Kolab::RelationMember member = Kolab::parseMemberUrl(memberUrl);
+        //TODO should we create a dummy item if it isn't yet available?
+        Akonadi::Item i;
+        if (!member.gid.isEmpty()) {
+            //Reference by GID
+            i.setGid(member.gid);
+        } else {
+            //Reference by imap uid
+            if (member.uid < 0) {
+                kWarning() << "Failed to parse uid: " << memberUrl;
+                continue;
+            }
+            i.setRemoteId(QString::number(member.uid));
+            kDebug() << "got member: " << member.uid << member.mailbox;
+            Akonadi::Collection parent;
+            {
+                //The root collection is not part of the mailbox path
+                Akonadi::Collection col;
+                col.setRemoteId(rootRemoteId());
+                col.setParentCollection(Akonadi::Collection::root());
+                parent = col;
+            }
+            Q_FOREACH(const QByteArray part, member.mailbox) {
+                Akonadi::Collection col;
+                col.setRemoteId(separatorCharacter() + QString::fromLatin1(part));
+                col.setParentCollection(parent);
+                parent = col;
+            }
+            i.setParentCollection(parent);
+        }
+        //TODO implement fallback to search if uid is not available
+        members << i;
+    }
+    mTagMembers.insert(QString::fromLatin1(tag.remoteId()), members);
+}
+
+void KolabRetrieveTagTask::extractRelation(const Kolab::KolabObjectReader &reader, qint64 remoteUid)
+{
+    Akonadi::Relation relation = reader.getRelation();
+    relation.setRemoteId(QByteArray::number(remoteUid));
+    mRelations << relation;
+}
+
 void KolabRetrieveTagTask::onHeadersFetchDone(KJob *job)
 {
     if (job->error()) {
@@ -157,8 +173,17 @@ void KolabRetrieveTagTask::onHeadersFetchDone(KJob *job)
         cancelTask(job->errorString());
         return;
     }
-    kDebug() << "Fetched tags: " << mTags.size() << mTagMembers.keys().size();
-    resourceState()->tagsRetrieved(mTags, mTagMembers);
+
+    if (!mTags.isEmpty() || !mTagMembers.isEmpty()) {
+        kDebug() << "Fetched tags: " << mTags.size() << mTagMembers.keys().size();
+        resourceState()->tagsRetrieved(mTags, mTagMembers);
+    }
+
+    if (!mRelations.isEmpty()) {
+        kDebug() << "Fetched relations:" << mRelations.size();
+        resourceState()->relationsRetrieved(mRelations);
+    }
+
     deleteLater();
 }
 
diff --git a/resources/kolab/kolabretrievetagstask.h b/resources/kolab/kolabretrievetagstask.h
index d790dbd..0dab163 100644
--- a/resources/kolab/kolabretrievetagstask.h
+++ b/resources/kolab/kolabretrievetagstask.h
@@ -23,6 +23,11 @@
 #include "kolabrelationresourcetask.h"
 #include <akonadi/tag.h>
 
+namespace Kolab
+{
+    class KolabObjectReader;
+} // namespace Kolab
+
 class KolabRetrieveTagTask : public KolabRelationResourceTask
 {
     Q_OBJECT
@@ -36,6 +41,7 @@ private:
     KIMAP::Session *mSession;
     Akonadi::Tag::List mTags;
     QHash<QString, Akonadi::Item::List> mTagMembers;
+    Akonadi::Relation::List mRelations;
 
 private Q_SLOTS:
     // void onItemsFetchDone(KJob *job);
@@ -48,6 +54,10 @@ private Q_SLOTS:
                             const QMap<qint64, KIMAP::MessagePtr> &messages);
     void onHeadersFetchDone(KJob *job);
 
+private:
+    void extractTag(const Kolab::KolabObjectReader &reader, qint64 remoteUid);
+    void extractRelation(const Kolab::KolabObjectReader &reader, qint64 remoteUid);
+
     // void onApplyCollectionChanged(const Akonadi::Collection &collection);
     // void onCancelTask(const QString &errorText);
     // void onChangeCommitted();


commit 37601f0bf9a4435202b8e51bb94a70d64e3fb152
Author: Aaron Seigo <aseigo at kde.org>
Date:   Wed Nov 5 15:57:19 2014 +0100

    add a relationsRetrieved method

diff --git a/resources/imap/resourcestate.cpp b/resources/imap/resourcestate.cpp
index b2460c4..fa6289c 100644
--- a/resources/imap/resourcestate.cpp
+++ b/resources/imap/resourcestate.cpp
@@ -418,3 +418,9 @@ void ResourceState::tagsRetrieved( const Akonadi::Tag::List &tags, const QHash<Q
 {
   m_resource->tagsRetrieved(tags, tagMembers);
 }
+
+
+void ResourceState::relationsRetrieved(const Akonadi::Relation::List &relations)
+{
+  m_resource->relationsRetrieved(relations);
+}
diff --git a/resources/imap/resourcestate.h b/resources/imap/resourcestate.h
index 9588be5..9e00562 100644
--- a/resources/imap/resourcestate.h
+++ b/resources/imap/resourcestate.h
@@ -120,6 +120,7 @@ public:
   virtual void collectionsRetrieved( const Akonadi::Collection::List &collections );
 
   virtual void tagsRetrieved( const Akonadi::Tag::List &tags, const QHash<QString, Akonadi::Item::List> & );
+  virtual void relationsRetrieved( const Akonadi::Relation::List &tags);
 
   virtual void collectionChangeCommitted( const Akonadi::Collection &collection );
 
diff --git a/resources/imap/resourcestateinterface.h b/resources/imap/resourcestateinterface.h
index d920199..82ea2e1 100644
--- a/resources/imap/resourcestateinterface.h
+++ b/resources/imap/resourcestateinterface.h
@@ -120,6 +120,7 @@ public:
 
   virtual MessageHelper::Ptr messageHelper() const = 0;
   virtual void tagsRetrieved( const Akonadi::Tag::List &tags, const QHash<QString, Akonadi::Item::List> & ) = 0;
+  virtual void relationsRetrieved( const Akonadi::Relation::List &tags) = 0;
 
   virtual Akonadi::Relation::List addedRelations() const = 0;
   virtual Akonadi::Relation::List removedRelations() const = 0;
diff --git a/resources/imap/tests/dummyresourcestate.cpp b/resources/imap/tests/dummyresourcestate.cpp
index 0e554e7..753099b 100644
--- a/resources/imap/tests/dummyresourcestate.cpp
+++ b/resources/imap/tests/dummyresourcestate.cpp
@@ -332,6 +332,11 @@ void DummyResourceState::tagsRetrieved( const Akonadi::Tag::List &tags, const QH
   recordCall( "tagsRetrieved",  QVariant::fromValue( qMakePair(tags, items) ) );
 }
 
+void DummyResourceState::relationsRetrieved( const Akonadi::Relation::List &relations )
+{
+  recordCall( "relationsRetrieved",  QVariant::fromValue( relations ) );
+}
+
 void DummyResourceState::tagChangeCommitted(const Akonadi::Tag &tag)
 {
   recordCall( "tagChangeCommitted", QVariant::fromValue( tag ) );
diff --git a/resources/imap/tests/dummyresourcestate.h b/resources/imap/tests/dummyresourcestate.h
index ba80a4c..0aa5317 100644
--- a/resources/imap/tests/dummyresourcestate.h
+++ b/resources/imap/tests/dummyresourcestate.h
@@ -119,6 +119,7 @@ public:
   virtual void collectionChangeCommitted( const Akonadi::Collection &collection );
 
   virtual void tagsRetrieved( const Akonadi::Tag::List &tags, const QHash<QString, Akonadi::Item::List> & );
+  virtual void relationsRetrieved( const Akonadi::Relation::List &tags );
   virtual void tagChangeCommitted( const Akonadi::Tag &tag );
 
   virtual void searchFinished( const QVector<qint64> &result, bool isRid = true );


commit 9d2920f1c684d60dfd0f0b4e6f392c9c78ffbe14
Author: Christian Mollekopf <chrigi_1 at fastmail.fm>
Date:   Tue Nov 4 14:52:42 2014 +0100

    IMAP-Resource: Remove all uses of the timestamp attribute.
    
    Updating this during every metadataretrievel resulted in a lot of updates,
    in i.e. kmail, that currently are very expensive (due to the favoritesproxymodel
    issue). Since it was only used in one place to determine wether the collection
    is new, we can drop it entierly. I removed the knownMailboxes hack with it,
    since we no longer use it anyways.

diff --git a/resources/imap/CMakeLists.txt b/resources/imap/CMakeLists.txt
index 20b5634..319ffd2 100644
--- a/resources/imap/CMakeLists.txt
+++ b/resources/imap/CMakeLists.txt
@@ -41,7 +41,6 @@ set( imapresource_LIB_SRCS
   retrieveitemstask.cpp
   searchtask.cpp
   sessionpool.cpp
-  timestampattribute.cpp
   uidvalidityattribute.cpp
   uidnextattribute.cpp
   settings.cpp
diff --git a/resources/imap/collectionmetadatahelper.cpp b/resources/imap/collectionmetadatahelper.cpp
index c0035aa..f3a6dba 100644
--- a/resources/imap/collectionmetadatahelper.cpp
+++ b/resources/imap/collectionmetadatahelper.cpp
@@ -19,7 +19,6 @@
 
 #include "collectionmetadatahelper.h"
 #include <imapaclattribute.h>
-#include <timestampattribute.h>
 
 Akonadi::Collection::Rights CollectionMetadataHelper::convertRights(const KIMAP::Acl::Rights imapRights, KIMAP::Acl::Rights parentRights)
 {
@@ -67,11 +66,11 @@ bool CollectionMetadataHelper::applyRights(Akonadi::Collection &collection, cons
         newRights &= ~Akonadi::Collection::CanChangeCollection;
     }
 
-    const bool isNewCollection = !collection.hasAttribute<TimestampAttribute>();
+    //This can result in false positives for new collections with defaults access rights.
+    //The caller needs to handles those.
     bool accessRevoked = false;
     if ((collection.rights() & Akonadi::Collection::CanCreateItem) &&
-        !(newRights & Akonadi::Collection::CanCreateItem) &&
-        !isNewCollection) {
+        !(newRights & Akonadi::Collection::CanCreateItem)) {
         // write access revoked
         accessRevoked = true;
     }
diff --git a/resources/imap/imapresourcebase.cpp b/resources/imap/imapresourcebase.cpp
index 7689b86..904f0a6 100644
--- a/resources/imap/imapresourcebase.cpp
+++ b/resources/imap/imapresourcebase.cpp
@@ -50,7 +50,6 @@
 #include "imapaclattribute.h"
 #include "imapquotaattribute.h"
 #include "noselectattribute.h"
-#include "timestampattribute.h"
 #include "uidvalidityattribute.h"
 #include "uidnextattribute.h"
 #include "highestmodseqattribute.h"
@@ -110,7 +109,6 @@ ImapResourceBase::ImapResourceBase( const QString &id )
   Akonadi::AttributeFactory::registerAttribute<UidValidityAttribute>();
   Akonadi::AttributeFactory::registerAttribute<UidNextAttribute>();
   Akonadi::AttributeFactory::registerAttribute<NoSelectAttribute>();
-  Akonadi::AttributeFactory::registerAttribute<TimestampAttribute>();
   Akonadi::AttributeFactory::registerAttribute<HighestModSeqAttribute>();
 
   Akonadi::AttributeFactory::registerAttribute<CollectionAnnotationsAttribute>();
diff --git a/resources/imap/resourcestate.cpp b/resources/imap/resourcestate.cpp
index b2460c4..50caf5c 100644
--- a/resources/imap/resourcestate.cpp
+++ b/resources/imap/resourcestate.cpp
@@ -26,7 +26,6 @@
 #include "sessionpool.h"
 #include "settings.h"
 #include "noselectattribute.h"
-#include "timestampattribute.h"
 
 #include <akonadi/agentsearchinterface.h>
 #include <kmessagebox.h>
@@ -248,26 +247,6 @@ void ResourceState::itemsChangesCommitted(const Akonadi::Item::List& items)
 void ResourceState::collectionsRetrieved( const Akonadi::Collection::List &collections )
 {
   m_resource->collectionsRetrieved( collections );
-
-  //FIXME get rid of this. If we retrieve metadata before syncing a folder I think we can live without this code.
-  if ( m_resource->settings()->retrieveMetadataOnFolderListing() ) {
-    QStringList oldMailBoxes = m_resource->settings()->knownMailBoxes();
-    QStringList newMailBoxes;
-
-    foreach ( const Akonadi::Collection &c, collections ) {
-      const QString mailBox = mailBoxForCollection( c );
-
-      if ( !c.hasAttribute<NoSelectAttribute>()
-        && !oldMailBoxes.contains( mailBox ) ) {
-        m_resource->synchronizeCollectionAttributes(c);
-      }
-
-      newMailBoxes << mailBox;
-    }
-
-    m_resource->settings()->setKnownMailBoxes( newMailBoxes );
-  }
-
   m_resource->startIdleIfNeeded();
 }
 
@@ -296,48 +275,6 @@ void ResourceState::searchFinished( const QVector<qint64> &result, bool isRid )
 void ResourceState::cancelTask( const QString &errorString )
 {
   m_resource->cancelTask( errorString );
-
-  // We get here in case of some error during the task. In such a case that can have
-  // been provoked by the fact that some of the metadata we had was wrong (most notably
-  // ACL and we took a wrong decision.
-  // So reset the timestamp of all the collections involved in the task, and also
-  // remove them from the "known mailboxes" list so that we get a chance to refresh
-  // the metadata about them ASAP.
-
-  Akonadi::Collection::List collections;
-  collections << m_arguments.collection
-              << m_arguments.parentCollection
-              << m_arguments.sourceCollection
-              << m_arguments.targetCollection;
-
-  foreach ( const Akonadi::Item &item, m_arguments.items ) {
-    if  ( item.isValid() && item.parentCollection().isValid() ) {
-        collections << item.parentCollection();
-    }
-  }
-
-  if ( m_arguments.collection.isValid() && m_arguments.collection.parentCollection().isValid() ) {
-    collections << m_arguments.collection.parentCollection();
-  }
-
-  const QStringList oldMailBoxes = m_resource->settings()->knownMailBoxes();
-  QStringList newMailBoxes = oldMailBoxes;
-
-  foreach ( const Akonadi::Collection &collection, collections ) {
-    if ( collection.isValid()
-      && collection.hasAttribute<TimestampAttribute>() ) {
-
-      Akonadi::Collection c = collection;
-      c.removeAttribute<TimestampAttribute>();
-
-      m_resource->modifyCollection( c );
-      newMailBoxes.removeAll( mailBoxForCollection( c ) );
-    }
-  }
-
-  if ( oldMailBoxes.size()!=newMailBoxes.size() ) {
-    m_resource->settings()->setKnownMailBoxes( newMailBoxes );
-  }
 }
 
 void ResourceState::deferTask()
diff --git a/resources/imap/retrievecollectionmetadatatask.cpp b/resources/imap/retrievecollectionmetadatatask.cpp
index a891861..30e4331 100644
--- a/resources/imap/retrievecollectionmetadatatask.cpp
+++ b/resources/imap/retrievecollectionmetadatatask.cpp
@@ -37,7 +37,6 @@
 #include "imapaclattribute.h"
 #include "imapquotaattribute.h"
 #include "noselectattribute.h"
-#include "timestampattribute.h"
 #include "collectionmetadatahelper.h"
 
 RetrieveCollectionMetadataTask::RetrieveCollectionMetadataTask( ResourceStateInterface::Ptr resource, QObject *parent )
@@ -190,7 +189,7 @@ void RetrieveCollectionMetadataTask::onRightsReceived( KJob *job )
 //                 << "newRights:" << newRights
 //                 << "oldRights:" << collection.rights();
 
-  const bool isNewCollection = !m_collection.hasAttribute<TimestampAttribute>();
+  const bool isNewCollection = !m_collection.hasAttribute<Akonadi::ImapAclAttribute>();
   const bool accessRevoked = CollectionMetadataHelper::applyRights(m_collection, imapRights, parentRights);
   if ( accessRevoked && !isNewCollection ) {
     // write access revoked
@@ -283,10 +282,6 @@ void RetrieveCollectionMetadataTask::onQuotasReceived( KJob *job )
 void RetrieveCollectionMetadataTask::endTaskIfNeeded()
 {
   if ( m_pendingMetaDataJobs <= 0 ) {
-    const uint currentTimestamp = QDateTime::currentDateTime().toTime_t();
-    TimestampAttribute *attr = m_collection.attribute<TimestampAttribute>( Akonadi::Collection::AddIfMissing );
-    attr->setTimestamp( currentTimestamp );
-
     collectionAttributesRetrieved( m_collection );
   }
 }
diff --git a/resources/imap/tests/testretrievecollectionmetadatatask.cpp b/resources/imap/tests/testretrievecollectionmetadatatask.cpp
index a05a2fb..29fe4db 100644
--- a/resources/imap/tests/testretrievecollectionmetadatatask.cpp
+++ b/resources/imap/tests/testretrievecollectionmetadatatask.cpp
@@ -27,7 +27,6 @@
 #include "imapaclattribute.h"
 #include "imapquotaattribute.h"
 #include "noselectattribute.h"
-#include "timestampattribute.h"
 #include <noinferiorsattribute.h>
 
 typedef QMap<QByteArray, QByteArray> QBYTEARRAYMAP;
@@ -64,7 +63,6 @@ private slots:
 
     collection = createCollectionChain( QLatin1String("/INBOX/Foo") );
     collection.setRights( 0 );
-    collection.addAttribute( new TimestampAttribute( QDateTime::currentDateTime().toTime_t() ) );
 
     capabilities.clear();
     capabilities << "ANNOTATEMORE" << "ACL" << "QUOTA";
@@ -108,7 +106,6 @@ private slots:
     aclAttribute->setRights( rightsMap );
     parentCollection.addAttribute( aclAttribute );
     collection.setParentCollection( parentCollection );
-    collection.removeAttribute<TimestampAttribute>();
     rights = Akonadi::Collection::AllRights;
     rights &= ~Akonadi::Collection::CanChangeCollection;
     QTest::newRow( "parent without create rights" ) << collection << capabilities << scenario
@@ -152,7 +149,6 @@ private slots:
     // Test that a warning is issued if the insert rights of a folder have been revoked on the server.
     //
     collection = createCollectionChain( QLatin1String("/INBOX/Foo") );
-    collection.addAttribute( new TimestampAttribute( QDateTime::currentDateTime().toTime_t() ) );
     collection.setParentCollection( parentCollection );
     collection.setRights( Akonadi::Collection::CanCreateItem );
 
@@ -187,7 +183,6 @@ private slots:
     collection.setRemoteId( "/INBOX" );
     collection.setRights( Akonadi::Collection::AllRights );
     collection.addAttribute( new NoInferiorsAttribute( true ) );
-    collection.removeAttribute<TimestampAttribute>();
     scenario.clear();
     scenario << defaultPoolConnectionScenario()
              << "C: A000003 GETANNOTATION \"INBOX\" \"*\" \"value.shared\""
@@ -211,7 +206,6 @@ private slots:
 
     collection = createCollectionChain( QLatin1String("/INBOX/Foo") );
     collection.setRights( 0 );
-    collection.removeAttribute<TimestampAttribute>();
 
     capabilities.clear();
     capabilities << "METADATA" << "ACL" << "QUOTA";
@@ -247,7 +241,6 @@ private slots:
 
     collection = createCollectionChain( QLatin1String("/INBOX/Foo") );
     collection.setRights( 0 );
-    collection.addAttribute( new TimestampAttribute( QDateTime::currentDateTime().toTime_t() ) );
 
     capabilities.clear();
     expectedAnnotations.clear();
@@ -309,11 +302,6 @@ private slots:
       if ( command == "collectionAttributesRetrieved" ) {
         Akonadi::Collection collection = parameter.value<Akonadi::Collection>();
         QCOMPARE( collection.rights(), expectedRights );
-        QVERIFY( collection.hasAttribute<TimestampAttribute>() );
-
-        const qint64 timestamp = collection.attribute<TimestampAttribute>()->timestamp();
-        const qint64 currentTimestamp = QDateTime::currentDateTime().toTime_t();
-        QVERIFY( qAbs( currentTimestamp - timestamp ) < 5 );
 
         if ( !expectedAnnotations.isEmpty() ) {
           QVERIFY( collection.hasAttribute<Akonadi::CollectionAnnotationsAttribute>() );
diff --git a/resources/imap/timestampattribute.cpp b/resources/imap/timestampattribute.cpp
deleted file mode 100644
index e1ab6f6..0000000
--- a/resources/imap/timestampattribute.cpp
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
-    Copyright (c) 2010 Klarälvdalens Datakonsult AB,
-                       a KDAB Group company <info at kdab.com>
-    Author: Kevin Ottens <kevin at kdab.com>
-
-    This library is free software; you can redistribute it and/or modify it
-    under the terms of the GNU Library General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or (at your
-    option) any later version.
-
-    This library is distributed in the hope that it will be useful, but WITHOUT
-    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
-    License for more details.
-
-    You should have received a copy of the GNU Library General Public License
-    along with this library; see the file COPYING.LIB.  If not, write to the
-    Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
-    02110-1301, USA.
-*/
-
-#include "timestampattribute.h"
-
-#include <QByteArray>
-
-#include <akonadi/attribute.h>
-
-TimestampAttribute::TimestampAttribute( uint timestamp )
-        : mTimestamp( timestamp )
-{
-}
-
-void TimestampAttribute::setTimestamp( uint timestamp )
-{
-    mTimestamp = timestamp;
-}
-
-uint TimestampAttribute::timestamp() const
-{
-    return mTimestamp;
-}
-
-QByteArray TimestampAttribute::type() const
-{
-    return "timestamp";
-}
-
-Akonadi::Attribute *TimestampAttribute::clone() const
-{
-    return new TimestampAttribute( mTimestamp );
-}
-
-QByteArray TimestampAttribute::serialized() const
-{
-    return QByteArray::number( mTimestamp );
-}
-
-void TimestampAttribute::deserialize( const QByteArray &data )
-{
-    mTimestamp = data.toInt();
-}
diff --git a/resources/imap/timestampattribute.h b/resources/imap/timestampattribute.h
deleted file mode 100644
index 1675acb..0000000
--- a/resources/imap/timestampattribute.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
-    Copyright (c) 2010 Klarälvdalens Datakonsult AB,
-                       a KDAB Group company <info at kdab.com>
-    Author: Kevin Ottens <kevin at kdab.com>
-
-    This library is free software; you can redistribute it and/or modify it
-    under the terms of the GNU Library General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or (at your
-    option) any later version.
-
-    This library is distributed in the hope that it will be useful, but WITHOUT
-    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
-    License for more details.
-
-    You should have received a copy of the GNU Library General Public License
-    along with this library; see the file COPYING.LIB.  If not, write to the
-    Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
-    02110-1301, USA.
-*/
-
-#ifndef TIMESTAMPATTRIBUTE_H
-#define TIMESTAMPATTRIBUTE_H
-
-#include <akonadi/attribute.h>
-
-class TimestampAttribute : public Akonadi::Attribute
-{
-public:
-    explicit TimestampAttribute( uint timestamp = 0 );
-    void setTimestamp( uint timestamp );
-    uint timestamp() const;
-    virtual QByteArray type() const;
-    virtual Attribute *clone() const;
-    virtual QByteArray serialized() const;
-    virtual void deserialize( const QByteArray &data );
-
-private:
-    uint mTimestamp;
-};
-
-#endif


commit 5a493687dfd79e3befaa186ee1e3cbcb7c524b79
Author: Christian Mollekopf <chrigi_1 at fastmail.fm>
Date:   Tue Nov 4 14:50:27 2014 +0100

    KolabResource: We no longer require the timestampattribute

diff --git a/resources/kolab/kolabresource.cpp b/resources/kolab/kolabresource.cpp
index 7c7576e..576224c 100644
--- a/resources/kolab/kolabresource.cpp
+++ b/resources/kolab/kolabresource.cpp
@@ -22,7 +22,6 @@
 #include "setupserver.h"
 #include <resourcestateinterface.h>
 #include <resourcestate.h>
-#include <timestampattribute.h>
 #include <retrieveitemstask.h>
 #include <collectionannotationsattribute.h>
 #include <changecollectiontask.h>





More information about the commits mailing list