1 #ifndef EFFECTUI_H
2 #define EFFECTUI_H
3 
4 #include "collapsiblewidget.h"
5 #include "effects/effect.h"
6 
7 /**
8  * @brief The EffectUI class
9  *
10  * EffectUI is a complete QWidget-based representation of an Effect that can be added to any Qt layout. It overrides
11  * CollapsibleWidget (meaning the Effect can be collapsed to just a titlebar to save space). The titlebar is
12  * automatically set to the Effect's name and the contents are composed of a grid layout (QGridLayout) corresponding
13  * to the Effect's EffectRow and EffectField children.
14  *
15  * Many EffectUIs can be created from a single Effect, and many Effects can be attached to a single EffectUI (provided
16  * the Effects are all the same type). Neither gains ownership of each other and deleting an EffectUI without any other
17  * work is perfectly safe (deleting an Effect with an open EffectUI however, is not).
18  */
19 class EffectUI : public CollapsibleWidget {
20   Q_OBJECT
21 public:
22   /**
23    * @brief EffectUI Constructor
24    *
25    * Creates a QWidget-based UI representation of an Effect.
26    *
27    * @param e
28    *
29    * The Effect to make a UI of. It must be a valid object.
30    */
31   EffectUI(Effect* e);
32 
33   /**
34    * @brief Attach additional effects to this UI
35    *
36    * Olive allows users to modify several effects (of the same type) with one UI representation. To do this, you can
37    * add any amount of extra Effect objects using this function and the UI will attach all of its UI functions to that
38    * Effect as well without creating any new QWidgets.
39    *
40    * @param e
41    *
42    * The Effect to add to this UI object.
43    */
44   void AddAdditionalEffect(Effect* e);
45 
46   /**
47    * @brief Get the primary Effect that this UI object was created for
48    *
49    * @return
50    *
51    * The Effect object passed to the constructor when creating this EffectUI.
52    */
53   Effect* GetEffect();
54 
55   /**
56    * @brief Get the Y position of a given row
57    *
58    * Retrieve the on-screen Y position of the attached Effect's EffectRow at a given index. This is primarily used for
59    * displaying UI elements that align with the the row's on-screen widgets (e.g. keyframes in the EffectControls
60    * panel).
61    *
62    * The Y value provided is specifically the center point of the row's name label. It gets mapped to a provided
63    * QWidget object so it can be used locally by that QWidget without further modification.
64    *
65    * @param row
66    *
67    * The index of the EffectRow to retrieve the Y position of.
68    *
69    * @param mapToWidget
70    *
71    * The widget to map the Y value to.
72    *
73    * @return
74    *
75    * The row's Y position.
76    */
77   int GetRowY(int row, QWidget *mapToWidget);
78 
79   /**
80    * @brief Update widgets with the current Effect's values.
81    *
82    * When the Timeline playhead moves, the current values in the Effect might change if its fields are keyframed.
83    * In order to visually update these values on the UI, this function should be called. It will loop through all
84    * fields of all attached effects and update them to the value at the current Timeline playhead.
85    *
86    * Currently this function is called by update_ui() which is also responsible for updating other parts of the UI
87    * like the Timeline and Viewer so they all get updated together.
88    */
89   void UpdateFromEffect();
90 
91   /**
92    * @brief Check if a given Clip has an Effect referenced by this EffectUI
93    *
94    * Olive allows users to modify several effects (of the same type) with one UI representation. The behavior is if
95    * multiple clips are selected that have effects of the same type, all those Effects can be modified by the same
96    * EffectUI object. However this behavior is undesirable if a single Clip has more than one of the same type of Effect
97    * (e.g. two or more blurs). In this scenario, the user will most likely expect two separate UI objects for each of
98    * these effects individually, rather than consolidating them into one UI object.
99    *
100    * To address this, EffectControls will check this function to determine if this EffectUI already references
101    * an Effect of this type from this Clip. If it does, it's assumed a new EffectUI should be made rather than
102    * consolidating that Effect into the same EffectUI.
103    *
104    * @param c
105    *
106    * The Clip to determine whether an Effect of this type is already referenced by this EffectUI.
107    *
108    * @return
109    *
110    * True is an Effect from this Clip is already attached to this EffectUI.
111    */
112   bool IsAttachedToClip(Clip* c);
113 
114 signals:
115   /**
116    * @brief Cut signal
117    *
118    * Emitted when the user selects Cut from the right-click context menu.
119    */
120   void CutRequested();
121 
122   /**
123    * @brief Copy signal
124    *
125    * Emitted when the user selects Copy from the right-click context menu.
126    */
127   void CopyRequested();
128 private:
129   /**
130    * @brief Retrieve the QWidget corresponding a specific EffectField
131    *
132    * Convenience function equivalent to widgets_.at(row).at(field).
133    *
134    * @param row
135    *
136    * EffectRow index to retrieve field QWidget from
137    *
138    * @param field
139    *
140    * EffectField index to retrieve QWidget from
141    *
142    * @return
143    *
144    * The QWidget at this row and field index.
145    */
146   QWidget* Widget(int row, int field);
147 
148   /**
149    * @brief Internal reference to the Effect this object was constructed around.
150    */
151   Effect* effect_;
152 
153   /**
154    * @brief Internal array of additional Effect objects attached to this UI.
155    */
156   QVector<Effect*> additional_effects_;
157 
158   /**
159    * @brief Layout for UI widgets
160    */
161   QGridLayout* layout_;
162 
163   /**
164    * @brief Grid array of QWidgets corresponding to the Effect's rows and fields
165    */
166   QVector< QVector<QWidget*> > widgets_;
167 
168   /**
169    * @brief Array of QLabel objects corresponding to each row's name().
170    */
171   QVector<QLabel*> labels_;
172 
173   /**
174    * @brief Array of KeyframeNavigator objects corresponding to each row.
175    */
176   QVector<KeyframeNavigator*> keyframe_navigators_;
177 
178   /**
179    * @brief Attach a KeyframeNavigator object to an EffectRow.
180    *
181    * Internal function for connecting a KeyframeNavigator UI object to an EffectRow.
182    *
183    * @param row
184    *
185    * The EffectRow object.
186    *
187    * @param nav
188    *
189    * The KeyframeNavigator object.
190    */
191   void AttachKeyframeNavigationToRow(EffectRow* row, KeyframeNavigator* nav);
192 private slots:
193   /**
194    * @brief Slot for titlebar's right-click signal to show a context menu for extra Effect functions.
195    */
196   void show_context_menu(const QPoint&);
197 };
198 
199 #endif // EFFECTUI_H
200