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