1
2
3 #include "toonzqt/flipconsole.h"
4
5 // TnzQt includes
6 #include "toonzqt/menubarcommand.h"
7 #include "toonzqt/dvscrollwidget.h"
8 #include "toonzqt/gutil.h"
9 #include "toonzqt/flipconsoleowner.h"
10
11 // TnzLib includes
12 #include "toonz/preferences.h"
13 #include "toonz/tframehandle.h"
14
15 // TnzBase includes
16 #include "tenv.h"
17
18 // TnzCore includes
19 #include "tconvert.h"
20 #include "timagecache.h"
21 #include "trop.h"
22
23 #include "../toonz/tapp.h"
24
25 // Qt includes
26 #include <QVBoxLayout>
27 #include <QHBoxLayout>
28 #include <QToolBar>
29 #include <QLabel>
30 #include <QFrame>
31 #include <QSlider>
32 #include <QTimerEvent>
33 #include <QToolButton>
34 #include <QPainter>
35 #include <QMouseEvent>
36 #include <QIcon>
37 #include <QAction>
38 #include <QWidgetAction>
39 #include <QStyle>
40 #include <QStylePainter>
41 #include <QStyleOption>
42 #include <QStyleOptionFrameV3>
43 #include <QSettings>
44 #include <QPushButton>
45 #include <QScrollBar>
46
47 using namespace DVGui;
48
49 //==========================================================================================
50 // Preliminary stuff - local namespace
51 //==========================================================================================
52 TEnv::IntVar FlipBookWhiteBgToggle("FlipBookWhiteBgToggle", 1);
53 TEnv::IntVar FlipBookBlackBgToggle("FlipBookBlackBgToggle", 0);
54 TEnv::IntVar FlipBookCheckBgToggle("FlipBookCheckBgToggle", 0);
55 namespace {
56 // Please refer to the "qss/standard/standard.qss" file for explanations of the
57 // following properties.
58
59 int PBHeight;
60
61 QImage PBOverlay;
62 QImage PBMarker;
63
64 int PBColorMarginLeft = 0;
65 int PBColorMarginTop = 0;
66 int PBColorMarginRight = 0;
67 int PBColorMarginBottom = 0;
68
69 int PBMarkerMarginLeft = 0;
70 int PBMarkerMarginRight = 0;
71
72 QColor PBBaseColor = QColor(235, 235, 235);
73 QColor PBNotStartedColor = QColor(210, 40, 40);
74 QColor PBStartedColor = QColor(220, 160, 160);
75 QColor PBFinishedColor = QColor(235, 235, 235);
76 } // namespace
77
78 //-----------------------------------------------------------------------------
79
getPBHeight() const80 int FlipSlider::getPBHeight() const { return PBHeight; }
setPBHeight(int height)81 void FlipSlider::setPBHeight(int height) {
82 setFixedHeight(height);
83 PBHeight = height;
84 }
85
getPBOverlay() const86 QImage FlipSlider::getPBOverlay() const { return PBOverlay; }
setPBOverlay(const QImage & img)87 void FlipSlider::setPBOverlay(const QImage &img) { PBOverlay = img; }
88
getPBMarker() const89 QImage FlipSlider::getPBMarker() const { return PBMarker; }
setPBMarker(const QImage & img)90 void FlipSlider::setPBMarker(const QImage &img) { PBMarker = img; }
91
getPBColorMarginLeft() const92 int FlipSlider::getPBColorMarginLeft() const { return PBColorMarginLeft; }
setPBColorMarginLeft(int margin)93 void FlipSlider::setPBColorMarginLeft(int margin) {
94 PBColorMarginLeft = margin;
95 }
96
getPBColorMarginTop() const97 int FlipSlider::getPBColorMarginTop() const { return PBColorMarginTop; }
setPBColorMarginTop(int margin)98 void FlipSlider::setPBColorMarginTop(int margin) { PBColorMarginTop = margin; }
99
getPBColorMarginRight() const100 int FlipSlider::getPBColorMarginRight() const { return PBColorMarginRight; }
setPBColorMarginRight(int margin)101 void FlipSlider::setPBColorMarginRight(int margin) {
102 PBColorMarginRight = margin;
103 }
104
getPBColorMarginBottom() const105 int FlipSlider::getPBColorMarginBottom() const { return PBColorMarginBottom; }
setPBColorMarginBottom(int margin)106 void FlipSlider::setPBColorMarginBottom(int margin) {
107 PBColorMarginBottom = margin;
108 }
109
getPBMarkerMarginLeft() const110 int FlipSlider::getPBMarkerMarginLeft() const { return PBMarkerMarginLeft; }
setPBMarkerMarginLeft(int margin)111 void FlipSlider::setPBMarkerMarginLeft(int margin) {
112 PBMarkerMarginLeft = margin;
113 }
114
getPBMarkerMarginRight() const115 int FlipSlider::getPBMarkerMarginRight() const { return PBMarkerMarginRight; }
setPBMarkerMarginRight(int margin)116 void FlipSlider::setPBMarkerMarginRight(int margin) {
117 PBMarkerMarginRight = margin;
118 }
119
getBaseColor() const120 QColor FlipSlider::getBaseColor() const { return PBBaseColor; }
setBaseColor(const QColor & color)121 void FlipSlider::setBaseColor(const QColor &color) { PBBaseColor = color; }
122
getNotStartedColor() const123 QColor FlipSlider::getNotStartedColor() const { return PBNotStartedColor; }
setNotStartedColor(const QColor & color)124 void FlipSlider::setNotStartedColor(const QColor &color) {
125 PBNotStartedColor = color;
126 }
127
getStartedColor() const128 QColor FlipSlider::getStartedColor() const { return PBStartedColor; }
setStartedColor(const QColor & color)129 void FlipSlider::setStartedColor(const QColor &color) {
130 PBStartedColor = color;
131 }
132
getFinishedColor() const133 QColor FlipSlider::getFinishedColor() const { return PBFinishedColor; }
setFinishedColor(const QColor & color)134 void FlipSlider::setFinishedColor(const QColor &color) {
135 PBFinishedColor = color;
136 }
137
138 FlipConsole *FlipConsole::m_currentConsole = 0;
139 QList<FlipConsole *> FlipConsole::m_visibleConsoles;
140 bool FlipConsole::m_isLinkedPlaying = false;
141 bool FlipConsole::m_areLinked = false;
142
143 //==========================================================================================
144
PlaybackExecutor()145 PlaybackExecutor::PlaybackExecutor() : m_fps(25), m_abort(false) {}
146
147 //-----------------------------------------------------------------------------
148
resetFps(int fps)149 void PlaybackExecutor::resetFps(int fps) { m_fps = fps; }
150
151 //-----------------------------------------------------------------------------
152
run()153 void PlaybackExecutor::run() {
154 // (Daniele)
155 // We'll build the fps considering an interval of roughly 1 second (the last
156 // one).
157 // However, the fps should be sampled at a faster rate. Each sample is taken
158 // at
159 // 1/4 second, and the last 4 samples data are stored to keep trace of the
160 // last
161 // second of playback.
162
163 TStopWatch timer;
164 timer.start();
165
166 TUINT32 timeResolution =
167 250; // Use a sufficient sampling resolution (currently 1/4 sec).
168 // Fps calculation is made once per sample.
169
170 int fps = m_fps, currSample = 0;
171 TUINT32 playedFramesCount = 0;
172 TUINT32 loadedInstant, nextSampleInstant = timeResolution;
173 TUINT32 sampleTotalLoadingTime = 0;
174
175 TUINT32 lastFrameCounts[4] = {0, 0, 0,
176 0}; // Keep the last 4 'played frames' counts.
177 TUINT32 lastSampleInstants[4] = {0, 0, 0,
178 0}; // Same for the last sampling instants
179 TUINT32 lastLoadingTimes[4] = {0, 0, 0,
180 0}; // Same for total sample loading times
181
182 double targetFrameTime =
183 1000.0 / abs(m_fps); // User-required time between frames
184
185 TUINT32 emissionInstant = 0; // Effective instant in which loading is invoked
186 double emissionInstantD = 0.0; // Double precision version of the above
187
188 double lastLoadingTime = 0.0; // Mean frame loading time in the last sample
189
190 while (!m_abort) {
191 emissionInstant = timer.getTotalTime();
192
193 // Draw the next frame
194 if (playedFramesCount)
195 emit nextFrame(fps); // Show the next frame, telling
196 // currently measured fps
197
198 if (FlipConsole::m_areLinked) {
199 // In case there are linked consoles, update them too.
200 // Their load time must be included in the fps calculation.
201 int i, consolesCount = FlipConsole::m_visibleConsoles.size();
202 for (i = 0; i < consolesCount; ++i) {
203 FlipConsole *console = FlipConsole::m_visibleConsoles.at(i);
204 if (console->isLinkable() && console != FlipConsole::m_currentConsole)
205 console->playbackExecutor().emitNextFrame(m_fps < 0 ? -fps : fps);
206 }
207 }
208
209 //-------- Each nextFrame() blocks until the frame has been shown ---------
210
211 ++playedFramesCount;
212 loadedInstant = timer.getTotalTime();
213 sampleTotalLoadingTime += (loadedInstant - emissionInstant);
214
215 // Recalculate data only after the specified time resolution has passed.
216 if (loadedInstant > nextSampleInstant) {
217 // Sampling instant. Perform calculations.
218
219 // Store values
220 TUINT32 framesCount = playedFramesCount - lastFrameCounts[currSample];
221 TUINT32 elapsedTime = loadedInstant - lastSampleInstants[currSample];
222 double loadingTime =
223 (sampleTotalLoadingTime - lastLoadingTimes[currSample]) /
224 (double)framesCount;
225
226 lastFrameCounts[currSample] = playedFramesCount;
227 lastSampleInstants[currSample] = loadedInstant;
228 lastLoadingTimes[currSample] = sampleTotalLoadingTime;
229
230 currSample = (currSample + 1) % 4;
231 nextSampleInstant = loadedInstant + timeResolution;
232
233 // Rebuild current fps
234 fps = troundp((1000 * framesCount) / (double)elapsedTime);
235 targetFrameTime = 1000.0 / abs(m_fps); // m_fps could have changed...
236
237 // In case the playback is too slow to keep the required pace, reset the
238 // emission timeline.
239 // Otherwise, it should be kept as the difference needs to be compensated
240 // to get the required fps.
241 if ((int)emissionInstant - (int)emissionInstantD >
242 20) // Reset beyond, say, 20 msecs tolerance.
243 emissionInstantD = (double)loadedInstant - loadingTime;
244 else
245 emissionInstantD +=
246 lastLoadingTime -
247 loadingTime; // Otherwise, just adapt to the new loading time
248
249 lastLoadingTime = loadingTime;
250 }
251
252 // Calculate the new emission instant
253 emissionInstant = std::max((int)(emissionInstantD += targetFrameTime), 0);
254
255 // Sleep until the next emission instant has been reached
256 while (timer.getTotalTime() < emissionInstant) msleep(1);
257 }
258
259 m_abort = false;
260 }
261
262 //==========================================================================================
263
FlipSlider(QWidget * parent)264 FlipSlider::FlipSlider(QWidget *parent)
265 : QAbstractSlider(parent), m_enabled(false), m_progressBarStatus(0) {
266 setObjectName("FlipSlider");
267 setOrientation(Qt::Horizontal);
268 setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
269 }
270
271 //-----------------------------------------------------------------------------
272
paintEvent(QPaintEvent * ev)273 void FlipSlider::paintEvent(QPaintEvent *ev) {
274 QPainter p(this);
275
276 // Draw the progress status colorbar
277 QRect sliderRect(QPoint(), size());
278 QRect colorRect(sliderRect.adjusted(PBMarkerMarginLeft, PBColorMarginTop,
279 -PBMarkerMarginRight,
280 -PBColorMarginBottom));
281
282 int val, maxValuePlusStep = maximum() + singleStep();
283 int colorWidth = colorRect.width(), colorHeight = colorRect.height();
284
285 p.setPen(Qt::NoPen);
286 int currPos = PBColorMarginLeft, nextPos;
287
288 // paint the base of slider
289 if (m_enabled && m_progressBarStatus && !m_progressBarStatus->empty()) {
290 unsigned int i, pbStatusSize = m_progressBarStatus->size();
291 for (i = 0, val = minimum() + singleStep(); i < pbStatusSize;
292 ++i, val += singleStep()) {
293 nextPos = sliderPositionFromValue(minimum(), maxValuePlusStep, val,
294 colorWidth) +
295 PBMarkerMarginLeft;
296 if (i == pbStatusSize - 1) nextPos += PBMarkerMarginRight;
297 p.fillRect(currPos, PBColorMarginTop, nextPos - currPos, colorHeight,
298 ((*m_progressBarStatus)[i] == PBFrameStarted)
299 ? PBStartedColor
300 : ((*m_progressBarStatus)[i] == PBFrameFinished)
301 ? PBFinishedColor
302 : PBNotStartedColor);
303 currPos = nextPos;
304 }
305
306 // Draw frames outside the pb
307 if (val < maximum())
308 p.fillRect(currPos, PBColorMarginTop,
309 width() - PBColorMarginRight - currPos, colorHeight,
310 PBNotStartedColor);
311 } else
312 p.fillRect(PBColorMarginLeft, PBColorMarginTop,
313 sliderRect.width() - PBColorMarginLeft - PBColorMarginRight,
314 colorHeight, PBBaseColor);
315
316 // Draw the PB Overlay
317 int overlayInnerWidth =
318 PBOverlay.width() - PBColorMarginLeft - PBColorMarginRight;
319 int markerInnerWidth =
320 PBMarker.width() - PBMarkerMarginLeft - PBMarkerMarginRight;
321
322 p.drawImage(QRect(0, 0, PBColorMarginLeft, height()), PBOverlay,
323 QRect(0, 0, PBColorMarginLeft, PBOverlay.height()));
324 p.drawImage(
325 QRect(PBColorMarginLeft, 0,
326 sliderRect.width() - PBColorMarginLeft - PBColorMarginRight,
327 height()),
328 PBOverlay,
329 QRect(PBColorMarginLeft, 0, overlayInnerWidth, PBOverlay.height()));
330 p.drawImage(
331 QRect(width() - PBColorMarginRight, 0, PBColorMarginRight, height()),
332 PBOverlay,
333 QRect(PBOverlay.width() - PBColorMarginRight, 0, PBColorMarginRight,
334 PBOverlay.height()));
335
336 // Draw the position marker
337 currPos = sliderPositionFromValue(minimum(), maxValuePlusStep, value(),
338 colorWidth) +
339 PBMarkerMarginLeft;
340 nextPos = sliderPositionFromValue(minimum(), maxValuePlusStep,
341 value() + singleStep(), colorWidth) +
342 PBMarkerMarginLeft;
343
344 p.drawImage(
345 QRect(currPos - PBMarkerMarginLeft, 0, PBMarkerMarginLeft, height()),
346 PBMarker, QRect(0, 0, PBMarkerMarginLeft, PBMarker.height()));
347 p.drawImage(
348 QRect(currPos, 0, nextPos - currPos, height()), PBMarker,
349 QRect(PBMarkerMarginLeft, 0, markerInnerWidth, PBMarker.height()));
350 p.drawImage(QRect(nextPos, 0, PBMarkerMarginRight, height()), PBMarker,
351 QRect(PBMarker.width() - PBMarkerMarginRight, 0,
352 PBMarkerMarginRight, PBMarker.height()));
353 }
354
355 //-----------------------------------------------------------------------------
356
sliderPositionFromValue(int min,int max,int val,int span)357 inline int FlipSlider::sliderPositionFromValue(int min, int max, int val,
358 int span) {
359 return tceil(span * ((val - min) / (double)(max - min)));
360 }
361
362 //-----------------------------------------------------------------------------
363
sliderValueFromPosition(int min,int max,int step,int pos,int span)364 inline int FlipSlider::sliderValueFromPosition(int min, int max, int step,
365 int pos, int span) {
366 int colorBarPos = pos - PBColorMarginLeft;
367 int colorSpan = span - PBColorMarginLeft - PBColorMarginRight;
368 int tempRelativePos = (max - min + step) * (colorBarPos / (double)colorSpan);
369 return min + (tempRelativePos - tempRelativePos % step);
370 }
371
372 //-----------------------------------------------------------------------------
373
pageStepVal(int val)374 inline int FlipSlider::pageStepVal(int val) {
375 return tcrop(value() + pageStep() * tsign(val - value()), minimum(),
376 maximum());
377 }
378
379 //-----------------------------------------------------------------------------
380
381 // Mouse Press behaviour:
382 // a) If middle button, just put frame to cursor position
383 // b) If left button, and cursor on current frame pos, do like (a)
384 // c) If left button, and cursor NOT on curr.. perform a page up/down on
385 // the side of cursor pos
mousePressEvent(QMouseEvent * me)386 void FlipSlider::mousePressEvent(QMouseEvent *me) {
387 emit flipSliderPressed();
388 int cursorValue = sliderValueFromPosition(minimum(), maximum(), singleStep(),
389 me->pos().x(), width());
390 if (me->button() == Qt::MidButton)
391 if (cursorValue == value())
392 setSliderDown(true);
393 else {
394 // Move the page step
395 setValue(pageStepVal(cursorValue));
396 }
397
398 else if (me->button() == Qt::LeftButton && cursorValue != value())
399 setValue(cursorValue);
400 }
401
402 //-----------------------------------------------------------------------------
403
mouseMoveEvent(QMouseEvent * me)404 void FlipSlider::mouseMoveEvent(QMouseEvent *me) {
405 if (isSliderDown() || me->buttons() & Qt::LeftButton) {
406 int cursorValue = sliderValueFromPosition(
407 minimum(), maximum(), singleStep(), me->pos().x(), width());
408 setValue(cursorValue);
409 }
410 }
411
412 //-----------------------------------------------------------------------------
413
mouseReleaseEvent(QMouseEvent * me)414 void FlipSlider::mouseReleaseEvent(QMouseEvent *me) {
415 setSliderDown(false);
416 emit flipSliderReleased();
417 }
418
419 //=============================================================================
420
421 enum {
422 eShowCompare = 0x001,
423 eShowBg = 0x002,
424 eShowFramerate = 0x004,
425 eShowVcr = 0x008,
426 eShowcolorFilter = 0x010,
427 eShowCustom = 0x020,
428 eShowHisto = 0x040,
429 eShowSave = 0x080,
430 eShowDefineSubCamera = 0x100,
431 eShowFilledRaster = 0x200,
432 eShowDefineLoadBox = 0x400,
433 eShowUseLoadBox = 0x800,
434 eShowViewerControls = 0x1000,
435 eShowSound = 0x2000,
436 eShowLocator = 0x4000,
437 eShowHowMany = 0x8000
438 };
439
FlipConsole(QVBoxLayout * mainLayout,std::vector<int> gadgetsMask,bool isLinkable,QWidget * customWidget,const QString & customizeId,FlipConsoleOwner * consoleOwner,bool enableBlanks)440 FlipConsole::FlipConsole(QVBoxLayout *mainLayout, std::vector<int> gadgetsMask,
441 bool isLinkable, QWidget *customWidget,
442 const QString &customizeId,
443 FlipConsoleOwner *consoleOwner, bool enableBlanks)
444 : m_gadgetsMask(gadgetsMask)
445 , m_from(1)
446 , m_to(1)
447 , m_step(1)
448 , m_currentFrame(1)
449 , m_framesCount(1)
450 , m_settings()
451 , m_fps(24)
452 , m_sceneFps(24)
453 , m_isPlay(false)
454 , m_reverse(false)
455 , m_doubleRed(0)
456 , m_doubleGreen(0)
457 , m_doubleBlue(0)
458 , m_doubleRedAction(0)
459 , m_doubleGreenAction(0)
460 , m_doubleBlueAction(0)
461 , m_fpsSlider(0)
462 , m_markerFrom(0)
463 , m_markerTo(-1)
464 , m_playbackExecutor()
465 , m_drawBlanksEnabled(enableBlanks)
466 , m_blanksCount(0)
467 , m_blankColor(TPixel::Transparent)
468 , m_blanksToDraw(0)
469 , m_isLinkable(isLinkable)
470 , m_customAction(0)
471 , m_customizeMask(eShowHowMany - 1)
472 , m_fpsLabelAction(0)
473 , m_fpsSliderAction(0)
474 , m_fpsFieldAction(0)
475 , m_fpsField(0)
476 , m_customizeId(customizeId)
477 , m_histoSep(0)
478 , m_filledRasterSep(0)
479 , m_viewerSep(0)
480 , m_bgSep(0)
481 , m_vcrSep(0)
482 , m_compareSep(0)
483 , m_saveSep(0)
484 , m_colorFilterSep(0)
485 , m_subcamSep(0)
486 , m_playToolBar(0)
487 , m_colorFilterGroup(0)
488 , m_fpsLabel(0)
489 , m_consoleOwner(consoleOwner)
490 , m_enableBlankFrameButton(0) {
491 QString s = QSettings().value(m_customizeId).toString();
492 if (s != "") m_customizeMask = s.toUInt();
493
494 if (m_gadgetsMask.size() == 0) return;
495
496 // mainLayout->setMargin(1);
497 // mainLayout->setSpacing(0);
498
499 // create toolbars other than frame slider
500 if (hasButton(m_gadgetsMask, eFrames)) {
501 createPlayToolBar(customWidget);
502
503 m_playToolBarContainer = new ToolBarContainer();
504
505 QHBoxLayout *hLayout = new QHBoxLayout;
506 hLayout->setMargin(0);
507 hLayout->setSpacing(0);
508 hLayout->setAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
509 {
510 DvScrollWidget *scrollableContainer = new DvScrollWidget;
511 scrollableContainer->setWidget(m_playToolBar);
512 hLayout->addWidget(scrollableContainer);
513
514 // show fps
515 if (hasButton(m_gadgetsMask, eRate)) {
516 QFrame *fpsSliderFrame = createFpsSlider();
517 hLayout->addWidget(fpsSliderFrame, 1);
518 }
519 }
520 m_playToolBarContainer->setLayout(hLayout);
521
522 mainLayout->addWidget(m_playToolBarContainer);
523 }
524
525 // create frame slider
526 if (hasButton(m_gadgetsMask, eFrames)) {
527 m_frameSliderFrame = createFrameSlider();
528 mainLayout->addWidget(m_frameSliderFrame);
529 }
530
531 applyCustomizeMask();
532
533 bool ret = connect(&m_playbackExecutor, SIGNAL(nextFrame(int)), this,
534 SLOT(onNextFrame(int)), Qt::BlockingQueuedConnection);
535
536 assert(ret);
537
538 // parent->setLayout(mainLayout);
539 }
540
541 //-----------------------------------------------------------------------------
542
showHideAllParts(bool isShow)543 void FlipConsole::showHideAllParts(bool isShow) {
544 m_playToolBarContainer->setVisible(isShow);
545 m_frameSliderFrame->setVisible(isShow);
546 }
547
548 //-----------------------------------------------------------------------------
549
showHidePlaybar(bool isShow)550 void FlipConsole::showHidePlaybar(bool isShow) {
551 m_playToolBarContainer->setVisible(isShow);
552 }
553
554 //-----------------------------------------------------------------------------
555
showHideFrameSlider(bool isShow)556 void FlipConsole::showHideFrameSlider(bool isShow) {
557 m_frameSliderFrame->setVisible(isShow);
558 }
559
560 //-----------------------------------------------------------------------------
561
562 void showEvent(QShowEvent *);
563 void hideEvent(QHideEvent *);
564
makeCurrent()565 void FlipConsole::makeCurrent() {
566 if (m_currentConsole == this) return;
567 int i = m_visibleConsoles.indexOf(this);
568 if (i >= 0) m_visibleConsoles.takeAt(i);
569 m_visibleConsoles.append(this);
570 m_currentConsole = this;
571 }
572
573 //-----------------------------------------------------------------------------
574
setActive(bool active)575 void FlipConsole::setActive(bool active) {
576 if (active)
577 makeCurrent();
578 else {
579 pressButton(ePause);
580 int i = m_visibleConsoles.indexOf(this);
581 if (i >= 0) m_visibleConsoles.takeAt(i);
582 if (m_currentConsole == this) {
583 if (!m_visibleConsoles.empty())
584 m_currentConsole = m_visibleConsoles.last();
585 else
586 m_currentConsole = 0;
587 }
588 }
589 }
590
591 //-----------------------------------------------------------------------------
592
593 #define LX 22
594 #define LY 22
595 class DoubleButton final : public QToolButton {
596 QAction *m_firstAction, *m_secondAction;
597 QIcon::Mode m_firstMode, m_secondMode;
598 QIcon::State m_firstState, m_secondState;
599 bool m_enabled;
600
601 public:
DoubleButton(QAction * firstAction,QAction * secondAction,QWidget * parent=0)602 DoubleButton(QAction *firstAction, QAction *secondAction, QWidget *parent = 0)
603 : QToolButton(parent)
604 , m_firstAction(firstAction)
605 , m_secondAction(secondAction)
606 , m_firstMode(QIcon::Normal)
607 , m_secondMode(QIcon::Normal)
608 , m_firstState(QIcon::Off)
609 , m_secondState(QIcon::Off)
610 , m_enabled(true) {
611 setFixedSize(LX, LY);
612 setMouseTracking(true);
613 setObjectName("flipDoubleButton");
614 }
setEnabledSecondButton(bool state)615 void setEnabledSecondButton(bool state) {
616 if (!state && m_secondAction->isChecked()) m_secondAction->trigger();
617 m_enabled = state;
618 update();
619 }
620
621 protected:
paintEvent(QPaintEvent * e)622 void paintEvent(QPaintEvent *e) override {
623 QPainter p(this);
624
625 p.drawPixmap(0, 0,
626 m_firstAction->icon().pixmap(
627 QSize(LX, LY / 2),
628 m_firstAction->isChecked() ? QIcon::Normal : m_firstMode,
629 m_firstAction->isChecked() ? QIcon::On : m_firstState));
630
631 QIcon::Mode mode =
632 m_enabled ? (m_secondAction->isChecked() ? QIcon::Normal : m_secondMode)
633 : QIcon::Disabled;
634 QIcon::State state =
635 m_enabled ? (m_secondAction->isChecked() ? QIcon::On : m_secondState)
636 : QIcon::Off;
637
638 p.drawPixmap(0, LY / 2 + 1,
639 m_secondAction->icon().pixmap(QSize(LX, LY / 2), mode, state));
640 }
641
mousePressEvent(QMouseEvent * e)642 void mousePressEvent(QMouseEvent *e) override {
643 QRect firstActionRect(0, 0, LX, LY / 2);
644 QRect secondActionRect(0, LY / 2 + 1, LX, LY / 2);
645
646 QPoint pos = e->pos();
647 if (firstActionRect.contains(pos)) {
648 m_firstAction->trigger();
649 } else {
650 if (m_enabled) m_secondAction->trigger();
651 }
652 update();
653 }
654
mouseMoveEvent(QMouseEvent * e)655 void mouseMoveEvent(QMouseEvent *e) override {
656 QPoint pos = e->pos();
657 QRect firstActionRect(0, 0, LX, LY / 2);
658 QRect secondActionRect(0, LY / 2 + 1, LX, LY / 2);
659
660 m_firstState = QIcon::Off;
661 m_secondState = QIcon::Off;
662 m_firstMode = QIcon::Normal;
663 m_secondMode = QIcon::Normal;
664
665 if (firstActionRect.contains(pos)) {
666 m_firstMode = QIcon::Active;
667 setToolTip(m_firstAction->toolTip());
668 } else if (secondActionRect.contains(pos) && m_enabled) {
669 m_secondMode = QIcon::Active;
670 setToolTip(m_secondAction->toolTip());
671 }
672 update();
673 }
674
leaveEvent(QEvent * e)675 void leaveEvent(QEvent *e) override {
676 m_firstMode = QIcon::Normal;
677 m_firstState = QIcon::Off;
678 m_secondMode = QIcon::Normal;
679 m_secondState = QIcon::Off;
680
681 update();
682
683 QToolButton::leaveEvent(e);
684 }
685 };
686
687 //-----------------------------------------------------------------------------
688
enableButton(UINT button,bool enable,bool doShowHide)689 void FlipConsole::enableButton(UINT button, bool enable, bool doShowHide) {
690 if (!m_playToolBar) return;
691
692 QList<QAction *> list = m_playToolBar->actions();
693 for (size_t i = 0; i < list.size(); i++)
694 if (list[i]->data().toUInt() == button) {
695 if (button == eSound) {
696 if (doShowHide) {
697 m_soundSep->setVisible(enable);
698 } else {
699 m_soundSep->setEnabled(enable);
700 }
701 }
702 if (button == eHisto) {
703 if (doShowHide) {
704 m_histoSep->setVisible(enable && m_customizeMask & eShowHisto);
705 } else {
706 m_histoSep->setEnabled(enable);
707 }
708 }
709 if (doShowHide) {
710 list[i]->setVisible(enable);
711 } else {
712 list[i]->setEnabled(enable);
713 }
714 if (!enable && list[i]->isChecked()) pressButton((EGadget)button);
715
716 return;
717 }
718
719 // double buttons are special, they are not accessible directly from the
720 // playtoolbar...
721 switch ((EGadget)button) {
722 case eGRed:
723 if (m_doubleRed) m_doubleRed->setEnabledSecondButton(enable);
724 break;
725 case eGGreen:
726 if (m_doubleGreen) m_doubleGreen->setEnabledSecondButton(enable);
727 break;
728 case eGBlue:
729 if (m_doubleBlue) m_doubleBlue->setEnabledSecondButton(enable);
730 break;
731 default:
732 break;
733 }
734 }
735
736 //----------------------------------------------------------------------------
737
toggleLinked()738 void FlipConsole::toggleLinked() {
739 m_areLinked = !m_areLinked;
740
741 int i;
742 FlipConsole *playingConsole = 0;
743 for (i = 0; i < m_visibleConsoles.size(); i++) {
744 playingConsole = m_visibleConsoles.at(i);
745 if (playingConsole->m_isLinkable &&
746 playingConsole->m_playbackExecutor.isRunning())
747 break;
748 }
749
750 if (i == m_visibleConsoles.size()) return;
751
752 // if we are here, flip is playing!
753 m_isLinkedPlaying = m_areLinked;
754 int button =
755 m_areLinked ? (playingConsole->m_isPlay ? ePlay : eLoop) : ePause;
756
757 for (i = 0; i < m_visibleConsoles.size(); i++) {
758 FlipConsole *console = m_visibleConsoles.at(i);
759 if (console->m_isLinkable && console != playingConsole) {
760 console->setChecked(button, true);
761 console->doButtonPressed(button);
762 }
763 }
764 }
765
766 //----------------------------------------------------------------------------
767
drawBlanks(int from,int to)768 bool FlipConsole::drawBlanks(int from, int to) {
769 if (m_blanksCount == 0 || m_isPlay || m_framesCount <= 1) return false;
770
771 // enable blanks only when the blank button is pressed
772 if (m_enableBlankFrameButton && !m_enableBlankFrameButton->isChecked())
773 return false;
774
775 if (m_blanksToDraw > 1 ||
776 (m_blanksToDraw == 0 &&
777 ((m_reverse && m_currentFrame - m_step < from) ||
778 (!m_reverse && m_currentFrame + m_step >
779 to)))) // we are on the last frame of the loop
780 {
781 m_blanksToDraw = (m_blanksToDraw == 0 ? m_blanksCount : m_blanksToDraw - 1);
782 m_settings.m_blankColor = m_blankColor;
783 m_settings.m_drawBlankFrame = true;
784 m_consoleOwner->onDrawFrame(from, m_settings);
785 m_settings.m_drawBlankFrame = false;
786 return true;
787 }
788
789 m_blanksToDraw = 0;
790 return false;
791 }
792
793 //----------------------------------------------------------------------------
794
onNextFrame(int fps)795 void FlipConsole::onNextFrame(int fps) {
796 if (fps < 0) // can be negative only if is a linked console; it means that
797 // the master console is playing backward
798 {
799 bool reverse = m_reverse;
800 m_reverse = true;
801 fps = -fps;
802 playNextFrame();
803 m_reverse = reverse;
804 } else
805 playNextFrame();
806
807 if (fps == -1) return;
808 if (m_fpsLabel)
809 m_fpsLabel->setText(tr(" FPS ") + QString::number(fps * tsign(m_fps)) +
810 "/");
811 if (m_fpsField) {
812 if (fps == abs(m_fps))
813 m_fpsField->setLineEditBackgroundColor(Qt::green);
814 else
815 m_fpsField->setLineEditBackgroundColor(Qt::red);
816 }
817 }
818
819 //----------------------------------------------------------------------------
820
playNextFrame()821 void FlipConsole::playNextFrame() {
822 int from = m_from, to = m_to;
823 if (m_markerFrom <= m_markerTo) from = m_markerFrom, to = m_markerTo;
824
825 if (m_framesCount == 0 ||
826 (m_isPlay && m_currentFrame == (m_reverse ? from : to))) {
827 doButtonPressed(ePause);
828 setChecked(m_isPlay ? ePlay : eLoop, false);
829 setChecked(ePause, true);
830 if (Preferences::instance()->rewindAfterPlaybackEnabled())
831 m_currentFrame = (m_reverse ? to : from);
832 emit playStateChanged(false);
833 } else {
834 if (drawBlanks(from, to)) return;
835
836 if (m_reverse)
837 m_currentFrame =
838 ((m_currentFrame - m_step < from) ? to : m_currentFrame - m_step);
839 else
840 m_currentFrame =
841 ((m_currentFrame + m_step > to) ? from : m_currentFrame + m_step);
842 }
843
844 m_currFrameSlider->setValue(m_currentFrame);
845 m_editCurrFrame->setText(QString::number(m_currentFrame));
846 m_settings.m_blankColor = TPixel::Transparent;
847 m_settings.m_recomputeIfNeeded = true;
848 m_consoleOwner->onDrawFrame(m_currentFrame, m_settings);
849 }
850
851 //-----------------------------------------------------------------------------
852
updateCurrentFPS(int val)853 void FlipConsole::updateCurrentFPS(int val) {
854 setCurrentFPS(val);
855 m_fpsSlider->setValue(m_fps);
856 }
857
858 //-----------------------------------------------------------------------------
859
setFrameRate(int val,bool forceUpdate)860 void FlipConsole::setFrameRate(int val, bool forceUpdate) {
861 if (m_sceneFps != val || forceUpdate) {
862 if (!m_fpsSlider) return;
863 m_fpsSlider->setValue(val);
864 setCurrentFPS(val);
865 }
866 m_sceneFps = val;
867 }
868
869 //-----------------------------------------------------------------------------
870
setCurrentFPS(bool dragging)871 void FlipConsole::setCurrentFPS(bool dragging) {
872 setCurrentFPS(m_fpsField->getValue());
873 m_fpsSlider->setValue(m_fps);
874 }
875
876 //-----------------------------------------------------------------------------
877
setCurrentFPS(int val)878 void FlipConsole::setCurrentFPS(int val) {
879 if (m_fps == val) return;
880
881 if (val == 0) val = 1;
882 m_fps = val;
883 m_fpsField->setValue(m_fps);
884
885 if (m_playbackExecutor.isRunning() || m_isLinkedPlaying)
886 m_reverse = (val < 0);
887
888 if (m_fpsLabel) m_fpsLabel->setText(tr(" FPS "));
889 if (m_fpsField) m_fpsField->setLineEditBackgroundColor(getFpsFieldColor());
890
891 m_playbackExecutor.resetFps(m_fps);
892 }
893
894 //-----------------------------------------------------------------------------
895
createButton(UINT buttonMask,const char * iconStr,const QString & tip,bool checkable,QActionGroup * group)896 void FlipConsole::createButton(UINT buttonMask, const char *iconStr,
897 const QString &tip, bool checkable,
898 QActionGroup *group) {
899 QIcon icon = createQIcon(iconStr);
900 QAction *action = new QAction(icon, tip, m_playToolBar);
901 action->setData(QVariant(buttonMask));
902 action->setCheckable(checkable);
903 if (group) group->addAction(action);
904 m_actions[(EGadget)buttonMask] = action;
905 m_playToolBar->addAction(action);
906 }
907
908 //-----------------------------------------------------------------------------
909
createCheckedButtonWithBorderImage(UINT buttonMask,const char * iconStr,const QString & tip,bool checkable,QActionGroup * group,const char * cmdId)910 QAction *FlipConsole::createCheckedButtonWithBorderImage(
911 UINT buttonMask, const char *iconStr, const QString &tip, bool checkable,
912 QActionGroup *group, const char *cmdId) {
913 QIcon icon = createQIcon(iconStr);
914 QWidgetAction *action = new QWidgetAction(m_playToolBar);
915 action->setIcon(icon);
916 action->setToolTip(tip);
917 action->setData(QVariant(buttonMask));
918 action->setCheckable(checkable);
919 if (group) group->addAction(action);
920 QToolButton *button = new QToolButton(m_playToolBar);
921 button->setDefaultAction(action);
922
923 m_buttons[(EGadget)buttonMask] = button;
924
925 if (cmdId) {
926 QAction *a = CommandManager::instance()->getAction(cmdId);
927 if (a) button->addAction(a);
928 }
929
930 action->setDefaultWidget(button);
931 button->setObjectName("chackableButtonWithImageBorder");
932 connect(button, SIGNAL(triggered(QAction *)), this,
933 SLOT(onButtonPressed(QAction *)));
934 // connect(action, SIGNAL(toggled(bool)), button, SLOT(setChecked(bool)));
935 m_playToolBar->addAction(action);
936 return action;
937 }
938
939 //-----------------------------------------------------------------------------
940
createDoubleButton(UINT buttonMask1,UINT buttonMask2,const char * iconStr1,const char * iconStr2,const QString & tip1,const QString & tip2,QActionGroup * group,DoubleButton * & widget)941 QAction *FlipConsole::createDoubleButton(
942 UINT buttonMask1, UINT buttonMask2, const char *iconStr1,
943 const char *iconStr2, const QString &tip1, const QString &tip2,
944 QActionGroup *group, DoubleButton *&widget) {
945 QAction *action1 =
946 new QAction(createQIcon(iconStr1, true), tip1, m_playToolBar);
947 QAction *action2 =
948 new QAction(createQIcon(iconStr2, true), tip2, m_playToolBar);
949 m_actions[(EGadget)buttonMask1] = action1;
950 m_actions[(EGadget)buttonMask2] = action2;
951
952 action1->setData(QVariant(buttonMask1));
953 action1->setCheckable(true);
954 action2->setData(QVariant(buttonMask2));
955 action2->setCheckable(true);
956
957 if (group) {
958 group->addAction(action1);
959 group->addAction(action2);
960 }
961
962 widget = new DoubleButton(action1, action2, this);
963 return m_playToolBar->addWidget(widget);
964
965 // m_playToolBar->addAction(action1);
966 // m_playToolBar->addAction(action2);
967 }
968
969 //-----------------------------------------------------------------------------
970
createOnOffButton(UINT buttonMask,const char * iconStr,const QString & tip,QActionGroup * group)971 void FlipConsole::createOnOffButton(UINT buttonMask, const char *iconStr,
972 const QString &tip, QActionGroup *group) {
973 QIcon icon = createQIcon(iconStr);
974 QAction *action = new QAction(icon, tip, m_playToolBar);
975 action->setData(QVariant(buttonMask));
976 action->setCheckable(true);
977 if (group) group->addAction(action);
978 m_playToolBar->addAction(action);
979 m_actions[(EGadget)buttonMask] = action;
980 }
981
982 //----------------------------------------------------------------------------------------------
983
addMenuItem(UINT id,const QString & text,QMenu * menu)984 void FlipConsole::addMenuItem(UINT id, const QString &text, QMenu *menu) {
985 QAction *a = new QAction(text, menu);
986 a->setCheckable(true);
987 a->setChecked(id & m_customizeMask);
988 a->setData(QVariant(id));
989 menu->addAction(a);
990 }
991
992 //----------------------------------------------------------------------------------------------
993
onCustomizeButtonPressed(QAction * a)994 void FlipConsole::onCustomizeButtonPressed(QAction *a) {
995 UINT id = a->data().toUInt();
996 if (a->isChecked())
997 m_customizeMask = m_customizeMask | id;
998 else
999 m_customizeMask = m_customizeMask & (~id);
1000
1001 QSettings().setValue(m_customizeId, QString::number(m_customizeMask));
1002
1003 applyCustomizeMask();
1004 }
1005
1006 //----------------------------------------------------------------------------------------------
applyCustomizeMask()1007 void FlipConsole::applyCustomizeMask() {
1008 enableButton(eSave, m_customizeMask & eShowSave);
1009 // if(m_saveSep)
1010 // m_saveSep->setVisible(m_customizeMask&eShowSave);
1011
1012 enableButton(eSaveImg, m_customizeMask & eShowCompare);
1013 enableButton(eCompare, m_customizeMask & eShowCompare);
1014 if (m_compareSep) m_compareSep->setVisible(m_customizeMask & eShowCompare);
1015
1016 enableButton(eDefineSubCamera, m_customizeMask & eShowDefineSubCamera);
1017 enableButton(eDefineLoadBox, m_customizeMask & eShowDefineLoadBox);
1018 enableButton(eUseLoadBox, m_customizeMask & eShowUseLoadBox);
1019 if (m_subcamSep) {
1020 int count = m_gadgetsMask.size();
1021 bool hasDefineLoadBox =
1022 std::find(m_gadgetsMask.begin(), m_gadgetsMask.end(), eDefineLoadBox) ==
1023 m_gadgetsMask.end();
1024 bool hasUseLoadBox = std::find(m_gadgetsMask.begin(), m_gadgetsMask.end(),
1025 eUseLoadBox) == m_gadgetsMask.end();
1026 bool hasDefineSubCam = std::find(m_gadgetsMask.begin(), m_gadgetsMask.end(),
1027 eDefineSubCamera) == m_gadgetsMask.end();
1028 m_subcamSep->setVisible(
1029 (hasDefineSubCam && m_customizeMask & eShowDefineSubCamera) ||
1030 (hasDefineLoadBox && m_customizeMask & eShowDefineLoadBox) ||
1031 (hasUseLoadBox && m_customizeMask & eShowUseLoadBox));
1032 }
1033
1034 enableButton(eWhiteBg, m_customizeMask & eShowBg);
1035 enableButton(eBlackBg, m_customizeMask & eShowBg);
1036 enableButton(eCheckBg, m_customizeMask & eShowBg);
1037 if (m_bgSep) m_bgSep->setVisible(m_customizeMask & eShowBg);
1038
1039 if (m_fpsLabel && m_fpsSlider && m_fpsField) {
1040 m_fpsLabel->setVisible(m_customizeMask & eShowFramerate);
1041 m_fpsSlider->setVisible(m_customizeMask & eShowFramerate);
1042 m_fpsField->setVisible(m_customizeMask & eShowFramerate);
1043 }
1044
1045 enableButton(eFirst, m_customizeMask & eShowVcr);
1046 enableButton(ePrev, m_customizeMask & eShowVcr);
1047 enableButton(ePause, m_customizeMask & eShowVcr);
1048 enableButton(ePlay, m_customizeMask & eShowVcr);
1049 enableButton(eLoop, m_customizeMask & eShowVcr);
1050 enableButton(eNext, m_customizeMask & eShowVcr);
1051 enableButton(eLast, m_customizeMask & eShowVcr);
1052
1053 enableButton(eSound, m_customizeMask & eShowSound);
1054 enableButton(eLocator, m_customizeMask & eShowLocator);
1055
1056 if (m_vcrSep) m_vcrSep->setVisible(m_customizeMask & eShowVcr);
1057
1058 enableButton(eMatte, m_customizeMask & eShowcolorFilter);
1059 enableButton(eHisto, m_customizeMask & eShowHisto);
1060 if (m_histoSep) m_histoSep->setVisible(m_customizeMask & eShowHisto);
1061
1062 if (m_doubleRedAction) {
1063 m_doubleRedAction->setVisible(m_customizeMask & eShowcolorFilter);
1064 m_doubleGreenAction->setVisible(m_customizeMask & eShowcolorFilter);
1065 m_doubleBlueAction->setVisible(m_customizeMask & eShowcolorFilter);
1066 } else {
1067 enableButton(eRed, m_customizeMask & eShowcolorFilter);
1068 enableButton(eGreen, m_customizeMask & eShowcolorFilter);
1069 enableButton(eBlue, m_customizeMask & eShowcolorFilter);
1070 }
1071
1072 if (m_colorFilterGroup)
1073 m_colorFilterGroup->setVisible(m_customizeMask & eShowcolorFilter);
1074
1075 if (m_colorFilterSep)
1076 m_colorFilterSep->setVisible(m_customizeMask & eShowcolorFilter);
1077
1078 if (m_customAction) {
1079 bool visible = bool(m_customizeMask & eShowCustom);
1080
1081 m_customAction->setVisible(visible);
1082 m_customSep->setVisible(visible);
1083 }
1084
1085 enableButton(eFilledRaster, m_customizeMask & eShowFilledRaster);
1086 if (m_filledRasterSep)
1087 m_filledRasterSep->setVisible(m_customizeMask & eShowFilledRaster);
1088
1089 enableButton(eZoomIn, m_customizeMask & eShowViewerControls);
1090 enableButton(eZoomOut, m_customizeMask & eShowViewerControls);
1091 enableButton(eFlipHorizontal, m_customizeMask & eShowViewerControls);
1092 enableButton(eFlipVertical, m_customizeMask & eShowViewerControls);
1093 enableButton(eResetView, m_customizeMask & eShowViewerControls);
1094 if (m_viewerSep)
1095 m_viewerSep->setVisible(m_customizeMask & eShowViewerControls);
1096
1097 update();
1098 }
1099
1100 //----------------------------------------------------------------------------------------------
1101
createCustomizeMenu(bool withCustomWidget)1102 void FlipConsole::createCustomizeMenu(bool withCustomWidget) {
1103 if (hasButton(m_gadgetsMask, eCustomize)) {
1104 QIcon icon = createQIcon("menu");
1105 QToolButton *button = new QToolButton();
1106 button->setIcon(icon);
1107 button->setPopupMode(QToolButton::MenuButtonPopup);
1108 button->setObjectName("flipCustomize");
1109
1110 QMenu *menu = new QMenu();
1111 button->setMenu(menu);
1112
1113 m_playToolBar->addWidget(button);
1114 m_playToolBar->addSeparator();
1115
1116 if (hasButton(m_gadgetsMask, eSave))
1117 addMenuItem(eShowSave, tr("Save"), menu);
1118
1119 if (hasButton(m_gadgetsMask, eSaveImg) ||
1120 hasButton(m_gadgetsMask, eCompare))
1121 addMenuItem(eShowCompare, tr("Snapshot"), menu);
1122
1123 if (hasButton(m_gadgetsMask, eDefineSubCamera))
1124 addMenuItem(eShowDefineSubCamera, tr("Define Sub-camera"), menu);
1125 if (hasButton(m_gadgetsMask, eDefineLoadBox))
1126 addMenuItem(eShowDefineLoadBox, tr("Define Loading Box"), menu);
1127 if (hasButton(m_gadgetsMask, eUseLoadBox))
1128 addMenuItem(eShowUseLoadBox, tr("Use Loading Box"), menu);
1129
1130 if (hasButton(m_gadgetsMask, eWhiteBg) ||
1131 hasButton(m_gadgetsMask, eBlackBg) ||
1132 hasButton(m_gadgetsMask, eCheckBg))
1133 addMenuItem(eShowBg, tr("Background Colors"), menu);
1134
1135 addMenuItem(eShowVcr, tr("Playback Controls"), menu);
1136
1137 if (hasButton(m_gadgetsMask, eRed) || hasButton(m_gadgetsMask, eGreen) ||
1138 hasButton(m_gadgetsMask, eBlue) || hasButton(m_gadgetsMask, eMatte))
1139 addMenuItem(eShowcolorFilter, tr("Color Channels"), menu);
1140
1141 if (hasButton(m_gadgetsMask, eSound))
1142 addMenuItem(eShowSound, tr("Sound"), menu);
1143
1144 if (hasButton(m_gadgetsMask, eHisto))
1145 addMenuItem(eShowHisto, tr("Histogram"), menu);
1146
1147 if (hasButton(m_gadgetsMask, eLocator))
1148 addMenuItem(eShowLocator, tr("Locator"), menu);
1149
1150 if (withCustomWidget) addMenuItem(eShowCustom, tr("Set Key"), menu);
1151
1152 if (hasButton(m_gadgetsMask, eFilledRaster))
1153 addMenuItem(eFilledRaster, tr("Display Areas as Filled"), menu);
1154
1155 if (hasButton(m_gadgetsMask, eZoomIn) ||
1156 hasButton(m_gadgetsMask, eZoomOut) ||
1157 hasButton(m_gadgetsMask, eFlipHorizontal) ||
1158 hasButton(m_gadgetsMask, eFlipVertical) ||
1159 hasButton(m_gadgetsMask, eResetView))
1160 addMenuItem(eShowViewerControls, tr("Viewer Controls"), menu);
1161
1162 if (hasButton(m_gadgetsMask, eRate))
1163 addMenuItem(eShowFramerate, tr("Framerate"), menu);
1164
1165 bool ret = connect(menu, SIGNAL(triggered(QAction *)), this,
1166 SLOT(onCustomizeButtonPressed(QAction *)));
1167 assert(ret);
1168 }
1169 }
1170
1171 //-----------------------------------------------------------------------------
1172
createPlayToolBar(QWidget * customWidget)1173 void FlipConsole::createPlayToolBar(QWidget *customWidget) {
1174 bool ret = true;
1175 bool withCustomWidget = customWidget != 0;
1176
1177 m_playToolBar = new QToolBar(this);
1178 m_playToolBar->setMovable(false);
1179 m_playToolBar->setObjectName("FlipConsolePlayToolBar");
1180 m_playToolBar->setIconSize(QSize(20, 20));
1181 // m_playToolBar->setObjectName("chackableButtonToolBar");
1182
1183 // m_playToolBar->setSizePolicy(QSizePolicy::Fixed,QSizePolicy::Fixed);
1184
1185 createCustomizeMenu(withCustomWidget);
1186
1187 if (hasButton(m_gadgetsMask, eSave)) {
1188 createButton(eSave, "save", tr("&Save Images"), false);
1189 // m_saveSep = m_playToolBar->addSeparator();
1190 }
1191
1192 // snapshot
1193 bool separator = false;
1194 if (hasButton(m_gadgetsMask, eSaveImg)) {
1195 createButton(eSaveImg, "snapshot", tr("&Snapshot"), false);
1196 separator = true;
1197 }
1198 if (hasButton(m_gadgetsMask, eCompare)) {
1199 createButton(eCompare, "compare", tr("&Compare to Snapshot"), true);
1200 separator = true;
1201 }
1202 if (separator) m_compareSep = m_playToolBar->addSeparator();
1203
1204 // sub camera
1205 separator = false;
1206 if (hasButton(m_gadgetsMask, eDefineSubCamera)) {
1207 createButton(eDefineSubCamera, "define_subcamera_preview",
1208 tr("&Define Sub-camera"), true);
1209 separator = true;
1210 }
1211 if (hasButton(m_gadgetsMask, eDefineLoadBox)) {
1212 createButton(eDefineLoadBox, "define_subcamera_preview",
1213 tr("&Define Loading Box"), true);
1214 separator = true;
1215 }
1216 if (hasButton(m_gadgetsMask, eUseLoadBox)) {
1217 createButton(eUseLoadBox, "use_subcamera_preview", tr("&Use Loading Box"),
1218 true);
1219 separator = true;
1220 }
1221 if (separator) m_subcamSep = m_playToolBar->addSeparator();
1222
1223 // preview BGs
1224 QActionGroup *group = new QActionGroup(m_playToolBar);
1225 if (hasButton(m_gadgetsMask, eWhiteBg))
1226 createOnOffButton(eWhiteBg, "preview_white", tr("&White Background"),
1227 group);
1228 if (hasButton(m_gadgetsMask, eBlackBg))
1229 createOnOffButton(eBlackBg, "preview_black", tr("&Black Background"),
1230 group);
1231 if (hasButton(m_gadgetsMask, eCheckBg))
1232 createOnOffButton(eCheckBg, "preview_checkboard",
1233 tr("&Checkered Background"), group);
1234 if (hasButton(m_gadgetsMask, eWhiteBg))
1235 m_bgSep = m_playToolBar->addSeparator();
1236
1237 // VCR buttons
1238 QActionGroup *playGroup = new QActionGroup(m_playToolBar);
1239 if (hasButton(m_gadgetsMask, eFirst))
1240 createButton(eFirst, "framefirst", tr("&First Frame"), false);
1241 if (hasButton(m_gadgetsMask, ePrev))
1242 createButton(ePrev, "frameprev", tr("&Previous Frame"), false);
1243 if (hasButton(m_gadgetsMask, ePause))
1244 createCheckedButtonWithBorderImage(ePause, "pause", tr("Pause"), true,
1245 playGroup, "A_Flip_Pause");
1246 if (hasButton(m_gadgetsMask, ePlay))
1247 createCheckedButtonWithBorderImage(ePlay, "play", tr("Play"), true,
1248 playGroup, "A_Flip_Play");
1249 if (hasButton(m_gadgetsMask, eLoop))
1250 createCheckedButtonWithBorderImage(eLoop, "loop", tr("Loop"), true,
1251 playGroup, "A_Flip_Loop");
1252
1253 if (hasButton(m_gadgetsMask, eNext))
1254 createButton(eNext, "framenext", tr("&Next Frame"), false);
1255 if (hasButton(m_gadgetsMask, eLast))
1256 createButton(eLast, "framelast", tr("&Last Frame"), false);
1257
1258 // separator
1259 if (hasButton(m_gadgetsMask, ePlay)) m_vcrSep = m_playToolBar->addSeparator();
1260
1261 // Channel Selector
1262 m_colorFilterGroup = new QActionGroup(m_playToolBar);
1263 m_colorFilterGroup->setExclusive(false);
1264 if (hasButton(m_gadgetsMask, eRed) && !hasButton(m_gadgetsMask, eGRed))
1265 createButton(eRed, "channelred", tr("Red Channel"), true);
1266 else if (hasButton(m_gadgetsMask, eRed) && hasButton(m_gadgetsMask, eGRed))
1267 m_doubleRedAction = createDoubleButton(
1268 eRed, eGRed, "half_R", "half_bw", tr("Red Channel"),
1269 tr("Red Channel in Grayscale"), m_colorFilterGroup, m_doubleRed);
1270
1271 if (hasButton(m_gadgetsMask, eGreen) && !hasButton(m_gadgetsMask, eGGreen))
1272 createButton(eGreen, "channelgreen", tr("Green Channel"), true);
1273 else if (hasButton(m_gadgetsMask, eGreen) &&
1274 hasButton(m_gadgetsMask, eGGreen))
1275 m_doubleGreenAction = createDoubleButton(
1276 eGreen, eGGreen, "half_G", "half_bw", tr("Green Channel"),
1277 tr("Green Channel in Grayscale"), m_colorFilterGroup, m_doubleGreen);
1278
1279 if (hasButton(m_gadgetsMask, eBlue) && !hasButton(m_gadgetsMask, eGBlue))
1280 createButton(eBlue, "channelblue", tr("Blue Channel"), true);
1281 else if (hasButton(m_gadgetsMask, eBlue) && hasButton(m_gadgetsMask, eGBlue))
1282 m_doubleBlueAction = createDoubleButton(
1283 eBlue, eGBlue, "half_B", "half_bw", tr("Blue Channel"),
1284 tr("Blue Channel in Grayscale"), m_colorFilterGroup, m_doubleBlue);
1285
1286 ret = ret && connect(m_colorFilterGroup, SIGNAL(triggered(QAction *)), this,
1287 SLOT(onButtonPressed(QAction *)));
1288
1289 if (hasButton(m_gadgetsMask, eMatte))
1290 createButton(eMatte, "channelmatte", tr("Alpha Channel"), true);
1291
1292 // separator
1293 if (hasButton(m_gadgetsMask, eRed) || hasButton(m_gadgetsMask, eGRed))
1294 m_colorFilterSep = m_playToolBar->addSeparator();
1295
1296 // Sound & Histogram & Locator
1297 if (hasButton(m_gadgetsMask, eSound) || hasButton(m_gadgetsMask, eHisto) ||
1298 hasButton(m_gadgetsMask, eLocator)) {
1299 if (hasButton(m_gadgetsMask, eSound)) {
1300 createButton(eSound, "sound", tr("&Soundtrack "), true);
1301 m_soundSep = m_playToolBar->addSeparator();
1302 }
1303 if (hasButton(m_gadgetsMask, eHisto))
1304 createButton(eHisto, "histograms", tr("&Histogram"), false);
1305 if (hasButton(m_gadgetsMask, eLocator))
1306 createButton(eLocator, "locator", tr("&Locator"), false);
1307 if (hasButton(m_gadgetsMask, eHisto) || hasButton(m_gadgetsMask, eLocator))
1308 m_histoSep = m_playToolBar->addSeparator();
1309 }
1310
1311 if (hasButton(m_gadgetsMask, eFilledRaster)) {
1312 createOnOffButton(eFilledRaster, "preview_white",
1313 tr("&Display Areas as Filled"), 0);
1314 m_filledRasterSep = m_playToolBar->addSeparator();
1315 }
1316
1317 if (withCustomWidget) {
1318 m_customAction = m_playToolBar->addWidget(customWidget);
1319 m_customSep = m_playToolBar->addSeparator();
1320 }
1321
1322 if (hasButton(m_gadgetsMask, eZoomIn) || hasButton(m_gadgetsMask, eZoomOut) ||
1323 hasButton(m_gadgetsMask, eFlipHorizontal) ||
1324 hasButton(m_gadgetsMask, eFlipVertical) ||
1325 hasButton(m_gadgetsMask, eResetView)) {
1326 if (hasButton(m_gadgetsMask, eZoomIn))
1327 createButton(eZoomIn, "zoomin", tr("&Zoom In"), false);
1328 if (hasButton(m_gadgetsMask, eZoomOut))
1329 createButton(eZoomOut, "zoomout", tr("&Zoom Out"), false);
1330 if (hasButton(m_gadgetsMask, eFlipHorizontal))
1331 createButton(eFlipHorizontal, "fliphoriz", tr("&Flip Horizontally"), 0);
1332 if (hasButton(m_gadgetsMask, eFlipVertical))
1333 createButton(eFlipVertical, "flipvert", tr("&Flip Vertically"), 0);
1334 if (hasButton(m_gadgetsMask, eResetView))
1335 createButton(eResetView, "reset", tr("&Reset View"), false);
1336 m_viewerSep = m_playToolBar->addSeparator();
1337 }
1338
1339 // for all actions in this toolbar
1340 ret = ret && connect(m_playToolBar, SIGNAL(actionTriggered(QAction *)), this,
1341 SLOT(onButtonPressed(QAction *)));
1342
1343 setChecked(ePause, true);
1344 setChecked(eWhiteBg, FlipBookWhiteBgToggle);
1345 setChecked(eBlackBg, FlipBookBlackBgToggle);
1346 setChecked(eCheckBg, FlipBookCheckBgToggle);
1347 assert(ret);
1348 }
1349
1350 //-----------------------------------------------------------------------------
1351
enableBlanks(bool state)1352 void FlipConsole::enableBlanks(bool state) {
1353 m_drawBlanksEnabled = state;
1354 m_blankColor = TPixel::Transparent;
1355 if (m_drawBlanksEnabled)
1356 Preferences::instance()->getBlankValues(m_blanksCount, m_blankColor);
1357 else {
1358 m_blanksCount = 0;
1359 m_blankColor = TPixel::Transparent;
1360 }
1361 }
1362
1363 //-----------------------------------------------------------------------------
1364 /*! call consoleOwner->onDrawFrame() intead of emitting drawFrame signal
1365 */
showCurrentFrame()1366 void FlipConsole::showCurrentFrame() {
1367 m_consoleOwner->onDrawFrame(m_currentFrame, m_settings);
1368 }
1369
1370 //-----------------------------------------------------------------------------
1371
setChecked(UINT button,bool state)1372 void FlipConsole::setChecked(UINT button, bool state) {
1373 int i;
1374 if (m_playToolBar) {
1375 QObjectList objectList = m_playToolBar->children();
1376 for (i = 0; i < (int)objectList.size(); i++) {
1377 QAction *action = dynamic_cast<QAction *>(objectList[i]);
1378 if (!action) {
1379 QToolButton *toolButton = dynamic_cast<QToolButton *>(objectList[i]);
1380 if (!toolButton) continue;
1381 action = toolButton->defaultAction();
1382 }
1383 if (action && action->data().toUInt() == button) {
1384 action->setChecked(state);
1385 return;
1386 }
1387 }
1388 }
1389
1390 if (m_colorFilterGroup) {
1391 QList<QAction *> list = m_colorFilterGroup->actions();
1392 for (i = 0; i < (int)list.size(); i++)
1393 if (list[i]->data().toUInt() == button) {
1394 list[i]->setChecked(state);
1395 return;
1396 }
1397 }
1398 }
1399
1400 //-----------------------------------------------------------------------------
1401
isChecked(UINT button) const1402 bool FlipConsole::isChecked(UINT button) const {
1403 QList<QAction *> list;
1404 int i;
1405
1406 if (m_playToolBar) {
1407 list = m_playToolBar->actions();
1408 for (i = 0; i < (int)list.size(); i++)
1409 if (list[i]->data().toUInt() == button) return list[i]->isChecked();
1410 }
1411
1412 if (m_colorFilterGroup) {
1413 list = m_colorFilterGroup->actions();
1414 for (i = 0; i < (int)list.size(); i++)
1415 if (list[i]->data().toUInt() == button) return list[i]->isChecked();
1416 }
1417
1418 return false;
1419 }
1420
1421 //-----------------------------------------------------------------------------
1422
pressLinkedConsoleButton(UINT button,FlipConsole * parent)1423 void FlipConsole::pressLinkedConsoleButton(UINT button, FlipConsole *parent) {
1424 int i;
1425 assert(parent);
1426
1427 for (i = 0; i < m_visibleConsoles.size(); i++) {
1428 FlipConsole *console = m_visibleConsoles.at(i);
1429 if (console->m_isLinkable && console != parent) {
1430 console->setChecked(button, parent ? parent->isChecked(button) : true);
1431 console->doButtonPressed(button);
1432 }
1433 }
1434 }
1435
1436 //-----------------------------------------------------------------------------
1437
onButtonPressed(int button)1438 void FlipConsole::onButtonPressed(int button) {
1439 makeCurrent();
1440 if (m_playbackExecutor.isRunning() &&
1441 (button == FlipConsole::ePlay || button == FlipConsole::eLoop)) {
1442 pressButton(ePause);
1443 } else {
1444 // Sync playback state among all viewers & combo viewers.
1445 // Note that the property "m_isLinkable" is used for distinguishing the
1446 // owner between (viewer / combo viewer) and (flipbook / color model).
1447 if (!m_isLinkable &&
1448 (button == FlipConsole::ePlay || button == FlipConsole::eLoop)) {
1449 bool stoppedOther = false;
1450 for (auto playingConsole : m_visibleConsoles) {
1451 if (playingConsole == this || playingConsole->isLinkable()) continue;
1452 if (playingConsole->m_playbackExecutor.isRunning()) {
1453 playingConsole->doButtonPressed(ePause);
1454 playingConsole->setChecked(ePlay, false);
1455 playingConsole->setChecked(eLoop, false);
1456 playingConsole->setChecked(ePause, true);
1457 stoppedOther = true;
1458 }
1459 }
1460 if (stoppedOther) {
1461 setChecked(ePlay, false);
1462 setChecked(eLoop, false);
1463 setChecked(ePause, true);
1464 return;
1465 }
1466 }
1467
1468 doButtonPressed(button);
1469 }
1470
1471 if (m_areLinked) pressLinkedConsoleButton(button, this);
1472 }
1473
1474 //-----------------------------------------------------------------------------
pressButton(EGadget buttonId)1475 void FlipConsole::pressButton(EGadget buttonId) {
1476 FlipConsole *console = this;
1477 if (m_visibleConsoles.indexOf(this) < 0 && m_visibleConsoles.size() > 0) {
1478 console = m_visibleConsoles.at(0);
1479 console->makeCurrent();
1480 }
1481 if (console->m_buttons.contains(buttonId) &&
1482 console->m_buttons[buttonId]->isEnabled())
1483 console->m_buttons[buttonId]->click();
1484 else if (console->m_actions.contains(buttonId) &&
1485 console->m_actions[buttonId]->isEnabled())
1486 console->m_actions[buttonId]->trigger();
1487 }
1488
1489 //-----------------------------------------------------------------------------
1490
onLoadBox(bool isDefine)1491 void FlipConsole::onLoadBox(bool isDefine) {
1492 int shrink, dummy;
1493
1494 Preferences::instance()->getViewValues(shrink, dummy);
1495
1496 if (shrink != 1) {
1497 #ifdef _WIN32
1498 MessageBox(0, "Cannot use loading box with a shrink factor! ", "Warning",
1499 MB_OK);
1500 #endif
1501 setChecked(eUseLoadBox, false);
1502 setChecked(eDefineLoadBox, false);
1503 m_settings.m_useLoadbox = m_settings.m_defineLoadbox = false;
1504 return;
1505 }
1506
1507 if (isDefine)
1508 m_settings.m_defineLoadbox = !m_settings.m_defineLoadbox;
1509 else
1510 m_settings.m_useLoadbox = !m_settings.m_useLoadbox;
1511
1512 if (m_settings.m_defineLoadbox && m_settings.m_useLoadbox) {
1513 setChecked(isDefine ? eUseLoadBox : eDefineLoadBox, false);
1514 if (isDefine)
1515 m_settings.m_useLoadbox = false;
1516 else
1517 m_settings.m_defineLoadbox = false;
1518 }
1519
1520 m_consoleOwner->onDrawFrame(m_currentFrame, m_settings);
1521 return;
1522 }
1523
1524 //-----------------------------------------------------------------------------
1525
doButtonPressed(UINT button)1526 void FlipConsole::doButtonPressed(UINT button) {
1527 emit buttonPressed((FlipConsole::EGadget)button);
1528
1529 int from = m_from, to = m_to;
1530 // When the level editing mode, ignore the preview frame range marker
1531 if (m_markerFrom <= m_markerTo && m_frameHandle &&
1532 m_frameHandle->isEditingScene())
1533 from = m_markerFrom, to = m_markerTo;
1534
1535 bool linked = m_areLinked && m_isLinkable;
1536
1537 switch (button) {
1538 case eFirst:
1539 m_currentFrame = from;
1540 break;
1541 case ePrev:
1542 m_currentFrame =
1543 (m_currentFrame - m_step < from) ? from : m_currentFrame - m_step;
1544 break;
1545 case eNext:
1546 m_currentFrame =
1547 (m_currentFrame + m_step > to) ? to : m_currentFrame + m_step;
1548 break;
1549 case eLast:
1550 m_currentFrame = to;
1551 break;
1552 case ePlay:
1553 case eLoop:
1554 // if ( isChecked(ePlay, false);
1555 // setChecked(eLoop, false);
1556 m_editCurrFrame->disconnect();
1557 m_currFrameSlider->disconnect();
1558
1559 m_isPlay = (button == ePlay);
1560
1561 if (linked && m_isLinkedPlaying) return;
1562
1563 if ((m_fps == 0 || m_framesCount == 0) && m_playbackExecutor.isRunning()) {
1564 doButtonPressed(ePause);
1565 if (m_fpsLabel) m_fpsLabel->setText(tr(" FPS ") + QString::number(m_fps));
1566 if (m_fpsField)
1567 m_fpsField->setLineEditBackgroundColor(getFpsFieldColor());
1568 return;
1569 }
1570 if (m_fpsLabel) m_fpsLabel->setText(tr(" FPS ") + "/");
1571 if (m_fpsField) m_fpsField->setLineEditBackgroundColor(Qt::red);
1572
1573 m_playbackExecutor.resetFps(m_fps);
1574 if (!m_playbackExecutor.isRunning()) m_playbackExecutor.start();
1575 m_isLinkedPlaying = linked;
1576
1577 m_reverse = (m_fps < 0);
1578
1579 if (!linked) {
1580 // if the play button pressed at the end frame, then go back to the
1581 // start frame and play
1582 if (m_currentFrame <= from ||
1583 m_currentFrame >=
1584 to) // the first frame of the playback is drawn right now
1585 m_currentFrame = m_reverse ? to : from;
1586 m_settings.m_recomputeIfNeeded = true;
1587 m_consoleOwner->onDrawFrame(m_currentFrame, m_settings);
1588 }
1589
1590 emit playStateChanged(true);
1591 return;
1592
1593 case ePause:
1594 if (!m_playbackExecutor.isRunning() && !m_isLinkedPlaying) {
1595 // Sync playback state among all viewers & combo viewers.
1596 // Note that the property "m_isLinkable" is used for distinguishing the
1597 // owner between (viewer / combo viewer) and (flipbook / color model).
1598 if (!m_isLinkable) {
1599 for (auto playingConsole : m_visibleConsoles) {
1600 if (playingConsole->isLinkable()) continue;
1601 if (playingConsole->m_playbackExecutor.isRunning())
1602 playingConsole->doButtonPressed(button);
1603 playingConsole->setChecked(ePlay, false);
1604 playingConsole->setChecked(eLoop, false);
1605 playingConsole->setChecked(ePause, true);
1606 }
1607 }
1608 return;
1609 }
1610
1611 m_isLinkedPlaying = false;
1612
1613 if (m_playbackExecutor.isRunning()) m_playbackExecutor.abort();
1614
1615 m_isPlay = false;
1616 m_blanksToDraw = 0;
1617
1618 m_consoleOwner->swapBuffers();
1619 m_consoleOwner->changeSwapBehavior(true);
1620
1621 if (m_settings.m_blankColor != TPixel::Transparent) {
1622 m_settings.m_blankColor = TPixel::Transparent;
1623 m_settings.m_recomputeIfNeeded = true;
1624 m_consoleOwner->onDrawFrame(m_currentFrame, m_settings);
1625 }
1626 if (m_fpsLabel) m_fpsLabel->setText(tr(" FPS "));
1627 if (m_fpsField) m_fpsField->setLineEditBackgroundColor(getFpsFieldColor());
1628 // setChecked(ePlay, false);
1629 // setChecked(eLoop, false);
1630 connect(m_editCurrFrame, SIGNAL(editingFinished()), this,
1631 SLOT(OnSetCurrentFrame()));
1632 connect(m_currFrameSlider, SIGNAL(flipSliderReleased()), this,
1633 SLOT(OnFrameSliderRelease()));
1634 connect(m_currFrameSlider, SIGNAL(flipSliderPressed()), this,
1635 SLOT(OnFrameSliderPress()));
1636 connect(m_currFrameSlider, SIGNAL(valueChanged(int)), this,
1637 SLOT(OnSetCurrentFrame(int)));
1638 connect(m_currFrameSlider, SIGNAL(flipSliderReleased()), this,
1639 SLOT(onSliderRelease()));
1640 emit playStateChanged(false);
1641 return;
1642
1643 case eGRed:
1644 case eGGreen:
1645 case eGBlue:
1646 case eRed:
1647 case eGreen:
1648 case eBlue:
1649 case eMatte: {
1650 if (button != eGRed) setChecked(eGRed, false);
1651 if (button != eGGreen) setChecked(eGGreen, false);
1652 if (button != eGBlue) setChecked(eGBlue, false);
1653
1654 if (button == eGRed || button == eGGreen || button == eGBlue) {
1655 m_settings.m_greytones = isChecked(button);
1656 setChecked(eRed, false);
1657 setChecked(eGreen, false);
1658 setChecked(eBlue, false);
1659 setChecked(eMatte, false);
1660 } else
1661 m_settings.m_greytones = false;
1662
1663 if (m_doubleRed) {
1664 m_doubleRed->update();
1665 m_doubleGreen->update();
1666 m_doubleBlue->update();
1667 }
1668
1669 int colorMask = 0;
1670 if (isChecked(eRed) || isChecked(eGRed))
1671 colorMask = colorMask | TRop::RChan;
1672 if (isChecked(eGreen) || isChecked(eGGreen))
1673 colorMask = colorMask | TRop::GChan;
1674 if (isChecked(eBlue) || isChecked(eGBlue))
1675 colorMask = colorMask | TRop::BChan;
1676 if (isChecked(eMatte)) colorMask = colorMask | TRop::MChan;
1677
1678 if (colorMask == (TRop::RChan | TRop::GChan | TRop::BChan) ||
1679 colorMask == (TRop::RChan | TRop::GChan | TRop::BChan | TRop::MChan))
1680 m_settings.m_colorMask = 0;
1681 else
1682 m_settings.m_colorMask = colorMask;
1683 break;
1684 }
1685 case eSound:
1686 // emit soundEnabled(isChecked(eSound));
1687 break;
1688
1689 case eWhiteBg:
1690 case eBlackBg:
1691 case eCheckBg:
1692 m_settings.m_bg = (EGadget)button;
1693 FlipBookWhiteBgToggle = isChecked(eWhiteBg);
1694 FlipBookBlackBgToggle = isChecked(eBlackBg);
1695 FlipBookCheckBgToggle = isChecked(eCheckBg);
1696 break;
1697
1698 case FlipConsole::eCompare:
1699 m_settings.m_doCompare = !m_settings.m_doCompare;
1700 break;
1701
1702 case eHisto:
1703 case eSaveImg:
1704 case eSave:
1705 case eLocator:
1706 // nothing to do
1707 return;
1708
1709 case eDefineSubCamera:
1710 // nothing to do
1711 return;
1712
1713 case eDefineLoadBox:
1714 onLoadBox(true);
1715 break;
1716
1717 case eUseLoadBox:
1718 onLoadBox(false);
1719 break;
1720
1721 case eFilledRaster:
1722 return;
1723
1724 case eFlipHorizontal:
1725 case eFlipVertical:
1726 case eZoomIn:
1727 case eZoomOut:
1728 case eResetView:
1729 return;
1730
1731 default:
1732 assert(false);
1733 break;
1734 }
1735
1736 m_currFrameSlider->setValue(m_currentFrame);
1737 m_editCurrFrame->setText(QString::number(m_currentFrame));
1738
1739 m_consoleOwner->onDrawFrame(m_currentFrame, m_settings);
1740 }
1741
1742 //--------------------------------------------------------------------
1743
createFrameSlider()1744 QFrame *FlipConsole::createFrameSlider() {
1745 QFrame *frameSliderFrame = new QFrame(this);
1746
1747 m_editCurrFrame = new DVGui::IntLineEdit(frameSliderFrame, m_currentFrame);
1748 m_editCurrFrame->setToolTip(tr("Set the current frame"));
1749 m_editCurrFrame->setFixedWidth(40);
1750
1751 m_currFrameSlider = new FlipSlider(frameSliderFrame);
1752 m_currFrameSlider->setToolTip(tr("Drag to play the animation"));
1753
1754 m_currFrameSlider->setRange(0, 0);
1755 m_currFrameSlider->setValue(0);
1756
1757 if (m_drawBlanksEnabled) {
1758 m_enableBlankFrameButton = new QPushButton(this);
1759 m_enableBlankFrameButton->setCheckable(true);
1760 m_enableBlankFrameButton->setChecked(true);
1761
1762 m_enableBlankFrameButton->setFixedHeight(24);
1763 m_enableBlankFrameButton->setFixedWidth(66);
1764 m_enableBlankFrameButton->setObjectName("enableBlankFrameButton");
1765 }
1766
1767 // layout
1768 QHBoxLayout *frameSliderLayout = new QHBoxLayout();
1769 frameSliderLayout->setSpacing(5);
1770 frameSliderLayout->setMargin(2);
1771 {
1772 frameSliderLayout->addWidget(m_editCurrFrame, 0);
1773 frameSliderLayout->addWidget(m_currFrameSlider, 1);
1774 if (m_drawBlanksEnabled)
1775 frameSliderLayout->addWidget(m_enableBlankFrameButton, 0);
1776 }
1777 frameSliderFrame->setLayout(frameSliderLayout);
1778
1779 connect(m_editCurrFrame, SIGNAL(editingFinished()), this,
1780 SLOT(OnSetCurrentFrame()));
1781 connect(m_currFrameSlider, SIGNAL(valueChanged(int)), this,
1782 SLOT(OnSetCurrentFrame(int)));
1783 connect(m_currFrameSlider, SIGNAL(flipSliderReleased()), this,
1784 SLOT(OnFrameSliderRelease()));
1785
1786 return frameSliderFrame;
1787 }
1788
1789 //--------------------------------------------------------------------
1790
createFpsSlider()1791 QFrame *FlipConsole::createFpsSlider() {
1792 QFrame *fpsSliderFrame = new QFrame(this);
1793 // frame per second
1794 m_fpsLabel = new QLabel(QString(" FPS -- /"), fpsSliderFrame);
1795 m_fpsSlider = new QScrollBar(Qt::Horizontal, fpsSliderFrame);
1796 m_fpsField = new DVGui::IntLineEdit(fpsSliderFrame, m_fps, -60, 60);
1797 m_fpsField->setFixedWidth(40);
1798
1799 m_fpsLabel->setMinimumWidth(m_fpsLabel->fontMetrics().width("_FPS_24___"));
1800 m_fpsLabel->setAlignment(Qt::AlignRight | Qt::AlignVCenter);
1801 m_fpsSlider->setObjectName("ViewerFpsSlider");
1802 m_fpsSlider->setRange(-60, 60);
1803 m_fpsSlider->setValue(m_fps);
1804 m_fpsSlider->setToolTip(tr("Set the playback frame rate"));
1805 m_fpsSlider->setContextMenuPolicy(Qt::NoContextMenu);
1806
1807 QHBoxLayout *hLay = new QHBoxLayout();
1808 hLay->setSpacing(0);
1809 hLay->setMargin(0);
1810 {
1811 hLay->addWidget(m_fpsLabel, 0);
1812 hLay->addWidget(m_fpsField, 0);
1813 hLay->addWidget(m_fpsSlider, 1);
1814 }
1815 fpsSliderFrame->setLayout(hLay);
1816
1817 connect(m_fpsSlider, SIGNAL(valueChanged(int)), this,
1818 SLOT(setCurrentFPS(int)));
1819 connect(m_fpsField, SIGNAL(editingFinished()), this, SLOT(onFPSEdited()));
1820
1821 return fpsSliderFrame;
1822 }
1823
1824 //--------------------------------------------------------------------
1825
onFPSEdited(void)1826 void FlipConsole::onFPSEdited(void) {
1827 // this will emit fpsSlider->ValueChanged as well
1828 m_fpsSlider->setValue(m_fpsField->getValue());
1829 }
1830
1831 //--------------------------------------------------------------------
1832
setFrameRange(int from,int to,int step,int current)1833 void FlipConsole::setFrameRange(int from, int to, int step, int current) {
1834 if (from != m_from || to != m_to || step != m_step) {
1835 m_from = from;
1836 m_to = to;
1837 m_step = step;
1838 m_to -= (m_to - m_from) % m_step;
1839 m_framesCount = (m_to - m_from) / m_step + 1;
1840 m_currFrameSlider->blockSignals(true);
1841 // m_currFrameSlider->setRange(0, m_framesCount-1);
1842 m_currFrameSlider->setRange(m_from, m_to);
1843 m_currFrameSlider->setSingleStep(m_step);
1844 m_currFrameSlider->blockSignals(false);
1845 }
1846
1847 if (m_playbackExecutor.isRunning() ||
1848 m_isLinkedPlaying) // if in playing mode, the slider and the frame
1849 // field are already set in the timer!
1850 return;
1851
1852 // limit the current frame in the range from-to
1853 if (current < from)
1854 current = from;
1855 else if (current > to)
1856 current = to;
1857
1858 m_currFrameSlider->blockSignals(true);
1859 setCurrentFrame(current);
1860 m_currFrameSlider->blockSignals(false);
1861 }
1862
1863 //--------------------------------------------------------------------
1864
incrementCurrentFrame(int delta)1865 void FlipConsole::incrementCurrentFrame(int delta) {
1866 m_currentFrame = m_currentFrame + delta;
1867 if (m_currentFrame < m_from)
1868 m_currentFrame += m_to - m_from + 1;
1869 else if (m_currentFrame > m_to)
1870 m_currentFrame -= m_to - m_from + 1;
1871
1872 m_editCurrFrame->setText(QString::number(m_currentFrame));
1873 m_currFrameSlider->setValue(m_currentFrame);
1874
1875 m_consoleOwner->onDrawFrame(m_currentFrame, m_settings);
1876 }
1877
1878 //--------------------------------------------------------------------
1879
OnSetCurrentFrame()1880 void FlipConsole::OnSetCurrentFrame() {
1881 int newFrame = m_editCurrFrame->text().toInt();
1882 if (m_step > 1) {
1883 newFrame -= ((newFrame - m_from) % m_step);
1884 m_editCurrFrame->setText(QString::number(newFrame));
1885 }
1886
1887 int i, deltaFrame = newFrame - m_currentFrame;
1888
1889 if (m_framesCount == 0) m_editCurrFrame->setText(QString::number(1));
1890
1891 if (m_framesCount == 0 || newFrame == m_currentFrame || newFrame == 0) return;
1892
1893 if (newFrame > m_to) {
1894 m_editCurrFrame->setText(QString::number(m_currentFrame));
1895 return;
1896 }
1897
1898 m_currentFrame = newFrame;
1899 m_currFrameSlider->setValue(m_currentFrame);
1900
1901 m_consoleOwner->onDrawFrame(m_currentFrame, m_settings);
1902
1903 if (m_areLinked)
1904 for (i = 0; i < m_visibleConsoles.size(); i++) {
1905 FlipConsole *console = m_visibleConsoles.at(i);
1906 if (console->m_isLinkable && console != this)
1907 console->incrementCurrentFrame(deltaFrame);
1908 }
1909 }
1910
1911 //--------------------------------------------------------------------
1912
onSliderRelease()1913 void FlipConsole::onSliderRelease() { emit sliderReleased(); }
1914
1915 //--------------------------------------------------------------------
OnFrameSliderRelease()1916 void FlipConsole::OnFrameSliderRelease() {
1917 m_settings.m_recomputeIfNeeded = true;
1918 m_currentFrame = -1;
1919 OnSetCurrentFrame();
1920 }
1921
OnFrameSliderPress()1922 void FlipConsole::OnFrameSliderPress() {
1923 m_settings.m_recomputeIfNeeded = false;
1924 }
1925
1926 //---------------------
1927 //----------------------------------
1928
OnSetCurrentFrame(int index)1929 void FlipConsole::OnSetCurrentFrame(int index) {
1930 if (m_framesCount == 0) return;
1931
1932 if (index == m_currentFrame) return;
1933
1934 int deltaFrame = index - m_currentFrame;
1935
1936 m_currentFrame = index;
1937
1938 assert(m_currentFrame <= m_to);
1939 m_editCurrFrame->setText(QString::number(m_currentFrame));
1940
1941 m_consoleOwner->onDrawFrame(m_currentFrame, m_settings);
1942
1943 if (m_areLinked)
1944 for (int i = 0; i < m_visibleConsoles.size(); i++) {
1945 FlipConsole *console = m_visibleConsoles.at(i);
1946 if (console->m_isLinkable && console != this)
1947 console->incrementCurrentFrame(deltaFrame);
1948 }
1949 }
1950
1951 //--------------------------------------------------------------------
1952
setCurrentFrame(int frame,bool forceResetting)1953 void FlipConsole::setCurrentFrame(int frame, bool forceResetting) {
1954 m_currentFrame = (frame == -1) ? m_from : frame;
1955 if ((m_playbackExecutor.isRunning() || m_isLinkedPlaying) &&
1956 !forceResetting) // if in playing mode, the slider and the frame field
1957 // are already set in the timer!
1958 return;
1959
1960 m_editCurrFrame->setValue(m_currentFrame);
1961 m_currFrameSlider->setValue(m_currentFrame);
1962 }
1963
1964 //--------------------------------------------------------------------
1965
enableProgressBar(bool enable)1966 void FlipConsole::enableProgressBar(bool enable) {
1967 m_currFrameSlider->setProgressBarEnabled(enable);
1968 }
1969
1970 //--------------------------------------------------------------------
1971
setProgressBarStatus(const std::vector<UCHAR> * pbStatus)1972 void FlipConsole::setProgressBarStatus(const std::vector<UCHAR> *pbStatus) {
1973 m_currFrameSlider->setProgressBarStatus(pbStatus);
1974 }
1975
1976 //--------------------------------------------------------------------
1977
getProgressBarStatus() const1978 const std::vector<UCHAR> *FlipConsole::getProgressBarStatus() const {
1979 return m_currFrameSlider->getProgressBarStatus();
1980 }
1981
1982 //--------------------------------------------------------------------
1983
onPreferenceChanged(const QString & prefName)1984 void FlipConsole::onPreferenceChanged(const QString &prefName) {
1985 // react only when related properties are changed
1986 if (prefName != "BlankCount" && prefName != "BlankColor" &&
1987 !prefName.isEmpty())
1988 return;
1989
1990 if (m_drawBlanksEnabled) {
1991 Preferences::instance()->getBlankValues(m_blanksCount, m_blankColor);
1992 if (m_blanksCount == 0) {
1993 if (m_enableBlankFrameButton->isVisible())
1994 m_enableBlankFrameButton->hide();
1995 } else {
1996 if (m_enableBlankFrameButton->isHidden())
1997 m_enableBlankFrameButton->show();
1998 QString buttonText = QString("+%1 Blank").arg(m_blanksCount);
1999 if (m_blanksCount > 1) buttonText += "s";
2000 m_enableBlankFrameButton->setText(buttonText);
2001
2002 // Set text color based on luminescence of blankColor color
2003 QString textColor;
2004 double luminescence =
2005 ((0.299 * (int)m_blankColor.r) + (0.587 * (int)m_blankColor.g) +
2006 (0.114 * (int)m_blankColor.b)) /
2007 255;
2008 if (luminescence > 0.5)
2009 textColor = QString("black");
2010 else
2011 textColor = QString("white");
2012
2013 m_enableBlankFrameButton->setStyleSheet(
2014 QString("#enableBlankFrameButton:checked { \
2015 background-color: rgb(%1,%2,%3); \
2016 color: %4;}")
2017 .arg(m_blankColor.r)
2018 .arg(m_blankColor.g)
2019 .arg(m_blankColor.b)
2020 .arg(textColor));
2021 m_enableBlankFrameButton->update();
2022 }
2023 }
2024 }
2025
2026 //====================================================================
2027
2028 class FlipConsoleActionsCreator : AuxActionsCreator {
createToggleAction(QObject * parent,const char * cmdId,const char * name,int buttonId)2029 void createToggleAction(QObject *parent, const char *cmdId, const char *name,
2030 int buttonId) {
2031 QAction *action = new QAction(name, parent);
2032 action->setData(QVariant(buttonId));
2033 CommandManager::instance()->define(cmdId, MiscCommandType, "", action);
2034 }
2035
2036 public:
createActions(QObject * parent)2037 void createActions(QObject *parent) override {
2038 /*createToggleAction(parent, "A_Flip_Play", "Play", FlipConsole::ePlay);
2039 createToggleAction(parent, "A_Flip_Pause", "Pause", FlipConsole::ePause);
2040 createToggleAction(parent, "A_Flip_Loop", "Loop", FlipConsole::eLoop);*/
2041 }
2042 } flipConsoleActionsCreator;
2043
2044 //--------------------------------------------------------------------
2045