File indexing completed on 2025-02-16 04:50:08

0001 /*
0002     SPDX-FileCopyrightText: 2019 Krzysztof Nowicki <krissn@op.pl>
0003 
0004     SPDX-License-Identifier: LGPL-2.0-or-later
0005 */
0006 
0007 #pragma once
0008 
0009 #include <QList>
0010 
0011 #include "ewsjob.h"
0012 
0013 template<typename Req, typename ReqItem, typename RespItem>
0014 class EwsAbstractChunkedJob
0015 {
0016 public:
0017     EwsAbstractChunkedJob(unsigned int chunkSize);
0018     ~EwsAbstractChunkedJob() = default;
0019 
0020     using ReqItemList = QList<ReqItem>;
0021     using RespItemList = QList<RespItem>;
0022 
0023     void setItems(const ReqItemList &items);
0024     const RespItemList &responses() const;
0025 
0026     template<typename ReqSetupFn, typename RespGetFn, typename ProgressFn, typename ResultFn>
0027     void start(ReqSetupFn reqSetupFn, RespGetFn respGetFn, ProgressFn progressFn, ResultFn resultFn);
0028 
0029 private:
0030     unsigned int mChunkSize;
0031     unsigned int mItemsDone;
0032     Req *mRequest = nullptr;
0033     ReqItemList mItems;
0034     RespItemList mResponses;
0035 };
0036 
0037 template<typename Req, typename ReqItem, typename RespItem>
0038 EwsAbstractChunkedJob<Req, ReqItem, RespItem>::EwsAbstractChunkedJob(unsigned int chunkSize)
0039     : mChunkSize(chunkSize)
0040     , mItemsDone(0)
0041 {
0042 }
0043 
0044 template<typename Req, typename ReqItem, typename RespItem>
0045 void EwsAbstractChunkedJob<Req, ReqItem, RespItem>::setItems(const ReqItemList &items)
0046 {
0047     mItems = items;
0048 }
0049 
0050 template<typename Req, typename ReqItem, typename RespItem>
0051 const QList<RespItem> &EwsAbstractChunkedJob<Req, ReqItem, RespItem>::responses() const
0052 {
0053     return mResponses;
0054 }
0055 
0056 template<typename Req, typename ReqItem, typename RespItem>
0057 template<typename ReqSetupFn, typename RespGetFn, typename ProgressFn, typename ResultFn>
0058 void EwsAbstractChunkedJob<Req, ReqItem, RespItem>::start(ReqSetupFn reqSetupFn, RespGetFn respGetFn, ProgressFn progressFn, ResultFn resultFn)
0059 {
0060     int itemsToDo = qMin<int>(mItems.size() - mItemsDone, mChunkSize);
0061     if (itemsToDo == 0) {
0062         resultFn(true, QString());
0063         return;
0064     }
0065 
0066     mRequest = reqSetupFn(mItems.cbegin() + mItemsDone, mItems.cbegin() + mItemsDone + itemsToDo);
0067     if (!mRequest) {
0068         resultFn(false, QStringLiteral("Failed to set-up request"));
0069         return;
0070     }
0071 
0072     mItemsDone += itemsToDo;
0073 
0074     QObject::connect(mRequest, &KJob::result, [this, reqSetupFn, respGetFn, progressFn, resultFn, itemsToDo](KJob *job) {
0075         if (job->error()) {
0076             resultFn(false, job->errorString());
0077             return;
0078         }
0079 
0080         Req *req = qobject_cast<Req *>(job);
0081         if (!req) {
0082             resultFn(false, QStringLiteral("Incorrect request object type"));
0083             return;
0084         }
0085 
0086         auto responses = respGetFn(req);
0087         Q_ASSERT(responses.size() == itemsToDo);
0088         mResponses += responses;
0089 
0090         progressFn(mItemsDone * 100 / mItems.size());
0091 
0092         start(reqSetupFn, respGetFn, progressFn, resultFn);
0093     });
0094 
0095     mRequest->start();
0096 }