File indexing completed on 2024-11-24 04:44:17

0001 /*
0002     SPDX-FileCopyrightText: 2014 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>
0003     SPDX-FileContributor: Kevin Krammer <kevin.krammer@kdab.com>
0004 
0005     SPDX-License-Identifier: LGPL-2.0-or-later
0006 */
0007 
0008 #include "kolabchangeitemstagstask.h"
0009 #include "kolabresource_debug.h"
0010 
0011 #include <Akonadi/ItemFetchJob>
0012 #include <Akonadi/ItemFetchScope>
0013 #include <Akonadi/TagFetchJob>
0014 #include <Akonadi/TagFetchScope>
0015 
0016 KolabChangeItemsTagsTask::KolabChangeItemsTagsTask(const ResourceStateInterface::Ptr &resource,
0017                                                    const QSharedPointer<TagConverter> &tagConverter,
0018                                                    QObject *parent)
0019     : KolabRelationResourceTask(resource, parent)
0020     , mTagConverter(tagConverter)
0021 {
0022 }
0023 
0024 void KolabChangeItemsTagsTask::startRelationTask(KIMAP::Session *session)
0025 {
0026     mSession = session;
0027 
0028     // It's entirely possible that we don't have an rid yet
0029 
0030     // compile a set of changed tags
0031     const auto addedTags{resourceState()->addedTags()};
0032     for (const Akonadi::Tag &tag : addedTags) {
0033         mChangedTags.append(tag);
0034     }
0035     const auto removedTags{resourceState()->removedTags()};
0036     for (const Akonadi::Tag &tag : removedTags) {
0037         mChangedTags.append(tag);
0038     }
0039     qCDebug(KOLABRESOURCE_LOG) << mChangedTags;
0040 
0041     processNextTag();
0042 }
0043 
0044 void KolabChangeItemsTagsTask::processNextTag()
0045 {
0046     if (mChangedTags.isEmpty()) {
0047         changeProcessed();
0048         return;
0049     }
0050 
0051     // "take first"
0052     const Akonadi::Tag tag = mChangedTags.takeFirst();
0053 
0054     // We have to fetch it again in case it changed since the notification was emitted (which is likely)
0055     // Otherwise we get an empty remoteid for new tags that were immediately applied on an item
0056     auto fetch = new Akonadi::TagFetchJob(tag);
0057     fetch->fetchScope().setFetchRemoteId(true);
0058     connect(fetch, &KJob::result, this, &KolabChangeItemsTagsTask::onTagFetchDone);
0059 }
0060 
0061 void KolabChangeItemsTagsTask::onTagFetchDone(KJob *job)
0062 {
0063     if (job->error()) {
0064         qCWarning(KOLABRESOURCE_LOG) << "TagFetch failed: " << job->errorString();
0065         // TODO: we could continue for the other tags?
0066         cancelTask(job->errorString());
0067         return;
0068     }
0069 
0070     const Akonadi::Tag::List tags = static_cast<Akonadi::TagFetchJob *>(job)->tags();
0071     if (tags.size() != 1) {
0072         qCWarning(KOLABRESOURCE_LOG) << "Invalid number of tags retrieved: " << tags.size();
0073         // TODO: we could continue for the other tags?
0074         cancelTask(job->errorString());
0075         return;
0076     }
0077 
0078     auto fetch = new Akonadi::ItemFetchJob(tags.first());
0079     fetch->fetchScope().setCacheOnly(true);
0080     fetch->fetchScope().setAncestorRetrieval(Akonadi::ItemFetchScope::All);
0081     fetch->fetchScope().setFetchGid(true);
0082     fetch->fetchScope().fetchFullPayload(true);
0083     fetch->setProperty("tag", QVariant::fromValue(tags.first()));
0084     connect(fetch, &KJob::result, this, &KolabChangeItemsTagsTask::onItemsFetchDone);
0085 }
0086 
0087 void KolabChangeItemsTagsTask::onItemsFetchDone(KJob *job)
0088 {
0089     if (job->error()) {
0090         qCWarning(KOLABRESOURCE_LOG) << "ItemFetch failed: " << job->errorString();
0091         // TODO: we could continue for the other tags?
0092         cancelTask(job->errorString());
0093         return;
0094     }
0095 
0096     auto changeHelper = new TagChangeHelper(this);
0097 
0098     connect(changeHelper, &TagChangeHelper::applyCollectionChanges, this, &KolabChangeItemsTagsTask::onApplyCollectionChanged);
0099     connect(changeHelper, &TagChangeHelper::cancelTask, this, &KolabChangeItemsTagsTask::onCancelTask);
0100     connect(changeHelper, &TagChangeHelper::changeCommitted, this, &KolabChangeItemsTagsTask::onChangeCommitted);
0101 
0102     const Akonadi::Item::List items = static_cast<Akonadi::ItemFetchJob *>(job)->items();
0103     qCDebug(KOLABRESOURCE_LOG) << items.size();
0104     const auto tag = job->property("tag").value<Akonadi::Tag>();
0105     {
0106         qCDebug(KOLABRESOURCE_LOG) << "Writing " << tag.name() << " with " << items.size() << " members to the server: ";
0107         for (const Akonadi::Item &item : items) {
0108             qCDebug(KOLABRESOURCE_LOG) << "member(localid, remoteid): " << item.id() << item.remoteId();
0109         }
0110     }
0111     Q_ASSERT(tag.isValid());
0112     changeHelper->start(tag, mTagConverter->createMessage(tag, items, resourceState()->userName()), mSession);
0113 }
0114 
0115 void KolabChangeItemsTagsTask::onApplyCollectionChanged(const Akonadi::Collection &collection)
0116 {
0117     mRelationCollection = collection;
0118     applyCollectionChanges(collection);
0119 }
0120 
0121 void KolabChangeItemsTagsTask::onCancelTask(const QString &errorText)
0122 {
0123     // TODO: we could continue for the other tags?
0124     cancelTask(errorText);
0125 }
0126 
0127 void KolabChangeItemsTagsTask::onChangeCommitted()
0128 {
0129     processNextTag();
0130 }
0131 
0132 #include "moc_kolabchangeitemstagstask.cpp"