diff --git a/autotests/data/dataitemmultifetchjob-error.txt b/autotests/data/dataitemmultifetchjob-error.txt new file mode 100644 index 0000000..ada1fb0 --- /dev/null +++ b/autotests/data/dataitemmultifetchjob-error.txt @@ -0,0 +1,3 @@ +C: PROPFIND /does_not_exist HTTP/1.1 +S: HTTP/1.1 404 Not found +X diff --git a/src/common/davcollectionsmultifetchjob.cpp b/src/common/davcollectionsmultifetchjob.cpp index 1d04c8b..89914f7 100644 --- a/src/common/davcollectionsmultifetchjob.cpp +++ b/src/common/davcollectionsmultifetchjob.cpp @@ -1,66 +1,69 @@ /* SPDX-FileCopyrightText: 2010 Tobias Koenig SPDX-License-Identifier: LGPL-2.0-or-later */ #include "davcollectionsmultifetchjob.h" #include "davcollectionsfetchjob.h" using namespace KDAV; namespace KDAV { 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(); } } diff --git a/src/common/davcollectionsmultifetchjob.h b/src/common/davcollectionsmultifetchjob.h index a704540..9bf9a6c 100644 --- a/src/common/davcollectionsmultifetchjob.h +++ b/src/common/davcollectionsmultifetchjob.h @@ -1,71 +1,71 @@ /* SPDX-FileCopyrightText: 2010 Tobias Koenig SPDX-License-Identifier: LGPL-2.0-or-later */ #ifndef KDAV_DAVCOLLECTIONSMULTIFETCHJOB_H #define KDAV_DAVCOLLECTIONSMULTIFETCHJOB_H #include "kdav_export.h" #include "davcollection.h" #include "davurl.h" -#include +#include #include namespace KDAV { class DavCollectionsMultiFetchJobPrivate; /** * @short A job that fetches all DAV collection. * * This job is used to fetch all DAV collection that are available * under a certain list of DAV urls. * * @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 public: /** * Creates a new dav collections multi fetch job. * * @param urls The list of DAV urls whose sub collections shall be fetched. * @param parent The parent object. */ explicit DavCollectionsMultiFetchJob(const DavUrl::List &urls, QObject *parent = nullptr); ~DavCollectionsMultiFetchJob(); /** * Starts the job. */ void start() override; /** * Returns the list of fetched DAV collections. */ Q_REQUIRED_RESULT DavCollection::List collections() const; Q_SIGNALS: /** * This signal is emitted every time a new collection has been discovered. * * @param collectionUrl The URL of the discovered collection * @param configuredUrl The URL given to the job */ void collectionDiscovered(KDAV::Protocol protocol, const QString &collectionUrl, const QString &configuredUrl); private: - void davJobFinished(KJob *); + void slotResult(KJob *) override; const std::unique_ptr d; }; } #endif