File indexing completed on 2025-02-02 04:18:31

0001 /*
0002  *  SPDX-FileCopyrightText: 2017 Dmitry Kazakov <dimula73@gmail.com>
0003  *
0004  *  SPDX-License-Identifier: GPL-2.0-or-later
0005  */
0006 
0007 #ifndef KISASYNCANIMATIONRENDERDIALOGBASE_H
0008 #define KISASYNCANIMATIONRENDERDIALOGBASE_H
0009 
0010 #include <QObject>
0011 #include "kis_types.h"
0012 #include "kritaui_export.h"
0013 
0014 #include <KisAsyncAnimationRendererBase.h>
0015 
0016 class KisTimeSpan;
0017 class KisViewManager;
0018 class KisRegion;
0019 
0020 /**
0021  * @brief KisAsyncAnimationRenderDialogBase is a special class for rendering multiple
0022  *        frames of the image and putting them somewhere (saving into a file or just
0023  *        pushing into an openGL cache)
0024  *
0025  * The class handles a lot of boilerplate code for you and optimizes regeneration of
0026  * the frames using multithreading, according to the user's settings. The responsibilities
0027  * of the class are the following:
0028  *
0029  * Rendering itself:
0030  *   - fetch the list of dirty frames using calcDirtyFrames()
0031  *   - create some clones of the image according to the user's settings
0032  *     to facilitate multithreaded rendering and processing of the frames
0033  *   - if the user doesn't have enough RAM, the clones will not be created
0034  *     (the memory overhead is calculated using "projections" metric of the
0035  *      statistics server).
0036  *   - feed the images/threads with dirty frames until the all the frames
0037  *     are done
0038  *
0039  * Progress reporting:
0040  *   - if batchMode() is false, the user will see a progress dialog showing
0041  *     the current progress with estimate about total processing timer
0042  *   - the user can also cancel the regeneration by pressing Cancel button
0043  *
0044  * Usage Details:
0045  *   - one should implement two methods to make the rendering work:
0046  *     - calcDirtyFrames()
0047  *     - createRenderer(KisImageSP image)
0048  *   - these methods will be called on the start of the rendering
0049  */
0050 class KRITAUI_EXPORT KisAsyncAnimationRenderDialogBase : public QObject
0051 {
0052     Q_OBJECT
0053 public:
0054     enum Result {
0055         RenderComplete,
0056         RenderCancelled,
0057         RenderFailed,
0058         RenderTimedOut
0059     };
0060 
0061 public:
0062     /**
0063      * @brief construct and initialize the dialog
0064      * @param actionTitle the first line of the status reports that the user sees in the dialog
0065      * @param image the image that will be as a source of frames. Make sure the image is *not*
0066      *              locked by the time regenerateRange() is called
0067      * @param busyWait the dialog will not show for the specified time (in milliseconds)
0068      */
0069     KisAsyncAnimationRenderDialogBase(const QString &actionTitle, KisImageSP image, int busyWait = 200);
0070     virtual ~KisAsyncAnimationRenderDialogBase();
0071 
0072     /**
0073      * @brief start generation of frames and (if not in batch mode) show the dialog
0074      *
0075      * The link to view manager is used to barrier lock with visual feedback in the
0076      * end of the operation
0077      */
0078     virtual Result regenerateRange(KisViewManager *viewManager);
0079 
0080     /**
0081      * Set area of image that will be regenerated. If \p roi is empty,
0082      * full area of the image is regenerated.
0083      */
0084     void setRegionOfInterest(const KisRegion &roi);
0085 
0086     /**
0087      * @see setRegionOfInterest()
0088      */
0089     KisRegion regionOfInterest() const;
0090 
0091     /**
0092      * @brief setting batch mode to true will prevent any dialogs or message boxes from
0093      *        showing on screen. Please take it into account that using batch mode prevents
0094      *        some potentially dangerous recovery execution paths (e.g. delete the existing
0095      *        frames in the destination folder). In such case the rendering will be stopped with
0096      *        RenderFailed result.
0097      */
0098     void setBatchMode(bool value);
0099 
0100     /**
0101      * @see setBatchMode
0102      */
0103     bool batchMode() const;
0104 
0105 private Q_SLOTS:
0106     void slotFrameCompleted(int frame);
0107     void slotFrameCancelled(int frame, KisAsyncAnimationRendererBase::CancelReason cancelReason);
0108 
0109     void slotCancelRegeneration();
0110     void slotUpdateCompressedProgressData();
0111 
0112 private:
0113     void tryInitiateFrameRegeneration();
0114     void updateProgressLabel();
0115     void cancelProcessingImpl(KisAsyncAnimationRendererBase::CancelReason cancelReason);
0116 
0117 protected:
0118     /**
0119      * @brief returns a list of frames that should be regenerated by the dialog
0120      *
0121      * Called by the dialog in the very beginning of regenerateRange()
0122      */
0123     virtual QList<int> calcDirtyFrames() const = 0;
0124 
0125     /**
0126      * @brief create a renderer object linked to \p image
0127      *
0128      * Renderer are special objects that connect to the individual image signals,
0129      * react on them and fetch the final frames data
0130      *
0131      * @see KisAsyncAnimationRendererBase
0132      */
0133     virtual KisAsyncAnimationRendererBase* createRenderer(KisImageSP image) = 0;
0134 
0135     virtual void initializeRendererForFrame(KisAsyncAnimationRendererBase *renderer,
0136                                             KisImageSP image, int frame) = 0;
0137 
0138 private:
0139     struct Private;
0140     const QScopedPointer<Private> m_d;
0141 };
0142 
0143 #endif // KISASYNCANIMATIONRENDERDIALOGBASE_H