]> git.sesse.net Git - kdenlive/blob - src/abstractscopewidget.h
Add animation feature to Slideshow Clip.
[kdenlive] / src / abstractscopewidget.h
1 /***************************************************************************
2  *   Copyright (C) 2010 by Simon Andreas Eugster (simon.eu@gmail.com)      *
3  *   This file is part of kdenlive. See www.kdenlive.org.                  *
4  *                                                                         *
5  *   This program is free software; you can redistribute it and/or modify  *
6  *   it under the terms of the GNU General Public License as published by  *
7  *   the Free Software Foundation; either version 2 of the License, or     *
8  *   (at your option) any later version.                                   *
9  ***************************************************************************/
10
11 /**
12   This abstract widget is a proof that abstract things sometimes *are* useful.
13
14   The widget expects three layers which
15   * Will be painted on top of each other on each update
16   * Are rendered in a separate thread so that the UI is not blocked
17   * Are rendered only if necessary (e.g., if a layer does not depend
18     on input images, it will not be re-rendered for incoming frames)
19
20   The layer order is as follows:
21      _____________________
22     /                     \
23    /      HUD Layer        \
24   /                         \
25   ---------------------------
26      _____________________
27     /                     \
28    /     Scope Layer       \
29   /                         \
30   ---------------------------
31      _____________________
32     /                     \
33    /   Background Layer    \
34   /                         \
35   ---------------------------
36
37   Colors of Scope Widgets are defined in here (and thus don't need to be
38   re-defined in the implementation of the widget's .ui file).
39
40   The custom context menu already contains entries, like for enabling auto-
41   refresh. It can certainly be extended in the implementation of the widget.
42
43   Note: Widgets deriving from this class should connect slotActiveMonitorChanged
44   to the appropriate signal.
45
46   If you intend to write an own widget inheriting from this one, please read
47   the comments on the unimplemented methods carefully. They are not only here
48   for optical amusement, but also contain important information.
49  */
50
51 #ifndef ABSTRACTSCOPEWIDGET_H
52 #define ABSTRACTSCOPEWIDGET_H
53
54 #include <QtCore>
55 #include <QWidget>
56
57 class QMenu;
58
59 class Monitor;
60 class Render;
61
62 class AbstractScopeWidget : public QWidget
63 {
64     Q_OBJECT
65
66 public:
67     AbstractScopeWidget(Monitor *projMonitor, Monitor *clipMonitor, QWidget *parent = 0);
68     virtual ~AbstractScopeWidget(); // Must be virtual because of inheritance, to avoid memory leaks
69     QPalette m_scopePalette;
70
71     /** Initializes widget settings (reads configuration).
72       Has to be called in the implementing object. */
73     void init();
74
75     ///// Unimplemented /////
76
77     virtual QString widgetName() const = 0;
78
79 protected:
80     ///// Variables /////
81
82     Monitor *m_projMonitor;
83     Monitor *m_clipMonitor;
84     Render *m_activeRender;
85
86
87     /** The context menu. Feel free to add new entries in your implementation. */
88     QMenu *m_menu;
89
90     /** Enables auto refreshing of the scope.
91         This is when a new frame is shown on the active monitor.
92         Resize events always force a recalculation. */
93     QAction *m_aAutoRefresh;
94
95     /** Realtime rendering. Should be disabled if it is not supported.
96         Use the accelerationFactor variable passed to the render functions as a hint of
97         how many times faster the scope should be calculated. */
98     QAction *m_aRealtime;
99
100
101     /** Offset from the widget's borders */
102     const uchar offset;
103
104     /** The rect on the widget we're painting in.
105         Can be used by the implementing widget, e.g. in the render methods.
106         Is updated when necessary (size changes). */
107     QRect m_scopeRect;
108
109     /** Images storing the calculated layers. Will be used on repaint events. */
110     QImage m_imgHUD;
111     QImage m_imgScope;
112     QImage m_imgBackground;
113
114     /** The acceleration factors can be accessed also by other renderer tasks,
115         e.g. to display the scope's acceleration factor in the HUD renderer. */
116     int m_accelFactorHUD;
117     int m_accelFactorScope;
118     int m_accelFactorBackground;
119
120     /** Reads the widget's configuration.
121         Can be extended in the implementing subclass (make sure to run readConfig as well). */
122     virtual void readConfig();
123     /** Writes the widget configuration.
124         Implementing widgets have to implement an own method and run it in their destructor. */
125     void writeConfig();
126     /** Identifier for the widget's configuration. */
127     QString configName();
128
129
130     ///// Unimplemented Methods /////
131
132     /** Where on the widget we can paint in.
133         May also update other variables that depend on the widget's size.  */
134     virtual QRect scopeRect() = 0;
135
136     /** @brief HUD renderer. Must emit signalHUDRenderingFinished(). @see renderScope */
137     virtual QImage renderHUD(uint accelerationFactor) = 0;
138     /** @brief Scope renderer. Must emit signalScopeRenderingFinished()
139         when calculation has finished, to allow multi-threading.
140         accelerationFactor hints how much faster than usual the calculation should be accomplished, if possible. */
141     virtual QImage renderScope(uint accelerationFactor, QImage) = 0;
142     /** @brief Background renderer. Must emit signalBackgroundRenderingFinished(). @see renderScope */
143     virtual QImage renderBackground(uint accelerationFactor) = 0;
144
145     /** Must return true if the HUD layer depends on the input monitor.
146         If it does not, then it does not need to be re-calculated when
147         a new frame from the monitor is incoming. */
148     virtual bool isHUDDependingOnInput() const = 0;
149     /** @see isHUDDependingOnInput() */
150     virtual bool isScopeDependingOnInput() const = 0;
151     /** @see isHUDDependingOnInput() */
152     virtual bool isBackgroundDependingOnInput() const = 0;
153
154     ///// Can be reimplemented /////
155     /** Calculates the acceleration factor to be used by the render thread.
156         This method can be refined in the subclass if required. */
157     virtual uint calculateAccelFactorHUD(uint oldMseconds, uint oldFactor);
158     virtual uint calculateAccelFactorScope(uint oldMseconds, uint oldFactor);
159     virtual uint calculateAccelFactorBackground(uint oldMseconds, uint oldFactor);
160
161     ///// Reimplemented /////
162
163     void mouseReleaseEvent(QMouseEvent *);
164     void paintEvent(QPaintEvent *);
165     void resizeEvent(QResizeEvent *);
166     void showEvent(QShowEvent *); // Called when the widget is activated via the Menu entry
167     //    void raise(); // Called only when  manually calling the event -> useless
168
169 protected slots:
170     /** Forces an update of all layers. */
171     void forceUpdate(bool doUpdate = true);
172     void forceUpdateHUD();
173     void forceUpdateScope();
174     void forceUpdateBackground();
175     void slotAutoRefreshToggled(bool);
176
177 signals:
178     /** mseconds represent the time taken for the calculation,
179         accelerationFactor is the acceleration factor that has been used. */
180     void signalHUDRenderingFinished(uint mseconds, uint accelerationFactor);
181     void signalScopeRenderingFinished(uint mseconds, uint accelerationFactor);
182     void signalBackgroundRenderingFinished(uint mseconds, uint accelerationFactor);
183
184 private:
185
186     /** Counts the number of frames that have been rendered in the active monitor.
187       The frame number will be reset when the calculation starts for the current frame. */
188     QAtomicInt m_newHUDFrames;
189     QAtomicInt m_newScopeFrames;
190     QAtomicInt m_newBackgroundFrames;
191
192     /** Counts the number of updates that, unlike new frames, force a recalculation
193       of the scope, like for example a resize event. */
194     QAtomicInt m_newHUDUpdates;
195     QAtomicInt m_newScopeUpdates;
196     QAtomicInt m_newBackgroundUpdates;
197
198     /** The semaphores ensure that the QFutures for the HUD/Scope/Background threads cannot
199       be assigned a new thread while it is still running. (Could cause deadlocks and other
200       nasty things known from parallelism. */
201     QSemaphore m_semaphoreHUD;
202     QSemaphore m_semaphoreScope;
203     QSemaphore m_semaphoreBackground;
204
205     QFuture<QImage> m_threadHUD;
206     QFuture<QImage> m_threadScope;
207     QFuture<QImage> m_threadBackground;
208
209     QImage m_scopeImage;
210
211     QString m_widgetName;
212
213     bool initialDimensionUpdateDone;
214     void prodHUDThread();
215     void prodScopeThread();
216     void prodBackgroundThread();
217
218
219 private slots:
220     /** @brief Must be called when the active monitor has shown a new frame.
221       This slot must be connected in the implementing class, it is *not*
222       done in this abstract class. */
223     void slotActiveMonitorChanged(bool isClipMonitor);
224     void customContextMenuRequested(const QPoint &pos);
225     /** To be called when a new frame has been received.
226       The scope then decides whether and when it wants to recalculate the scope, depending
227       on whether it is currently visible and whether a calculation thread is already running. */
228     void slotRenderZoneUpdated();
229     void slotRenderZoneUpdated(QImage);
230     /** The following slots are called when rendering of a component has finished. They e.g. update
231       the widget and decide whether to immediately restart the calculation thread. */
232     void slotHUDRenderingFinished(uint mseconds, uint accelerationFactor);
233     void slotScopeRenderingFinished(uint mseconds, uint accelerationFactor);
234     void slotBackgroundRenderingFinished(uint mseconds, uint accelerationFactor);
235
236     /** Resets the acceleration factors to 1 when realtime rendering is disabled. */
237     void slotResetRealtimeFactor(bool realtimeChecked);
238
239 };
240
241 #endif // ABSTRACTSCOPEWIDGET_H