File indexing completed on 2024-11-10 04:40:30
0001 /* 0002 SPDX-FileCopyrightText: 2006 Tobias Koenig <tokoe@kde.org> 0003 2006 Marc Mutz <mutz@kde.org> 0004 2006 - 2007 Volker Krause <vkrause@kde.org> 0005 0006 SPDX-License-Identifier: LGPL-2.0-or-later 0007 */ 0008 0009 #pragma once 0010 0011 #include "akonadicore_export.h" 0012 0013 #include <KCompositeJob> 0014 0015 #include <memory> 0016 0017 class QString; 0018 0019 namespace Akonadi 0020 { 0021 namespace Protocol 0022 { 0023 class Command; 0024 using CommandPtr = QSharedPointer<Command>; 0025 } 0026 0027 class JobPrivate; 0028 class Session; 0029 class SessionPrivate; 0030 0031 /** 0032 * @short Base class for all actions in the Akonadi storage. 0033 * 0034 * This class encapsulates a request to the pim storage service, 0035 * the code looks like 0036 * 0037 * @code 0038 * 0039 * Akonadi::Job *job = new Akonadi::SomeJob( some parameter ); 0040 * connect( job, SIGNAL(result(KJob*)), 0041 * this, SLOT(slotResult(KJob*)) ); 0042 * 0043 * @endcode 0044 * 0045 * The job is queued for execution as soon as the event loop is entered 0046 * again. 0047 * 0048 * And the slotResult is usually at least: 0049 * 0050 * @code 0051 * 0052 * if ( job->error() ) { 0053 * // handle error... 0054 * } 0055 * 0056 * @endcode 0057 * 0058 * With the synchronous interface the code looks like 0059 * 0060 * @code 0061 * Akonadi::SomeJob *job = new Akonadi::SomeJob( some parameter ); 0062 * if ( !job->exec() ) { 0063 * qDebug() << "Error:" << job->errorString(); 0064 * } else { 0065 * // do something 0066 * } 0067 * @endcode 0068 * 0069 * @warning Using the synchronous method is error prone, use this only 0070 * if the asynchronous access is not possible. See the documentation of 0071 * KJob::exec() for more details. 0072 * 0073 * Subclasses must reimplement doStart(). 0074 * 0075 * @note KJob-derived objects delete itself, it is thus not possible 0076 * to create job objects on the stack! 0077 * 0078 * @author Volker Krause <vkrause@kde.org>, Tobias Koenig <tokoe@kde.org>, Marc Mutz <mutz@kde.org> 0079 */ 0080 class AKONADICORE_EXPORT Job : public KCompositeJob 0081 { 0082 Q_OBJECT 0083 0084 friend class Session; 0085 friend class SessionPrivate; 0086 0087 public: 0088 /** 0089 * Describes a list of jobs. 0090 */ 0091 using List = QList<Job *>; 0092 0093 /** 0094 * Describes the error codes that can be emitted by this class. 0095 * Subclasses can provide additional codes, starting from UserError 0096 * onwards 0097 */ 0098 enum Error { 0099 ConnectionFailed = UserDefinedError, ///< The connection to the Akonadi server failed. 0100 ProtocolVersionMismatch, ///< The server protocol version is too old or too new. 0101 UserCanceled, ///< The user canceled this job. 0102 Unknown, ///< Unknown error. 0103 UserError = UserDefinedError + 42 ///< Starting point for error codes defined by sub-classes. 0104 }; 0105 0106 /** 0107 * Creates a new job. 0108 * 0109 * If the parent object is a Job object, the new job will be a subjob of @p parent. 0110 * If the parent object is a Session object, it will be used for server communication 0111 * instead of the default session. 0112 * 0113 * @param parent The parent object, job or session. 0114 */ 0115 explicit Job(QObject *parent = nullptr); 0116 0117 /** 0118 * Destroys the job. 0119 */ 0120 ~Job() override; 0121 0122 /** 0123 * Jobs are started automatically once entering the event loop again, no need 0124 * to explicitly call this. 0125 */ 0126 void start() override; 0127 0128 /** 0129 * Returns the error string, if there has been an error, an empty 0130 * string otherwise. 0131 */ 0132 [[nodiscard]] QString errorString() const final; 0133 0134 Q_SIGNALS: 0135 /** 0136 * This signal is emitted directly before the job will be started. 0137 * 0138 * @param job The started job. 0139 */ 0140 void aboutToStart(Akonadi::Job *job); 0141 0142 /** 0143 * This signal is emitted if the job has finished all write operations, ie. 0144 * if this signal is emitted, the job guarantees to not call writeData() again. 0145 * Do not emit this signal directly, call emitWriteFinished() instead. 0146 * 0147 * @param job This job. 0148 * @see emitWriteFinished() 0149 */ 0150 void writeFinished(Akonadi::Job *job); 0151 0152 protected: 0153 /** 0154 * This method must be reimplemented in the concrete jobs. It will be called 0155 * after the job has been started and a connection to the Akonadi backend has 0156 * been established. 0157 */ 0158 virtual void doStart() = 0; 0159 0160 /** 0161 * This method should be reimplemented in the concrete jobs in case you want 0162 * to handle incoming data. It will be called on received data from the backend. 0163 * The default implementation does nothing. 0164 * 0165 * @param tag The tag of the corresponding command, empty if this is an untagged response. 0166 * @param response The received response 0167 * 0168 * @return Implementations should return true if the last response was processed and 0169 * the job can emit result. Return false if more responses from server are expected. 0170 */ 0171 virtual bool doHandleResponse(qint64 tag, const Protocol::CommandPtr &response); 0172 0173 /** 0174 * Adds the given job as a subjob to this job. This method is automatically called 0175 * if you construct a job using another job as parent object. 0176 * The base implementation does the necessary setup to share the network connection 0177 * with the backend. 0178 * 0179 * @param job The new subjob. 0180 */ 0181 bool addSubjob(KJob *job) override; 0182 0183 /** 0184 * Removes the given subjob of this job. 0185 * 0186 * @param job The subjob to remove. 0187 */ 0188 bool removeSubjob(KJob *job) override; 0189 0190 /** 0191 * Kills the execution of the job. 0192 */ 0193 bool doKill() override; 0194 0195 /** 0196 * Call this method to indicate that this job will not call writeData() again. 0197 * @see writeFinished() 0198 */ 0199 void emitWriteFinished(); 0200 0201 protected Q_SLOTS: 0202 void slotResult(KJob *job) override; 0203 0204 protected: 0205 /// @cond PRIVATE 0206 Job(JobPrivate *dd, QObject *parent); 0207 std::unique_ptr<JobPrivate> const d_ptr; 0208 /// @endcond 0209 0210 private: 0211 Q_DECLARE_PRIVATE(Job) 0212 0213 /// @cond PRIVATE 0214 Q_PRIVATE_SLOT(d_func(), void startNext()) 0215 Q_PRIVATE_SLOT(d_func(), void signalCreationToJobTracker()) 0216 Q_PRIVATE_SLOT(d_func(), void signalStartedToJobTracker()) 0217 Q_PRIVATE_SLOT(d_func(), void delayedEmitResult()) 0218 /// @endcond 0219 }; 0220 0221 }