timeruler more or less done
This commit is contained in:
@@ -6,19 +6,47 @@ QString padded(int arg, int padding) {
|
|||||||
return QString("%1").arg(arg, padding, 10, QChar('0'));
|
return QString("%1").arg(arg, padding, 10, QChar('0'));
|
||||||
}
|
}
|
||||||
|
|
||||||
QString olive::timestamp_to_timecode(const rational ×tamp)
|
QString olive::timestamp_to_timecode(const rational& timestamp,
|
||||||
|
const rational& timebase,
|
||||||
|
const TimecodeDisplay& display)
|
||||||
{
|
{
|
||||||
double timestamp_dbl = timestamp.ToDouble();
|
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),
|
switch (display) {
|
||||||
padded(mins, 2),
|
case kTimecodeFrames:
|
||||||
padded(secs, 2),
|
case kTimecodeSeconds:
|
||||||
padded(fraction, 3));
|
{
|
||||||
|
int total_seconds = qFloor(timestamp_dbl);
|
||||||
|
|
||||||
|
int hours = total_seconds / 3600;
|
||||||
|
int mins = total_seconds / 60 - hours * 60;
|
||||||
|
int secs = total_seconds - mins * 60;
|
||||||
|
|
||||||
|
if (display == kTimecodeSeconds) {
|
||||||
|
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));
|
||||||
|
} else {
|
||||||
|
rational frame_rate = timebase.flipped();
|
||||||
|
|
||||||
|
int frames = qRound((timestamp_dbl - total_seconds) * frame_rate.ToDouble());
|
||||||
|
|
||||||
|
return QString("%1:%2:%3;%4").arg(padded(hours, 2),
|
||||||
|
padded(mins, 2),
|
||||||
|
padded(secs, 2),
|
||||||
|
padded(frames, 2));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case kFrames:
|
||||||
|
return QString::number(timestamp.numerator() / timebase.numerator());
|
||||||
|
case kMilliseconds:
|
||||||
|
return QString::number(qFloor(timestamp_dbl * 1000));
|
||||||
|
}
|
||||||
|
|
||||||
|
return QString();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,7 +7,14 @@
|
|||||||
|
|
||||||
namespace olive {
|
namespace olive {
|
||||||
|
|
||||||
QString timestamp_to_timecode(const rational& timestamp);
|
enum TimecodeDisplay {
|
||||||
|
kTimecodeFrames,
|
||||||
|
kTimecodeSeconds,
|
||||||
|
kFrames,
|
||||||
|
kMilliseconds
|
||||||
|
};
|
||||||
|
|
||||||
|
QString timestamp_to_timecode(const rational& timestamp, const rational& timebase, const TimecodeDisplay& display);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -23,10 +23,12 @@
|
|||||||
#include <QHBoxLayout>
|
#include <QHBoxLayout>
|
||||||
#include <QPushButton>
|
#include <QPushButton>
|
||||||
|
|
||||||
|
#include "common/timecodefunctions.h"
|
||||||
#include "ui/icons/icons.h"
|
#include "ui/icons/icons.h"
|
||||||
|
|
||||||
PlaybackControls::PlaybackControls(QWidget *parent) :
|
PlaybackControls::PlaybackControls(QWidget *parent) :
|
||||||
QWidget(parent)
|
QWidget(parent),
|
||||||
|
time_base_(0)
|
||||||
{
|
{
|
||||||
// Create lower controls
|
// Create lower controls
|
||||||
QHBoxLayout* lower_control_layout = new QHBoxLayout(this);
|
QHBoxLayout* lower_control_layout = new QHBoxLayout(this);
|
||||||
@@ -45,7 +47,7 @@ PlaybackControls::PlaybackControls(QWidget *parent) :
|
|||||||
lower_left_layout->setSpacing(0);
|
lower_left_layout->setSpacing(0);
|
||||||
lower_left_layout->setMargin(0);
|
lower_left_layout->setMargin(0);
|
||||||
|
|
||||||
cur_tc_lbl_ = new QLabel("00:00:00;00");
|
cur_tc_lbl_ = new QLabel();
|
||||||
lower_left_layout->addWidget(cur_tc_lbl_);
|
lower_left_layout->addWidget(cur_tc_lbl_);
|
||||||
lower_left_layout->addStretch();
|
lower_left_layout->addStretch();
|
||||||
|
|
||||||
@@ -112,3 +114,15 @@ void PlaybackControls::SetTimecodeEnabled(bool enabled)
|
|||||||
lower_left_container_->setVisible(enabled);
|
lower_left_container_->setVisible(enabled);
|
||||||
lower_right_container_->setVisible(enabled);
|
lower_right_container_->setVisible(enabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PlaybackControls::SetTimebase(const rational &r)
|
||||||
|
{
|
||||||
|
time_base_ = r;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PlaybackControls::SetTime(const rational &r)
|
||||||
|
{
|
||||||
|
Q_ASSERT(time_base_.denominator() != 0);
|
||||||
|
|
||||||
|
cur_tc_lbl_->setText(olive::timestamp_to_timecode(r, time_base_, olive::kTimecodeFrames));
|
||||||
|
}
|
||||||
|
|||||||
@@ -24,6 +24,8 @@
|
|||||||
#include <QWidget>
|
#include <QWidget>
|
||||||
#include <QLabel>
|
#include <QLabel>
|
||||||
|
|
||||||
|
#include "common/rational.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief A playback controls widget providing buttons for navigating media
|
* @brief A playback controls widget providing buttons for navigating media
|
||||||
*
|
*
|
||||||
@@ -40,6 +42,11 @@ public:
|
|||||||
*/
|
*/
|
||||||
void SetTimecodeEnabled(bool enabled);
|
void SetTimecodeEnabled(bool enabled);
|
||||||
|
|
||||||
|
void SetTimebase(const rational& r);
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
void SetTime(const rational& r);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
/**
|
/**
|
||||||
* @brief Signal emitted when "Go to Start" is clicked
|
* @brief Signal emitted when "Go to Start" is clicked
|
||||||
@@ -72,6 +79,8 @@ private:
|
|||||||
|
|
||||||
QLabel* cur_tc_lbl_;
|
QLabel* cur_tc_lbl_;
|
||||||
QLabel* end_tc_lbl_;
|
QLabel* end_tc_lbl_;
|
||||||
|
|
||||||
|
rational time_base_;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // PLAYBACKCONTROLS_H
|
#endif // PLAYBACKCONTROLS_H
|
||||||
|
|||||||
@@ -26,12 +26,11 @@ TimeRuler::TimeRuler(bool text_visible, QWidget* parent) :
|
|||||||
// Mediocre but reliable way of scaling UI objects by font/DPI size
|
// Mediocre but reliable way of scaling UI objects by font/DPI size
|
||||||
minimum_gap_between_lines_ = QFontMetricsWidth(&fm, "H");
|
minimum_gap_between_lines_ = QFontMetricsWidth(&fm, "H");
|
||||||
|
|
||||||
|
// Set width of playhead marker
|
||||||
|
playhead_width_ = minimum_gap_between_lines_;
|
||||||
|
|
||||||
// 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
|
|
||||||
SetTimebase(rational(1001, 30000));
|
|
||||||
// END TEST CODE
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void TimeRuler::SetTextVisible(bool e)
|
void TimeRuler::SetTextVisible(bool e)
|
||||||
@@ -107,8 +106,10 @@ void TimeRuler::paintEvent(QPaintEvent *e)
|
|||||||
qreal real_divider = qMax(1.0, time_base_.flipped().ToDouble() / reverse_divider);
|
qreal real_divider = qMax(1.0, time_base_.flipped().ToDouble() / reverse_divider);
|
||||||
|
|
||||||
// Set where the loop ends (affected by text)
|
// Set where the loop ends (affected by text)
|
||||||
int loop_start = -1;
|
int loop_start = - playhead_width_;
|
||||||
int loop_end = width();
|
int loop_end = width() + playhead_width_;
|
||||||
|
|
||||||
|
olive::TimecodeDisplay display_type = olive::kTimecodeSeconds;
|
||||||
|
|
||||||
// Determine where it can draw text
|
// Determine where it can draw text
|
||||||
int text_skip = 1;
|
int text_skip = 1;
|
||||||
@@ -117,7 +118,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, olive::timestamp_to_timecode(0));
|
int average_text_width = QFontMetricsWidth(&fm, olive::timestamp_to_timecode(0, time_base_, display_type));
|
||||||
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++;
|
||||||
@@ -170,7 +171,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 = olive::timestamp_to_timecode(sec);
|
QString timecode_string = olive::timestamp_to_timecode(sec, time_base_, display_type);
|
||||||
|
|
||||||
int text_x = i;
|
int text_x = i;
|
||||||
|
|
||||||
@@ -199,6 +200,7 @@ void TimeRuler::paintEvent(QPaintEvent *e)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If we found the playhead along here, draw it last
|
||||||
if (playhead_pos >= 0) {
|
if (playhead_pos >= 0) {
|
||||||
p.setPen(Qt::NoPen);
|
p.setPen(Qt::NoPen);
|
||||||
p.setBrush(Qt::red);
|
p.setBrush(Qt::red);
|
||||||
@@ -223,14 +225,14 @@ void TimeRuler::DrawPlayhead(QPainter *p, int x, int y)
|
|||||||
p->setRenderHint(QPainter::Antialiasing);
|
p->setRenderHint(QPainter::Antialiasing);
|
||||||
|
|
||||||
int half_text_height = text_height_ / 3;
|
int half_text_height = text_height_ / 3;
|
||||||
int half_gap = minimum_gap_between_lines_ / 2;
|
int half_width = playhead_width_ / 2;
|
||||||
|
|
||||||
QPoint points[] = {
|
QPoint points[] = {
|
||||||
QPoint(x, y),
|
QPoint(x, y),
|
||||||
QPoint(x - half_gap, y - half_text_height),
|
QPoint(x - half_width, y - half_text_height),
|
||||||
QPoint(x - half_gap, y - text_height_),
|
QPoint(x - half_width, y - text_height_),
|
||||||
QPoint(x + half_gap, y - text_height_),
|
QPoint(x + half_width, y - text_height_),
|
||||||
QPoint(x + half_gap, y - half_text_height)
|
QPoint(x + half_width, y - half_text_height)
|
||||||
};
|
};
|
||||||
|
|
||||||
p->drawPolygon(points, 5);
|
p->drawPolygon(points, 5);
|
||||||
|
|||||||
@@ -47,6 +47,8 @@ private:
|
|||||||
|
|
||||||
int minimum_gap_between_lines_;
|
int minimum_gap_between_lines_;
|
||||||
|
|
||||||
|
int playhead_width_;
|
||||||
|
|
||||||
int scroll_;
|
int scroll_;
|
||||||
|
|
||||||
bool text_visible_;
|
bool text_visible_;
|
||||||
|
|||||||
@@ -20,8 +20,9 @@
|
|||||||
|
|
||||||
#include "viewer.h"
|
#include "viewer.h"
|
||||||
|
|
||||||
#include <QVBoxLayout>
|
|
||||||
#include <QLabel>
|
#include <QLabel>
|
||||||
|
#include <QResizeEvent>
|
||||||
|
#include <QVBoxLayout>
|
||||||
|
|
||||||
ViewerWidget::ViewerWidget(QWidget *parent) :
|
ViewerWidget::ViewerWidget(QWidget *parent) :
|
||||||
QWidget(parent)
|
QWidget(parent)
|
||||||
@@ -38,6 +39,13 @@ ViewerWidget::ViewerWidget(QWidget *parent) :
|
|||||||
// Create time ruler
|
// Create time ruler
|
||||||
ruler_ = new TimeRuler(false, this);
|
ruler_ = new TimeRuler(false, this);
|
||||||
layout->addWidget(ruler_);
|
layout->addWidget(ruler_);
|
||||||
|
connect(ruler_, SIGNAL(TimeChanged(int64_t)), this, SLOT(RulerTimeChange(int64_t)));
|
||||||
|
|
||||||
|
// Create scrollbar
|
||||||
|
scrollbar_ = new QScrollBar(Qt::Horizontal, this);
|
||||||
|
layout->addWidget(scrollbar_);
|
||||||
|
connect(scrollbar_, SIGNAL(valueChanged(int)), ruler_, SLOT(SetScroll(int)));
|
||||||
|
scrollbar_->setPageStep(ruler_->width());
|
||||||
|
|
||||||
// Create lower controls
|
// Create lower controls
|
||||||
controls_ = new PlaybackControls(this);
|
controls_ = new PlaybackControls(this);
|
||||||
@@ -46,16 +54,34 @@ ViewerWidget::ViewerWidget(QWidget *parent) :
|
|||||||
layout->addWidget(controls_);
|
layout->addWidget(controls_);
|
||||||
|
|
||||||
// FIXME: Test code
|
// FIXME: Test code
|
||||||
connect(controls_, SIGNAL(PlayClicked()), this, SLOT(TemporaryTestFunction()));
|
SetTimebase(rational(1001, 30000));
|
||||||
// End test code
|
// End test code
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ViewerWidget::SetTimebase(const rational &r)
|
||||||
|
{
|
||||||
|
time_base_ = r;
|
||||||
|
|
||||||
|
ruler_->SetTimebase(r);
|
||||||
|
controls_->SetTimebase(r);
|
||||||
|
}
|
||||||
|
|
||||||
void ViewerWidget::SetTexture(GLuint tex)
|
void ViewerWidget::SetTexture(GLuint tex)
|
||||||
{
|
{
|
||||||
gl_widget_->SetTexture(tex);
|
gl_widget_->SetTexture(tex);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ViewerWidget::TemporaryTestFunction()
|
void ViewerWidget::RulerTimeChange(int64_t i)
|
||||||
{
|
{
|
||||||
emit TimeChanged(69);
|
rational time_set = rational(i, 1) * time_base_;
|
||||||
|
|
||||||
|
controls_->SetTime(time_set);
|
||||||
|
|
||||||
|
emit TimeChanged(time_set);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ViewerWidget::resizeEvent(QResizeEvent *event)
|
||||||
|
{
|
||||||
|
// Set scrollbar page step to the width
|
||||||
|
scrollbar_->setPageStep(event->size().width());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,9 +21,10 @@
|
|||||||
#ifndef VIEWER_WIDGET_H
|
#ifndef VIEWER_WIDGET_H
|
||||||
#define VIEWER_WIDGET_H
|
#define VIEWER_WIDGET_H
|
||||||
|
|
||||||
#include <QWidget>
|
|
||||||
#include <QPushButton>
|
|
||||||
#include <QLabel>
|
#include <QLabel>
|
||||||
|
#include <QPushButton>
|
||||||
|
#include <QScrollBar>
|
||||||
|
#include <QWidget>
|
||||||
|
|
||||||
#include "common/rational.h"
|
#include "common/rational.h"
|
||||||
#include "viewerglwidget.h"
|
#include "viewerglwidget.h"
|
||||||
@@ -43,6 +44,8 @@ public:
|
|||||||
|
|
||||||
void SetTimeRulerEnabled(bool enabled);
|
void SetTimeRulerEnabled(bool enabled);
|
||||||
|
|
||||||
|
void SetTimebase(const rational& r);
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
/**
|
/**
|
||||||
* @brief Set the texture to draw and draw it
|
* @brief Set the texture to draw and draw it
|
||||||
@@ -56,6 +59,9 @@ public slots:
|
|||||||
signals:
|
signals:
|
||||||
void TimeChanged(const rational&);
|
void TimeChanged(const rational&);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual void resizeEvent(QResizeEvent *event) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ViewerGLWidget* gl_widget_;
|
ViewerGLWidget* gl_widget_;
|
||||||
|
|
||||||
@@ -63,8 +69,12 @@ private:
|
|||||||
|
|
||||||
TimeRuler* ruler_;
|
TimeRuler* ruler_;
|
||||||
|
|
||||||
|
QScrollBar* scrollbar_;
|
||||||
|
|
||||||
|
rational time_base_;
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void TemporaryTestFunction();
|
void RulerTimeChange(int64_t i);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // VIEWER_WIDGET_H
|
#endif // VIEWER_WIDGET_H
|
||||||
|
|||||||
Reference in New Issue
Block a user