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