1 | /* |
2 | Copyright (c) 2006 Tobias Koenig <tokoe@kde.org> |
3 | 2006 Marc Mutz <mutz@kde.org> |
4 | 2006 - 2007 Volker Krause <vkrause@kde.org> |
5 | |
6 | This library is free software; you can redistribute it and/or modify it |
7 | under the terms of the GNU Library General Public License as published by |
8 | the Free Software Foundation; either version 2 of the License, or (at your |
9 | option) any later version. |
10 | |
11 | This library is distributed in the hope that it will be useful, but WITHOUT |
12 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
13 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public |
14 | License for more details. |
15 | |
16 | You should have received a copy of the GNU Library General Public License |
17 | along with this library; see the file COPYING.LIB. If not, write to the |
18 | Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA |
19 | 02110-1301, USA. |
20 | */ |
21 | |
22 | #ifndef AKONADI_JOB_H |
23 | #define AKONADI_JOB_H |
24 | |
25 | #include "akonadi_export.h" |
26 | |
27 | #include <kcompositejob.h> |
28 | |
29 | class QString; |
30 | |
31 | namespace Akonadi { |
32 | |
33 | class JobPrivate; |
34 | class Session; |
35 | class SessionPrivate; |
36 | |
37 | /** |
38 | * @short Base class for all actions in the Akonadi storage. |
39 | * |
40 | * This class encapsulates a request to the pim storage service, |
41 | * the code looks like |
42 | * |
43 | * @code |
44 | * |
45 | * Akonadi::Job *job = new Akonadi::SomeJob( some parameter ); |
46 | * connect( job, SIGNAL(result(KJob*)), |
47 | * this, SLOT(slotResult(KJob*)) ); |
48 | * |
49 | * @endcode |
50 | * |
51 | * The job is queued for execution as soon as the event loop is entered |
52 | * again. |
53 | * |
54 | * And the slotResult is usually at least: |
55 | * |
56 | * @code |
57 | * |
58 | * if ( job->error() ) { |
59 | * // handle error... |
60 | * } |
61 | * |
62 | * @endcode |
63 | * |
64 | * With the synchronous interface the code looks like |
65 | * |
66 | * @code |
67 | * Akonadi::SomeJob *job = new Akonadi::SomeJob( some parameter ); |
68 | * if ( !job->exec() ) { |
69 | * qDebug() << "Error:" << job->errorString(); |
70 | * } else { |
71 | * // do something |
72 | * } |
73 | * @endcode |
74 | * |
75 | * @warning Using the synchronous method is error prone, use this only |
76 | * if the asynchronous access is not possible. See the documentation of |
77 | * KJob::exec() for more details. |
78 | * |
79 | * Subclasses must reimplement doStart(). |
80 | * |
81 | * @note KJob-derived objects delete itself, it is thus not possible |
82 | * to create job objects on the stack! |
83 | * |
84 | * @author Volker Krause <vkrause@kde.org>, Tobias Koenig <tokoe@kde.org>, Marc Mutz <mutz@kde.org> |
85 | */ |
86 | class AKONADI_EXPORT Job : public KCompositeJob |
87 | { |
88 | Q_OBJECT |
89 | |
90 | friend class Session; |
91 | friend class SessionPrivate; |
92 | |
93 | public: |
94 | /** |
95 | * Describes a list of jobs. |
96 | */ |
97 | typedef QList<Job *> List; |
98 | |
99 | /** |
100 | * Describes the error codes that can be emitted by this class. |
101 | * Subclasses can provide additional codes, starting from UserError |
102 | * onwards |
103 | */ |
104 | enum Error { |
105 | ConnectionFailed = UserDefinedError, ///< The connection to the Akonadi server failed. |
106 | ProtocolVersionMismatch, ///< The server protocol version is too old or too new. |
107 | UserCanceled, ///< The user canceld this job. |
108 | Unknown, ///< Unknown error. |
109 | UserError = UserDefinedError + 42 ///< Starting point for error codes defined by sub-classes. |
110 | }; |
111 | |
112 | /** |
113 | * Creates a new job. |
114 | * |
115 | * If the parent object is a Job object, the new job will be a subjob of @p parent. |
116 | * If the parent object is a Session object, it will be used for server communication |
117 | * instead of the default session. |
118 | * |
119 | * @param parent The parent object, job or session. |
120 | */ |
121 | explicit Job(QObject *parent = 0); |
122 | |
123 | /** |
124 | * Destroys the job. |
125 | */ |
126 | virtual ~Job(); |
127 | |
128 | /** |
129 | * Jobs are started automatically once entering the event loop again, no need |
130 | * to explicitly call this. |
131 | */ |
132 | void start(); |
133 | |
134 | /** |
135 | * Returns the error string, if there has been an error, an empty |
136 | * string otherwise. |
137 | */ |
138 | virtual QString errorString() const; |
139 | |
140 | Q_SIGNALS: |
141 | /** |
142 | * This signal is emitted directly before the job will be started. |
143 | * |
144 | * @param job The started job. |
145 | */ |
146 | void aboutToStart(Akonadi::Job *job); |
147 | |
148 | /** |
149 | * This signal is emitted if the job has finished all write operations, ie. |
150 | * if this signal is emitted, the job guarantees to not call writeData() again. |
151 | * Do not emit this signal directly, call emitWriteFinished() instead. |
152 | * |
153 | * @param job This job. |
154 | * @see emitWriteFinished() |
155 | */ |
156 | void writeFinished(Akonadi::Job *job); |
157 | |
158 | protected: |
159 | /** |
160 | * This method must be reimplemented in the concrete jobs. It will be called |
161 | * after the job has been started and a connection to the Akonadi backend has |
162 | * been established. |
163 | */ |
164 | virtual void doStart() = 0; |
165 | |
166 | /** |
167 | * This method should be reimplemented in the concrete jobs in case you want |
168 | * to handle incoming data. It will be called on received data from the backend. |
169 | * The default implementation does nothing. |
170 | * |
171 | * @param tag The tag of the corresponding command, empty if this is an untagged response. |
172 | * @param data The received data. |
173 | */ |
174 | virtual void doHandleResponse(const QByteArray &tag, const QByteArray &data); |
175 | |
176 | /** |
177 | * Adds the given job as a subjob to this job. This method is automatically called |
178 | * if you construct a job using another job as parent object. |
179 | * The base implementation does the necessary setup to share the network connection |
180 | * with the backend. |
181 | * |
182 | * @param job The new subjob. |
183 | */ |
184 | virtual bool addSubjob(KJob *job); |
185 | |
186 | /** |
187 | * Removes the given subjob of this job. |
188 | * |
189 | * @param job The subjob to remove. |
190 | */ |
191 | virtual bool removeSubjob(KJob *job); |
192 | |
193 | /** |
194 | * Kills the execution of the job. |
195 | */ |
196 | virtual bool doKill(); |
197 | |
198 | /** |
199 | * Call this method to indicate that this job will not call writeData() again. |
200 | * @see writeFinished() |
201 | */ |
202 | void emitWriteFinished(); |
203 | |
204 | protected Q_SLOTS: |
205 | virtual void slotResult(KJob *job); |
206 | |
207 | protected: |
208 | //@cond PRIVATE |
209 | Job(JobPrivate *dd, QObject *parent); |
210 | JobPrivate *const d_ptr; |
211 | //@endcond |
212 | |
213 | private: |
214 | Q_DECLARE_PRIVATE(Job) |
215 | |
216 | //@cond PRIVATE |
217 | Q_PRIVATE_SLOT(d_func(), void slotSubJobAboutToStart(Akonadi::Job *)) |
218 | Q_PRIVATE_SLOT(d_func(), void startNext()) |
219 | Q_PRIVATE_SLOT(d_func(), void signalCreationToJobTracker()) |
220 | Q_PRIVATE_SLOT(d_func(), void signalStartedToJobTracker()) |
221 | Q_PRIVATE_SLOT(d_func(), void delayedEmitResult()) |
222 | //@endcond |
223 | }; |
224 | |
225 | } |
226 | |
227 | #endif |
228 | |