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 }