diff --git a/src/common/davcollectionsmultifetchjob.h b/src/common/davcollectionsmultifetchjob.h --- a/src/common/davcollectionsmultifetchjob.h +++ b/src/common/davcollectionsmultifetchjob.h @@ -12,7 +12,7 @@ #include "davcollection.h" #include "davurl.h" -#include +#include #include @@ -28,7 +28,7 @@ * @note This class just combines multiple calls of DavCollectionsFetchJob * into one job. */ -class KDAV_EXPORT DavCollectionsMultiFetchJob : public KJob +class KDAV_EXPORT DavCollectionsMultiFetchJob : public KCompositeJob { Q_OBJECT @@ -62,7 +62,7 @@ void collectionDiscovered(KDAV::Protocol protocol, const QString &collectionUrl, const QString &configuredUrl); private: - void davJobFinished(KJob *); + void slotResult(KJob *) override; const std::unique_ptr d; }; diff --git a/src/common/davcollectionsmultifetchjob.cpp b/src/common/davcollectionsmultifetchjob.cpp --- a/src/common/davcollectionsmultifetchjob.cpp +++ b/src/common/davcollectionsmultifetchjob.cpp @@ -14,53 +14,56 @@ class DavCollectionsMultiFetchJobPrivate { public: - DavUrl::List mUrls; DavCollection::List mCollections; - int mSubJobCount = -1; }; } DavCollectionsMultiFetchJob::DavCollectionsMultiFetchJob(const DavUrl::List &urls, QObject *parent) - : KJob(parent) + : KCompositeJob(parent) , d(new DavCollectionsMultiFetchJobPrivate) { - d->mUrls = urls; - d->mSubJobCount = urls.size(); + for (const DavUrl &url : qAsConst(urls)) { + DavCollectionsFetchJob *job = new DavCollectionsFetchJob(url, this); + connect(job, &DavCollectionsFetchJob::collectionDiscovered, this, &DavCollectionsMultiFetchJob::collectionDiscovered); + addSubjob(job); + } } DavCollectionsMultiFetchJob::~DavCollectionsMultiFetchJob() = default; void DavCollectionsMultiFetchJob::start() { - if (d->mUrls.isEmpty()) { + if (!hasSubjobs()) { emitResult(); - } - - for (const DavUrl &url : qAsConst(d->mUrls)) { - DavCollectionsFetchJob *job = new DavCollectionsFetchJob(url, this); - connect(job, &DavCollectionsFetchJob::result, this, &DavCollectionsMultiFetchJob::davJobFinished); - connect(job, &DavCollectionsFetchJob::collectionDiscovered, this, &DavCollectionsMultiFetchJob::collectionDiscovered); - job->start(); + } else { + for (KJob *job : subjobs()) { + job->start(); + } } } DavCollection::List DavCollectionsMultiFetchJob::collections() const { return d->mCollections; } -void DavCollectionsMultiFetchJob::davJobFinished(KJob *job) +void DavCollectionsMultiFetchJob::slotResult(KJob *job) { - DavCollectionsFetchJob *fetchJob = qobject_cast(job); + // If we use KCompositeJob::slotResult(job) we end up with behaviour that's very + // hard to unittest: the valid URLs might or might not get processed. + // Let's wait until all subjobs are done before emitting result. - if (job->error()) { + if (job->error() && !error()) { + // Store error only if first error setError(job->error()); setErrorText(job->errorText()); - } else { + } + if (!job->error()) { + DavCollectionsFetchJob *fetchJob = qobject_cast(job); d->mCollections << fetchJob->collections(); } - - if (--d->mSubJobCount == 0) { + removeSubjob(job); + if (!hasSubjobs()) { emitResult(); } }