]> git.sesse.net Git - kdenlive/blob - src/abstractscopewidget.h
Abstract scopes: Moved pens to ASW so other widgets can use them
[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     ///// Variables /////
80     static const QPen penThick;
81     static const QPen penThin;
82     static const QPen penLight;
83     static const QPen penDark;
84
85 protected:
86     ///// Variables /////
87
88     Monitor *m_projMonitor;
89     Monitor *m_clipMonitor;
90     Render *m_activeRender;
91
92
93     /** The context menu. Feel free to add new entries in your implementation. */
94     QMenu *m_menu;
95
96     /** Enables auto refreshing of the scope.
97         This is when a new frame is shown on the active monitor.
98         Resize events always force a recalculation. */
99     QAction *m_aAutoRefresh;
100
101     /** Realtime rendering. Should be disabled if it is not supported.
102         Use the accelerationFactor variable passed to the render functions as a hint of
103         how many times faster the scope should be calculated. */
104     QAction *m_aRealtime;
105
106
107     /** Offset from the widget's borders */
108     const uchar offset;
109
110     /** The rect on the widget we're painting in.
111         Can be used by the implementing widget, e.g. in the render methods.
112         Is updated when necessary (size changes). */
113     QRect m_scopeRect;
114
115     /** Images storing the calculated layers. Will be used on repaint events. */
116     QImage m_imgHUD;
117     QImage m_imgScope;
118     QImage m_imgBackground;
119
120     /** The acceleration factors can be accessed also by other renderer tasks,
121         e.g. to display the scope's acceleration factor in the HUD renderer. */
122     int m_accelFactorHUD;
123     int m_accelFactorScope;
124     int m_accelFactorBackground;
125
126     /** Reads the widget's configuration.
127         Can be extended in the implementing subclass (make sure to run readConfig as well). */
128     virtual void readConfig();
129     /** Writes the widget configuration.
130         Implementing widgets have to implement an own method and run it in their destructor. */
131     void writeConfig();
132     /** Identifier for the widget's configuration. */
133     QString configName();
134
135
136     ///// Unimplemented Methods /////
137
138     /** Where on the widget we can paint in.
139         May also update other variables that depend on the widget's size.  */
140     virtual QRect scopeRect() = 0;
141
142     /** @brief HUD renderer. Must emit signalHUDRenderingFinished(). @see renderScope */
143     virtual QImage renderHUD(uint accelerationFactor) = 0;
144     /** @brief Scope renderer. Must emit signalScopeRenderingFinished()
145         when calculation has finished, to allow multi-threading.
146         accelerationFactor hints how much faster than usual the calculation should be accomplished, if possible. */
147     virtual QImage renderScope(uint accelerationFactor, QImage) = 0;
148     /** @brief Background renderer. Must emit signalBackgroundRenderingFinished(). @see renderScope */
149     virtual QImage renderBackground(uint accelerationFactor) = 0;
150
151     /** Must return true if the HUD layer depends on the input monitor.
152         If it does not, then it does not need to be re-calculated when
153         a new frame from the monitor is incoming. */
154     virtual bool isHUDDependingOnInput() const = 0;
155     /** @see isHUDDependingOnInput() */
156     virtual bool isScopeDependingOnInput() const = 0;
157     /** @see isHUDDependingOnInput() */
158     virtual bool isBackgroundDependingOnInput() const = 0;
159
160     ///// Can be reimplemented /////
161     /** Calculates the acceleration factor to be used by the render thread.
162         This method can be refined in the subclass if required. */
163     virtual uint calculateAccelFactorHUD(uint oldMseconds, uint oldFactor);
164     virtual uint calculateAccelFactorScope(uint oldMseconds, uint oldFactor);
165     virtual uint calculateAccelFactorBackground(uint oldMseconds, uint oldFactor);
166
167     ///// Reimplemented /////
168
169     void mouseReleaseEvent(QMouseEvent *);
170     void paintEvent(QPaintEvent *);
171     void resizeEvent(QResizeEvent *);
172     void showEvent(QShowEvent *); // Called when the widget is activated via the Menu entry
173     //    void raise(); // Called only when  manually calling the event -> useless
174
175 protected slots:
176     /** Forces an update of all layers. */
177     void forceUpdate(bool doUpdate = true);
178     void forceUpdateHUD();
179     void forceUpdateScope();
180     void forceUpdateBackground();
181     void slotAutoRefreshToggled(bool);
182
183 signals:
184     /** mseconds represent the time taken for the calculation,
185         accelerationFactor is the acceleration factor that has been used. */
186     void signalHUDRenderingFinished(uint mseconds, uint accelerationFactor);
187     void signalScopeRenderingFinished(uint mseconds, uint accelerationFactor);
188     void signalBackgroundRenderingFinished(uint mseconds, uint accelerationFactor);
189
190 private:
191
192     /** Counts the number of frames that have been rendered in the active monitor.
193       The frame number will be reset when the calculation starts for the current frame. */
194     QAtomicInt m_newHUDFrames;
195     QAtomicInt m_newScopeFrames;
196     QAtomicInt m_newBackgroundFrames;
197
198     /** Counts the number of updates that, unlike new frames, force a recalculation
199       of the scope, like for example a resize event. */
200     QAtomicInt m_newHUDUpdates;
201     QAtomicInt m_newScopeUpdates;
202     QAtomicInt m_newBackgroundUpdates;
203
204     /** The semaphores ensure that the QFutures for the HUD/Scope/Background threads cannot
205       be assigned a new thread while it is still running. (Could cause deadlocks and other
206       nasty things known from parallelism. */
207     QSemaphore m_semaphoreHUD;
208     QSemaphore m_semaphoreScope;
209     QSemaphore m_semaphoreBackground;
210
211     QFuture<QImage> m_threadHUD;
212     QFuture<QImage> m_threadScope;
213     QFuture<QImage> m_threadBackground;
214
215     QImage m_scopeImage;
216
217     QString m_widgetName;
218
219     bool initialDimensionUpdateDone;
220     void prodHUDThread();
221     void prodScopeThread();
222     void prodBackgroundThread();
223
224
225 private slots:
226     /** @brief Must be called when the active monitor has shown a new frame.
227       This slot must be connected in the implementing class, it is *not*
228       done in this abstract class. */
229     void slotActiveMonitorChanged(bool isClipMonitor);
230     void customContextMenuRequested(const QPoint &pos);
231     /** To be called when a new frame has been received.
232       The scope then decides whether and when it wants to recalculate the scope, depending
233       on whether it is currently visible and whether a calculation thread is already running. */
234     void slotRenderZoneUpdated();
235     void slotRenderZoneUpdated(QImage);
236     /** The following slots are called when rendering of a component has finished. They e.g. update
237       the widget and decide whether to immediately restart the calculation thread. */
238     void slotHUDRenderingFinished(uint mseconds, uint accelerationFactor);
239     void slotScopeRenderingFinished(uint mseconds, uint accelerationFactor);
240     void slotBackgroundRenderingFinished(uint mseconds, uint accelerationFactor);
241
242     /** Resets the acceleration factors to 1 when realtime rendering is disabled. */
243     void slotResetRealtimeFactor(bool realtimeChecked);
244
245 };
246
247 #endif // ABSTRACTSCOPEWIDGET_H