File indexing completed on 2024-09-15 03:42:53
0001 /* 0002 SPDX-FileCopyrightText: 2014 Alejandro Fiestas Olivares <afiestas@kde.org> 0003 0004 SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL 0005 */ 0006 0007 #ifndef SOLID_JOB_H 0008 #define SOLID_JOB_H 0009 0010 #include <QObject> 0011 0012 #include "solid_export.h" 0013 0014 namespace Solid 0015 { 0016 class JobPrivate; 0017 /** 0018 * This class represents an asynchronous job performed by Solid, 0019 * it is usually not used directly but instead it is inherited by some 0020 * other class, for example \See AcPluggedJob or \See StatesJob 0021 * 0022 * There are two ways of using this class, one is via exec() which will block 0023 * the thread until a result is fetched, the other is via connecting to the 0024 * signal result() 0025 * 0026 * Please, think twice before using exec(), it should be used only in either 0027 * unittest or cli apps. 0028 * 0029 * @note Job and its subclasses are meant to be used 0030 * in a fire-and-forget way. Jobs will delete themselves 0031 * when they finish using deleteLater() 0032 * 0033 * @note Even given their asynchronous nature, Jobs are still executed in the 0034 * main thread, so any blocking code executed in it will block the app calling it. 0035 */ 0036 class SOLID_EXPORT Job : public QObject 0037 { 0038 Q_OBJECT 0039 Q_PROPERTY(int error READ error NOTIFY result) 0040 Q_PROPERTY(QString errorText READ errorText NOTIFY result) 0041 0042 public: 0043 explicit Job(QObject *parent = nullptr); 0044 virtual ~Job(); 0045 0046 enum Error { 0047 /** Indicates there is no error */ 0048 NoError = 0, 0049 /** Subclasses should define error codes starting at this value */ 0050 UserDefinedError = 100, 0051 }; 0052 Q_ENUM(Error) 0053 0054 /** 0055 * Executes the job synchronously. 0056 * 0057 * This will start a nested QEventLoop internally. Nested event loop can be dangerous and 0058 * can have unintended side effects, you should avoid calling exec() whenever you can and use the 0059 * asynchronous interface of SolidJob instead. 0060 * 0061 * Should you indeed call this method, you need to make sure that all callers are reentrant, 0062 * so that events delivered by the inner event loop don't cause non-reentrant functions to be 0063 * called, which usually wreaks havoc. 0064 * 0065 * Note that the event loop started by this method does not process user input events, which means 0066 * your user interface will effectively be blocked. Other events like paint or network events are 0067 * still being processed. The advantage of not processing user input events is that the chance of 0068 * accidental reentrancy is greatly reduced. Still you should avoid calling this function. 0069 * 0070 * @return true if the job has been executed without error, false otherwise 0071 */ 0072 bool exec(); 0073 0074 /** 0075 * Returns the error code, if there has been an error. 0076 * 0077 * Make sure to call this once result() has been emitted 0078 * 0079 * @return the error code for this job, 0 if no error. 0080 */ 0081 int error() const; 0082 0083 /** 0084 * Returns the error text if there has been an error. 0085 * 0086 * Only call if error is not 0. 0087 * 0088 * This is usually some extra data associated with the error, 0089 * such as a URL. Use errorString() to get a human-readable, 0090 * translated message. 0091 * 0092 * @return a string to help understand the error 0093 */ 0094 QString errorText() const; 0095 0096 public Q_SLOTS: 0097 /** 0098 * Starts the job asynchronously. 0099 * 0100 * This method will schedule doStart() to be executed in the next 0101 * loop. This is done so this method returns as soon as possible. 0102 * 0103 * When the job is finished, result() is emitted. 0104 */ 0105 void start(); 0106 0107 private Q_SLOTS: 0108 /** 0109 * Implementation fo start() that will be executed in next loop 0110 * 0111 * This slot is always called in the next loop, triggered by start(). 0112 * 0113 * When implementing this method it is important to remember that jobs 0114 * are not executed on a different thread (unless done that way), so any 0115 * blocking task has to be done in a different thread or process. 0116 */ 0117 virtual void doStart() = 0; 0118 0119 protected: 0120 /** 0121 * Sets the error code. 0122 * 0123 * It should be called when an error 0124 * is encountered in the job, just before calling emitResult(). 0125 * 0126 * You should define an enum of error codes, 0127 * with values starting at KJob::UserDefinedError, and use 0128 * those. For example, 0129 * @code 0130 * enum ExampleErrors{ 0131 * InvalidFoo = UserDefinedError, 0132 * BarNotFound 0133 * }; 0134 * @endcode 0135 * 0136 * @param errorCode the error code 0137 * @see emitResult() 0138 */ 0139 void setError(int errorCode); 0140 0141 /** 0142 * Sets the error text. 0143 * 0144 * It should be called when an error 0145 * is encountered in the job, just before calling emitResult(). 0146 * 0147 * Provides extra information about the error that cannot be 0148 * determined directly from the error code. For example, a 0149 * URL or filename. This string is not normally translatable. 0150 * 0151 * @param errorText the error text 0152 * @see emitResult(), setError() 0153 */ 0154 void setErrorText(const QString &errorText); 0155 0156 /** 0157 * Utility function to emit the result signal, and suicide this job. 0158 * @note Deletes this job using deleteLater(). 0159 * @see result() 0160 */ 0161 void emitResult(); 0162 0163 JobPrivate *const d_ptr; 0164 SOLID_NO_EXPORT Job(JobPrivate &dd, QObject *parent); 0165 0166 private: 0167 Q_DECLARE_PRIVATE(Job) 0168 0169 Q_SIGNALS: 0170 void result(Solid::Job *job); 0171 }; 0172 } 0173 0174 #endif // SOLID_JOB_H