diff --git a/app/panel/timeline/timeline.cpp b/app/panel/timeline/timeline.cpp index c38cbe04a..9f5cd45e4 100644 --- a/app/panel/timeline/timeline.cpp +++ b/app/panel/timeline/timeline.cpp @@ -45,6 +45,9 @@ TimelinePanel::TimelinePanel(QWidget *parent) : // End test code Retranslate(); + +// ruler_->SetScale(90.0); +// view_->SetScale(90.0); } void TimelinePanel::Clear() diff --git a/app/ui/style/olive-dark/style.css b/app/ui/style/olive-dark/style.css index c2bf689f8..8c3552592 100644 --- a/app/ui/style/olive-dark/style.css +++ b/app/ui/style/olive-dark/style.css @@ -73,3 +73,9 @@ NodeViewItemWidget { qproperty-titlebarColor: #4040a0; qproperty-borderColor: #000000; } + +/* Timeline playhead styling */ +TimelinePlayhead { + qproperty-playheadColor: #ff0000; + qproperty-playheadHighlightColor: rgba(255, 255, 255, 0.33); +} diff --git a/app/ui/style/olive-light/style.css b/app/ui/style/olive-light/style.css index e30729303..cc660afb4 100644 --- a/app/ui/style/olive-light/style.css +++ b/app/ui/style/olive-light/style.css @@ -72,4 +72,10 @@ QTreeView, QListView, QLineEdit, QMenu, QProgressBar, QPushButton::checked, Node NodeViewItemWidget { qproperty-titlebarColor: #a0a0ff; qproperty-borderColor: #000000; -} \ No newline at end of file +} + +/* Timeline playhead styling */ +TimelinePlayhead { + qproperty-playheadColor: #ff0000; + qproperty-playheadHighlightColor: rgba(0, 0, 0, 0.25); +} diff --git a/app/widget/timelineview/CMakeLists.txt b/app/widget/timelineview/CMakeLists.txt index 4c7a23cbe..02642a2cb 100644 --- a/app/widget/timelineview/CMakeLists.txt +++ b/app/widget/timelineview/CMakeLists.txt @@ -16,6 +16,8 @@ set(OLIVE_SOURCES ${OLIVE_SOURCES} + widget/timelineview/timelineplayhead.h + widget/timelineview/timelineplayhead.cpp widget/timelineview/timelineview.h widget/timelineview/timelineview.cpp widget/timelineview/timelineviewrect.h diff --git a/app/widget/timelineview/timelineplayhead.cpp b/app/widget/timelineview/timelineplayhead.cpp new file mode 100644 index 000000000..e9eac8c9e --- /dev/null +++ b/app/widget/timelineview/timelineplayhead.cpp @@ -0,0 +1,26 @@ +#include "timelineplayhead.h" + +TimelinePlayhead::TimelinePlayhead() +{ + +} + +QColor TimelinePlayhead::PlayheadColor() +{ + return playhead_color_; +} + +QColor TimelinePlayhead::PlayheadHighlightColor() +{ + return playhead_highlight_color_; +} + +void TimelinePlayhead::SetPlayheadColor(QColor c) +{ + playhead_color_ = c; +} + +void TimelinePlayhead::SetPlayheadHighlightColor(QColor c) +{ + playhead_highlight_color_ = c; +} diff --git a/app/widget/timelineview/timelineplayhead.h b/app/widget/timelineview/timelineplayhead.h new file mode 100644 index 000000000..0ceaa99d3 --- /dev/null +++ b/app/widget/timelineview/timelineplayhead.h @@ -0,0 +1,25 @@ +#ifndef TIMELINEPLAYHEADSTYLE_H +#define TIMELINEPLAYHEADSTYLE_H + +#include + +class TimelinePlayhead : public QWidget +{ + Q_OBJECT + Q_PROPERTY(QColor playheadColor READ PlayheadColor WRITE SetPlayheadColor DESIGNABLE true) + Q_PROPERTY(QColor playheadHighlightColor READ PlayheadHighlightColor WRITE SetPlayheadHighlightColor DESIGNABLE true) +public: + TimelinePlayhead(); + + QColor PlayheadColor(); + QColor PlayheadHighlightColor(); + + void SetPlayheadColor(QColor c); + void SetPlayheadHighlightColor(QColor c); + +private: + QColor playhead_color_; + QColor playhead_highlight_color_; +}; + +#endif // TIMELINEPLAYHEADSTYLE_H diff --git a/app/widget/timelineview/timelineview.cpp b/app/widget/timelineview/timelineview.cpp index 83afcc0fc..2570f3c8c 100644 --- a/app/widget/timelineview/timelineview.cpp +++ b/app/widget/timelineview/timelineview.cpp @@ -49,7 +49,6 @@ void TimelineView::AddClip(ClipBlock *clip) // Set up clip with view parameters (clip item will automatically size its rect accordingly) clip_item->SetClip(clip); - clip_item->SetTimebase(timebase_); clip_item->SetScale(scale_); // Add to list of clip items that can be iterated through @@ -74,10 +73,6 @@ void TimelineView::SetTimebase(const rational &timebase) { timebase_ = timebase; - foreach (TimelineViewClipItem* item, clip_items_) { - item->SetTimebase(timebase_); - } - playhead_line_->SetTimebase(timebase_); } @@ -113,7 +108,7 @@ void TimelineView::mousePressEvent(QMouseEvent *event) ghost->SetIn(clip->in()); ghost->SetOut(clip->out()); - ghost->SetTimebase(timebase_); + ghost->SetScale(scale_); ghost->setPos(clip_item->pos()); diff --git a/app/widget/timelineview/timelineviewclipitem.cpp b/app/widget/timelineview/timelineviewclipitem.cpp index d2c775726..429ec809d 100644 --- a/app/widget/timelineview/timelineviewclipitem.cpp +++ b/app/widget/timelineview/timelineviewclipitem.cpp @@ -48,7 +48,7 @@ void TimelineViewClipItem::SetClip(ClipBlock *clip) void TimelineViewClipItem::UpdateRect() { - if (clip_ == nullptr || !TimebaseIsValid()) { + if (clip_ == nullptr) { return; } diff --git a/app/widget/timelineview/timelineviewplayheaditem.cpp b/app/widget/timelineview/timelineviewplayheaditem.cpp index ba7446e4d..dabbcf6e4 100644 --- a/app/widget/timelineview/timelineviewplayheaditem.cpp +++ b/app/widget/timelineview/timelineviewplayheaditem.cpp @@ -1,11 +1,13 @@ #include "timelineviewplayheaditem.h" +#include #include #include #include TimelineViewPlayheadItem::TimelineViewPlayheadItem(QGraphicsItem *parent) : - TimelineViewRect(parent) + TimelineViewRect(parent), + playhead_(0) { } @@ -17,6 +19,13 @@ void TimelineViewPlayheadItem::SetPlayhead(const int64_t &playhead) UpdateRect(); } +void TimelineViewPlayheadItem::SetTimebase(const rational &timebase) +{ + timebase_ = timebase; + + UpdateRect(); +} + void TimelineViewPlayheadItem::UpdateRect() { double x = TimeToScreenCoord(rational(playhead_ * timebase_.numerator(), timebase_.denominator())); @@ -33,10 +42,10 @@ void TimelineViewPlayheadItem::paint(QPainter *painter, const QStyleOptionGraphi // FIXME: Make adjustable through CSS painter->setPen(Qt::NoPen); - painter->setBrush(QColor(255, 255, 255, 128)); + painter->setBrush(style_.PlayheadHighlightColor()); painter->drawRect(rect()); - painter->setPen(Qt::red); + painter->setPen(style_.PlayheadColor()); painter->setBrush(Qt::NoBrush); painter->drawLine(QLineF(rect().topLeft(), rect().bottomLeft())); } diff --git a/app/widget/timelineview/timelineviewplayheaditem.h b/app/widget/timelineview/timelineviewplayheaditem.h index 7c5db0a85..d7f325c9d 100644 --- a/app/widget/timelineview/timelineviewplayheaditem.h +++ b/app/widget/timelineview/timelineviewplayheaditem.h @@ -1,6 +1,7 @@ #ifndef TIMELINEVIEWPLAYHEADITEM_H #define TIMELINEVIEWPLAYHEADITEM_H +#include "timelineplayhead.h" #include "timelineviewrect.h" class TimelineViewPlayheadItem : public TimelineViewRect @@ -10,6 +11,8 @@ public: void SetPlayhead(const int64_t& playhead); + void SetTimebase(const rational& timebase); + protected: virtual void UpdateRect() override; @@ -17,6 +20,10 @@ protected: private: int64_t playhead_; + + rational timebase_; + + TimelinePlayhead style_; }; #endif // TIMELINEVIEWPLAYHEADITEM_H diff --git a/app/widget/timelineview/timelineviewrect.cpp b/app/widget/timelineview/timelineviewrect.cpp index 0e76506ed..4e6355eb4 100644 --- a/app/widget/timelineview/timelineviewrect.cpp +++ b/app/widget/timelineview/timelineviewrect.cpp @@ -7,26 +7,14 @@ TimelineViewRect::TimelineViewRect(QGraphicsItem* parent) : } -void TimelineViewRect::SetTimebase(const rational &timebase) -{ - timebase_ = timebase; - timebase_dbl_ = timebase_.toDouble(); - - UpdateRect(); -} - void TimelineViewRect::SetScale(const double &scale) { scale_ = scale; - UpdateRect(); -} -bool TimelineViewRect::TimebaseIsValid() -{ - return timebase_.denominator() != 0; + UpdateRect(); } double TimelineViewRect::TimeToScreenCoord(const rational &time) { - return time.toDouble() / timebase_dbl_ * scale_; + return time.toDouble() * scale_; } diff --git a/app/widget/timelineview/timelineviewrect.h b/app/widget/timelineview/timelineviewrect.h index 8e3637722..e1dcdf1d4 100644 --- a/app/widget/timelineview/timelineviewrect.h +++ b/app/widget/timelineview/timelineviewrect.h @@ -10,21 +10,13 @@ class TimelineViewRect : public QGraphicsRectItem public: TimelineViewRect(QGraphicsItem* parent = nullptr); - void SetTimebase(const rational& timebase); - void SetScale(const double& scale); protected: virtual void UpdateRect() = 0; - bool TimebaseIsValid(); - double TimeToScreenCoord(const rational& time); - rational timebase_; - - double timebase_dbl_; - double scale_; }; diff --git a/app/widget/timeruler/timeruler.cpp b/app/widget/timeruler/timeruler.cpp index e1b37956c..bd0140eb7 100644 --- a/app/widget/timeruler/timeruler.cpp +++ b/app/widget/timeruler/timeruler.cpp @@ -78,7 +78,11 @@ void TimeRuler::SetScale(double d) void TimeRuler::SetTimebase(const rational &r) { - time_base_ = r; + timebase_ = r; + + timebase_dbl_ = timebase_.toDouble(); + + timebase_flipped_dbl_ = timebase_.flipped().toDouble(); update(); } @@ -97,12 +101,10 @@ void TimeRuler::SetScroll(int s) update(); } -void TimeRuler::paintEvent(QPaintEvent *e) +void TimeRuler::paintEvent(QPaintEvent *) { - Q_UNUSED(e) - // Nothing to paint if the timebase is invalid - if (time_base_.denominator() == 0) { + if (timebase_.denominator() == 0) { return; } @@ -113,10 +115,10 @@ void TimeRuler::paintEvent(QPaintEvent *e) // Depending on the scale, we don't need all the lines drawn or else they'll start to become unhelpful // Determine an even number to divide the frame count by - int rough_frames_in_second = qRound(time_base_.flipped().toDouble()); + int rough_frames_in_second = qRound(timebase_flipped_dbl_); int test_divider = 1; while (!((rough_frames_in_second%test_divider == 0 || test_divider > rough_frames_in_second) - && scale_ * test_divider >= minimum_gap_between_lines_)) { + && scale_ * test_divider * timebase_dbl_ >= minimum_gap_between_lines_)) { if (test_divider < rough_frames_in_second) { test_divider++; } else { @@ -124,7 +126,7 @@ void TimeRuler::paintEvent(QPaintEvent *e) } } double reverse_divider = double(rough_frames_in_second) / double(test_divider); - qreal real_divider = qMax(1.0, time_base_.flipped().toDouble() / reverse_divider); + qreal real_divider = qMax(1.0, timebase_flipped_dbl_ / reverse_divider); // Set where the loop ends (affected by text) int loop_start = - playhead_width_; @@ -136,8 +138,8 @@ void TimeRuler::paintEvent(QPaintEvent *e) int text_y = 0; if (text_visible_) { QFontMetrics fm = p.fontMetrics(); - double width_of_second = time_base_.flipped().toDouble() * scale_; - int average_text_width = QFontMetricsWidth(&fm, olive::timestamp_to_timecode(0, time_base_, kTimecodeDisplay)); + double width_of_second = scale_; + int average_text_width = QFontMetricsWidth(&fm, olive::timestamp_to_timecode(0, timebase_, kTimecodeDisplay)); half_average_text_width = average_text_width/2; while (width_of_second * text_skip < average_text_width) { text_skip++; @@ -166,21 +168,14 @@ void TimeRuler::paintEvent(QPaintEvent *e) int line_halfsec_bottom = line_top + line_length / 3 * 2; int line_frame_bottom = line_top + line_length / 3; - int playhead_pos = -1; - for (int i=loop_start;i qFloor(double(last_unit)/real_divider)) { // Determine if this unit is a whole second or not - int sec = qFloor(double(unit) * time_base_.toDouble()); + int sec = qFloor(double(unit) * timebase_dbl_); if (sec > last_sec) { // This line marks a second so we make it long @@ -190,7 +185,7 @@ void TimeRuler::paintEvent(QPaintEvent *e) // Try to draw text here if (text_visible_ && sec%text_skip == 0) { - QString timecode_string = olive::timestamp_to_timecode(sec, time_base_, kTimecodeDisplay); + QString timecode_string = olive::timestamp_to_timecode(sec, timebase_, kTimecodeDisplay); int text_x = i; @@ -219,10 +214,11 @@ void TimeRuler::paintEvent(QPaintEvent *e) } } - // If we found the playhead along here, draw it last - if (playhead_pos >= 0) { + // Draw the playhead if it's on screen at the moment + int playhead_pos = qFloor(static_cast(time_) * timebase_dbl_); + if (playhead_pos + playhead_width_ >= 0 && playhead_pos - playhead_width_ < width()) { p.setPen(Qt::NoPen); - p.setBrush(Qt::red); // FIXME: Make configurable in CSS + p.setBrush(style_.PlayheadColor()); DrawPlayhead(&p, playhead_pos, height()); } } @@ -250,16 +246,17 @@ void TimeRuler::DrawPlayhead(QPainter *p, int x, int y) QPoint(x, y), QPoint(x - half_width, y - half_text_height), QPoint(x - half_width, y - text_height_), - QPoint(x + half_width, y - text_height_), - QPoint(x + half_width, y - half_text_height) + QPoint(x + 1 + half_width, y - text_height_), + QPoint(x + 1 + half_width, y - half_text_height), + QPoint(x + 1, y), }; - p->drawPolygon(points, 5); + p->drawPolygon(points, 6); } double TimeRuler::ScreenToUnitFloat(int screen) { - return (screen + scroll_) / scale_; + return (screen + scroll_) / scale_ / timebase_dbl_; } int64_t TimeRuler::ScreenToUnit(int screen) diff --git a/app/widget/timeruler/timeruler.h b/app/widget/timeruler/timeruler.h index 0fc8936ef..83ee68eae 100644 --- a/app/widget/timeruler/timeruler.h +++ b/app/widget/timeruler/timeruler.h @@ -25,6 +25,7 @@ #include #include "common/rational.h" +#include "widget/timelineview/timelineplayhead.h" class TimeRuler : public QWidget { @@ -77,10 +78,16 @@ private: double scale_; - rational time_base_; + rational timebase_; + + double timebase_dbl_; + + double timebase_flipped_dbl_; int64_t time_; + TimelinePlayhead style_; + }; #endif // TIMERULER_H