File indexing completed on 2024-04-21 04:49:10

0001 /*
0002     SPDX-FileCopyrightText: 2011 Michal Malek <michalm@jabster.pl>
0003     SPDX-FileCopyrightText: 1998-2010 Sebastian Trueg <trueg@k3b.org>
0004 
0005     SPDX-License-Identifier: GPL-2.0-or-later
0006 */
0007 
0008 
0009 #ifndef K3BJOB_H
0010 #define K3BJOB_H
0011 
0012 #include "k3b_export.h"
0013 #include "k3bdevicetypes.h"
0014 #include "k3bglobals.h"
0015 #include "k3bjobhandler.h"
0016 
0017 #include <QObject>
0018 #include <QString>
0019 
0020 namespace K3b {
0021     namespace Device {
0022         class Device;
0023     }
0024 
0025     /**
0026      * This is the baseclass for all the jobs in K3b which actually do the work like burning a cd!
0027      * The Job object takes care of registering with the k3bcore or with a parent Job.
0028      *
0029      * Every job has a jobhandler which can be another job (in which case the job is handled as
0030      * a subjob) or an arbitrary class implementing the JobHandler interface.
0031      *
0032      * A Job should never create any widgets. User interaction should be done through the methods
0033      * questionYesNo, waitForMedium.
0034      *
0035      * @author Sebastian Trueg
0036      */
0037     class LIBK3B_EXPORT Job : public QObject, public JobHandler
0038     {
0039         Q_OBJECT
0040 
0041     public:
0042         ~Job() override;
0043 
0044         /**
0045          * \reimplemented from JobHandler
0046          */
0047         bool isJob() const override { return true; }
0048 
0049         JobHandler* jobHandler() const;
0050 
0051         /**
0052          * Is the job active?
0053          * The default implementation is based on the jobStarted() and jobFinished()
0054          * methods and there is normally no need to reimplement this.
0055          */
0056         virtual bool active() const;
0057 
0058         /**
0059          * The default implementation is based on the canceled() signal.
0060          *
0061          * This means that one cannot count on this value being valid
0062          * in a slot connected to the canceled() signal. It is, however, save
0063          * to call this method from a slot connected to the finished() signal
0064          * in case the job makes proper usage of the jobStarted/jobFinished
0065          * methods.
0066          */
0067         virtual bool hasBeenCanceled() const;
0068 
0069         virtual QString jobDescription() const { return "Job"; }
0070         virtual QString jobDetails() const { return QString(); }
0071         
0072         /**
0073          * @returns job source (e.g. path to image file)
0074          */
0075         virtual QString jobSource() const { return QString(); }
0076         
0077         /**
0078          * @return job target (e.g. name of the burner)
0079          */
0080         virtual QString jobTarget() const { return QString(); }
0081 
0082         /**
0083          * @returns the number of running subjobs.
0084          * this is useful for proper cancellation of jobs.
0085          */
0086         int numRunningSubJobs() const;
0087 
0088         QList<Job*> runningSubJobs() const;
0089 
0090         static const char DEFAULT_SIGNAL_CONNECTION[];
0091 
0092         /**
0093          * Connect a job 1-to-1. Useful for wrapper jobs.
0094          *
0095          * If a parameter is set to 0 it will not be connected at all
0096          */
0097         void connectJob( Job* subJob,
0098                          const char* finishedSlot = DEFAULT_SIGNAL_CONNECTION,
0099                          const char* newTaskSlot = DEFAULT_SIGNAL_CONNECTION,
0100                          const char* newSubTaskSlot = DEFAULT_SIGNAL_CONNECTION,
0101                          const char* progressSlot = DEFAULT_SIGNAL_CONNECTION,
0102                          const char* subProgressSlot = DEFAULT_SIGNAL_CONNECTION,
0103                          const char* processedSizeSlot = DEFAULT_SIGNAL_CONNECTION,
0104                          const char* processedSubSizeSlot = DEFAULT_SIGNAL_CONNECTION );
0105 
0106         /**
0107          * Connect a subjob.
0108          *
0109          * \param newTaskSlot    If DEFAULT_SIGNAL_CONNECTION the newTask signal from the subjob will
0110          *                       be connected to the newSubTask signal
0111          * \param newSubTaskSlot If DEFAULT_SIGNAL_CONNECTION the newSubTask signal from the subjob
0112          *                       will create an infoMessage signal
0113          * \param progressSlot   If DEFAULT_SIGNAL_CONNECTION the percent signal of the subjob will be
0114          *                       connected to the subPercent signal.
0115          * debuggingOutput and infoMessage will always be direcctly connected.
0116          *
0117          * If a parameter is set to 0 it will not be connected at all
0118          */
0119         void connectSubJob( Job* subJob,
0120                             const char* finishedSlot = DEFAULT_SIGNAL_CONNECTION,
0121                             const char* newTaskSlot = DEFAULT_SIGNAL_CONNECTION,
0122                             const char* newSubTaskSlot = DEFAULT_SIGNAL_CONNECTION,
0123                             const char* progressSlot = DEFAULT_SIGNAL_CONNECTION,
0124                             const char* subProgressSlot = DEFAULT_SIGNAL_CONNECTION,
0125                             const char* processedSizeSlot = DEFAULT_SIGNAL_CONNECTION,
0126                             const char* processedSubSizeSlot = DEFAULT_SIGNAL_CONNECTION );
0127 
0128         /**
0129          * Message types to be used in combination with the infoMessage signal.
0130          *
0131          * \see infoMessage()
0132          */
0133         enum MessageType {
0134             MessageInfo,     /**< Informational message. For example a message that informs the user about what is
0135                                 currently going on */
0136             MessageWarning,  /**< A warning message. Something did not go perfectly but the job may continue. */
0137             MessageError,    /**< An error. Only use this message type if the job will actually fail afterwards
0138                                 with a call to jobFinished( false ) */
0139             MessageSuccess   /**< This message type may be used to inform the user that a sub job has
0140                                 been successfully finished. */
0141         };
0142 
0143         /**
0144          * reimplemented from JobHandler
0145          */
0146         Device::MediaType waitForMedium( Device::Device*,
0147                                                  Device::MediaStates mediaState = Device::STATE_EMPTY,
0148                                                  Device::MediaTypes mediaType = Device::MEDIA_WRITABLE_CD,
0149                                                  const K3b::Msf& minMediaSize = K3b::Msf(),
0150                                                  const QString& message = QString() ) override;
0151 
0152         /**
0153          * reimplemented from JobHandler
0154          */
0155         bool questionYesNo( const QString& text,
0156                                     const QString& caption = QString(),
0157                                     const KGuiItem& buttonYes = KStandardGuiItem::ok(),
0158                                     const KGuiItem& buttonNo = KStandardGuiItem::cancel() ) override;
0159 
0160         /**
0161          * reimplemented from JobHandler
0162          */
0163         void blockingInformation( const QString& text,
0164                                           const QString& caption = QString() ) override;
0165 
0166         /**
0167          * Wait for the job to finish. In case the job is not running
0168          * this method returns immediately. Otherwise it will start a local
0169          * event loop to wait for the job to finish.
0170          */
0171         void wait();
0172 
0173     public Q_SLOTS:
0174         /**
0175          * This is the slot that starts the job. The first call should always
0176          * be jobStarted().
0177          *
0178          * Once the job has finished it has to call jobFinished() with the result as
0179          * a parameter.
0180          *
0181          * \see jobStarted()
0182          * \see jobFinished()
0183          */
0184         virtual void start() = 0;
0185 
0186         /**
0187          * This slot should cancel the job. The job has to emit the canceled() signal and make a call
0188          * to jobFinished().
0189          * It is not important to do any of those two directly in this slot though.
0190          */
0191         virtual void cancel() = 0;
0192 
0193         void setJobHandler( K3b::JobHandler* );
0194 
0195     Q_SIGNALS:
0196         void infoMessage( const QString& msg, int type );
0197         void percent( int p );
0198         void subPercent( int p );
0199         void processedSize( int processed, int size );
0200         void processedSubSize( int processed, int size );
0201         void newTask( const QString& job );
0202         void newSubTask( const QString& job );
0203         void debuggingOutput(const QString&, const QString&);
0204         void nextTrack( int track, int numTracks );
0205 
0206         void canceled();
0207 
0208         /**
0209          * Emitted once the job has been started. Never emit this signal directly.
0210          * Use jobStarted() instead, otherwise the job will not be properly registered
0211          */
0212         void started();
0213 
0214         /**
0215          * Emitted once the job has been finished. Never emit this signal directly.
0216          * Use jobFinished() instead, otherwise the job will not be properly deregistered
0217          */
0218         void finished( bool success );
0219 
0220     protected:
0221         /**
0222          * \param hdl the handler of the job. This allows for some user interaction without
0223          *            specifying any details (like the GUI).
0224          *            The job handler can also be another job. In that case this job is a sub job
0225          *            and will be part of the parents running sub jobs.
0226          *
0227          * \see runningSubJobs()
0228          * \see numRunningSubJobs()
0229          */
0230         Job( JobHandler* hdl, QObject* parent = 0 );
0231 
0232         /**
0233          * Call this in start() to properly register the job and emit the started() signal.
0234          * Do never emit the started() signal manually.
0235          *
0236          * Always call Job::jobStarted in reimplementations.
0237          */
0238         virtual void jobStarted();
0239 
0240         /**
0241          * Call this at the end of the job to properly deregister the job and emit the finished() signal.
0242          * Do never emit the finished() signal manually.
0243          *
0244          * Always call Job::jobFinished in reimplementations.
0245          */
0246         virtual void jobFinished( bool success );
0247 
0248     private Q_SLOTS:
0249         void slotCanceled();
0250         void slotNewSubTask( const QString& str );
0251 
0252     private:
0253         void registerSubJob( Job* );
0254         void unregisterSubJob( Job* );
0255 
0256         class Private;
0257         Private* const d;
0258     };
0259 
0260 
0261     /**
0262      * Every job used to actually burn a medium is derived from BurnJob.
0263      * This class implements additional signals like buffer status or writing speed
0264      * as well as a handling of the used writing application.
0265      */
0266     class LIBK3B_EXPORT BurnJob : public Job
0267     {
0268         Q_OBJECT
0269 
0270     public:
0271         explicit BurnJob( JobHandler* hdl, QObject* parent = 0 );
0272         ~BurnJob() override;
0273 
0274         /**
0275          * The writing device used by this job.
0276          */
0277         virtual Device::Device* writer() const { return 0; }
0278 
0279         /**
0280          * use WritingApp
0281          */
0282         WritingApp writingApp() const;
0283 
0284         /**
0285          * WritingApp "ored" together
0286          */
0287         virtual WritingApps supportedWritingApps() const;
0288 
0289     public Q_SLOTS:
0290         /**
0291          * use WritingApp
0292          */
0293         void setWritingApp( K3b::WritingApp w );
0294 
0295     Q_SIGNALS:
0296         void bufferStatus( int );
0297 
0298         void deviceBuffer( int );
0299 
0300         /**
0301          * @param speed current writing speed in Kb
0302          * @param multiplicator use 150 for CDs and 1380 for DVDs
0303          * FIXME: maybe one should be able to ask the burnjob if it burns a CD or a DVD and remove the
0304          *        multiplicator parameter)
0305          */
0306         void writeSpeed( int speed, K3b::Device::SpeedMultiplicator multiplicator );
0307 
0308         /**
0309          * This signal may be used to inform when the burning starts or ends
0310          * The BurningProgressDialog for example uses it to enable and disable
0311          * the buffer and writing speed displays.
0312          */
0313         void burning(bool);
0314 
0315     private:
0316         class Private;
0317         Private* const d;
0318      };
0319 }
0320 
0321 #endif