File indexing completed on 2024-11-10 04:40:44

0001 /*
0002     SPDX-FileCopyrightText: 2014 Christian Mollekopf <mollekopf@kolabsys.com>
0003 
0004     SPDX-License-Identifier: LGPL-2.0-or-later
0005 */
0006 namespace Akonadi
0007 {
0008 class Item;
0009 }
0010 
0011 #include "relationsync.h"
0012 #include "akonadicore_debug.h"
0013 
0014 #include "jobs/relationcreatejob.h"
0015 #include "jobs/relationdeletejob.h"
0016 #include "jobs/relationfetchjob.h"
0017 
0018 using namespace Akonadi;
0019 
0020 RelationSync::RelationSync(QObject *parent)
0021     : Job(parent)
0022 {
0023 }
0024 
0025 RelationSync::~RelationSync()
0026 {
0027 }
0028 
0029 void RelationSync::setRemoteRelations(const Akonadi::Relation::List &relations)
0030 {
0031     mRemoteRelations = relations;
0032     mRemoteRelationsSet = true;
0033     diffRelations();
0034 }
0035 
0036 void RelationSync::doStart()
0037 {
0038     auto fetch = new Akonadi::RelationFetchJob({Akonadi::Relation::GENERIC}, this);
0039     connect(fetch, &KJob::result, this, &RelationSync::onLocalFetchDone);
0040 }
0041 
0042 void RelationSync::onLocalFetchDone(KJob *job)
0043 {
0044     auto fetch = static_cast<Akonadi::RelationFetchJob *>(job);
0045     mLocalRelations = fetch->relations();
0046     mLocalRelationsFetched = true;
0047     diffRelations();
0048 }
0049 
0050 void RelationSync::diffRelations()
0051 {
0052     if (!mRemoteRelationsSet || !mLocalRelationsFetched) {
0053         qCDebug(AKONADICORE_LOG) << "waiting for delivery: " << mRemoteRelationsSet << mLocalRelationsFetched;
0054         return;
0055     }
0056 
0057     QHash<QByteArray, Akonadi::Relation> relationByRid;
0058     for (const Akonadi::Relation &localRelation : std::as_const(mLocalRelations)) {
0059         if (!localRelation.remoteId().isEmpty()) {
0060             relationByRid.insert(localRelation.remoteId(), localRelation);
0061         }
0062     }
0063 
0064     for (const Akonadi::Relation &remoteRelation : std::as_const(mRemoteRelations)) {
0065         if (relationByRid.contains(remoteRelation.remoteId())) {
0066             relationByRid.remove(remoteRelation.remoteId());
0067         } else {
0068             // New relation or had its GID updated, so create one now
0069             auto createJob = new RelationCreateJob(remoteRelation, this);
0070             connect(createJob, &KJob::result, this, &RelationSync::checkDone);
0071         }
0072     }
0073 
0074     for (const Akonadi::Relation &removedRelation : std::as_const(relationByRid)) {
0075         // Removed remotely, remove locally
0076         auto removeJob = new RelationDeleteJob(removedRelation, this);
0077         connect(removeJob, &KJob::result, this, &RelationSync::checkDone);
0078     }
0079     checkDone();
0080 }
0081 
0082 void RelationSync::slotResult(KJob *job)
0083 {
0084     if (job->error()) {
0085         qCWarning(AKONADICORE_LOG) << "Error during CollectionSync: " << job->errorString() << job->metaObject()->className();
0086         // pretend there were no errors
0087         Akonadi::Job::removeSubjob(job);
0088     } else {
0089         Akonadi::Job::slotResult(job);
0090     }
0091 }
0092 
0093 void RelationSync::checkDone()
0094 {
0095     if (hasSubjobs()) {
0096         qCDebug(AKONADICORE_LOG) << "Still going";
0097         return;
0098     }
0099     qCDebug(AKONADICORE_LOG) << "done";
0100     emitResult();
0101 }
0102 
0103 #include "moc_relationsync.cpp"