1/*
2 * BluezQt - Asynchronous BlueZ wrapper library
3 *
4 * SPDX-FileCopyrightText: 2014 Alejandro Fiestas Olivares <afiestas@kde.org>
5 * SPDX-FileCopyrightText: 2014-2015 David Rosca <nowrep@gmail.com>
6 *
7 * SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
8 */
9
10#ifndef BLUEZQT_JOB_H
11#define BLUEZQT_JOB_H
12
13#include <QObject>
14
15#include "bluezqt_export.h"
16
17#include <memory>
18
19namespace BluezQt
20{
21class JobPrivate;
22
23/**
24 * @class BluezQt::Job job.h <BluezQt/Job>
25 *
26 * This class represents an asynchronous job performed by BluezQt,
27 * it is usually not used directly but instead it is inherit by some
28 * other class.
29 *
30 * There are two ways of using this class, one is via exec() which will block
31 * the thread until a result is fetched, the other is via connecting to the
32 * signal result()
33 *
34 * Please, think twice before using exec(), it should be used only in either
35 * unittest or cli apps.
36 *
37 * @note Job and its subclasses are meant to be used in a fire-and-forget way.
38 * Jobs will delete themselves when they finish using deleteLater().
39 *
40 * @note Even given their asynchronous nature, Jobs are still executed in the
41 * main thread, so any blocking code executed in it will block the app calling it.
42 *
43 * @see InitManagerJob
44 * @see InitObexManagerJob
45 */
46class BLUEZQT_EXPORT Job : public QObject
47{
48 Q_OBJECT
49 Q_PROPERTY(int error READ error)
50 Q_PROPERTY(QString errorText READ errorText)
51 Q_PROPERTY(bool running READ isRunning)
52 Q_PROPERTY(bool finished READ isFinished)
53
54public:
55 /**
56 * Creates a new Job object.
57 *
58 * @param parent
59 */
60 explicit Job(QObject *parent = nullptr);
61
62 /**
63 * Destroys a Job object.
64 */
65 ~Job() override;
66
67 /**
68 * Error type
69 *
70 * @see error() const
71 */
72 enum Error {
73 /** Indicates there is no error */
74 NoError = 0,
75 /** Subclasses should define error codes starting at this value */
76 UserDefinedError = 100
77 };
78 Q_ENUM(Error)
79
80 /**
81 * Executes the job synchronously.
82 *
83 * This will start a nested QEventLoop internally. Nested event loop can be dangerous and
84 * can have unintended side effects, you should avoid calling exec() whenever you can and use the
85 * asynchronous interface of Job instead.
86 *
87 * Should you indeed call this method, you need to make sure that all callers are reentrant,
88 * so that events delivered by the inner event loop don't cause non-reentrant functions to be
89 * called, which usually wreaks havoc.
90 *
91 * Note that the event loop started by this method does not process user input events, which means
92 * your user interface will effectively be blocked. Other events like paint or network events are
93 * still being processed. The advantage of not processing user input events is that the chance of
94 * accidental reentrancy is greatly reduced. Still you should avoid calling this function.
95 *
96 * @warning This method blocks until the job finishes!
97 *
98 * @return true if the job has been executed without error, false otherwise
99 */
100 bool exec();
101
102 /**
103 * Returns the error code, if there has been an error.
104 *
105 * Make sure to call this once result() has been emitted
106 *
107 * @return the error code for this job, 0 if no error.
108 */
109 int error() const;
110
111 /**
112 * Returns the error text if there has been an error.
113 *
114 * Only call if error is not 0.
115 *
116 * This is usually some extra data associated with the error,
117 * such as a URL. Use errorString() to get a human-readable,
118 * translated message.
119 *
120 * @return a string to help understand the error
121 */
122 QString errorText() const;
123
124 /**
125 * Returns whether the job is currently running
126 *
127 * @return true if the job is running
128 */
129 bool isRunning() const;
130
131 /**
132 * Returns whether the job have already finished
133 *
134 * @return true if the job already finished
135 */
136 bool isFinished() const;
137
138public Q_SLOTS:
139 /**
140 * Starts the job asynchronously.
141 *
142 * This method will schedule doStart() to be executed in the next
143 * loop. This is done so this method returns as soon as possible.
144 *
145 * When the job is finished, result() is emitted.
146 */
147 void start();
148
149 /**
150 * Kills the job.
151 *
152 * This method will kill the job and then call deleteLater().
153 * Only jobs started with start() can be killed.
154 *
155 * It will not emit result signal.
156 */
157 void kill();
158
159protected Q_SLOTS:
160 /**
161 * Implementation for start() that will be executed in next loop
162 *
163 * This slot is always called in the next loop, triggered by start().
164 *
165 * When implementing this method is important to remember that jobs
166 * are not executed on a different thread (unless done that way), so any
167 * blocking task has to be done in a different thread or process.
168 */
169 virtual void doStart() = 0;
170
171protected:
172 /**
173 * Sets the error code.
174 *
175 * It should be called when an error
176 * is encountered in the job, just before calling emitResult().
177 *
178 * You should define an enum of error codes,
179 * with values starting at Job::UserDefinedError, and use
180 * those. For example:
181 * @code
182 * enum ExampleErrors{
183 * InvalidFoo = UserDefinedError,
184 * BarNotFound
185 * };
186 * @endcode
187 *
188 * @param errorCode the error code
189 * @see emitResult()
190 */
191 void setError(int errorCode);
192
193 /**
194 * Sets the error text.
195 *
196 * It should be called when an error
197 * is encountered in the job, just before calling emitResult().
198 *
199 * Provides extra information about the error that cannot be
200 * determined directly from the error code. For example, a
201 * URL or filename. This string is not normally translatable.
202 *
203 * @param errorText the error text
204 * @see emitResult(), setError()
205 */
206 void setErrorText(const QString &errorText);
207
208 /**
209 * Utility function to emit the result signal, and remove this job.
210 *
211 * @note Deletes this job using deleteLater().
212 * @see result() const
213 */
214 void emitResult();
215
216 /**
217 * Implementation for emitting the result signal
218 *
219 * This function is needed to be able to emit result() signal
220 * with the job pointer's type being subclass
221 */
222 virtual void doEmitResult() = 0;
223
224private:
225 std::unique_ptr<JobPrivate> const d_ptr;
226
227 Q_DECLARE_PRIVATE(Job)
228};
229
230} // namespace BluezQt
231
232#endif // BLUEZQT_JOB_H
233

source code of bluez-qt/src/job.h