1 /* 2 * Copyright (c) 2017 Dmitry Kazakov <dimula73@gmail.com> 3 * 4 * This program is free software; you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License as published by 6 * the Free Software Foundation; either version 2 of the License, or 7 * (at your option) any later version. 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with this program; if not, write to the Free Software 16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 17 */ 18 19 #ifndef KISASYNCANIMATIONRENDERDIALOGBASE_H 20 #define KISASYNCANIMATIONRENDERDIALOGBASE_H 21 22 #include <QObject> 23 #include "kis_types.h" 24 #include "kritaui_export.h" 25 26 class KisTimeRange; 27 class KisAsyncAnimationRendererBase; 28 class KisViewManager; 29 class KisRegion; 30 31 /** 32 * @brief KisAsyncAnimationRenderDialogBase is a special class for rendering multiple 33 * frames of the image and putting them somewhere (saving into a file or just 34 * pushing into an openGL cache) 35 * 36 * The class handles a lot of boilerplate code for you and optimizes regeneration of 37 * the frames using multithreading, according to the user's settings. The responsibilities 38 * of the class are the following: 39 * 40 * Rendering itself: 41 * - fetch the list of dirtly frames using calcDirtyFrames() 42 * - create some clones of the image according to the user's settings 43 * to facilitate multithreaded rendering and processing of the frames 44 * - if the user doesn't have enough RAM, the clones will not be created 45 * (the memory overhead is calculated using "projections" metric of the 46 * statistics server). 47 * - feed the images/threads with dirty frames until the all the frames 48 * are done 49 * 50 * Progress reporting: 51 * - if batchMode() is false, the user will see a progress dialog showing 52 * the current progress with estimate about total processing timer 53 * - the user can also cancel the regeneration by pressing Cancel button 54 * 55 * Usage Details: 56 * - one should implement two methods to make the rendering work: 57 * - calcDirtyFrames() 58 * - createRenderer(KisImageSP image) 59 * - these methods will be called on the start of the rendering 60 */ 61 class KRITAUI_EXPORT KisAsyncAnimationRenderDialogBase : public QObject 62 { 63 Q_OBJECT 64 public: 65 enum Result { 66 RenderComplete, 67 RenderCancelled, 68 RenderFailed 69 }; 70 71 public: 72 /** 73 * @brief construct and initialize the dialog 74 * @param actionTitle the first line of the status reports that the user sees in the dialog 75 * @param image the image that will be as a source of frames. Make sure the image is *not* 76 * locked by the time regenerateRange() is called 77 * @param busyWait the dialog will not show for the specified time (in milliseconds) 78 */ 79 KisAsyncAnimationRenderDialogBase(const QString &actionTitle, KisImageSP image, int busyWait = 200); 80 virtual ~KisAsyncAnimationRenderDialogBase(); 81 82 /** 83 * @brief start generation of frames and (if not in batch mode) show the dialog 84 * 85 * The link to view manager is used to barrier lock with visual feedback in the 86 * end of the operation 87 */ 88 virtual Result regenerateRange(KisViewManager *viewManager); 89 90 /** 91 * Set area of image that will be regenerated. If \p roi is empty, 92 * full area of the image is regenerated. 93 */ 94 void setRegionOfInterest(const KisRegion &roi); 95 96 /** 97 * @see setRegionOfInterest() 98 */ 99 KisRegion regionOfInterest() const; 100 101 /** 102 * @brief setting batch mode to true will prevent any dialogs or message boxes from 103 * showing on screen. Please take it into account that using batch mode prevents 104 * some potentially dangerous recovery execution paths (e.g. delete the existing 105 * frames in the destination folder). In such case the rendering will be stopped with 106 * RenderFailed result. 107 */ 108 void setBatchMode(bool value); 109 110 /** 111 * @see setBatchMode 112 */ 113 bool batchMode() const; 114 115 private Q_SLOTS: 116 void slotFrameCompleted(int frame); 117 void slotFrameCancelled(int frame); 118 119 void slotCancelRegeneration(); 120 void slotUpdateCompressedProgressData(); 121 122 private: 123 void tryInitiateFrameRegeneration(); 124 void updateProgressLabel(); 125 void cancelProcessingImpl(bool isUserCancelled); 126 127 protected: 128 /** 129 * @brief returns a list of frames that should be regenerated by the dialog 130 * 131 * Called by the dialog in the very beginning of regenerateRange() 132 */ 133 virtual QList<int> calcDirtyFrames() const = 0; 134 135 /** 136 * @brief create a renderer object linked to \p image 137 * 138 * Renderer are special objects that connect to the individual image signals, 139 * react on them and fetch the final frames data 140 * 141 * @see KisAsyncAnimationRendererBase 142 */ 143 virtual KisAsyncAnimationRendererBase* createRenderer(KisImageSP image) = 0; 144 145 virtual void initializeRendererForFrame(KisAsyncAnimationRendererBase *renderer, 146 KisImageSP image, int frame) = 0; 147 148 private: 149 struct Private; 150 const QScopedPointer<Private> m_d; 151 }; 152 153 #endif // KISASYNCANIMATIONRENDERDIALOGBASE_H 154