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

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