Branch 'kolab/integration/4.13.0' - 4 commits - resources/kolab
Christian Mollekopf
mollekopf at kolabsys.com
Thu Jan 8 17:12:14 CET 2015
resources/kolab/CMakeLists.txt | 1
resources/kolab/kolabchangeitemstagstask.cpp | 14 -
resources/kolab/kolabchangetagtask.cpp | 8
resources/kolab/kolabretrievecollectionstask.cpp | 1
resources/kolab/tagchangehelper.cpp | 41 ----
resources/kolab/updatemessagejob.cpp | 233 +++++++++++++++++++++++
resources/kolab/updatemessagejob.h | 84 ++++++++
7 files changed, 337 insertions(+), 45 deletions(-)
New commits:
commit b27e0473d334602a52c3cf9b2e6e6661b5cffad2
Author: Christian Mollekopf <chrigi_1 at fastmail.fm>
Date: Thu Jan 8 17:11:58 2015 +0100
Revert "Filter tag items by resource."
This reverts commit c9761baf173a01ce4a1f8e6cfccc7d7b4b45690c.
This didn't work and is now done in the akonadi server.
Conflicts:
resources/kolab/kolabchangeitemstagstask.cpp
diff --git a/resources/kolab/kolabchangeitemstagstask.cpp b/resources/kolab/kolabchangeitemstagstask.cpp
index 785664d..cf1564b 100644
--- a/resources/kolab/kolabchangeitemstagstask.cpp
+++ b/resources/kolab/kolabchangeitemstagstask.cpp
@@ -103,13 +103,7 @@ void KolabChangeItemsTagsTask::onItemsFetchDone(KJob *job)
return;
}
- Akonadi::Item::List items;
- //Filter by resource as all other references make no sense
- Q_FOREACH (const Akonadi::Item &i, static_cast<Akonadi::ItemFetchJob*>(job)->items()) {
- if (i.parentCollection().resource() == resourceState()->resourceIdentifier()) {
- items << i;
- }
- }
+ const Akonadi::Item::List items = static_cast<Akonadi::ItemFetchJob*>(job)->items();
kDebug() << items.size();
TagChangeHelper *changeHelper = new TagChangeHelper(this);
diff --git a/resources/kolab/kolabchangetagtask.cpp b/resources/kolab/kolabchangetagtask.cpp
index e6b31ad..f58e85d 100644
--- a/resources/kolab/kolabchangetagtask.cpp
+++ b/resources/kolab/kolabchangetagtask.cpp
@@ -52,13 +52,7 @@ void KolabChangeTagTask::onItemsFetchDone(KJob *job)
return;
}
- Akonadi::Item::List items;
- //Filter by resource as all other references make no sense
- Q_FOREACH (const Akonadi::Item &i, static_cast<Akonadi::ItemFetchJob*>(job)->items()) {
- if (i.parentCollection().resource() == resourceState()->resourceIdentifier()) {
- items << i;
- }
- }
+ const Akonadi::Item::List items = static_cast<Akonadi::ItemFetchJob*>(job)->items();
TagChangeHelper *changeHelper = new TagChangeHelper(this);
commit c4444aa93b5ff32c55b12421eaec93ba756b5b71
Author: Christian Mollekopf <chrigi_1 at fastmail.fm>
Date: Thu Jan 8 17:10:36 2015 +0100
Debug info for tags.
diff --git a/resources/kolab/kolabchangeitemstagstask.cpp b/resources/kolab/kolabchangeitemstagstask.cpp
index 21269fe..785664d 100644
--- a/resources/kolab/kolabchangeitemstagstask.cpp
+++ b/resources/kolab/kolabchangeitemstagstask.cpp
@@ -120,6 +120,12 @@ void KolabChangeItemsTagsTask::onItemsFetchDone(KJob *job)
connect(changeHelper, SIGNAL(changeCommitted()), this, SLOT(onChangeCommitted()));
const Akonadi::Tag tag = job->property("tag").value<Akonadi::Tag>();
+ {
+ kDebug() << "Writing " << tag.name() << " with " << items.size() << " members to the server: ";
+ foreach (const Akonadi::Item &item, items) {
+ kDebug() << "member(localid, remoteid): " << item.id() << item.remoteId();
+ }
+ }
Q_ASSERT(tag.isValid());
changeHelper->start(tag, mTagConverter->createMessage(tag, items, resourceState()->userName()), mSession);
}
commit d071f3ad1846a9d94f58af57aa5a76047c8594e5
Author: Christian Mollekopf <chrigi_1 at fastmail.fm>
Date: Thu Jan 8 17:10:25 2015 +0100
UpdateMessageJob to prepare for tag merging.
diff --git a/resources/kolab/CMakeLists.txt b/resources/kolab/CMakeLists.txt
index 7dd587c..5e0a889 100644
--- a/resources/kolab/CMakeLists.txt
+++ b/resources/kolab/CMakeLists.txt
@@ -28,6 +28,7 @@ set(kolabresource_LIB_SRCS
tagchangehelper.cpp
kolabretrievetagstask.cpp
kolabsettings.cpp
+ updatemessagejob.cpp
)
kde4_add_kcfg_files(kolabresource_LIB_SRCS ../imap/settingsbase.kcfgc)
diff --git a/resources/kolab/tagchangehelper.cpp b/resources/kolab/tagchangehelper.cpp
index 73e8c78..56d021a 100644
--- a/resources/kolab/tagchangehelper.cpp
+++ b/resources/kolab/tagchangehelper.cpp
@@ -23,6 +23,7 @@
#include "kolabrelationresourcetask.h"
#include "kolabhelpers.h"
+#include "updatemessagejob.h"
#include <imapflags.h>
#include <uidnextattribute.h>
@@ -62,6 +63,13 @@ KMime::Message::Ptr TagConverter::createMessage(const Akonadi::Tag &tag, const A
return message;
}
+struct TagMerger : public Merger {
+ virtual KMime::Message::Ptr merge(KMime::Message::Ptr newMessage, QList<KMime::Message::Ptr> conflictingMessages) const
+ {
+ return newMessage;
+ }
+};
+
void TagChangeHelper::start(const Akonadi::Tag &tag, const KMime::Message::Ptr &message, KIMAP::Session *session)
{
Q_ASSERT(tag.isValid());
@@ -69,13 +77,9 @@ void TagChangeHelper::start(const Akonadi::Tag &tag, const KMime::Message::Ptr &
const qint64 oldUid = tag.remoteId().toLongLong();
kDebug(5327) << mailBox << oldUid;
- qint64 uidNext = -1;
- // Using uidnext here is mutually exclusive with doing the item sync
- // if (UidNextAttribute *uidNextAttr = mTask->relationCollection().attribute<UidNextAttribute>()) {
- // uidNext = uidNextAttr->uidNext();
- // }
+ const qint64 uidNext = -1;
- ReplaceMessageJob *append = new ReplaceMessageJob(message, session, mailBox, uidNext, oldUid, this);
+ UpdateMessageJob *append = new UpdateMessageJob(message, session, tag.gid(), QSharedPointer<TagMerger>(new TagMerger), mailBox, uidNext, oldUid, this);
connect(append, SIGNAL(result(KJob*)), this, SLOT(onReplaceDone(KJob*)));
append->setProperty("tag", QVariant::fromValue(tag));
append->start();
@@ -86,31 +90,6 @@ void TagChangeHelper::recordNewUid(qint64 newUid, Akonadi::Tag tag)
Q_ASSERT(newUid > 0);
Q_ASSERT(tag.isValid());
- Akonadi::Collection c = mTask->relationCollection();
-
- // Get the current uid next value and store it
- // UidNextAttribute *uidAttr = 0;
- // int oldNextUid = 0;
- // if (c.hasAttribute("uidnext")) {
- // uidAttr = static_cast<UidNextAttribute*>(c.attribute("uidnext"));
- // oldNextUid = uidAttr->uidNext();
- // }
-
- // If the uid we just got back is the expected next one of the box
- // then update the property to the probable next uid to keep the cache in sync.
- // If not something happened in our back, so we don't update and a refetch will
- // happen at some point.
- // if (newUid == oldNextUid) {
- // if (uidAttr == 0) {
- // uidAttr = new UidNextAttribute(newUid + 1);
- // c.addAttribute(uidAttr);
- // } else {
- // uidAttr->setUidNext(newUid + 1);
- // }
-
- // emit applyCollectionChanges(c);
- // }
-
const QByteArray remoteId = QByteArray::number(newUid);
kDebug(5327) << "Setting remote ID to " << remoteId << " on tag with local id: " << tag.id();
//Make sure we only update the id and send nothing else
diff --git a/resources/kolab/updatemessagejob.cpp b/resources/kolab/updatemessagejob.cpp
new file mode 100644
index 0000000..a5149e1
--- /dev/null
+++ b/resources/kolab/updatemessagejob.cpp
@@ -0,0 +1,233 @@
+/*
+ Copyright (c) 2014 Christian Mollekopf <mollekopf at kolabsys.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 "updatemessagejob.h"
+
+#include <KIMAP/AppendJob>
+#include <KIMAP/SearchJob>
+#include <KIMAP/SelectJob>
+#include <KIMAP/StoreJob>
+#include <KIMAP/FetchJob>
+#include <KIMAP/ImapSet>
+#include <KDebug>
+#include <KMime/Message>
+#include <replacemessagejob.h>
+
+#include "imapflags.h"
+
+//Check if the expected uid message is still there => no modification, replace message.
+//otherwise search for uptodate message by subject containing UID, merge contents, and replace message
+
+UpdateMessageJob::UpdateMessageJob(const KMime::Message::Ptr &msg, KIMAP::Session *session, const QByteArray &kolabUid, QSharedPointer<Merger> merger, const QString &mailbox, qint64 uidNext, qint64 oldUid, QObject *parent)
+ : KJob(parent),
+ mSession(session),
+ mMessage(msg),
+ mMailbox(mailbox),
+ mUidNext(uidNext),
+ mOldUid(oldUid),
+ mNewUid(-1),
+ mMessageId(msg->messageID()->asUnicodeString().toUtf8()),
+ mKolabUid(kolabUid),
+ mMerger(merger)
+{
+}
+
+void UpdateMessageJob::start()
+{
+ KIMAP::FetchJob * fetchJob = new KIMAP::FetchJob(mSession);
+
+ fetchJob->setSequenceSet(KIMAP::ImapSet(mOldUid));
+ fetchJob->setUidBased(true);
+
+ KIMAP::FetchJob::FetchScope scope;
+ scope.parts.clear();
+ scope.mode = KIMAP::FetchJob::FetchScope::Headers;
+ fetchJob->setScope(scope);
+
+ connect(fetchJob, SIGNAL(headersReceived(QString,
+ QMap<qint64,qint64>,
+ QMap<qint64,qint64>,
+ QMap<qint64,KIMAP::MessageAttribute>,
+ QMap<qint64,KIMAP::MessageFlags>,
+ QMap<qint64,KIMAP::MessagePtr>)),
+ this, SLOT(onHeadersReceived(QString,
+ QMap<qint64,qint64>,
+ QMap<qint64,qint64>,
+ QMap<qint64,KIMAP::MessageAttribute>,
+ QMap<qint64,KIMAP::MessageFlags>,
+ QMap<qint64,KIMAP::MessagePtr>)));
+ connect(fetchJob, SIGNAL(result(KJob*)),
+ this, SLOT(onHeadersFetchDone(KJob*)));
+ fetchJob->start();
+
+
+}
+
+void UpdateMessageJob::onHeadersReceived(QString,
+ QMap<qint64,qint64> uids,
+ QMap<qint64,qint64>,
+ QMap<qint64,KIMAP::MessageAttribute>,
+ QMap<qint64,KIMAP::MessageFlags> flags,
+ QMap<qint64,KIMAP::MessagePtr>)
+{
+ //Filter deleted messages
+ foreach (qint64 number, uids.keys()) { //krazy:exclude=foreach
+ // const KMime::Message::Ptr msg = messages[number];
+ if (!flags[number].contains(ImapFlags::Deleted)) {
+ mFoundUids << uids[number];
+ }
+ }
+}
+
+void UpdateMessageJob::onHeadersFetchDone(KJob *job)
+{
+ if (job->error()) {
+ kWarning() << "Failed to fetch message: " << job->errorString();
+ }
+ if (mFoundUids.size() >= 1) {
+ kDebug() << "Fast-forward update, replacing message.";
+ appendMessage();
+ } else {
+ if (mSession->selectedMailBox() != mMailbox) {
+ KIMAP::SelectJob *select = new KIMAP::SelectJob(mSession);
+ select->setMailBox(mMailbox);
+ connect(select, SIGNAL(result(KJob*)), this, SLOT(onSelectDone(KJob*)));
+ select->start();
+ } else {
+ searchForLatestVersion();
+ }
+ }
+}
+
+void UpdateMessageJob::onSelectDone(KJob *job)
+{
+ if (job->error()) {
+ kWarning() << job->errorString();
+ setError(KJob::UserDefinedError);
+ emitResult();
+ } else {
+ searchForLatestVersion();
+ }
+}
+
+void UpdateMessageJob::searchForLatestVersion()
+{
+ KIMAP::SearchJob *search = new KIMAP::SearchJob(mSession);
+ search->setUidBased(true);
+ search->setSearchLogic(KIMAP::SearchJob::And);
+ search->addSearchCriteria(KIMAP::SearchJob::Header, "Subject " + mKolabUid);
+ connect(search, SIGNAL(result(KJob*)),
+ this, SLOT(onSearchDone(KJob*)));
+ search->start();
+}
+
+void UpdateMessageJob::onSearchDone(KJob *job)
+{
+ if (job->error()) {
+ kWarning() << job->errorString();
+ setError(KJob::UserDefinedError);
+ emitResult();
+ return;
+ }
+
+ KIMAP::SearchJob *search = static_cast<KIMAP::SearchJob*>(job);
+
+ if (search->results().count() >= 1) {
+ mOldUid = search->results().first();
+ //TODO deal with all of them
+
+ KIMAP::FetchJob * fetchJob = new KIMAP::FetchJob(mSession);
+ fetchJob->setSequenceSet(KIMAP::ImapSet(mOldUid));
+ fetchJob->setUidBased(true);
+
+ KIMAP::FetchJob::FetchScope scope;
+ scope.parts.clear();
+ scope.mode = KIMAP::FetchJob::FetchScope::Full;
+ fetchJob->setScope(scope);
+
+ connect(fetchJob, SIGNAL(headersReceived(QString,
+ QMap<qint64,qint64>,
+ QMap<qint64,qint64>,
+ QMap<qint64,KIMAP::MessageAttribute>,
+ QMap<qint64,KIMAP::MessageFlags>,
+ QMap<qint64,KIMAP::MessagePtr>)),
+ this, SLOT(onConflictingMessagesReceived(QString,
+ QMap<qint64,qint64>,
+ QMap<qint64,qint64>,
+ QMap<qint64,KIMAP::MessageAttribute>,
+ QMap<qint64,KIMAP::MessageFlags>,
+ QMap<qint64,KIMAP::MessagePtr>)));
+ connect(fetchJob, SIGNAL(result(KJob*)),
+ this, SLOT(onConflictingMessageFetchDone(KJob*)));
+ fetchJob->start();
+ } else {
+ kWarning() << "failed to find latest version of object";
+ appendMessage();
+ }
+}
+
+void UpdateMessageJob::onConflictingMessagesReceived(QString,
+ QMap<qint64,qint64> uids,
+ QMap<qint64,qint64>,
+ QMap<qint64,KIMAP::MessageAttribute>,
+ QMap<qint64,KIMAP::MessageFlags> flags,
+ QMap<qint64,KIMAP::MessagePtr> messages)
+{
+ foreach (qint64 number, uids.keys()) { //krazy:exclude=foreach
+ if (!flags[number].contains(ImapFlags::Deleted)) {
+ mMessagesToMerge << messages[number];
+ }
+ }
+}
+
+void UpdateMessageJob::onConflictingMessageFetchDone(KJob *job)
+{
+ if (job->error()) {
+ kWarning() << "Failed to retrieve messages to merge: " << job->errorString();
+ }
+ mMessage = mMerger->merge(mMessage, mMessagesToMerge);
+ appendMessage();
+}
+
+void UpdateMessageJob::appendMessage()
+{
+ const qint64 uidNext = -1;
+ ReplaceMessageJob *replace = new ReplaceMessageJob(mMessage, mSession, mMailbox, uidNext, mOldUid, this);
+ connect(replace, SIGNAL(result(KJob*)), this, SLOT(onReplaceDone(KJob*)));
+ replace->start();
+}
+
+void UpdateMessageJob::onReplaceDone(KJob *job)
+{
+ if (job->error()) {
+ kWarning() << job->errorString();
+ setError(KJob::UserDefinedError);
+ emitResult();
+ return;
+ }
+ ReplaceMessageJob *replaceJob = static_cast<ReplaceMessageJob*>(job);
+ mNewUid = replaceJob->newUid();
+ emitResult();
+}
+
+qint64 UpdateMessageJob::newUid() const
+{
+ return mNewUid;
+}
+
diff --git a/resources/kolab/updatemessagejob.h b/resources/kolab/updatemessagejob.h
new file mode 100644
index 0000000..99ddc90
--- /dev/null
+++ b/resources/kolab/updatemessagejob.h
@@ -0,0 +1,84 @@
+/*
+ Copyright (c) 2014 Christian Mollekopf <mollekopf at kolabsys.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 UPDATEMESSAGEJOB_H
+#define UPDATEMESSAGEJOB_H
+
+#include <KJob>
+#include <KMime/Message>
+#include <KIMAP/Session>
+#include <KIMAP/FetchJob>
+
+struct Merger {
+ virtual ~Merger() {}
+ virtual KMime::Message::Ptr merge(KMime::Message::Ptr newMessage, QList<KMime::Message::Ptr> conflictingMessages) const = 0;
+};
+
+/**
+ * This job appends a message, marks the old one as deleted, and returns the uid of the appended message.
+ */
+class UpdateMessageJob : public KJob
+{
+ Q_OBJECT
+public:
+ UpdateMessageJob(const KMime::Message::Ptr &msg, KIMAP::Session *session, const QByteArray &kolabUid, QSharedPointer<Merger> merger, const QString &mailbox, qint64 uidNext = -1, qint64 oldUid = -1, QObject *parent = 0);
+
+ qint64 newUid() const;
+
+ void start();
+
+private:
+ void searchForLatestVersion();
+ void appendMessage();
+
+private Q_SLOTS:
+ void onHeadersReceived(QString,
+ QMap<qint64,qint64> uids,
+ QMap<qint64,qint64>,
+ QMap<qint64,KIMAP::MessageAttribute>,
+ QMap<qint64,KIMAP::MessageFlags>,
+ QMap<qint64,KIMAP::MessagePtr>);
+ void onHeadersFetchDone(KJob *job);
+ void onSelectDone(KJob *job);
+ void onSearchDone(KJob *job);
+ void onConflictingMessagesReceived(QString,
+ QMap<qint64,qint64> uids,
+ QMap<qint64,qint64>,
+ QMap<qint64,KIMAP::MessageAttribute>,
+ QMap<qint64,KIMAP::MessageFlags>,
+ QMap<qint64,KIMAP::MessagePtr>);
+ void onConflictingMessageFetchDone(KJob *job);
+ void onReplaceDone(KJob *job);
+
+private:
+ KIMAP::Session *mSession;
+ KMime::Message::Ptr mMessage;
+ const QString mMailbox;
+ qint64 mUidNext;
+ qint64 mOldUid;
+ qint64 mNewUid;
+ const QByteArray mMessageId;
+ const QByteArray mKolabUid;
+ QList<qint64> mFoundUids;
+ QList<KIMAP::MessagePtr> mMessagesToMerge;
+ QSharedPointer<Merger> mMerger;
+};
+
+#endif
+
commit 87c14b51e97e99e9554cd1dfc874f18b7aa53b60
Author: Christian Mollekopf <chrigi_1 at fastmail.fm>
Date: Thu Jan 8 14:11:41 2015 +0100
Print mailbox where myrights failed.
diff --git a/resources/kolab/kolabretrievecollectionstask.cpp b/resources/kolab/kolabretrievecollectionstask.cpp
index 87956bc..353df77 100644
--- a/resources/kolab/kolabretrievecollectionstask.cpp
+++ b/resources/kolab/kolabretrievecollectionstask.cpp
@@ -157,6 +157,7 @@ void RetrieveMetadataJob::onRightsReceived( KJob *job )
mJobs--;
if ( job->error() ) {
kWarning() << "MyRights failed: " << job->errorString();
+ kWarning() << "mailbox " << static_cast<KIMAP::MyRightsJob*>( job )->mailBox();
setError(KJob::UserDefinedError);
checkDone();
return; // Well, no metadata for us then...
More information about the commits
mailing list