File indexing completed on 2025-01-19 06:44:36
0001 /* 0002 * BluezQt - Asynchronous BlueZ wrapper library 0003 * 0004 * SPDX-FileCopyrightText: 2014 Alejandro Fiestas Olivares <afiestas@kde.org> 0005 * SPDX-FileCopyrightText: 2014-2015 David Rosca <nowrep@gmail.com> 0006 * 0007 * SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL 0008 */ 0009 0010 #ifndef BLUEZQT_JOB_H 0011 #define BLUEZQT_JOB_H 0012 0013 #include <QObject> 0014 0015 #include "bluezqt_export.h" 0016 0017 #include <memory> 0018 0019 namespace BluezQt 0020 { 0021 class JobPrivate; 0022 0023 /** 0024 * @class BluezQt::Job job.h <BluezQt/Job> 0025 * 0026 * This class represents an asynchronous job performed by BluezQt, 0027 * it is usually not used directly but instead it is inherit by some 0028 * other class. 0029 * 0030 * There are two ways of using this class, one is via exec() which will block 0031 * the thread until a result is fetched, the other is via connecting to the 0032 * signal result() 0033 * 0034 * Please, think twice before using exec(), it should be used only in either 0035 * unittest or cli apps. 0036 * 0037 * @note Job and its subclasses are meant to be used in a fire-and-forget way. 0038 * Jobs will delete themselves when they finish using deleteLater(). 0039 * 0040 * @note Even given their asynchronous nature, Jobs are still executed in the 0041 * main thread, so any blocking code executed in it will block the app calling it. 0042 * 0043 * @see InitManagerJob 0044 * @see InitObexManagerJob 0045 */ 0046 class BLUEZQT_EXPORT Job : public QObject 0047 { 0048 Q_OBJECT 0049 Q_PROPERTY(int error READ error) 0050 Q_PROPERTY(QString errorText READ errorText) 0051 Q_PROPERTY(bool running READ isRunning) 0052 Q_PROPERTY(bool finished READ isFinished) 0053 0054 public: 0055 /** 0056 * Creates a new Job object. 0057 * 0058 * @param parent 0059 */ 0060 explicit Job(QObject *parent = nullptr); 0061 0062 /** 0063 * Destroys a Job object. 0064 */ 0065 ~Job() override; 0066 0067 /** 0068 * Error type 0069 * 0070 * @see error() const 0071 */ 0072 enum Error { 0073 /** Indicates there is no error */ 0074 NoError = 0, 0075 /** Subclasses should define error codes starting at this value */ 0076 UserDefinedError = 100 0077 }; 0078 Q_ENUM(Error) 0079 0080 /** 0081 * Executes the job synchronously. 0082 * 0083 * This will start a nested QEventLoop internally. Nested event loop can be dangerous and 0084 * can have unintended side effects, you should avoid calling exec() whenever you can and use the 0085 * asynchronous interface of Job instead. 0086 * 0087 * Should you indeed call this method, you need to make sure that all callers are reentrant, 0088 * so that events delivered by the inner event loop don't cause non-reentrant functions to be 0089 * called, which usually wreaks havoc. 0090 * 0091 * Note that the event loop started by this method does not process user input events, which means 0092 * your user interface will effectively be blocked. Other events like paint or network events are 0093 * still being processed. The advantage of not processing user input events is that the chance of 0094 * accidental reentrancy is greatly reduced. Still you should avoid calling this function. 0095 * 0096 * @warning This method blocks until the job finishes! 0097 * 0098 * @return true if the job has been executed without error, false otherwise 0099 */ 0100 bool exec(); 0101 0102 /** 0103 * Returns the error code, if there has been an error. 0104 * 0105 * Make sure to call this once result() has been emitted 0106 * 0107 * @return the error code for this job, 0 if no error. 0108 */ 0109 int error() const; 0110 0111 /** 0112 * Returns the error text if there has been an error. 0113 * 0114 * Only call if error is not 0. 0115 * 0116 * This is usually some extra data associated with the error, 0117 * such as a URL. Use errorString() to get a human-readable, 0118 * translated message. 0119 * 0120 * @return a string to help understand the error 0121 */ 0122 QString errorText() const; 0123 0124 /** 0125 * Returns whether the job is currently running 0126 * 0127 * @return true if the job is running 0128 */ 0129 bool isRunning() const; 0130 0131 /** 0132 * Returns whether the job have already finished 0133 * 0134 * @return true if the job already finished 0135 */ 0136 bool isFinished() const; 0137 0138 public Q_SLOTS: 0139 /** 0140 * Starts the job asynchronously. 0141 * 0142 * This method will schedule doStart() to be executed in the next 0143 * loop. This is done so this method returns as soon as possible. 0144 * 0145 * When the job is finished, result() is emitted. 0146 */ 0147 void start(); 0148 0149 /** 0150 * Kills the job. 0151 * 0152 * This method will kill the job and then call deleteLater(). 0153 * Only jobs started with start() can be killed. 0154 * 0155 * It will not emit result signal. 0156 */ 0157 void kill(); 0158 0159 protected Q_SLOTS: 0160 /** 0161 * Implementation for start() that will be executed in next loop 0162 * 0163 * This slot is always called in the next loop, triggered by start(). 0164 * 0165 * When implementing this method is important to remember that jobs 0166 * are not executed on a different thread (unless done that way), so any 0167 * blocking task has to be done in a different thread or process. 0168 */ 0169 virtual void doStart() = 0; 0170 0171 protected: 0172 /** 0173 * Sets the error code. 0174 * 0175 * It should be called when an error 0176 * is encountered in the job, just before calling emitResult(). 0177 * 0178 * You should define an enum of error codes, 0179 * with values starting at Job::UserDefinedError, and use 0180 * those. For example: 0181 * @code 0182 * enum ExampleErrors{ 0183 * InvalidFoo = UserDefinedError, 0184 * BarNotFound 0185 * }; 0186 * @endcode 0187 * 0188 * @param errorCode the error code 0189 * @see emitResult() 0190 */ 0191 void setError(int errorCode); 0192 0193 /** 0194 * Sets the error text. 0195 * 0196 * It should be called when an error 0197 * is encountered in the job, just before calling emitResult(). 0198 * 0199 * Provides extra information about the error that cannot be 0200 * determined directly from the error code. For example, a 0201 * URL or filename. This string is not normally translatable. 0202 * 0203 * @param errorText the error text 0204 * @see emitResult(), setError() 0205 */ 0206 void setErrorText(const QString &errorText); 0207 0208 /** 0209 * Utility function to emit the result signal, and remove this job. 0210 * 0211 * @note Deletes this job using deleteLater(). 0212 * @see result() const 0213 */ 0214 void emitResult(); 0215 0216 /** 0217 * Implementation for emitting the result signal 0218 * 0219 * This function is needed to be able to emit result() signal 0220 * with the job pointer's type being subclass 0221 */ 0222 virtual void doEmitResult() = 0; 0223 0224 private: 0225 std::unique_ptr<JobPrivate> const d_ptr; 0226 0227 Q_DECLARE_PRIVATE(Job) 0228 }; 0229 0230 } // namespace BluezQt 0231 0232 #endif // BLUEZQT_JOB_H