1 #pragma once
2 
3 #ifndef FLICONSOLE_H
4 #define FLICONSOLE_H
5 
6 #include <QWidget>
7 #include <QAction>
8 #include <QMap>
9 #include <QList>
10 #include <QTime>
11 #include <QStyleOption>
12 #include <QStyleOptionFrameV3>
13 #include <QColor>
14 #include <QImage>
15 
16 #include "tcommon.h"
17 #include "tpixel.h"
18 #include "toonzqt/intfield.h"
19 #include "toonz/imagepainter.h"
20 #include "tstopwatch.h"
21 #include <QThread>
22 
23 #undef DVAPI
24 #undef DVVAR
25 #ifdef TOONZQT_EXPORTS
26 #define DVAPI DV_EXPORT_API
27 #define DVVAR DV_EXPORT_VAR
28 #else
29 #define DVAPI DV_IMPORT_API
30 #define DVVAR DV_IMPORT_VAR
31 #endif
32 
33 class QToolBar;
34 class QLabel;
35 class QSlider;
36 class QTimerEvent;
37 class QVBoxLayout;
38 class QActionGroup;
39 class QAbstractButton;
40 class QPushButton;
41 class QScrollBar;
42 class DoubleButton;
43 class FlipSlider;
44 class FlipConsole;
45 class ToolBarContainer;
46 class FlipConsoleOwner;
47 class TFrameHandle;
48 //-----------------------------------------------------------------------------
49 
50 class PlaybackExecutor final : public QThread {
51   Q_OBJECT
52 
53   int m_fps;
54   bool m_abort;
55 
56 public:
57   PlaybackExecutor();
58 
59   void resetFps(int fps);
60 
61   void run() override;
abort()62   void abort() { m_abort = true; }
63 
emitNextFrame(int fps)64   void emitNextFrame(int fps) { emit nextFrame(fps); }
65 
66 signals:
67   void nextFrame(int fps);  // Must be connect with Qt::BlockingQueuedConnection
68                             // connection type.
69 };
70 
71 //-----------------------------------------------------------------------------
72 
73 // Implements a flipbook slider with a progress bar in background.
74 class FlipSlider final : public QAbstractSlider {
75   Q_OBJECT
76 
77   Q_PROPERTY(int PBHeight READ getPBHeight WRITE setPBHeight)
78 
79   Q_PROPERTY(QImage PBOverlay READ getPBOverlay WRITE setPBOverlay)
80   Q_PROPERTY(QImage PBMarker READ getPBMarker WRITE setPBMarker)
81 
82   Q_PROPERTY(int PBColorMarginLeft READ getPBColorMarginLeft WRITE
83                  setPBColorMarginLeft)
84   Q_PROPERTY(
85       int PBColorMarginTop READ getPBColorMarginTop WRITE setPBColorMarginTop)
86   Q_PROPERTY(int PBColorMarginRight READ getPBColorMarginRight WRITE
87                  setPBColorMarginRight)
88   Q_PROPERTY(int PBColorMarginBottom READ getPBColorMarginBottom WRITE
89                  setPBColorMarginBottom)
90 
91   Q_PROPERTY(int PBMarkerMarginLeft READ getPBMarkerMarginLeft WRITE
92                  setPBMarkerMarginLeft)
93   Q_PROPERTY(int PBMarkerMarginRight READ getPBMarkerMarginRight WRITE
94                  setPBMarkerMarginRight)
95 
96   Q_PROPERTY(QColor baseColor READ getBaseColor WRITE setBaseColor)
97   Q_PROPERTY(
98       QColor notStartedColor READ getNotStartedColor WRITE setNotStartedColor)
99   Q_PROPERTY(QColor startedColor READ getStartedColor WRITE setStartedColor)
100   Q_PROPERTY(QColor finishedColor READ getFinishedColor WRITE setFinishedColor)
101 
102   bool m_enabled;
103   const std::vector<UCHAR> *m_progressBarStatus;
104 
105 public:
106   enum { PBFrameNotStarted, PBFrameStarted, PBFrameFinished };
107 
108   FlipSlider(QWidget *parent);
~FlipSlider()109   ~FlipSlider() {}
110 
setProgressBarEnabled(bool enabled)111   void setProgressBarEnabled(bool enabled) { m_enabled = enabled; }
112 
setProgressBarStatus(const std::vector<UCHAR> * pbStatus)113   void setProgressBarStatus(const std::vector<UCHAR> *pbStatus) {
114     m_progressBarStatus = pbStatus;
115   }
116 
getProgressBarStatus()117   const std::vector<UCHAR> *getProgressBarStatus() const {
118     return m_progressBarStatus;
119   }
120 
121 public:
122   // Properties setters-getters
123 
124   int getPBHeight() const;
125   void setPBHeight(int height);
126 
127   QImage getPBOverlay() const;
128   void setPBOverlay(const QImage &img);
129 
130   QImage getPBMarker() const;
131   void setPBMarker(const QImage &img);
132 
133   int getPBColorMarginLeft() const;
134   void setPBColorMarginLeft(int margin);
135 
136   int getPBColorMarginTop() const;
137   void setPBColorMarginTop(int margin);
138 
139   int getPBColorMarginRight() const;
140   void setPBColorMarginRight(int margin);
141 
142   int getPBColorMarginBottom() const;
143   void setPBColorMarginBottom(int margin);
144 
145   int getPBMarkerMarginLeft() const;
146   void setPBMarkerMarginLeft(int margin);
147 
148   int getPBMarkerMarginRight() const;
149   void setPBMarkerMarginRight(int margin);
150 
151   QColor getBaseColor() const;
152   void setBaseColor(const QColor &color);
153 
154   QColor getNotStartedColor() const;
155   void setNotStartedColor(const QColor &color);
156 
157   QColor getStartedColor() const;
158   void setStartedColor(const QColor &color);
159 
160   QColor getFinishedColor() const;
161   void setFinishedColor(const QColor &color);
162 
163 protected:
164   void paintEvent(QPaintEvent *ev) override;
165 
166   void mousePressEvent(QMouseEvent *me) override;
167   void mouseMoveEvent(QMouseEvent *me) override;
168   void mouseReleaseEvent(QMouseEvent *me) override;
169 
170 private:
171   int sliderPositionFromValue(int min, int max, int pos, int span);
172   int sliderValueFromPosition(int min, int max, int step, int pos, int span);
173   int pageStepVal(int val);
174 
175 signals:
176   void flipSliderReleased();
177   void flipSliderPressed();
178 };
179 
180 //-----------------------------------------------------------------------------
181 
182 class DVAPI FlipConsole final : public QWidget {
183   Q_OBJECT
184 
185   QColor m_fpsFieldColor;
186   Q_PROPERTY(QColor FpsFieldColor READ getFpsFieldColor WRITE setFpsFieldColor)
187 
188 public:
189   enum EGadget {
190     eBegin,
191     ePlay,
192     eLoop,
193     ePause,
194     ePrev,
195     eNext,
196     eFirst,
197     eLast,
198     eRed,
199     eGreen,
200     eBlue,
201     eGRed,
202     eGGreen,
203     eGBlue,
204     eMatte,
205     eFrames,
206     eRate,
207     eSound,
208     eHisto,
209     eSaveImg,
210     eCompare,
211     eCustomize,
212     eSave,
213     eDefineSubCamera,
214     eFilledRaster,  // Used only in LineTest
215     eDefineLoadBox,
216     eUseLoadBox,
217     eLocator,
218     eZoomIn,
219     eZoomOut,
220     eFlipHorizontal,
221     eFlipVertical,
222     eResetView,
223     // following values are hard-coded in ImagePainter
224     eBlackBg = 0x40000,
225     eWhiteBg = 0x80000,
226     eCheckBg = 0x100000,
227     eEnd
228   };
229 
230   static FlipConsole *m_currentConsole;
231   static QList<FlipConsole *> m_visibleConsoles;
232   static bool m_isLinkedPlaying;
233   static bool m_areLinked;
234 
235   // blanksEnabled==true->at begin of each loop a number of blank frames are
236   // drawn (according to rpeferences settings)
237   FlipConsole(QVBoxLayout *layout, std::vector<int> gadgetsMask,
238               bool isLinkable, QWidget *customWidget,
239               const QString &customizeId,
240               FlipConsoleOwner *consoleOwner,  // call
241                                                // consoleOwner->onDrawFrame()
242                                                // intead of emitting drawFrame
243                                                // signal
244               bool enableBlanks = false);
245   void enableBlanks(bool state);
246 
247   void setFrameRange(
248       int from, int to, int step,
249       int current = -1);  // if current==-1, current position will be ==from
getFrameRange(int & from,int & to,int & step)250   void getFrameRange(int &from, int &to, int &step) const {
251     from = m_from, to = m_to, step = m_step;
252   }
253   void setFrameRate(int rate, bool forceUpdate = true);
254   // if doShowHide==true, applies set visible, otherwise applies setEnabled
255   void enableButton(UINT button, bool enable, bool doShowHide = true);
256   void showCurrentFrame();
getCurrentFrame()257   int getCurrentFrame() const { return m_currentFrame; }
getCurrentFps()258   int getCurrentFps() const { return m_fps; }
259   void setChecked(UINT button, bool state);
260   bool isChecked(UINT button) const;
261   void setCurrentFrame(int frame, bool forceResetting = false);
setMarkers(int fromIndex,int toIndex)262   void setMarkers(int fromIndex, int toIndex) {
263     m_markerFrom = fromIndex + 1;
264     m_markerTo   = toIndex + 1;
265   }
pressButton(UINT button)266   void pressButton(UINT button) {
267     doButtonPressed(button);
268     setChecked(button, !isChecked(button));
269   }
270 
271   // the main (currently the only) use for current flipconsole and setActive is
272   // to
273   // support shortcuts handling
274   // setActive() should be called every time the visibility state of the console
275   // changes
276   // a list of visible console is maintained. calling setActive(false) for the
277   // current
278   // console makes automatically current the next one in the list
getCurrent()279   static FlipConsole *getCurrent() { return m_currentConsole; };
280 
281   static void toggleLinked();
282 
283   void makeCurrent();
284   void setActive(bool active);
285 
286   void pressButton(EGadget buttonId);
287 
288   void showHideAllParts(bool);
289   void showHidePlaybar(bool);
290   void showHideFrameSlider(bool);
291 
292   void enableProgressBar(bool enable);
293   void setProgressBarStatus(const std::vector<UCHAR> *status);
294   const std::vector<UCHAR> *getProgressBarStatus() const;
295 
setFrameHandle(TFrameHandle * frameHandle)296   void setFrameHandle(TFrameHandle *frameHandle) {
297     m_frameHandle = frameHandle;
298   }
299 
isLinkable()300   bool isLinkable() const { return m_isLinkable; }
301   void playNextFrame();
302   void updateCurrentFPS(int val);
303 
hasButton(std::vector<int> buttonMask,FlipConsole::EGadget buttonId)304   bool hasButton(std::vector<int> buttonMask, FlipConsole::EGadget buttonId) {
305     if (buttonMask.size() == 0) return true;
306     return std::find(buttonMask.begin(), buttonMask.end(), buttonId) ==
307            buttonMask.end();
308   }
309 
setFpsFieldColor(const QColor & color)310   void setFpsFieldColor(const QColor &color) { m_fpsFieldColor = color; }
getFpsFieldColor()311   QColor getFpsFieldColor() const { return m_fpsFieldColor; }
312 
313 signals:
314 
315   void buttonPressed(FlipConsole::EGadget button);
316 
317   void playStateChanged(bool isPlaying);
318   void sliderReleased();
319 
320 private:
321   UINT m_customizeMask;
322   QString m_customizeId;
323   QAction *m_customAction;
324   PlaybackExecutor m_playbackExecutor;
325 
326   QAction *m_customSep, *m_rateSep, *m_histoSep, *m_bgSep, *m_vcrSep,
327       *m_compareSep, *m_saveSep, *m_colorFilterSep, *m_soundSep, *m_subcamSep,
328       *m_filledRasterSep, *m_viewerSep;
329 
330   QToolBar *m_playToolBar;
331   QActionGroup *m_colorFilterGroup;
332   ToolBarContainer *m_playToolBarContainer;
333   QFrame *m_frameSliderFrame;
334 
335   QLabel *m_fpsLabel;
336   QScrollBar *m_fpsSlider;
337   DVGui::IntLineEdit *m_fpsField;
338   QAction *m_fpsFieldAction;
339   QAction *m_fpsLabelAction;
340   QAction *m_fpsSliderAction;
341   QFrame *createFpsSlider();
342   QAction *m_doubleRedAction, *m_doubleGreenAction, *m_doubleBlueAction;
343   DoubleButton *m_doubleRed, *m_doubleGreen, *m_doubleBlue;
344   std::vector<int> m_gadgetsMask;
345   int m_from, m_to, m_step;
346   int m_currentFrame, m_framesCount;
347   ImagePainter::VisualSettings m_settings;
348 
349   bool m_isPlay;
350   int m_fps, m_sceneFps;
351   bool m_reverse;
352   int m_markerFrom, m_markerTo;
353   bool m_drawBlanksEnabled;
354   int m_blanksCount;
355   TPixel m_blankColor;
356   int m_blanksToDraw;
357   bool m_isLinkable;
358 
359   QMap<EGadget, QAbstractButton *> m_buttons;
360   QMap<EGadget, QAction *> m_actions;
361 
362   void createCustomizeMenu(bool withCustomWidget);
363   void addMenuItem(UINT id, const QString &text, QMenu *menu);
364   void createButton(UINT buttonMask, const char *iconStr, const QString &tip,
365                     bool checkable, QActionGroup *groupIt = 0);
366   QAction *createCheckedButtonWithBorderImage(
367       UINT buttonMask, const char *iconStr, const QString &tip, bool checkable,
368       QActionGroup *groupIt = 0, const char *cmdId = 0);
369   void createOnOffButton(UINT buttonMask, const char *iconStr,
370                          const QString &tip, QActionGroup *group);
371   QAction *createDoubleButton(UINT buttonMask1, UINT buttonMask2,
372                               const char *iconStr1, const char *iconStr2,
373                               const QString &tip1, const QString &tip2,
374                               QActionGroup *group, DoubleButton *&w);
375 
376   QFrame *createFrameSlider();
377   void createPlayToolBar(QWidget *customWidget);
378   DVGui::IntLineEdit *m_editCurrFrame;
379   FlipSlider *m_currFrameSlider;
380 
381   void doButtonPressed(UINT button);
382   static void pressLinkedConsoleButton(UINT button, FlipConsole *skipIt);
383   void applyCustomizeMask();
384   void onLoadBox(bool isDefine);
385 
386   QPushButton *m_enableBlankFrameButton;
387 
388   FlipConsoleOwner *m_consoleOwner;
389   TFrameHandle *m_frameHandle;
390 
391 protected slots:
392 
393   void OnSetCurrentFrame();
394   void OnFrameSliderRelease();
395   void OnFrameSliderPress();
396   void OnSetCurrentFrame(int);
397   void setCurrentFPS(int);
398   void setCurrentFPS(bool dragging);
onButtonPressed(QAction * action)399   inline void onButtonPressed(QAction *action) {
400     onButtonPressed(action->data().toUInt());
401   }
402   void onButtonPressed(int button);
403   void incrementCurrentFrame(int delta);
404   void onNextFrame(int fps);
405   void onCustomizeButtonPressed(QAction *);
406   bool drawBlanks(int from, int to);
407   void onSliderRelease();
408 
409   void onFPSEdited();
410 
411 public slots:
412   void onPreferenceChanged(const QString &);
413 
414 private:
415   friend class PlaybackExecutor;
playbackExecutor()416   PlaybackExecutor &playbackExecutor() { return m_playbackExecutor; }
417 };
418 
419 #endif
420