waveformview: show in/out points in waveformview
Moved drawing routines to the base class that is used by both TimeRuler and WaveformView
This commit is contained in:
@@ -26,6 +26,11 @@ const uint64_t &AudioParams::channel_layout() const
|
||||
return channel_layout_;
|
||||
}
|
||||
|
||||
rational AudioParams::time_base() const
|
||||
{
|
||||
return rational(1, sample_rate());
|
||||
}
|
||||
|
||||
AudioRenderingParams::AudioRenderingParams() :
|
||||
format_(SampleFormat::SAMPLE_FMT_INVALID)
|
||||
{
|
||||
|
||||
@@ -14,6 +14,7 @@ public:
|
||||
|
||||
const int& sample_rate() const;
|
||||
const uint64_t& channel_layout() const;
|
||||
rational time_base() const;
|
||||
|
||||
private:
|
||||
int sample_rate_;
|
||||
|
||||
@@ -62,13 +62,13 @@ void TimeBasedWidget::ConnectViewerNode(ViewerOutput *node)
|
||||
ConnectedNodeChanged(viewer_node_);
|
||||
|
||||
if (viewer_node_) {
|
||||
ConnectNodeInternal(viewer_node_);
|
||||
|
||||
connect(viewer_node_, &ViewerOutput::LengthChanged, this, &TimeBasedWidget::UpdateMaximumScroll);
|
||||
|
||||
if ((points_ = ConnectTimelinePoints())) {
|
||||
ruler()->ConnectTimelinePoints(points_);
|
||||
}
|
||||
|
||||
ConnectNodeInternal(viewer_node_);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -152,6 +152,11 @@ TimelinePoints *TimeBasedWidget::ConnectTimelinePoints()
|
||||
return static_cast<Sequence*>(viewer_node_->parent());
|
||||
}
|
||||
|
||||
TimelinePoints *TimeBasedWidget::GetConnectedTimelinePoints() const
|
||||
{
|
||||
return points_;
|
||||
}
|
||||
|
||||
void TimeBasedWidget::SetTime(int64_t timestamp)
|
||||
{
|
||||
ruler_->SetTime(timestamp);
|
||||
|
||||
@@ -87,6 +87,8 @@ protected:
|
||||
|
||||
virtual TimelinePoints* ConnectTimelinePoints();
|
||||
|
||||
TimelinePoints* GetConnectedTimelinePoints() const;
|
||||
|
||||
protected slots:
|
||||
/**
|
||||
* @brief Slot to center the horizontal scroll bar on the playhead's current position
|
||||
|
||||
@@ -1,15 +1,23 @@
|
||||
#include "seekablewidget.h"
|
||||
|
||||
#include <QMouseEvent>
|
||||
#include <QPainter>
|
||||
#include <QtMath>
|
||||
|
||||
#include "common/qtutils.h"
|
||||
|
||||
SeekableWidget::SeekableWidget(QWidget* parent) :
|
||||
TimelineScaledWidget(parent),
|
||||
time_(0),
|
||||
timeline_points_(nullptr),
|
||||
scroll_(0)
|
||||
{
|
||||
QFontMetrics fm = fontMetrics();
|
||||
|
||||
text_height_ = fm.height();
|
||||
|
||||
// Set width of playhead marker
|
||||
playhead_width_ = QFontMetricsWidth(fm, "H");
|
||||
}
|
||||
|
||||
void SeekableWidget::ConnectTimelinePoints(TimelinePoints *points)
|
||||
@@ -108,3 +116,86 @@ void SeekableWidget::SeekToScreenPoint(int screen)
|
||||
|
||||
emit TimeChanged(timestamp);
|
||||
}
|
||||
|
||||
void SeekableWidget::DrawTimelinePoints(QPainter* p, int marker_bottom)
|
||||
{
|
||||
if (!timeline_points()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Draw in/out workarea
|
||||
if (timeline_points()->workarea()->enabled()) {
|
||||
int workarea_left = qMax(0, TimeToScreen(timeline_points()->workarea()->in()));
|
||||
int workarea_right;
|
||||
|
||||
if (timeline_points()->workarea()->out() == TimelineWorkArea::kResetOut) {
|
||||
workarea_right = width();
|
||||
} else {
|
||||
workarea_right = qMin(width(), TimeToScreen(timeline_points()->workarea()->out()));
|
||||
}
|
||||
|
||||
p->fillRect(workarea_left, 0, workarea_right - workarea_left, height(), palette().highlight());
|
||||
}
|
||||
|
||||
// Draw markers
|
||||
if (marker_bottom > 0 && !timeline_points()->markers()->list().isEmpty()) {
|
||||
|
||||
int marker_top = marker_bottom - text_height_;
|
||||
|
||||
// FIXME: Hardcoded marker colors
|
||||
p->setPen(Qt::black);
|
||||
p->setBrush(Qt::green);
|
||||
|
||||
foreach (TimelineMarker* marker, timeline_points()->markers()->list()) {
|
||||
int marker_left = TimeToScreen(marker->time().in());
|
||||
int marker_right = TimeToScreen(marker->time().out());
|
||||
|
||||
if (marker_left >= width() || marker_right < 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (marker->time().length() == 0) {
|
||||
// Single point in time marker
|
||||
DrawPlayhead(p, marker_left, marker_bottom);
|
||||
} else {
|
||||
// Marker range
|
||||
int rect_left = qMax(0, marker_left);
|
||||
int rect_right = qMin(width(), marker_right);
|
||||
|
||||
QRect marker_rect(rect_left, marker_top, rect_right - rect_left, marker_bottom - marker_top);
|
||||
|
||||
p->drawRect(marker_rect);
|
||||
|
||||
if (!marker->name().isEmpty()) {
|
||||
p->drawText(marker_rect, marker->name());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SeekableWidget::DrawPlayhead(QPainter *p, int x, int y)
|
||||
{
|
||||
int half_width = playhead_width_ / 2;
|
||||
|
||||
if (x + half_width < 0 || x - half_width > width()) {
|
||||
return;
|
||||
}
|
||||
|
||||
p->setRenderHint(QPainter::Antialiasing);
|
||||
|
||||
int half_text_height = text_height() / 3;
|
||||
|
||||
QPoint points[] = {
|
||||
QPoint(x, y),
|
||||
QPoint(x - half_width, y - half_text_height),
|
||||
QPoint(x - half_width, y - 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, 6);
|
||||
|
||||
p->setRenderHint(QPainter::Antialiasing, false);
|
||||
}
|
||||
|
||||
@@ -31,6 +31,8 @@ protected:
|
||||
|
||||
virtual void ScaleChangedEvent(const double&) override;
|
||||
|
||||
void DrawTimelinePoints(QPainter *p, int marker_bottom = 0);
|
||||
|
||||
TimelinePoints* timeline_points() const;
|
||||
|
||||
double ScreenToUnitFloat(int screen);
|
||||
@@ -42,6 +44,16 @@ protected:
|
||||
|
||||
int TimeToScreen(const rational& time);
|
||||
|
||||
void DrawPlayhead(QPainter* p, int x, int y);
|
||||
|
||||
inline const int& text_height() const {
|
||||
return text_height_;
|
||||
}
|
||||
|
||||
inline const int& playhead_width() const {
|
||||
return playhead_width_;
|
||||
}
|
||||
|
||||
inline const QColor& GetPlayheadColor() const
|
||||
{
|
||||
return style_.GetPlayheadColor();
|
||||
@@ -67,6 +79,10 @@ private:
|
||||
|
||||
int scroll_;
|
||||
|
||||
int text_height_;
|
||||
|
||||
int playhead_width_;
|
||||
|
||||
};
|
||||
|
||||
#endif // SEEKABLEWIDGET_H
|
||||
|
||||
@@ -39,16 +39,12 @@ TimeRuler::TimeRuler(bool text_visible, bool cache_status_visible, QWidget* pare
|
||||
setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Maximum);
|
||||
|
||||
// Text height is used to calculate widget height
|
||||
text_height_ = fm.height();
|
||||
cache_status_height_ = text_height_ / 4;
|
||||
cache_status_height_ = text_height() / 4;
|
||||
|
||||
// Get the "minimum" space allowed between two line markers on the ruler (in screen pixels)
|
||||
// Mediocre but reliable way of scaling UI objects by font/DPI size
|
||||
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
|
||||
UpdateHeight();
|
||||
}
|
||||
@@ -93,65 +89,17 @@ void TimeRuler::paintEvent(QPaintEvent *)
|
||||
|
||||
// Draw timeline points if connected
|
||||
if (timeline_points()) {
|
||||
int marker_bottom = height() - text_height();
|
||||
|
||||
// Draw in/out workarea
|
||||
if (timeline_points()->workarea()->enabled()) {
|
||||
int workarea_left = qMax(0, TimeToScreen(timeline_points()->workarea()->in()));
|
||||
int workarea_right;
|
||||
|
||||
if (timeline_points()->workarea()->out() == TimelineWorkArea::kResetOut) {
|
||||
workarea_right = width();
|
||||
} else {
|
||||
workarea_right = qMin(width(), TimeToScreen(timeline_points()->workarea()->out()));
|
||||
}
|
||||
|
||||
p.fillRect(workarea_left, 0, workarea_right - workarea_left, height(), palette().highlight());
|
||||
if (show_cache_status_) {
|
||||
marker_bottom -= cache_status_height_;
|
||||
}
|
||||
|
||||
// Draw markers
|
||||
if (!timeline_points()->markers()->list().isEmpty()) {
|
||||
int marker_bottom = height() - text_height_;
|
||||
|
||||
if (show_cache_status_) {
|
||||
marker_bottom -= cache_status_height_;
|
||||
}
|
||||
|
||||
if (text_visible_) {
|
||||
marker_bottom -= cache_status_height_;
|
||||
}
|
||||
|
||||
int marker_top = marker_bottom - text_height_;
|
||||
|
||||
// FIXME: Hardcoded marker colors
|
||||
p.setPen(Qt::black);
|
||||
p.setBrush(Qt::green);
|
||||
|
||||
foreach (TimelineMarker* marker, timeline_points()->markers()->list()) {
|
||||
int marker_left = TimeToScreen(marker->time().in());
|
||||
int marker_right = TimeToScreen(marker->time().out());
|
||||
|
||||
if (marker_left >= width() || marker_right < 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (marker->time().length() == 0) {
|
||||
// Single point in time marker
|
||||
DrawPlayhead(&p, marker_left, marker_bottom);
|
||||
} else {
|
||||
// Marker range
|
||||
int rect_left = qMax(0, marker_left);
|
||||
int rect_right = qMin(width(), marker_right);
|
||||
|
||||
QRect marker_rect(rect_left, marker_top, rect_right - rect_left, marker_bottom - marker_top);
|
||||
|
||||
p.drawRect(marker_rect);
|
||||
|
||||
if (!marker->name().isEmpty()) {
|
||||
p.drawText(marker_rect, marker->name());
|
||||
}
|
||||
}
|
||||
}
|
||||
if (text_visible_) {
|
||||
marker_bottom -= cache_status_height_;
|
||||
}
|
||||
|
||||
DrawTimelinePoints(&p, marker_bottom);
|
||||
}
|
||||
|
||||
double width_of_frame = timebase_dbl() * GetScale();
|
||||
@@ -325,11 +273,9 @@ void TimeRuler::paintEvent(QPaintEvent *)
|
||||
|
||||
// Draw the playhead if it's on screen at the moment
|
||||
int playhead_pos = UnitToScreen(GetTime());
|
||||
if (playhead_pos + playhead_width_ >= 0 && playhead_pos - playhead_width_ < width()) {
|
||||
p.setPen(Qt::NoPen);
|
||||
p.setBrush(GetPlayheadColor());
|
||||
DrawPlayhead(&p, playhead_pos, line_bottom);
|
||||
}
|
||||
p.setPen(Qt::NoPen);
|
||||
p.setBrush(GetPlayheadColor());
|
||||
DrawPlayhead(&p, playhead_pos, line_bottom);
|
||||
}
|
||||
|
||||
void TimeRuler::TimebaseChangedEvent(const rational &tb)
|
||||
@@ -339,25 +285,6 @@ void TimeRuler::TimebaseChangedEvent(const rational &tb)
|
||||
update();
|
||||
}
|
||||
|
||||
void TimeRuler::DrawPlayhead(QPainter *p, int x, int y)
|
||||
{
|
||||
p->setRenderHint(QPainter::Antialiasing);
|
||||
|
||||
int half_text_height = text_height_ / 3;
|
||||
int half_width = playhead_width_ / 2;
|
||||
|
||||
QPoint points[] = {
|
||||
QPoint(x, y),
|
||||
QPoint(x - half_width, y - half_text_height),
|
||||
QPoint(x - half_width, y - 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, 6);
|
||||
}
|
||||
|
||||
int TimeRuler::CacheStatusHeight() const
|
||||
{
|
||||
return fontMetrics().height() / 4;
|
||||
@@ -365,11 +292,11 @@ int TimeRuler::CacheStatusHeight() const
|
||||
|
||||
void TimeRuler::UpdateHeight()
|
||||
{
|
||||
int height = text_height_;
|
||||
int height = text_height();
|
||||
|
||||
// Add text height
|
||||
if (text_visible_) {
|
||||
height += text_height_;
|
||||
height += text_height();
|
||||
}
|
||||
|
||||
// Add cache status height
|
||||
@@ -378,7 +305,7 @@ void TimeRuler::UpdateHeight()
|
||||
}
|
||||
|
||||
// Add marker height
|
||||
height += text_height_;
|
||||
height += text_height();
|
||||
|
||||
setFixedHeight(height);
|
||||
}
|
||||
|
||||
@@ -50,18 +50,12 @@ protected:
|
||||
private:
|
||||
void UpdateHeight();
|
||||
|
||||
void DrawPlayhead(QPainter* p, int x, int y);
|
||||
|
||||
int CacheStatusHeight() const;
|
||||
|
||||
int text_height_;
|
||||
|
||||
int cache_status_height_;
|
||||
|
||||
int minimum_gap_between_lines_;
|
||||
|
||||
int playhead_width_;
|
||||
|
||||
bool text_visible_;
|
||||
|
||||
bool centered_text_;
|
||||
|
||||
@@ -128,7 +128,7 @@ void ViewerWidget::ConnectNodeInternal(ViewerOutput *n)
|
||||
if (!n->video_params().time_base().isNull()) {
|
||||
SetTimebase(n->video_params().time_base());
|
||||
} else if (n->audio_params().sample_rate() > 0) {
|
||||
SetTimebase(rational(1, n->audio_params().sample_rate()));
|
||||
SetTimebase(n->audio_params().time_base());
|
||||
} else {
|
||||
SetTimebase(rational());
|
||||
}
|
||||
@@ -157,6 +157,10 @@ void ViewerWidget::ConnectNodeInternal(ViewerOutput *n)
|
||||
UpdateRendererParameters();
|
||||
|
||||
UpdateStack();
|
||||
|
||||
if (GetConnectedTimelinePoints()) {
|
||||
waveform_view_->ConnectTimelinePoints(GetConnectedTimelinePoints());
|
||||
}
|
||||
}
|
||||
|
||||
void ViewerWidget::DisconnectNodeInternal(ViewerOutput *n)
|
||||
@@ -177,6 +181,8 @@ void ViewerWidget::DisconnectNodeInternal(ViewerOutput *n)
|
||||
SizeChangedSlot(0, 0);
|
||||
|
||||
gl_widget_->DisconnectColorManager();
|
||||
|
||||
waveform_view_->ConnectTimelinePoints(nullptr);
|
||||
}
|
||||
|
||||
void ViewerWidget::ConnectedNodeChanged(ViewerOutput *n)
|
||||
|
||||
@@ -29,7 +29,7 @@ void WaveformView::SetBackend(AudioRenderBackend *backend)
|
||||
connect(backend_, &AudioRenderBackend::QueueComplete, this, static_cast<void (WaveformView::*)()>(&WaveformView::update));
|
||||
connect(backend_, &AudioRenderBackend::ParamsChanged, this, &WaveformView::BackendParamsChanged);
|
||||
|
||||
SetTimebase(rational(1, backend_->params().sample_rate()));
|
||||
SetTimebase(backend_->params().time_base());
|
||||
}
|
||||
|
||||
update();
|
||||
@@ -91,6 +91,8 @@ void WaveformView::paintEvent(QPaintEvent *event)
|
||||
|
||||
QPainter p(this);
|
||||
|
||||
DrawTimelinePoints(&p);
|
||||
|
||||
// FIXME: Hardcoded color
|
||||
p.setPen(Qt::green);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user