File indexing completed on 2024-04-28 04:00:49

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