File indexing completed on 2024-05-12 05:22:15
0001 /* 0002 * This file is part of LibKGAPI library 0003 * 0004 * SPDX-FileCopyrightText: 2013 Daniel Vrátil <dvratil@redhat.com> 0005 * 0006 * SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL 0007 */ 0008 0009 #pragma once 0010 0011 #include "kgapicore_export.h" 0012 #include "types.h" 0013 0014 #include <QObject> 0015 0016 class QNetworkAccessManager; 0017 class QNetworkReply; 0018 class QNetworkRequest; 0019 0020 namespace KGAPI2 0021 { 0022 0023 /** 0024 * @headerfile job.h 0025 * @brief Abstract base class for all jobs in LibKGAPI 0026 * 0027 * Usual workflow of Job subclasses is to reimplement Job::start, 0028 * Job::dispatchRequest and Job::handleReply, then enqueue a QNetworkRequest using 0029 * Job::enqueueRequest. Authorization headers and standard query parameters will be 0030 * set by Job class. The request will automatically be scheduled in a queue and 0031 * dispatched by calling Job::dispatchRequest implementation. When a reply is received, 0032 * the Job will automatically perform error handling and if there is no error, the 0033 * reply is passed to implementation of Job::handleReply. 0034 * 0035 * Job is automatically started when program enters an event loop. 0036 * 0037 * @author Daniel Vrátil <dvratil@redhat.com> 0038 * @since 2.0 0039 */ 0040 class KGAPICORE_EXPORT Job : public QObject 0041 { 0042 Q_OBJECT 0043 0044 /** 0045 * @brief Maximum interval between requests. 0046 * 0047 * Some Google APIs have a quota on maximum amount of requests per account 0048 * per second. When this quota is exceeded, the Job will automatically increase 0049 * the interval between dispatching requests, wait for a while and then try 0050 * again. If however the interval is increased over @p maxTimeout, the job 0051 * will fail and finish immediately. By default @p maxTimeout is @p -1, which 0052 * allows the interval to be increased indefinitely. 0053 * 0054 * @see Job::maxTimeout, Job::setMaxTimeout 0055 */ 0056 Q_PROPERTY(int maxTimeout READ maxTimeout WRITE setMaxTimeout) 0057 0058 /** 0059 * @brief Whether the job is running 0060 * 0061 * This property indicates whether the job is running or not. The value is 0062 * set to @p true when the job is started (see Job::start) and back to 0063 * @p false right before Job::finished is emitted. 0064 * 0065 * @see Job::isRunning, Job::finished 0066 */ 0067 Q_PROPERTY(bool isRunning READ isRunning NOTIFY finished) 0068 public: 0069 /** 0070 * @brief Constructor for jobs that don't require authentication 0071 * 0072 * @param parent 0073 */ 0074 explicit Job(QObject *parent = nullptr); 0075 0076 /** 0077 * @brief Constructor for jobs that require authentication 0078 * 0079 * @param account Account to use to authenticate the requests send by this job 0080 * @param parent 0081 * @see Job::Account, Job::setAccount 0082 */ 0083 explicit Job(const AccountPtr &account, QObject *parent = nullptr); 0084 0085 struct KGAPICORE_EXPORT StandardParams { 0086 static const QString PrettyPrint; 0087 static const QString Fields; 0088 }; 0089 0090 /** 0091 * @brief Destructor 0092 */ 0093 ~Job() override; 0094 0095 /** 0096 * @brief Error code 0097 * 0098 * This method can only be called after the job has emitted Job::finished 0099 * signal. Calling this method on a running job will always return 0100 * KGAPI2::NoError. 0101 * 0102 * @return Returns code of occurred error or KGAPI2::NoError when no error 0103 * has occurred. 0104 */ 0105 KGAPI2::Error error() const; 0106 0107 /** 0108 * @brief Error string 0109 * 0110 * This method can only be called after the job has emitted Job::finished 0111 * signal. Calling this method on a running job will always return an empty 0112 * string. 0113 * 0114 * @return Returns localized description of error or an empty string if no 0115 * error has occurred. 0116 */ 0117 QString errorString() const; 0118 0119 /** 0120 * @brief Set maximum quota timeout 0121 * 0122 * Sets maximum interval for which the job should wait before trying to submit 0123 * a request that has previously failed due to exceeded quota. 0124 * 0125 * Default timeout is 1 seconds, then after every failed request the timeout 0126 * is increased exponentially until reaching @p maxTimeout. 0127 * 0128 * @param maxTimeout Maximum timeout (in seconds), or @p -1 for no timeout 0129 */ 0130 void setMaxTimeout(int maxTimeout); 0131 0132 /** 0133 * @brief Maximum quota limit. 0134 * 0135 * @return Returns maximum timeout in seconds or -1 if there is no timeout set. 0136 * @see Job::setMaxTimeout 0137 */ 0138 int maxTimeout() const; 0139 0140 /** 0141 * @brief Whether job is running 0142 * 0143 * A job is considered running from the moment it's started until 0144 * until Job::finished is emitted. Some methods should not be 0145 * called when a job is running. 0146 * 0147 * @return Returns whether this job is currently running. 0148 * @sa start() 0149 */ 0150 bool isRunning() const; 0151 0152 /** 0153 * @brief Set account to be used to authenticate requests 0154 * 0155 * By default, no account is set and all request are sent without any 0156 * authentication. 0157 * 0158 * @param account Account to use 0159 */ 0160 void setAccount(const AccountPtr &account); 0161 0162 /** 0163 * @brief Returns account used to authenticate requests 0164 * 0165 * For jobs that don't require authentication, this method returns a null 0166 * pointer. 0167 * 0168 * @return Am Account or a null pointer when no account was set. 0169 */ 0170 AccountPtr account() const; 0171 0172 /** 0173 * @brief Sets whether response will have indentations and line breaks. 0174 * 0175 * When this is false, it can reduce the response payload size, 0176 * which might lead to better performance in some environments. 0177 * Default is false. 0178 * 0179 * @param prettyPrint 0180 */ 0181 void setPrettyPrint(bool prettyPrint); 0182 0183 /** 0184 * @brief Returns prettyPrint query parameter. 0185 * 0186 * @return prettyPrint query parameter 0187 */ 0188 bool prettyPrint() const; 0189 0190 /** 0191 * @brief Set subset of fields to include in the response. 0192 * 0193 * Use for better performance. 0194 * 0195 * @param fields List of fields 0196 */ 0197 void setFields(const QStringList &fields); 0198 0199 static QString buildSubfields(const QString &field, const QStringList &fields); 0200 0201 /** 0202 * @brief Returns fields selector. 0203 * 0204 * @return List of fields 0205 */ 0206 QStringList fields() const; 0207 0208 /** 0209 * @brief Restarts this job 0210 * 0211 * When a job finishes, it's possible to run it again, without having 0212 * to create a new job. 0213 * 0214 * The job will throw away all results retrieved in previous run and retrieve 0215 * everything again. 0216 * 0217 * @see Job::aboutToStart 0218 */ 0219 void restart(); 0220 0221 Q_SIGNALS: 0222 0223 /** 0224 * @brief Emitted when @p job has finished 0225 * 0226 * The signal is emitted every time, no matter whether the job is successful 0227 * or an error has occurred. 0228 * 0229 * Subclasses should never ever emit this signal directly. 0230 * Use Job::emitFinished instead. 0231 * 0232 * @param job The job that has finished 0233 * @sa emitFinished() 0234 */ 0235 void finished(KGAPI2::Job *job); 0236 0237 /** 0238 * @brief Emitted when a job progress changes. 0239 * 0240 * Note that some jobs might not provide progress information, thus this 0241 * signal will never be emitted. 0242 * 0243 * @param job The job that the information relates to 0244 * @param processed Amount of already processed items 0245 * @param total Total amount of items to process 0246 */ 0247 void progress(KGAPI2::Job *job, int processed, int total); 0248 0249 protected: 0250 /** 0251 * @brief Set job error to @p error 0252 * 0253 * @param error Error code to set 0254 * @see Job::error 0255 */ 0256 void setError(KGAPI2::Error error); 0257 0258 /** 0259 * @brief Set job error description to @p errorString 0260 * 0261 * @param errorString Error description to set 0262 * @see Job::errorString 0263 */ 0264 void setErrorString(const QString &errorString); 0265 0266 /** 0267 * @brief Emits Job::finished() signal 0268 * 0269 * Subclasses should always use this method instead of directly emitting 0270 * Job::finished(). 0271 */ 0272 virtual void emitFinished(); 0273 0274 /** 0275 * @brief This method is invoked right before finished() is emitted 0276 * 0277 * Subclasses can reimplement this method to do a final cleanup before 0278 * the Job::finished() signal is emitted. 0279 * 0280 * @note Note that after Job::finished() the job is not running anymore and 0281 * therefore the job should not modify any data accessible by user. 0282 */ 0283 virtual void aboutToFinish(); 0284 0285 /** 0286 * @brief Emit progress() signal 0287 * 0288 * Subclasses should always use this method instead of directly emitting 0289 * Job::progress(). 0290 * 0291 * @param processed Amount of already processed items 0292 * @param total Total amount of items to process 0293 */ 0294 virtual void emitProgress(int processed, int total); 0295 0296 /** 0297 * @brief This method is invoked right before Job::start() is called. 0298 * 0299 * Subclasses should reset their internal state and call parent implementation. 0300 */ 0301 virtual void aboutToStart(); 0302 0303 /** 0304 * @brief This method is invoked when job is started. 0305 * 0306 * Job is automatically started when application enters event loop. 0307 */ 0308 virtual void start() = 0; 0309 0310 /** 0311 * @brief Dispatches @p request via @p accessManager 0312 * 0313 * Because different types of request require different HTTP method to be 0314 * used, subclasses must reimplement this method and use respective HTTP 0315 * method to send the @p request via @p accessManager. 0316 * 0317 * @param accessManager QNetworkAccessManager used to dispatch the request 0318 * @param request Request to dispatch 0319 * @param data Data to sent in the body of the request 0320 * @param contentType Content-Type of @p data 0321 */ 0322 virtual void dispatchRequest(QNetworkAccessManager *accessManager, const QNetworkRequest &request, const QByteArray &data, const QString &contentType) = 0; 0323 0324 /** 0325 * @brief Called when a reply is received. 0326 * 0327 * Subclasses must reimplement this method to handle reply content. 0328 * 0329 * @param reply A reply received from server 0330 * @param rawData Raw content of the reply. Don't use QNetworkReply::readAll, 0331 * because this method has already been called by Job and thus it would 0332 * return nothing. 0333 */ 0334 virtual void handleReply(const QNetworkReply *reply, const QByteArray &rawData) = 0; 0335 0336 /** 0337 * @brief Enqueues @p request in dispatcher queue 0338 * 0339 * Subclasses should call this method to enqueue the @p request in main job 0340 * queue. The request is automatically dispatched, and reply is handled. 0341 * Authorization headers and standards query parameters will be applied. 0342 * 0343 * @param request Request to enqueue 0344 * @param data Data to be send in body of the request 0345 * @param contentType Content type of @p data 0346 */ 0347 virtual void enqueueRequest(const QNetworkRequest &request, const QByteArray &data = QByteArray(), const QString &contentType = QString()); 0348 0349 private: 0350 class Private; 0351 Private *const d; 0352 friend class Private; 0353 0354 friend class AuthJob; 0355 }; 0356 0357 } // namespace KGAPI2