File indexing completed on 2024-05-19 03:56:21

0001 /*
0002     This file is part of the KDE project
0003 
0004     SPDX-FileCopyrightText: 2000 Stephan Kulow <coolo@kde.org>
0005     SPDX-FileCopyrightText: 2000 David Faure <faure@kde.org>
0006     SPDX-FileCopyrightText: 2006 Kevin Ottens <ervin@kde.org>
0007 
0008     SPDX-License-Identifier: LGPL-2.0-or-later
0009 */
0010 
0011 #ifndef KJOB_H
0012 #define KJOB_H
0013 
0014 #include <QObject>
0015 #include <QPair>
0016 #include <kcoreaddons_export.h>
0017 #include <memory>
0018 
0019 class KJobUiDelegate;
0020 
0021 class KJobPrivate;
0022 /**
0023  * @class KJob kjob.h KJob
0024  *
0025  * The base class for all jobs.
0026  * For all jobs created in an application, the code looks like
0027  *
0028  * \code
0029  * void SomeClass::methodWithAsynchronousJobCall()
0030  * {
0031  *   KJob *job = someoperation(some parameters);
0032  *   connect(job, &KJob::result, this, &SomeClass::handleResult);
0033  *   job->start();
0034  * }
0035  * \endcode
0036  *   (other connects, specific to the job)
0037  *
0038  * And handleResult is usually at least:
0039  *
0040  * \code
0041  * void SomeClass::handleResult(KJob *job)
0042  * {
0043  *   if (job->error()) {
0044  *       doSomething();
0045  *   }
0046  * }
0047  * \endcode
0048  *
0049  * With the synchronous interface the code looks like
0050  *
0051  * \code
0052  * void SomeClass::methodWithSynchronousJobCall()
0053  * {
0054  *   KJob *job = someoperation( some parameters );
0055  *   if (!job->exec()) {
0056  *       // An error occurred
0057  *   } else {
0058  *       // Do something
0059  *   }
0060  * }
0061  * \endcode
0062  *
0063  * Subclasses must implement start(), which should trigger the execution of
0064  * the job (although the work should be done asynchronously). errorString()
0065  * should also be reimplemented by any subclasses that introduce new error
0066  * codes.
0067  *
0068  * @note KJob and its subclasses are meant to be used in a fire-and-forget way.
0069  * Jobs will delete themselves when they finish using deleteLater() (although
0070  * this behaviour can be changed), so a job instance will disappear after the
0071  * next event loop run.
0072  */
0073 class KCOREADDONS_EXPORT KJob : public QObject
0074 {
0075     Q_OBJECT
0076     Q_PROPERTY(int error READ error NOTIFY result)
0077     Q_PROPERTY(QString errorText READ errorText NOTIFY result)
0078     Q_PROPERTY(QString errorString READ errorString NOTIFY result)
0079     Q_PROPERTY(ulong percent READ percent NOTIFY percentChanged) // KF6 TODO: make "int", is enough
0080     Q_PROPERTY(Capabilities capabilities READ capabilities CONSTANT)
0081 
0082 public:
0083     /**
0084      * Describes the unit used in the methods that handle reporting the job progress info.
0085      * @see totalAmount
0086      */
0087     enum Unit {
0088         Bytes = 0, ///< Directory and file sizes in bytes
0089         Files, ///< The number of files handled by the job
0090         Directories, ///< The number of directories handled by the job
0091         Items, ///< The number of items (e.g. both directories and files) handled by the job
0092                ///< @since 5.72
0093 
0094         UnitsCount, ///< @internal since 5.87, used internally only, do not use.
0095     };
0096     Q_ENUM(Unit)
0097 
0098     /**
0099      * @see Capabilities
0100      */
0101     enum Capability {
0102         NoCapabilities = 0x0000, ///< None of the capabilities exist
0103         Killable = 0x0001, ///< The job can be killed
0104         Suspendable = 0x0002, ///< The job can be suspended
0105     };
0106     Q_ENUM(Capability)
0107 
0108     /**
0109      * Stores a combination of #Capability values.
0110      */
0111     Q_DECLARE_FLAGS(Capabilities, Capability)
0112     Q_FLAG(Capabilities)
0113 
0114     /**
0115      * Creates a new KJob object.
0116      *
0117      * @param parent the parent QObject
0118      */
0119     explicit KJob(QObject *parent = nullptr);
0120 
0121     /**
0122      * Destroys a KJob object.
0123      */
0124     ~KJob() override;
0125 
0126     /**
0127      * Attach a UI delegate to this job.
0128      *
0129      * If the job had another UI delegate, it's automatically deleted. Once
0130      * attached to the job, the UI delegate will be deleted with the job.
0131      *
0132      * @param delegate the new UI delegate to use
0133      * @see KJobUiDelegate
0134      */
0135     void setUiDelegate(KJobUiDelegate *delegate);
0136 
0137     /**
0138      * Retrieves the delegate attached to this job.
0139      *
0140      * @return the delegate attached to this job, or @c nullptr if there's no such delegate
0141      */
0142     KJobUiDelegate *uiDelegate() const;
0143 
0144     /**
0145      * Returns the capabilities of this job.
0146      *
0147      * @return the capabilities that this job supports
0148      * @see setCapabilities()
0149      */
0150     Capabilities capabilities() const;
0151 
0152     /**
0153      * Returns if the job was suspended with the suspend() call.
0154      *
0155      * @return if the job was suspended
0156      * @see suspend() resume()
0157      */
0158     bool isSuspended() const;
0159 
0160     /**
0161      * Starts the job asynchronously.
0162      *
0163      * When the job is finished, result() is emitted.
0164      *
0165      * Warning: Never implement any synchronous workload in this method. This method
0166      * should just trigger the job startup, not do any work itself. It is expected to
0167      * be non-blocking.
0168      *
0169      * This is the method all subclasses need to implement.
0170      * It should setup and trigger the workload of the job. It should not do any
0171      * work itself. This includes all signals and terminating the job, e.g. by
0172      * emitResult(). The workload, which could be another method of the
0173      * subclass, is to be triggered using the event loop, e.g. by code like:
0174      * \code
0175      * void ExampleJob::start()
0176      * {
0177      *  QTimer::singleShot(0, this, &ExampleJob::doWork);
0178      * }
0179      * \endcode
0180      */
0181     Q_SCRIPTABLE virtual void start() = 0;
0182 
0183     enum KillVerbosity {
0184         Quietly,
0185         EmitResult,
0186     };
0187     Q_ENUM(KillVerbosity)
0188 
0189 public Q_SLOTS:
0190     /**
0191      * Aborts this job.
0192      *
0193      * This kills and deletes the job.
0194      *
0195      * @param verbosity if equals to EmitResult, Job will emit signal result
0196      * and ask uiserver to close the progress window.
0197      * @p verbosity is set to EmitResult for subjobs. Whether applications
0198      * should call with Quietly or EmitResult depends on whether they rely
0199      * on result being emitted or not. Please notice that if @p verbosity is
0200      * set to Quietly, signal result will NOT be emitted.
0201      * @return true if the operation is supported and succeeded, false otherwise
0202      */
0203     bool kill(KJob::KillVerbosity verbosity = KJob::Quietly);
0204 
0205     /**
0206      * Suspends this job.
0207      * The job should be kept in a state in which it is possible to resume it.
0208      *
0209      * @return true if the operation is supported and succeeded, false otherwise
0210      */
0211     bool suspend();
0212 
0213     /**
0214      * Resumes this job.
0215      *
0216      * @return true if the operation is supported and succeeded, false otherwise
0217      */
0218     bool resume();
0219 
0220 protected:
0221     /**
0222      * Aborts this job quietly.
0223      *
0224      * This simply kills the job, no error reporting or job deletion should be involved.
0225      *
0226      * @return true if the operation is supported and succeeded, false otherwise
0227      */
0228     virtual bool doKill();
0229 
0230     /**
0231      * Suspends this job.
0232      *
0233      * @return true if the operation is supported and succeeded, false otherwise
0234      */
0235     virtual bool doSuspend();
0236 
0237     /**
0238      * Resumes this job.
0239      *
0240      * @return true if the operation is supported and succeeded, false otherwise
0241      */
0242     virtual bool doResume();
0243 
0244     /**
0245      * Sets the capabilities for this job.
0246      *
0247      * @param capabilities are the capabilities supported by this job
0248      * @see capabilities()
0249      */
0250     void setCapabilities(Capabilities capabilities);
0251 
0252 public:
0253     /**
0254      * Executes the job synchronously.
0255      *
0256      * This will start a nested QEventLoop internally. Nested event loop can be dangerous and
0257      * can have unintended side effects, you should avoid calling exec() whenever you can and use the
0258      * asynchronous interface of KJob instead.
0259      *
0260      * Should you indeed call this method, you need to make sure that all callers are reentrant,
0261      * so that events delivered by the inner event loop don't cause non-reentrant functions to be
0262      * called, which usually wreaks havoc.
0263      *
0264      * Note that the event loop started by this method does not process user input events, which means
0265      * your user interface will effectively be blocked. Other events like paint or network events are
0266      * still being processed. The advantage of not processing user input events is that the chance of
0267      * accidental reentrance is greatly reduced. Still you should avoid calling this function.
0268      *
0269      * @return true if the job has been executed without error, false otherwise
0270      */
0271     bool exec();
0272 
0273     enum {
0274         /*** Indicates there is no error */
0275         NoError = 0,
0276         /*** Indicates the job was killed */
0277         KilledJobError = 1,
0278         /*** Subclasses should define error codes starting at this value */
0279         UserDefinedError = 100,
0280     };
0281 
0282     /**
0283      * Returns the error code, if there has been an error.
0284      *
0285      * Only call this method from the slot connected to result().
0286      *
0287      * @return the error code for this job, 0 if no error.
0288      */
0289     int error() const;
0290 
0291     /**
0292      * Returns the error text if there has been an error.
0293      *
0294      * Only call if error is not 0.
0295      *
0296      * This is usually some extra data associated with the error,
0297      * such as a URL.  Use errorString() to get a human-readable,
0298      * translated message.
0299      *
0300      * @return a string to help understand the error
0301      */
0302     QString errorText() const;
0303 
0304     /**
0305      * A human-readable error message.
0306      *
0307      * This provides a translated, human-readable description of the
0308      * error.  Only call if error is not 0.
0309      *
0310      * Subclasses should implement this to create a translated
0311      * error message from the error code and error text.
0312      * For example:
0313      * \code
0314      * if (error() == ReadFailed) {
0315      *   i18n("Could not read \"%1\"", errorText());
0316      * }
0317      * \endcode
0318      *
0319      * @return a translated error message, providing error() is 0
0320      */
0321     virtual QString errorString() const;
0322 
0323     /**
0324      * Returns the processed amount of a given unit for this job.
0325      *
0326      * @param unit the unit of the requested amount
0327      * @return the processed size
0328      */
0329     Q_SCRIPTABLE qulonglong processedAmount(Unit unit) const;
0330 
0331     /**
0332      * Returns the total amount of a given unit for this job.
0333      *
0334      * @param unit the unit of the requested amount
0335      * @return the total size
0336      */
0337     Q_SCRIPTABLE qulonglong totalAmount(Unit unit) const;
0338 
0339     /**
0340      * Returns the overall progress of this job.
0341      *
0342      * @return the overall progress of this job
0343      */
0344     unsigned long percent() const;
0345 
0346     /**
0347      * Sets the auto-delete property of the job. If @p autodelete is
0348      * set to @c false the job will not delete itself once it is finished.
0349      *
0350      * The default for any KJob is to automatically delete itself, which
0351      * implies that the job was created on the heap (using <tt>new</tt>).
0352      * If the job is created on the stack (which isn't the typical use-case
0353      * for a job) then you must set auto-delete to @c false, otherwise you
0354      * could get a crash when the job finishes and tries to delete itself.
0355      *
0356      * @note If you set auto-delete to @c false then you need to kill the
0357      * job manually, ideally by calling kill().
0358      *
0359      * @param autodelete set to @c false to disable automatic deletion
0360      * of the job.
0361      */
0362     void setAutoDelete(bool autodelete);
0363 
0364     /**
0365      * Returns whether this job automatically deletes itself once
0366      * the job is finished.
0367      *
0368      * @return whether the job is deleted automatically after
0369      * finishing.
0370      */
0371     bool isAutoDelete() const;
0372 
0373     /**
0374      * This method can be used to indicate to classes listening to signals from a job
0375      * that they should ideally show a progress bar, but not a finished notification.
0376      *
0377      * For example when opening a remote URL, a job will emit the progress of the
0378      * download, which can be used to show a progress dialog or a Plasma notification,
0379      * then when the job is done it'll emit e.g. the finished signal. Showing the user the
0380      * progress dialog is useful, however the dialog/notification about the download being
0381      * finished isn't of much interest, because the user can see the application that invoked
0382      * the job opening the actual file that was downloaded.
0383      *
0384      * @since 5.92
0385      */
0386     void setFinishedNotificationHidden(bool hide = true);
0387 
0388     /**
0389      * Whether to <em>not</em> show a finished notification when a job's finished
0390      * signal is emitted.
0391      *
0392      * @see setFinishedNotificationHidden()
0393      *
0394      * @since 5.92
0395      */
0396     bool isFinishedNotificationHidden() const;
0397 
0398     /**
0399      * Returns @c true if this job was started with exec(), which starts a nested event-loop
0400      * (with QEventLoop::ExcludeUserInputEvents, which blocks the GUI), otherwise returns
0401      * @c false which indicates this job was started asynchronously with start().
0402      *
0403      * This is useful for code that for example shows a dialog to ask the user a question,
0404      * and that would be no-op since the user cannot interact with the dialog.
0405      *
0406      * @since 5.95
0407      */
0408     bool isStartedWithExec() const;
0409 
0410 Q_SIGNALS:
0411     /**
0412      * Emitted when the job is finished, in any case. It is used to notify
0413      * observers that the job is terminated and that progress can be hidden.
0414      *
0415      * Since 5.75 this signal is guaranteed to be emitted exactly once.
0416      *
0417      * This is a private signal, it can't be emitted directly by subclasses of
0418      * KJob, use emitResult() instead.
0419      *
0420      * In general, to be notified of a job's completion, client code should connect to result()
0421      * rather than finished(), so that kill(Quietly) is indeed quiet.
0422      * However if you store a list of jobs and they might get killed silently,
0423      * then you must connect to this instead of result(), to avoid dangling pointers in your list.
0424      *
0425      * @param job the job that emitted this signal
0426      * @internal
0427      *
0428      * @see result
0429      */
0430     void finished(KJob *job
0431 #if !defined(K_DOXYGEN)
0432                   ,
0433                   QPrivateSignal
0434 #endif
0435     );
0436 
0437     /**
0438      * Emitted when the job is suspended.
0439      *
0440      * This is a private signal, it can't be emitted directly by subclasses of
0441      * KJob.
0442      *
0443      * @param job the job that emitted this signal
0444      */
0445     void suspended(KJob *job
0446 #if !defined(K_DOXYGEN)
0447                    ,
0448                    QPrivateSignal
0449 #endif
0450     );
0451 
0452     /**
0453      * Emitted when the job is resumed.
0454      *
0455      * This is a private signal, it can't be emitted directly by subclasses of
0456      * KJob.
0457      *
0458      * @param job the job that emitted this signal
0459      */
0460     void resumed(KJob *job
0461 #if !defined(K_DOXYGEN)
0462                  ,
0463                  QPrivateSignal
0464 #endif
0465     );
0466 
0467     /**
0468      * Emitted when the job is finished (except when killed with KJob::Quietly).
0469      *
0470      * Since 5.75 this signal is guaranteed to be emitted at most once.
0471      *
0472      * Use error to know if the job was finished with error.
0473      *
0474      * This is a private signal, it can't be emitted directly by subclasses of
0475      * KJob, use emitResult() instead.
0476      *
0477      * Please connect to this signal instead of finished.
0478      *
0479      * @param job the job that emitted this signal
0480      *
0481      * @see kill
0482      */
0483     void result(KJob *job
0484 #if !defined(K_DOXYGEN)
0485                 ,
0486                 QPrivateSignal
0487 #endif
0488     );
0489 
0490     /**
0491      * Emitted to display general description of this job. A description has
0492      * a title and two optional fields which can be used to complete the
0493      * description.
0494      *
0495      * Examples of titles are "Copying", "Creating resource", etc.
0496      * The fields of the description can be "Source" with an URL, and,
0497      * "Destination" with an URL for a "Copying" description.
0498      * @param job the job that emitted this signal
0499      * @param title the general description of the job
0500      * @param field1 first field (localized name and value)
0501      * @param field2 second field (localized name and value)
0502      */
0503     void description(KJob *job,
0504                      const QString &title,
0505                      const QPair<QString, QString> &field1 = QPair<QString, QString>(),
0506                      const QPair<QString, QString> &field2 = QPair<QString, QString>());
0507     /**
0508      * Emitted to display state information about this job.
0509      * Examples of message are "Resolving host", "Connecting to host...", etc.
0510      *
0511      * @param job the job that emitted this signal
0512      * @param message the info message
0513      */
0514     void infoMessage(KJob *job, const QString &message);
0515 
0516     /**
0517      * Emitted to display a warning about this job.
0518      *
0519      * @param job the job that emitted this signal
0520      * @param message the warning message
0521      */
0522     void warning(KJob *job, const QString &message);
0523 
0524 Q_SIGNALS:
0525     // These signals must be connected from KIO::KCoreDirLister (among others),
0526     // therefore they must be public.
0527     /**
0528      * Emitted when we know the amount the job will have to process. The unit of this
0529      * amount is sent too. It can be emitted several times if the job manages several
0530      * different units.
0531      *
0532      * @note This is a private signal, it shouldn't be emitted directly by subclasses of
0533      * KJob, use setTotalAmount() instead.
0534      *
0535      * @param job the job that emitted this signal
0536      * @param unit the unit of the total amount
0537      * @param amount the total amount
0538      *
0539      * @since 5.80
0540      */
0541     void totalAmountChanged(KJob *job,
0542                             KJob::Unit unit,
0543                             qulonglong amount
0544 #if !defined(K_DOXYGEN)
0545                             ,
0546                             QPrivateSignal
0547 #endif
0548     );
0549 
0550     /**
0551      * Regularly emitted to show the progress of this job by giving the current amount.
0552      * The unit of this amount is sent too. It can be emitted several times if the job
0553      * manages several different units.
0554      *
0555      * @note This is a private signal, it shouldn't be emitted directly by subclasses of
0556      * KJob, use setProcessedAmount() instead.
0557      *
0558      * @param job the job that emitted this signal
0559      * @param unit the unit of the processed amount
0560      * @param amount the processed amount
0561      *
0562      * @since 5.80
0563      */
0564     void processedAmountChanged(KJob *job,
0565                                 KJob::Unit unit,
0566                                 qulonglong amount
0567 #if !defined(K_DOXYGEN)
0568                                 ,
0569                                 QPrivateSignal
0570 #endif
0571     );
0572 
0573     /**
0574      * Emitted when we know the size of this job (data size in bytes for transfers,
0575      * number of entries for listings, etc).
0576      *
0577      * @note This is a private signal, it shouldn't be emitted directly by subclasses of
0578      * KJob, use setTotalAmount() instead.
0579      *
0580      * @param job the job that emitted this signal
0581      * @param size the total size
0582      */
0583     void totalSize(KJob *job, qulonglong size);
0584 
0585     /**
0586      * Regularly emitted to show the progress of this job
0587      * (current data size in bytes for transfers, entries listed, etc.).
0588      *
0589      * @note This is a private signal, it shouldn't be emitted directly by subclasses of
0590      * KJob, use setProcessedAmount() instead.
0591      *
0592      * @param job the job that emitted this signal
0593      * @param size the processed size
0594      */
0595     void processedSize(KJob *job, qulonglong size);
0596 
0597     /**
0598      * Progress signal showing the overall progress of the job. This is
0599      * valid for any kind of job, and allows using a progress bar very
0600      * easily. (see KProgressBar).
0601      *
0602      * Note that this signal is not emitted for finished jobs.
0603      *
0604      * @note This is a private signal, it shouldn't be emitted directly
0605      * by subclasses of KJob, use emitPercent(), setPercent() setTotalAmount()
0606      * or setProcessedAmount() instead.
0607      *
0608      * @param job the job that emitted this signal
0609      * @param percent the percentage
0610      *
0611      * @since 5.80
0612      */
0613     void percentChanged(KJob *job,
0614                         unsigned long percent
0615 #if !defined(K_DOXYGEN)
0616                         ,
0617                         QPrivateSignal
0618 #endif
0619     );
0620 
0621     /**
0622      * Emitted to display information about the speed of this job.
0623      *
0624      * @note This is a private signal, it shouldn't be emitted directly by subclasses of
0625      * KJob, use emitSpeed() instead.
0626      *
0627      * @param job the job that emitted this signal
0628      * @param speed the speed in bytes/s
0629      */
0630     void speed(KJob *job, unsigned long speed);
0631 
0632 protected:
0633     /**
0634      * Returns if the job has been finished and has emitted the finished() signal.
0635      *
0636      * @return if the job has been finished
0637      * @see finished()
0638      * @since 5.75
0639      */
0640     // KF6 TODO: make public. Useful at least for unittests that run multiple jobs in parallel.
0641     bool isFinished() const;
0642 
0643     /**
0644      * Sets the error code.
0645      *
0646      * It should be called when an error
0647      * is encountered in the job, just before calling emitResult().
0648      *
0649      * You should define an (anonymous) enum of error codes,
0650      * with values starting at KJob::UserDefinedError, and use
0651      * those.  For example,
0652      * @code
0653      * enum {
0654      *   InvalidFoo = UserDefinedError,
0655      *   BarNotFound,
0656      * };
0657      * @endcode
0658      *
0659      * @param errorCode the error code
0660      * @see emitResult()
0661      */
0662     void setError(int errorCode);
0663 
0664     /**
0665      * Sets the error text.
0666      *
0667      * It should be called when an error
0668      * is encountered in the job, just before calling emitResult().
0669      *
0670      * Provides extra information about the error that cannot be
0671      * determined directly from the error code.  For example, a
0672      * URL or filename.  This string is not normally translatable.
0673      *
0674      * @param errorText the error text
0675      * @see emitResult(), errorString(), setError()
0676      */
0677     void setErrorText(const QString &errorText);
0678 
0679     /**
0680      * Sets the processed size. The processedAmount() and percent() signals
0681      * are emitted if the values changed. The percent() signal is emitted
0682      * only for the progress unit.
0683      *
0684      * @param unit the unit of the new processed amount
0685      * @param amount the new processed amount
0686      */
0687     void setProcessedAmount(Unit unit, qulonglong amount);
0688 
0689     /**
0690      * Sets the total size. The totalSize() and percent() signals
0691      * are emitted if the values changed. The percent() signal is emitted
0692      * only for the progress unit.
0693      *
0694      * @param unit the unit of the new total amount
0695      * @param amount the new total amount
0696      */
0697     void setTotalAmount(Unit unit, qulonglong amount);
0698 
0699     /**
0700      * Sets the unit that will be used internally to calculate
0701      * the progress percentage.
0702      * The default progress unit is Bytes.
0703      * @since 5.76
0704      */
0705     void setProgressUnit(Unit unit);
0706 
0707     /**
0708      * Sets the overall progress of the job. The percent() signal
0709      * is emitted if the value changed.
0710      *
0711      * The job takes care of this if you call setProcessedAmount
0712      * in Bytes (or the unit set by setProgressUnit).
0713      * This method allows you to set your own progress, as an alternative.
0714      *
0715      * @param percentage the new overall progress
0716      */
0717     void setPercent(unsigned long percentage);
0718 
0719     /**
0720      * Utility function to emit the result signal, and end this job.
0721      * It first notifies the observers to hide the progress for this job using
0722      * the finished() signal.
0723      *
0724      * @note Deletes this job using deleteLater().
0725      *
0726      * @see result()
0727      * @see finished()
0728      */
0729     void emitResult();
0730 
0731     /**
0732      * Utility function for inherited jobs.
0733      * Emits the percent signal if bigger than previous value,
0734      * after calculating it from the parameters.
0735      *
0736      * @param processedAmount the processed amount
0737      * @param totalAmount the total amount
0738      * @see percent()
0739      */
0740     void emitPercent(qulonglong processedAmount, qulonglong totalAmount);
0741 
0742     /**
0743      * Utility function for inherited jobs.
0744      * Emits the speed signal and starts the timer for removing that info
0745      *
0746      * @param speed the speed in bytes/s
0747      */
0748     void emitSpeed(unsigned long speed);
0749 
0750 protected:
0751     std::unique_ptr<KJobPrivate> const d_ptr;
0752 
0753     KCOREADDONS_NO_EXPORT KJob(KJobPrivate &dd, QObject *parent);
0754 
0755 private:
0756     KCOREADDONS_NO_EXPORT void finishJob(bool emitResult);
0757 
0758     Q_DECLARE_PRIVATE(KJob)
0759 };
0760 
0761 Q_DECLARE_OPERATORS_FOR_FLAGS(KJob::Capabilities)
0762 
0763 #endif