time ruler interactivity

This commit is contained in:
itsmattkc
2019-07-24 21:46:28 -07:00
parent 705ecc0910
commit 3564e71c1c
7 changed files with 113 additions and 59 deletions
+2
View File
@@ -24,5 +24,7 @@ set(OLIVE_SOURCES
common/qobjectlistcast.h common/qobjectlistcast.h
common/qtversionabstraction.h common/qtversionabstraction.h
common/qtversionabstraction.cpp common/qtversionabstraction.cpp
common/timecodefunctions.h
common/timecodefunctions.cpp
PARENT_SCOPE PARENT_SCOPE
) )
+22
View File
@@ -1,2 +1,24 @@
#include "timecodefunctions.h" #include "timecodefunctions.h"
#include <QtMath>
QString padded(int arg, int padding) {
return QString("%1").arg(arg, padding, 10, QChar('0'));
}
QString olive::timestamp_to_timecode(const rational &timestamp)
{
double timestamp_dbl = timestamp.ToDouble();
int total_seconds = qFloor(timestamp_dbl);
int hours = total_seconds / 3600;
int mins = total_seconds / 60 - hours * 60;
int secs = total_seconds - mins * 60;
int fraction = qRound((timestamp_dbl - total_seconds) * 1000);
return QString("%1:%2:%3.%4").arg(padded(hours, 2),
padded(mins, 2),
padded(secs, 2),
padded(fraction, 3));
}
+8
View File
@@ -1,6 +1,14 @@
#ifndef TIMECODEFUNCTIONS_H #ifndef TIMECODEFUNCTIONS_H
#define TIMECODEFUNCTIONS_H #define TIMECODEFUNCTIONS_H
#include <QString>
#include "common/rational.h"
namespace olive {
QString timestamp_to_timecode(const rational& timestamp);
}
#endif // TIMECODEFUNCTIONS_H #endif // TIMECODEFUNCTIONS_H
+58 -52
View File
@@ -1,19 +1,24 @@
#include "timeruler.h" #include "timeruler.h"
#include <QDebug> #include <QDebug>
#include <QMouseEvent>
#include <QPainter> #include <QPainter>
#include <QtMath> #include <QtMath>
#include "common/timecodefunctions.h"
#include "common/qtversionabstraction.h" #include "common/qtversionabstraction.h"
TimeRuler::TimeRuler(bool text_visible, QWidget* parent) : TimeRuler::TimeRuler(bool text_visible, QWidget* parent) :
QWidget(parent), QWidget(parent),
scroll_(0), scroll_(0),
centered_text_(true), centered_text_(true),
scale_(16.0) scale_(16.0),
time_(0)
{ {
QFontMetrics fm = fontMetrics(); QFontMetrics fm = fontMetrics();
setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Maximum);
// Text height is used to calculate widget height // Text height is used to calculate widget height
text_height_ = fm.height(); text_height_ = fm.height();
@@ -24,12 +29,9 @@ TimeRuler::TimeRuler(bool text_visible, QWidget* parent) :
// Text visibility affects height, so we set that here // Text visibility affects height, so we set that here
SetTextVisible(text_visible); SetTextVisible(text_visible);
// FIXME: Test code // FIXME: TEST CODE
time_base_ = rational(1001, 30000); SetTimebase(rational(1001, 30000));
connect(&test_timer_, SIGNAL(timeout()), this, SLOT(TimeOut())); // END TEST CODE
test_timer_.setInterval(20);
test_timer_.start();
// End test code
} }
void TimeRuler::SetTextVisible(bool e) void TimeRuler::SetTextVisible(bool e)
@@ -61,6 +63,13 @@ void TimeRuler::SetTimebase(const rational &r)
update(); update();
} }
void TimeRuler::SetTime(const int64_t &r)
{
time_ = r;
update();
}
void TimeRuler::SetScroll(int s) void TimeRuler::SetScroll(int s)
{ {
scroll_ = s; scroll_ = s;
@@ -79,31 +88,10 @@ void TimeRuler::paintEvent(QPaintEvent *e)
QPainter p(this); QPainter p(this);
int last_unit = -1; int64_t last_unit = -1;
int last_sec = -1; int last_sec = -1;
/*
// Test code that draws a line every single time unit
for (int i=0;i<width();i++) {
int unit = qFloor((i + scroll_) / scale_);
int sec = qFloor(unit * time_base_.ToDouble());
if (unit > last_unit) { // Depending on the scale, we don't need all the lines drawn or else they'll start to become unhelpful
if (sec > last_sec) {
p.setPen(Qt::red);
last_sec = sec;
} else {
p.setPen(Qt::white);
}
p.drawLine(i, height()/2, i, height());
last_unit = unit;
}
}
*/
// Depending on the scale,
// Determine an even number to divide the frame count by // 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(time_base_.flipped().ToDouble());
int test_divider = 1; int test_divider = 1;
@@ -129,7 +117,7 @@ void TimeRuler::paintEvent(QPaintEvent *e)
if (text_visible_) { if (text_visible_) {
QFontMetrics fm = p.fontMetrics(); QFontMetrics fm = p.fontMetrics();
double width_of_second = time_base_.flipped().ToDouble() * scale_; double width_of_second = time_base_.flipped().ToDouble() * scale_;
int average_text_width = QFontMetricsWidth(&fm, "00:00:00;00"); // FIXME: Hardcoded string int average_text_width = QFontMetricsWidth(&fm, olive::timestamp_to_timecode(0));
half_average_text_width = average_text_width/2; half_average_text_width = average_text_width/2;
while (width_of_second * text_skip < average_text_width) { while (width_of_second * text_skip < average_text_width) {
text_skip++; text_skip++;
@@ -146,6 +134,7 @@ void TimeRuler::paintEvent(QPaintEvent *e)
} }
// Set line color to main text color // Set line color to main text color
p.setBrush(Qt::NoBrush);
p.setPen(palette().text().color()); p.setPen(palette().text().color());
// Calculate where each line starts // Calculate where each line starts
@@ -157,14 +146,21 @@ void TimeRuler::paintEvent(QPaintEvent *e)
int line_halfsec_bottom = line_top + line_length / 3 * 2; int line_halfsec_bottom = line_top + line_length / 3 * 2;
int line_frame_bottom = line_top + line_length / 3; int line_frame_bottom = line_top + line_length / 3;
int playhead_pos = -1;
for (int i=loop_start;i<loop_end;i++) { for (int i=loop_start;i<loop_end;i++) {
int unit = qFloor((i + scroll_) / scale_); int64_t unit = ScreenToUnit(i);
// Queue a playhead draw
if (unit == time_ && playhead_pos == -1) {
playhead_pos = i;
}
// Check if enough space has passed since the last line drawn // Check if enough space has passed since the last line drawn
if (qFloor(unit/real_divider) > qFloor(last_unit/real_divider)) { if (qFloor(double(unit)/real_divider) > qFloor(double(last_unit)/real_divider)) {
// Determine if this unit is a whole second or not // Determine if this unit is a whole second or not
int sec = qFloor(unit * time_base_.ToDouble()); int sec = qFloor(double(unit) * time_base_.ToDouble());
if (sec > last_sec) { if (sec > last_sec) {
// This line marks a second so we make it long // This line marks a second so we make it long
@@ -174,7 +170,7 @@ void TimeRuler::paintEvent(QPaintEvent *e)
// Try to draw text here // Try to draw text here
if (text_visible_ && sec%text_skip == 0) { if (text_visible_ && sec%text_skip == 0) {
QString timecode_string = QString("00:00:%1;00").arg(sec, 2, 10, QChar('0')); QString timecode_string = olive::timestamp_to_timecode(sec);
int text_x = i; int text_x = i;
@@ -203,9 +199,23 @@ void TimeRuler::paintEvent(QPaintEvent *e)
} }
} }
p.setPen(Qt::NoPen); if (playhead_pos >= 0) {
p.setBrush(Qt::red); p.setPen(Qt::NoPen);
DrawPlayhead(&p, 100, height()); p.setBrush(Qt::red);
DrawPlayhead(&p, playhead_pos, height());
}
}
void TimeRuler::mousePressEvent(QMouseEvent *event)
{
SeekToScreenPoint(event->pos().x());
}
void TimeRuler::mouseMoveEvent(QMouseEvent *event)
{
if (event->buttons() & Qt::LeftButton) {
SeekToScreenPoint(event->pos().x());
}
} }
void TimeRuler::DrawPlayhead(QPainter *p, int x, int y) void TimeRuler::DrawPlayhead(QPainter *p, int x, int y)
@@ -226,25 +236,21 @@ void TimeRuler::DrawPlayhead(QPainter *p, int x, int y)
p->drawPolygon(points, 5); p->drawPolygon(points, 5);
} }
double TimeRuler::UnitToScreen(const int &u) double TimeRuler::ScreenToUnitFloat(int screen)
{ {
return u * scale_; return (screen + scroll_) / scale_;
} }
int TimeRuler::ScreenToUnit(const int &p) int64_t TimeRuler::ScreenToUnit(int screen)
{ {
double uf = p / scale_; return qFloor(ScreenToUnitFloat(screen));
int u = qRound(uf);
if (qFuzzyCompare(UnitToScreen(u), uf)) {
return u;
}
return -1;
} }
void TimeRuler::TimeOut() void TimeRuler::SeekToScreenPoint(int screen)
{ {
SetScroll(scroll_ + 2); int64_t timestamp = qMax(0, qRound(ScreenToUnitFloat(screen)));
SetTime(timestamp);
emit TimeChanged(timestamp);
} }
+13 -7
View File
@@ -20,18 +20,28 @@ public:
void SetCenteredText(bool c); void SetCenteredText(bool c);
void SetTime(const int64_t &r);
public slots: public slots:
void SetScroll(int s); void SetScroll(int s);
protected: protected:
virtual void paintEvent(QPaintEvent* e) override; virtual void paintEvent(QPaintEvent* e) override;
virtual void mousePressEvent(QMouseEvent *event) override;
virtual void mouseMoveEvent(QMouseEvent *event) override;
signals:
void TimeChanged(int64_t);
private: private:
void DrawPlayhead(QPainter* p, int x, int y); void DrawPlayhead(QPainter* p, int x, int y);
double UnitToScreen(const int& u); double ScreenToUnitFloat(int screen);
int ScreenToUnit(const int& p); int64_t ScreenToUnit(int screen);
void SeekToScreenPoint(int screen);
int text_height_; int text_height_;
@@ -47,12 +57,8 @@ private:
rational time_base_; rational time_base_;
// FIXME: Test code only int64_t time_;
QTimer test_timer_;
private slots:
void TimeOut();
// End test code
}; };
#endif // TIMERULER_H #endif // TIMERULER_H
+4
View File
@@ -35,6 +35,10 @@ ViewerWidget::ViewerWidget(QWidget *parent) :
gl_widget_ = new ViewerGLWidget(this); gl_widget_ = new ViewerGLWidget(this);
layout->addWidget(gl_widget_); layout->addWidget(gl_widget_);
// Create time ruler
ruler_ = new TimeRuler(false, this);
layout->addWidget(ruler_);
// Create lower controls // Create lower controls
controls_ = new PlaybackControls(this); controls_ = new PlaybackControls(this);
controls_->SetTimecodeEnabled(true); controls_->SetTimecodeEnabled(true);
+6
View File
@@ -28,6 +28,7 @@
#include "common/rational.h" #include "common/rational.h"
#include "viewerglwidget.h" #include "viewerglwidget.h"
#include "widget/playbackcontrols/playbackcontrols.h" #include "widget/playbackcontrols/playbackcontrols.h"
#include "widget/timeruler/timeruler.h"
/** /**
* @brief An OpenGL-based viewer widget with playback controls (a PlaybackControls widget). * @brief An OpenGL-based viewer widget with playback controls (a PlaybackControls widget).
@@ -40,6 +41,8 @@ public:
void SetPlaybackControlsEnabled(bool enabled); void SetPlaybackControlsEnabled(bool enabled);
void SetTimeRulerEnabled(bool enabled);
public slots: public slots:
/** /**
* @brief Set the texture to draw and draw it * @brief Set the texture to draw and draw it
@@ -55,8 +58,11 @@ signals:
private: private:
ViewerGLWidget* gl_widget_; ViewerGLWidget* gl_widget_;
PlaybackControls* controls_; PlaybackControls* controls_;
TimeRuler* ruler_;
private slots: private slots:
void TemporaryTestFunction(); void TemporaryTestFunction();
}; };