all time-based panels are now derived from a common base class

Cuts down on a lot of duplicate code between
TimelineWidget/ViewerWidget/CurveWidget/NodeParamView
and TimelinePanel/ViewerPanel/CurvePanel/ParamPanel since they all use similar
time functions.
This commit is contained in:
itsmattkc
2020-02-01 19:39:43 +11:00
parent 5d58479f0a
commit 17c1493aa7
62 changed files with 1076 additions and 1042 deletions
+6 -5
View File
@@ -192,8 +192,8 @@ void ExportDialog::accept()
QMatrix4x4 transform;
int dest_width = video_tab_->width_slider()->GetValue();
int dest_height = video_tab_->height_slider()->GetValue();
int dest_width = static_cast<int>(video_tab_->width_slider()->GetValue());
int dest_height = static_cast<int>(video_tab_->height_slider()->GetValue());
if (video_tab_->scaling_method_combobox()->isEnabled()) {
int source_width = viewer_node_->video_params().width();
@@ -444,13 +444,14 @@ QMatrix4x4 ExportDialog::GenerateMatrix(ExportVideoTab::ScalingMethod method, in
void ExportDialog::UpdateViewerDimensions()
{
preview_viewer_->SetOverrideSize(video_tab_->width_slider()->GetValue(), video_tab_->height_slider()->GetValue());
preview_viewer_->SetOverrideSize(static_cast<int>(video_tab_->width_slider()->GetValue()),
static_cast<int>(video_tab_->height_slider()->GetValue()));
preview_viewer_->SetMatrix(GenerateMatrix(static_cast<ExportVideoTab::ScalingMethod>(video_tab_->scaling_method_combobox()->currentData().toInt()),
viewer_node_->video_params().width(),
viewer_node_->video_params().height(),
video_tab_->width_slider()->GetValue(),
video_tab_->height_slider()->GetValue()));
static_cast<int>(video_tab_->width_slider()->GetValue()),
static_cast<int>(video_tab_->height_slider()->GetValue())));
}
void ExportDialog::ExporterIsDone()
+1
View File
@@ -21,6 +21,7 @@ add_subdirectory(node)
add_subdirectory(param)
add_subdirectory(project)
add_subdirectory(taskmanager)
add_subdirectory(timebased)
add_subdirectory(timeline)
add_subdirectory(tool)
add_subdirectory(viewer)
+9 -36
View File
@@ -1,16 +1,13 @@
#include "curve.h"
CurvePanel::CurvePanel(QWidget *parent) :
PanelWidget(parent)
TimeBasedPanel(parent)
{
// FIXME: This won't work if there's ever more than one of this panel
setObjectName("CurvePanel");
// Create main widget and set it
widget_ = new CurveWidget();
setWidget(widget_);
connect(widget_, &CurveWidget::TimeChanged, this, &CurvePanel::TimeChanged);
SetTimeBasedWidget(new CurveWidget());
// Set strings
Retranslate();
@@ -18,48 +15,24 @@ CurvePanel::CurvePanel(QWidget *parent) :
void CurvePanel::SetInput(NodeInput *input)
{
widget_->SetInput(input);
}
void CurvePanel::SetTimebase(const rational &timebase)
{
widget_->SetTimebase(timebase);
}
void CurvePanel::SetTime(const int64_t &timestamp)
{
widget_->SetTime(timestamp);
}
void CurvePanel::ZoomIn()
{
widget_->SetScale(widget_->GetScale() * 2);
}
void CurvePanel::ZoomOut()
{
widget_->SetScale(widget_->GetScale() * 0.5);
static_cast<CurveWidget*>(GetTimeBasedWidget())->SetInput(input);
}
void CurvePanel::IncreaseTrackHeight()
{
widget_->SetVerticalScale(widget_->GetVerticalScale() * 2);
CurveWidget* c = static_cast<CurveWidget*>(GetTimeBasedWidget());
c->SetVerticalScale(c->GetVerticalScale() * 2);
}
void CurvePanel::DecreaseTrackHeight()
{
widget_->SetVerticalScale(widget_->GetVerticalScale() * 0.5);
}
void CurvePanel::changeEvent(QEvent *e)
{
if (e->type() == QEvent::LanguageChange) {
Retranslate();
}
PanelWidget::changeEvent(e);
CurveWidget* c = static_cast<CurveWidget*>(GetTimeBasedWidget());
c->SetVerticalScale(c->GetVerticalScale() * 0.5);
}
void CurvePanel::Retranslate()
{
TimeBasedPanel::Retranslate();
SetTitle(tr("Curve Editor"));
}
+3 -19
View File
@@ -1,10 +1,10 @@
#ifndef CURVEPANEL_H
#define CURVEPANEL_H
#include "panel/timebased/timebased.h"
#include "widget/curvewidget/curvewidget.h"
#include "widget/panel/panel.h"
class CurvePanel : public PanelWidget
class CurvePanel : public TimeBasedPanel
{
Q_OBJECT
public:
@@ -13,28 +13,12 @@ public:
public slots:
void SetInput(NodeInput* input);
void SetTimebase(const rational& timebase);
void SetTime(const int64_t& timestamp);
virtual void ZoomIn() override;
virtual void ZoomOut() override;
virtual void IncreaseTrackHeight() override;
virtual void DecreaseTrackHeight() override;
signals:
void TimeChanged(const int64_t& timestamp);
protected:
virtual void changeEvent(QEvent* e) override;
private:
void Retranslate();
CurveWidget* widget_;
virtual void Retranslate() override;
};
+4 -17
View File
@@ -28,11 +28,8 @@ FootageViewerPanel::FootageViewerPanel(QWidget *parent) :
// FIXME: This won't work if there's ever more than one of this panel
setObjectName("FootageViewerPanel");
// QObject system handles deleting this
viewer_ = new FootageViewerWidget(this);
// Set ViewerWidget as the central widget
setWidget(viewer_);
SetTimeBasedWidget(new FootageViewerWidget());
// Set strings
Retranslate();
@@ -40,7 +37,7 @@ FootageViewerPanel::FootageViewerPanel(QWidget *parent) :
void FootageViewerPanel::SetFootage(Footage *f)
{
static_cast<FootageViewerWidget*>(viewer_)->SetFootage(f);
static_cast<FootageViewerWidget*>(GetTimeBasedWidget())->SetFootage(f);
if (f) {
SetSubtitle(f->name());
@@ -49,19 +46,9 @@ void FootageViewerPanel::SetFootage(Footage *f)
}
}
void FootageViewerPanel::changeEvent(QEvent *e)
{
if (e->type() == QEvent::LanguageChange) {
Retranslate();
}
PanelWidget::changeEvent(e);
}
void FootageViewerPanel::Retranslate()
{
SetTitle(tr("Footage Viewer"));
ViewerPanelBase::Retranslate();
if (!static_cast<FootageViewerWidget*>(viewer_)->GetFootage()) {
SetSubtitle(tr("(none)"));
}
SetTitle(tr("Footage Viewer"));
}
+1 -4
View File
@@ -36,10 +36,7 @@ public:
void SetFootage(Footage* f);
protected:
virtual void changeEvent(QEvent* e) override;
private:
void Retranslate();
virtual void Retranslate() override;
};
+10 -34
View File
@@ -21,59 +21,35 @@
#include "param.h"
ParamPanel::ParamPanel(QWidget* parent) :
PanelWidget(parent)
TimeBasedPanel(parent)
{
// FIXME: This won't work if there's ever more than one of this panel
setObjectName("ParamPanel");
view_ = new NodeParamView(this);
connect(view_, &NodeParamView::TimeChanged, this, &ParamPanel::TimeChanged);
connect(view_, &NodeParamView::SelectedInputChanged, this, &ParamPanel::SelectedInputChanged);
connect(view_, &NodeParamView::TimebaseChanged, this, &ParamPanel::TimebaseChanged);
setWidget(view_);
NodeParamView* view = new NodeParamView();
connect(view, &NodeParamView::SelectedInputChanged, this, &ParamPanel::SelectedInputChanged);
SetTimeBasedWidget(view);
Retranslate();
}
void ParamPanel::ZoomIn()
{
view_->SetScale(view_->GetScale() * 2);
}
void ParamPanel::ZoomOut()
{
view_->SetScale(view_->GetScale() * 0.5);
}
void ParamPanel::SetNodes(QList<Node *> nodes)
{
view_->SetNodes(nodes);
static_cast<NodeParamView*>(GetTimeBasedWidget())->SetNodes(nodes);
Retranslate();
}
void ParamPanel::SetTime(const int64_t &timestamp)
{
view_->SetTime(timestamp);
}
void ParamPanel::changeEvent(QEvent *e)
{
if (e->type() == QEvent::LanguageChange) {
Retranslate();
}
PanelWidget::changeEvent(e);
}
void ParamPanel::Retranslate()
{
SetTitle(tr("Parameter Editor"));
if (view_->nodes().isEmpty()) {
NodeParamView* view = static_cast<NodeParamView*>(GetTimeBasedWidget());
if (view->nodes().isEmpty()) {
SetSubtitle(tr("(none)"));
} else if (view_->nodes().size() == 1) {
SetSubtitle(view_->nodes().first()->Name());
} else if (view->nodes().size() == 1) {
SetSubtitle(view->nodes().first()->Name());
} else {
SetSubtitle(tr("(multiple)"));
}
+3 -17
View File
@@ -21,38 +21,24 @@
#ifndef PARAM_H
#define PARAM_H
#include "panel/timebased/timebased.h"
#include "widget/nodeparamview/nodeparamview.h"
#include "widget/panel/panel.h"
class ParamPanel : public PanelWidget
class ParamPanel : public TimeBasedPanel
{
Q_OBJECT
public:
ParamPanel(QWidget* parent);
virtual void ZoomIn() override;
virtual void ZoomOut() override;
public slots:
void SetNodes(QList<Node*> nodes);
void SetTime(const int64_t& timestamp);
signals:
void TimeChanged(const int64_t& timestamp);
void SelectedInputChanged(NodeInput* input);
void TimebaseChanged(const rational& timebase);
protected:
virtual void changeEvent(QEvent* e) override;
virtual void Retranslate() override;
private:
void Retranslate();
NodeParamView* view_;
};
#endif // PARAM_H
+22
View File
@@ -0,0 +1,22 @@
# Olive - Non-Linear Video Editor
# Copyright (C) 2019 Olive Team
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
set(OLIVE_SOURCES
${OLIVE_SOURCES}
panel/timebased/timebased.h
panel/timebased/timebased.cpp
PARENT_SCOPE
)
+131
View File
@@ -0,0 +1,131 @@
#include "timebased.h"
TimeBasedPanel::TimeBasedPanel(QWidget *parent) :
PanelWidget(parent),
widget_(nullptr)
{
}
rational TimeBasedPanel::GetTime()
{
return widget_->GetTime();
}
void TimeBasedPanel::GoToStart()
{
widget_->GoToStart();
}
void TimeBasedPanel::PrevFrame()
{
widget_->PrevFrame();
}
void TimeBasedPanel::NextFrame()
{
widget_->NextFrame();
}
void TimeBasedPanel::GoToEnd()
{
widget_->GoToEnd();
}
void TimeBasedPanel::ZoomIn()
{
widget_->ZoomIn();
}
void TimeBasedPanel::ZoomOut()
{
widget_->ZoomOut();
}
void TimeBasedPanel::SetTimebase(const rational &timebase)
{
widget_->SetTimebase(timebase);
}
void TimeBasedPanel::SetTime(const int64_t &timestamp)
{
widget_->SetTime(timestamp);
}
void TimeBasedPanel::GoToPrevCut()
{
widget_->GoToPrevCut();
}
void TimeBasedPanel::GoToNextCut()
{
widget_->GoToNextCut();
}
void TimeBasedPanel::PlayPause()
{
emit PlayPauseRequested();
}
void TimeBasedPanel::ShuttleLeft()
{
emit ShuttleLeftRequested();
}
void TimeBasedPanel::ShuttleStop()
{
emit ShuttleStopRequested();
}
void TimeBasedPanel::ShuttleRight()
{
emit ShuttleRightRequested();
}
TimeBasedWidget *TimeBasedPanel::GetTimeBasedWidget() const
{
return widget_;
}
ViewerOutput *TimeBasedPanel::GetConnectedViewer() const
{
return widget_->GetConnectedNode();
}
void TimeBasedPanel::ConnectViewerNode(ViewerOutput *node)
{
if (widget_->GetConnectedNode()) {
disconnect(widget_->GetConnectedNode(), &ViewerOutput::MediaNameChanged, this, &TimeBasedPanel::SetSubtitle);
Retranslate();
}
widget_->ConnectViewerNode(node);
if (node) {
connect(node, &ViewerOutput::MediaNameChanged, this, &TimeBasedPanel::SetSubtitle);
SetSubtitle(node->media_name());
}
}
void TimeBasedPanel::SetTimeBasedWidget(TimeBasedWidget *widget)
{
if (widget_) {
disconnect(widget_, &TimeBasedWidget::TimeChanged, this, &TimeBasedPanel::TimeChanged);
disconnect(widget_, &TimeBasedWidget::TimebaseChanged, this, &TimeBasedPanel::TimebaseChanged);
}
widget_ = widget;
if (widget_) {
connect(widget_, &TimeBasedWidget::TimeChanged, this, &TimeBasedPanel::TimeChanged);
connect(widget_, &TimeBasedWidget::TimebaseChanged, this, &TimeBasedPanel::TimebaseChanged);
}
setWidget(widget_);
}
void TimeBasedPanel::Retranslate()
{
if (!GetTimeBasedWidget()->GetConnectedNode()) {
SetSubtitle(tr("(none)"));
}
}
+75
View File
@@ -0,0 +1,75 @@
#ifndef TIMEBASEDPANEL_H
#define TIMEBASEDPANEL_H
#include "widget/panel/panel.h"
#include "widget/timebased/timebased.h"
class TimeBasedPanel : public PanelWidget
{
Q_OBJECT
public:
TimeBasedPanel(QWidget *parent = nullptr);
void ConnectViewerNode(ViewerOutput* node);
void DisconnectViewerNode();
rational GetTime();
ViewerOutput* GetConnectedViewer() const;
virtual void ZoomIn() override;
virtual void ZoomOut() override;
virtual void GoToStart() override;
virtual void PrevFrame() override;
virtual void NextFrame() override;
virtual void GoToEnd() override;
virtual void GoToPrevCut() override;
virtual void GoToNextCut() override;
virtual void PlayPause() override;
virtual void ShuttleLeft() override;
virtual void ShuttleStop() override;
virtual void ShuttleRight() override;
public slots:
void SetTimebase(const rational& timebase);
void SetTime(const int64_t& timestamp);
signals:
void TimeChanged(const int64_t& time);
void TimebaseChanged(const rational& timebase);
void PlayPauseRequested();
void ShuttleLeftRequested();
void ShuttleStopRequested();
void ShuttleRightRequested();
protected:
TimeBasedWidget* GetTimeBasedWidget() const;
void SetTimeBasedWidget(TimeBasedWidget* widget);
virtual void Retranslate() override;
private:
TimeBasedWidget* widget_;
};
#endif // TIMEBASEDPANEL_H
+15 -78
View File
@@ -21,137 +21,74 @@
#include "timeline.h"
TimelinePanel::TimelinePanel(QWidget *parent) :
PanelWidget(parent)
TimeBasedPanel(parent)
{
// FIXME: This won't work if there's ever more than one of this panel
setObjectName("TimelinePanel");
timeline_widget_ = new TimelineWidget();
setWidget(timeline_widget_);
connect(timeline_widget_, SIGNAL(TimeChanged(const int64_t&)), this, SIGNAL(TimeChanged(const int64_t&)));
SetTimeBasedWidget(new TimelineWidget());
Retranslate();
}
void TimelinePanel::Clear()
{
timeline_widget_->Clear();
}
void TimelinePanel::SetTimebase(const rational &timebase)
{
timeline_widget_->SetTimebase(timebase);
}
void TimelinePanel::SetTime(const int64_t &timestamp)
{
timeline_widget_->SetTime(timestamp);
}
void TimelinePanel::ConnectTimelineNode(ViewerOutput *node)
{
if (timeline_widget_->GetConnectedNode()) {
disconnect(timeline_widget_->GetConnectedNode(), &ViewerOutput::MediaNameChanged, this, &TimelinePanel::SetSubtitle);
Retranslate();
}
timeline_widget_->ConnectTimelineNode(node);
if (node) {
connect(node, &ViewerOutput::MediaNameChanged, this, &TimelinePanel::SetSubtitle);
SetSubtitle(node->media_name());
}
}
void TimelinePanel::DisconnectTimelineNode()
{
timeline_widget_->DisconnectTimelineNode();
static_cast<TimelineWidget*>(GetTimeBasedWidget())->Clear();
}
void TimelinePanel::SplitAtPlayhead()
{
timeline_widget_->SplitAtPlayhead();
}
void TimelinePanel::ZoomIn()
{
timeline_widget_->ZoomIn();
}
void TimelinePanel::ZoomOut()
{
timeline_widget_->ZoomOut();
static_cast<TimelineWidget*>(GetTimeBasedWidget())->SplitAtPlayhead();
}
void TimelinePanel::SelectAll()
{
timeline_widget_->SelectAll();
static_cast<TimelineWidget*>(GetTimeBasedWidget())->SelectAll();
}
void TimelinePanel::DeselectAll()
{
timeline_widget_->DeselectAll();
static_cast<TimelineWidget*>(GetTimeBasedWidget())->DeselectAll();
}
void TimelinePanel::RippleToIn()
{
timeline_widget_->RippleToIn();
static_cast<TimelineWidget*>(GetTimeBasedWidget())->RippleToIn();
}
void TimelinePanel::RippleToOut()
{
timeline_widget_->RippleToOut();
static_cast<TimelineWidget*>(GetTimeBasedWidget())->RippleToOut();
}
void TimelinePanel::EditToIn()
{
timeline_widget_->EditToIn();
static_cast<TimelineWidget*>(GetTimeBasedWidget())->EditToIn();
}
void TimelinePanel::EditToOut()
{
timeline_widget_->EditToOut();
}
void TimelinePanel::GoToPrevCut()
{
timeline_widget_->GoToPrevCut();
}
void TimelinePanel::GoToNextCut()
{
timeline_widget_->GoToNextCut();
static_cast<TimelineWidget*>(GetTimeBasedWidget())->EditToOut();
}
void TimelinePanel::DeleteSelected()
{
timeline_widget_->DeleteSelected();
static_cast<TimelineWidget*>(GetTimeBasedWidget())->DeleteSelected();
}
void TimelinePanel::IncreaseTrackHeight()
{
timeline_widget_->IncreaseTrackHeight();
static_cast<TimelineWidget*>(GetTimeBasedWidget())->IncreaseTrackHeight();
}
void TimelinePanel::DecreaseTrackHeight()
{
timeline_widget_->DecreaseTrackHeight();
}
void TimelinePanel::changeEvent(QEvent *e)
{
if (e->type() == QEvent::LanguageChange) {
Retranslate();
}
PanelWidget::changeEvent(e);
static_cast<TimelineWidget*>(GetTimeBasedWidget())->DecreaseTrackHeight();
}
void TimelinePanel::Retranslate()
{
SetTitle(tr("Timeline"));
TimeBasedPanel::Retranslate();
if (!timeline_widget_->GetConnectedNode()) {
SetSubtitle(tr("(none)"));
}
SetTitle(tr("Timeline"));
}
+3 -29
View File
@@ -21,14 +21,13 @@
#ifndef TIMELINE_PANEL_H
#define TIMELINE_PANEL_H
#include "widget/panel/panel.h"
#include "panel/timebased/timebased.h"
#include "widget/timelinewidget/timelinewidget.h"
/**
* @brief Panel container for a TimelineWidget
*/
class TimelinePanel : public PanelWidget
class TimelinePanel : public TimeBasedPanel
{
Q_OBJECT
public:
@@ -36,16 +35,8 @@ public:
void Clear();
void ConnectTimelineNode(ViewerOutput* node);
void DisconnectTimelineNode();
void SplitAtPlayhead();
virtual void ZoomIn() override;
virtual void ZoomOut() override;
virtual void SelectAll() override;
virtual void DeselectAll() override;
@@ -58,31 +49,14 @@ public:
virtual void EditToOut() override;
virtual void GoToPrevCut() override;
virtual void GoToNextCut() override;
virtual void DeleteSelected() override;
virtual void IncreaseTrackHeight() override;
virtual void DecreaseTrackHeight() override;
public slots:
void SetTimebase(const rational& timebase);
void SetTime(const int64_t& timestamp);
protected:
virtual void changeEvent(QEvent* e) override;
signals:
void TimeChanged(const int64_t& time);
private:
void Retranslate();
TimelineWidget* timeline_widget_;
virtual void Retranslate() override;
};
+1
View File
@@ -37,6 +37,7 @@ protected:
private:
void Retranslate();
};
#endif // TOOL_PANEL_H
+3 -47
View File
@@ -26,60 +26,16 @@ ViewerPanel::ViewerPanel(QWidget *parent) :
// FIXME: This won't work if there's ever more than one of this panel
setObjectName("ViewerPanel");
// QObject system handles deleting this
viewer_ = new ViewerWidget(this);
connect(viewer_, SIGNAL(TimeChanged(const int64_t&)), this, SIGNAL(TimeChanged(const int64_t&)));
// Set ViewerWidget as the central widget
setWidget(viewer_);
SetTimeBasedWidget(new ViewerWidget());
// Set strings
Retranslate();
}
void ViewerPanel::ConnectViewerNode(ViewerOutput *node)
{
if (viewer_->GetConnectedViewer()) {
disconnect(viewer_->GetConnectedViewer(), &ViewerOutput::MediaNameChanged, this, &ViewerPanel::SetSubtitle);
Retranslate();
}
viewer_->ConnectViewerNode(node);
if (node) {
connect(node, &ViewerOutput::MediaNameChanged, this, &ViewerPanel::SetSubtitle);
SetSubtitle(node->media_name());
}
}
rational ViewerPanel::GetTime()
{
return viewer_->GetTime();
}
ViewerOutput *ViewerPanel::GetConnectedViewer() const
{
return viewer_->GetConnectedViewer();
}
void ViewerPanel::SetTime(const int64_t &timestamp)
{
viewer_->SetTime(timestamp);
}
void ViewerPanel::changeEvent(QEvent *e)
{
if (e->type() == QEvent::LanguageChange) {
Retranslate();
}
PanelWidget::changeEvent(e);
}
void ViewerPanel::Retranslate()
{
SetTitle(tr("Viewer"));
ViewerPanelBase::Retranslate();
if (!viewer_->GetConnectedViewer()) {
SetSubtitle(tr("(none)"));
}
SetTitle(tr("Viewer"));
}
+1 -16
View File
@@ -33,23 +33,8 @@ class ViewerPanel : public ViewerPanelBase {
public:
ViewerPanel(QWidget* parent);
void ConnectViewerNode(ViewerOutput* node);
rational GetTime();
ViewerOutput* GetConnectedViewer() const;
public slots:
void SetTime(const int64_t& timestamp);
protected:
virtual void changeEvent(QEvent* e) override;
signals:
void TimeChanged(const int64_t&);
private:
void Retranslate();
virtual void Retranslate() override;
};
+13 -35
View File
@@ -1,56 +1,34 @@
#include "viewerbase.h"
ViewerPanelBase::ViewerPanelBase(QWidget *parent) :
PanelWidget(parent)
TimeBasedPanel(parent)
{
}
void ViewerPanelBase::ZoomIn()
{
viewer_->SetScale(viewer_->scale() * 2);
}
void ViewerPanelBase::ZoomOut()
{
viewer_->SetScale(viewer_->scale() * 0.5);
}
void ViewerPanelBase::GoToStart()
{
viewer_->GoToStart();
}
void ViewerPanelBase::PrevFrame()
{
viewer_->PrevFrame();
}
void ViewerPanelBase::PlayPause()
{
viewer_->TogglePlayPause();
}
void ViewerPanelBase::NextFrame()
{
viewer_->NextFrame();
}
void ViewerPanelBase::GoToEnd()
{
viewer_->GoToEnd();
static_cast<ViewerWidget*>(GetTimeBasedWidget())->TogglePlayPause();
}
void ViewerPanelBase::ShuttleLeft()
{
viewer_->ShuttleLeft();
static_cast<ViewerWidget*>(GetTimeBasedWidget())->ShuttleLeft();
}
void ViewerPanelBase::ShuttleStop()
{
viewer_->ShuttleStop();
static_cast<ViewerWidget*>(GetTimeBasedWidget())->ShuttleStop();
}
void ViewerPanelBase::ShuttleRight()
{
viewer_->ShuttleRight();
static_cast<ViewerWidget*>(GetTimeBasedWidget())->ShuttleRight();
}
void ViewerPanelBase::ConnectTimeBasedPanel(TimeBasedPanel *panel)
{
connect(panel, &TimeBasedPanel::PlayPauseRequested, this, &ViewerPanelBase::PlayPause);
connect(panel, &TimeBasedPanel::ShuttleLeftRequested, this, &ViewerPanelBase::ShuttleLeft);
connect(panel, &TimeBasedPanel::ShuttleStopRequested, this, &ViewerPanelBase::ShuttleStop);
connect(panel, &TimeBasedPanel::ShuttleRightRequested, this, &ViewerPanelBase::ShuttleRight);
}
+3 -18
View File
@@ -1,39 +1,24 @@
#ifndef VIEWERPANELBASE_H
#define VIEWERPANELBASE_H
#include "widget/panel/panel.h"
#include "panel/timebased/timebased.h"
#include "widget/viewer/viewer.h"
class ViewerPanelBase : public PanelWidget
class ViewerPanelBase : public TimeBasedPanel
{
Q_OBJECT
public:
ViewerPanelBase(QWidget* parent = nullptr);
virtual void ZoomIn() override;
virtual void ZoomOut() override;
virtual void GoToStart() override;
virtual void PrevFrame() override;
virtual void PlayPause() override;
virtual void NextFrame() override;
virtual void GoToEnd() override;
virtual void ShuttleLeft() override;
virtual void ShuttleStop() override;
virtual void ShuttleRight() override;
protected:
ViewerWidget* viewer_;
private:
void ConnectTimeBasedPanel(TimeBasedPanel* panel);
};
+1 -1
View File
@@ -187,7 +187,7 @@ void Sequence::Open(Sequence* sequence)
NodePanel* node_panel = PanelManager::instance()->MostRecentlyFocused<NodePanel>();
viewer_panel->ConnectViewerNode(sequence->viewer_output_);
timeline_panel->ConnectTimelineNode(sequence->viewer_output_);
timeline_panel->ConnectViewerNode(sequence->viewer_output_);
node_panel->SetGraph(sequence);
}
+4 -2
View File
@@ -56,7 +56,7 @@ DiskManager::~DiskManager()
ds << h.file_size;
}
} else {
qWarning() << "Failed to write cache index";
qWarning() << "Failed to write cache index:" << GetCacheIndexFilename();
}
}
}
@@ -196,5 +196,7 @@ qint64 DiskManager::DiskLimit()
QString DiskManager::GetCacheIndexFilename()
{
return QDir(QStandardPaths::writableLocation(QStandardPaths::AppLocalDataLocation)).filePath("diskindex");
QDir d(QStandardPaths::writableLocation(QStandardPaths::AppLocalDataLocation));
d.mkpath(".");
return d.filePath("diskindex");
}
+1
View File
@@ -31,6 +31,7 @@ add_subdirectory(projectexplorer)
add_subdirectory(projecttoolbar)
add_subdirectory(slider)
add_subdirectory(taskview)
add_subdirectory(timebased)
add_subdirectory(timelinewidget)
add_subdirectory(timeruler)
add_subdirectory(toolbar)
+8 -8
View File
@@ -53,7 +53,7 @@ void CurveView::drawBackground(QPainter *painter, const QRectF &rect)
painter->setPen(QPen(palette().window().color(), 1));
do {
x_grid_interval = qRound(x_interval * scale_ * timebase_dbl());
x_grid_interval = qRound(x_interval * GetScale() * timebase_dbl());
x_interval *= 2.0;
} while (x_grid_interval < minimum_grid_space_);
@@ -70,7 +70,7 @@ void CurveView::drawBackground(QPainter *painter, const QRectF &rect)
// Add vertical lines
for (int i=x_start;i<rect.right();i+=x_grid_interval) {
int value = qRound(static_cast<double>(i) / scale_ / timebase_dbl());
int value = qRound(static_cast<double>(i) / GetScale() / timebase_dbl());
painter->drawText(i + text_padding_, qRound(scene_bottom_left.y()) - text_padding_, QString::number(value));
lines.append(QLine(i, qRound(rect.top()), i, qRound(rect.bottom())));
}
@@ -183,7 +183,7 @@ void CurveView::KeyframeAboutToBeRemoved(NodeKeyframe *key)
disconnect(key, &NodeKeyframe::TypeChanged, this, &CurveView::KeyframeTypeChanged);
}
void CurveView::ScaleChangedEvent(double scale)
void CurveView::ScaleChangedEvent(const double& scale)
{
KeyframeViewBase::ScaleChangedEvent(scale);
@@ -208,10 +208,10 @@ void CurveView::wheelEvent(QWheelEvent *event)
if (WheelEventIsAZoomEvent(event)) {
if (event->delta() != 0) {
if (event->delta() > 0) {
emit ScaleChanged(scale_ * 1.1);
emit ScaleChanged(GetScale() * 1.1);
SetYScale(y_scale_ * 1.1);
} else {
emit ScaleChanged(scale_ * 0.9);
emit ScaleChanged(GetScale() * 0.9);
SetYScale(y_scale_ * 0.9);
}
}
@@ -259,18 +259,18 @@ void CurveView::SetItemYFromKeyframeValue(NodeKeyframe *key, KeyframeViewItem *i
QPointF CurveView::ScalePoint(const QPointF &point)
{
// Flips Y coordinate because curves are drawn bottom to top
return QPointF(point.x() * scale_, - point.y() * y_scale_);
return QPointF(point.x() * GetScale(), - point.y() * y_scale_);
}
void CurveView::CreateBezierControlPoints(KeyframeViewItem* item)
{
BezierControlPointItem* bezier_in_pt = new BezierControlPointItem(item->key(), NodeKeyframe::kInHandle, item);
bezier_in_pt->SetXScale(scale_);
bezier_in_pt->SetXScale(GetScale());
bezier_control_points_.append(bezier_in_pt);
connect(bezier_in_pt, &QObject::destroyed, this, &CurveView::BezierControlPointDestroyed, Qt::DirectConnection);
BezierControlPointItem* bezier_out_pt = new BezierControlPointItem(item->key(), NodeKeyframe::kOutHandle, item);
bezier_out_pt->SetXScale(scale_);
bezier_out_pt->SetXScale(GetScale());
bezier_control_points_.append(bezier_out_pt);
connect(bezier_out_pt, &QObject::destroyed, this, &CurveView::BezierControlPointDestroyed, Qt::DirectConnection);
}
+1 -1
View File
@@ -23,7 +23,7 @@ protected:
virtual void KeyframeAboutToBeRemoved(NodeKeyframe *key) override;
virtual void ScaleChangedEvent(double scale) override;
virtual void ScaleChangedEvent(const double &scale) override;
virtual void VerticalScaleChangedEvent(double scale) override;
+27 -41
View File
@@ -12,7 +12,7 @@
#include "widget/keyframeview/keyframeviewundo.h"
CurveWidget::CurveWidget(QWidget *parent) :
QWidget(parent),
TimeBasedWidget(parent),
input_(nullptr),
bridge_(nullptr)
{
@@ -51,8 +51,7 @@ CurveWidget::CurveWidget(QWidget *parent) :
ruler_view_layout->setMargin(0);
ruler_view_layout->setSpacing(0);
ruler_ = new TimeRuler();
ruler_view_layout->addWidget(ruler_);
ruler_view_layout->addWidget(ruler());
view_ = new CurveView();
ruler_view_layout->addWidget(view_);
@@ -60,15 +59,10 @@ CurveWidget::CurveWidget(QWidget *parent) :
layout->addLayout(ruler_view_layout);
// Connect ruler and view together
connect(ruler_, &TimeRuler::TimeChanged, view_, &CurveView::SetTime);
connect(view_, &CurveView::TimeChanged, ruler_, &TimeRuler::SetTime);
connect(ruler_, &TimeRuler::TimeChanged, this, &CurveWidget::TimeChanged);
connect(view_, &CurveView::TimeChanged, this, &CurveWidget::TimeChanged);
connect(ruler_, &TimeRuler::TimeChanged, this, &CurveWidget::UpdateBridgeTime);
connect(view_, &CurveView::TimeChanged, this, &CurveWidget::UpdateBridgeTime);
connect(view_, &CurveView::TimeChanged, this, &CurveWidget::SetTimeAndSignal);
connect(view_->scene(), &QGraphicsScene::selectionChanged, this, &CurveWidget::SelectionChanged);
connect(view_, &CurveView::ScaleChanged, this, &CurveWidget::SetScale);
connect(view_->horizontalScrollBar(), &QScrollBar::valueChanged, ruler_, &TimeRuler::SetScroll);
connect(view_->horizontalScrollBar(), &QScrollBar::valueChanged, ruler(), &TimeRuler::SetScroll);
widget_bridge_layout_ = new QHBoxLayout();
widget_bridge_layout_->addStretch();
@@ -127,32 +121,6 @@ void CurveWidget::SetInput(NodeInput *input)
UpdateInputLabel();
}
void CurveWidget::SetTimebase(const rational &timebase)
{
ruler_->SetTimebase(timebase);
view_->SetTimebase(timebase);
}
void CurveWidget::SetTime(const int64_t &timestamp)
{
ruler_->SetTime(timestamp);
view_->SetTime(timestamp);
UpdateBridgeTime(timestamp);
}
const double &CurveWidget::GetScale()
{
return ruler_->scale();
}
void CurveWidget::SetScale(double scale)
{
scale = qMin(scale, TimelineViewBase::kMaximumScale);
ruler_->SetScale(scale);
view_->SetScale(scale, true);
}
const double &CurveWidget::GetVerticalScale()
{
return view_->GetYScale();
@@ -171,6 +139,28 @@ void CurveWidget::changeEvent(QEvent *e)
QWidget::changeEvent(e);
}
void CurveWidget::TimeChangedEvent(const int64_t &timestamp)
{
TimeBasedWidget::TimeChangedEvent(timestamp);
view_->SetTime(timestamp);
UpdateBridgeTime(timestamp);
}
void CurveWidget::TimebaseChangedEvent(const rational &timebase)
{
TimeBasedWidget::TimebaseChangedEvent(timebase);
view_->SetTimebase(timebase);
}
void CurveWidget::ScaleChangedEvent(const double &scale)
{
TimeBasedWidget::ScaleChangedEvent(scale);
view_->SetScaleAndCenterOnPlayhead(scale);
}
void CurveWidget::UpdateInputLabel()
{
if (input_) {
@@ -283,9 +273,5 @@ void CurveWidget::KeyframeTypeButtonTriggered(bool checked)
void CurveWidget::KeyControlRequestedTimeChanged(const rational &time)
{
int64_t timestamp = Timecode::time_to_timestamp(time, view_->timebase());
SetTime(timestamp);
emit TimeChanged(timestamp);
SetTimeAndSignal(Timecode::time_to_timestamp(time, view_->timebase()));
}
+8 -18
View File
@@ -9,9 +9,9 @@
#include "node/input.h"
#include "widget/nodeparamview/nodeparamviewkeyframecontrol.h"
#include "widget/nodeparamview/nodeparamviewwidgetbridge.h"
#include "widget/timeruler/timeruler.h"
#include "widget/timebased/timebased.h"
class CurveWidget : public QWidget
class CurveWidget : public TimeBasedWidget
{
Q_OBJECT
public:
@@ -21,24 +21,16 @@ public:
void SetInput(NodeInput* input);
void SetTimebase(const rational& timebase);
void SetTime(const int64_t& timestamp);
const double& GetScale();
const double& GetVerticalScale();
void SetVerticalScale(const double& vscale);
public slots:
void SetScale(double scale);
signals:
void TimeChanged(const int64_t& timestamp);
protected:
virtual void changeEvent(QEvent *) override;
virtual void TimeChangedEvent(const int64_t &) override;
virtual void TimebaseChangedEvent(const rational &) override;
virtual void ScaleChangedEvent(const double &) override;
private:
void UpdateInputLabel();
@@ -48,14 +40,14 @@ private:
void SetKeyframeButtonCheckedFromType(NodeKeyframe::Type type);
void UpdateBridgeTime(const int64_t& timestamp);
QPushButton* linear_button_;
QPushButton* bezier_button_;
QPushButton* hold_button_;
TimeRuler* ruler_;
CurveView* view_;
NodeInput* input_;
@@ -69,8 +61,6 @@ private:
NodeParamViewKeyframeControl* key_control_;
private slots:
void UpdateBridgeTime(const int64_t& timestamp);
void SelectionChanged();
void KeyframeTypeButtonTriggered(bool checked);
+5 -3
View File
@@ -59,7 +59,7 @@ void KeyframeViewBase::RemoveKeyframe(NodeKeyframePtr key)
KeyframeViewItem *KeyframeViewBase::AddKeyframeInternal(NodeKeyframePtr key)
{
KeyframeViewItem* item = new KeyframeViewItem(key);
item->SetScale(scale_);
item->SetScale(GetScale());
item_map_.insert(key.get(), item);
scene()->addItem(item);
return item;
@@ -210,8 +210,10 @@ void KeyframeViewBase::mouseReleaseEvent(QMouseEvent *event)
}
}
void KeyframeViewBase::ScaleChangedEvent(double scale)
void KeyframeViewBase::ScaleChangedEvent(const double &scale)
{
TimelineViewBase::ScaleChangedEvent(scale);
QMap<NodeKeyframe*, KeyframeViewItem*>::const_iterator iterator;
for (iterator=item_map_.begin();iterator!=item_map_.end();iterator++) {
@@ -333,7 +335,7 @@ void KeyframeViewBase::ProcessBezierDrag(QPointF mouse_diff_scaled, bool include
QPointF KeyframeViewBase::GetScaledCursorPos(const QPoint &cursor_pos)
{
return QPointF(static_cast<double>(cursor_pos.x()) / scale_,
return QPointF(static_cast<double>(cursor_pos.x()) / GetScale(),
static_cast<double>(cursor_pos.y()) / y_scale_);
}
+1 -1
View File
@@ -27,7 +27,7 @@ protected:
virtual void mouseMoveEvent(QMouseEvent *event) override;
virtual void mouseReleaseEvent(QMouseEvent *event) override;
virtual void ScaleChangedEvent(double scale) override;
virtual void ScaleChangedEvent(const double& scale) override;
virtual void VerticalScaleChangedEvent(double scale);
+21 -36
View File
@@ -28,7 +28,7 @@
#include "node/output/viewer/viewer.h"
NodeParamView::NodeParamView(QWidget *parent) :
QWidget(parent),
TimeBasedWidget(true, false, parent),
last_scroll_val_(0)
{
// Create horizontal layout to place scroll area in (and keyframe editing eventually)
@@ -64,8 +64,7 @@ NodeParamView::NodeParamView(QWidget *parent) :
keyframe_area_layout->setMargin(0);
// Create ruler object
ruler_ = new TimeRuler(true);
keyframe_area_layout->addWidget(ruler_);
keyframe_area_layout->addWidget(ruler());
// Create keyframe view
keyframe_view_ = new KeyframeView();
@@ -74,10 +73,9 @@ NodeParamView::NodeParamView(QWidget *parent) :
keyframe_area_layout->addWidget(keyframe_view_);
// Connect ruler and keyframe view together
connect(ruler_, &TimeRuler::TimeChanged, keyframe_view_, &KeyframeView::SetTime);
connect(keyframe_view_, &KeyframeView::TimeChanged, ruler_, &TimeRuler::SetTime);
connect(ruler_, &TimeRuler::TimeChanged, this, &NodeParamView::RulerTimeChanged);
connect(keyframe_view_, &KeyframeView::TimeChanged, this, &NodeParamView::RulerTimeChanged);
connect(ruler(), &TimeRuler::TimeChanged, keyframe_view_, &KeyframeView::SetTime);
connect(keyframe_view_, &KeyframeView::TimeChanged, ruler(), &TimeRuler::SetTime);
connect(keyframe_view_, &KeyframeView::TimeChanged, this, &NodeParamView::SetTime);
// Connect keyframe view scaling to this
connect(keyframe_view_, &KeyframeView::ScaleChanged, this, &NodeParamView::SetScale);
@@ -106,10 +104,12 @@ NodeParamView::NodeParamView(QWidget *parent) :
connect(vertical_scrollbar_, &QScrollBar::valueChanged, scroll_area->verticalScrollBar(), &QScrollBar::setValue);
connect(vertical_scrollbar_, &QScrollBar::valueChanged, keyframe_view_->verticalScrollBar(), &QScrollBar::setValue);
connect(keyframe_view_->horizontalScrollBar(), SIGNAL(valueChanged(int)), ruler_, SLOT(SetScroll(int)));
connect(keyframe_view_->horizontalScrollBar(), &QScrollBar::valueChanged, ruler(), &TimeRuler::SetScroll);
// Set a default scale - FIXME: Hardcoded
SetScale(120);
SetMaximumScale(TimelineViewBase::kMaximumScale);
}
void NodeParamView::SetNodes(QList<Node *> nodes)
@@ -169,38 +169,32 @@ void NodeParamView::resizeEvent(QResizeEvent *event)
vertical_scrollbar_->setPageStep(vertical_scrollbar_->height());
}
const QList<Node *> &NodeParamView::nodes()
void NodeParamView::ScaleChangedEvent(const double &scale)
{
return nodes_;
TimeBasedWidget::ScaleChangedEvent(scale);
keyframe_view_->SetScaleAndCenterOnPlayhead(scale);
}
const double &NodeParamView::GetScale() const
void NodeParamView::TimebaseChangedEvent(const rational &timebase)
{
return ruler_->scale();
TimeBasedWidget::TimebaseChangedEvent(timebase);
keyframe_view_->SetTimebase(timebase);
}
void NodeParamView::SetScale(double scale)
void NodeParamView::TimeChangedEvent(const int64_t &timestamp)
{
scale = qMin(scale, TimelineViewBase::kMaximumScale);
TimeBasedWidget::TimeChangedEvent(timestamp);
ruler_->SetScale(scale);
keyframe_view_->SetScale(scale, true);
}
void NodeParamView::SetTime(const int64_t &timestamp)
{
ruler_->SetTime(timestamp);
keyframe_view_->SetTime(timestamp);
UpdateItemTime(timestamp);
}
void NodeParamView::SetTimebase(const rational &timebase)
const QList<Node *> &NodeParamView::nodes()
{
ruler_->SetTimebase(timebase);
keyframe_view_->SetTimebase(timebase);
emit TimebaseChanged(timebase);
return nodes_;
}
void NodeParamView::UpdateItemTime(const int64_t &timestamp)
@@ -212,18 +206,9 @@ void NodeParamView::UpdateItemTime(const int64_t &timestamp)
}
}
void NodeParamView::RulerTimeChanged(const int64_t &timestamp)
{
UpdateItemTime(timestamp);
emit TimeChanged(timestamp);
}
void NodeParamView::ItemRequestedTimeChanged(const rational &time)
{
int64_t timestamp = Timecode::time_to_timestamp(time, keyframe_view_->timebase());
SetTime(timestamp);
emit TimeChanged(timestamp);
SetTimeAndSignal(Timecode::time_to_timestamp(time, keyframe_view_->timebase()));
}
void NodeParamView::ForceKeyframeViewToScroll(int min, int max)
+7 -20
View File
@@ -27,45 +27,34 @@
#include "node/node.h"
#include "nodeparamviewitem.h"
#include "widget/keyframeview/keyframeview.h"
#include "widget/timeruler/timeruler.h"
#include "widget/timebased/timebased.h"
class NodeParamView : public QWidget
class NodeParamView : public TimeBasedWidget
{
Q_OBJECT
public:
NodeParamView(QWidget* parent);
NodeParamView(QWidget* parent = nullptr);
void SetNodes(QList<Node*> nodes);
const QList<Node*>& nodes();
const double& GetScale() const;
public slots:
void SetScale(double scale);
void SetTime(const int64_t& timestamp);
signals:
void TimeChanged(const int64_t& timestamp);
void SelectedInputChanged(NodeInput* input);
void TimebaseChanged(const rational& timebase);
protected:
virtual void resizeEvent(QResizeEvent *event) override;
private:
void SetTimebase(const rational& timebase);
virtual void ScaleChangedEvent(const double &) override;
virtual void TimebaseChangedEvent(const rational&) override;
virtual void TimeChangedEvent(const int64_t &) override;
private:
void UpdateItemTime(const int64_t &timestamp);
QVBoxLayout* param_layout_;
KeyframeView* keyframe_view_;
TimeRuler* ruler_;
QList<Node*> nodes_;
QList<NodeParamViewItem*> items_;
@@ -77,8 +66,6 @@ private:
int last_scroll_val_;
private slots:
void RulerTimeChanged(const int64_t& timestamp);
void ItemRequestedTimeChanged(const rational& time);
void ForceKeyframeViewToScroll(int min, int max);
+12
View File
@@ -101,3 +101,15 @@ void PanelWidget::UpdateTitle()
setWindowTitle(tr("%1: %2").arg(title_, subtitle_));
}
}
void PanelWidget::changeEvent(QEvent *e)
{
if (e->type() == QEvent::LanguageChange) {
Retranslate();
}
QDockWidget::changeEvent(e);
}
void PanelWidget::Retranslate()
{
}
+3
View File
@@ -119,6 +119,9 @@ protected:
*/
void paintEvent(QPaintEvent *event) override;
virtual void changeEvent(QEvent* e) override;
virtual void Retranslate();
protected slots:
/**
@@ -49,7 +49,8 @@ PlaybackControls::PlaybackControls(QWidget *parent) :
lower_left_layout->setSpacing(0);
lower_left_layout->setMargin(0);
cur_tc_lbl_ = new QLabel();
cur_tc_lbl_ = new TimeSlider();
connect(cur_tc_lbl_, &TimeSlider::ValueChanged, this, &PlaybackControls::TimeChanged);
lower_left_layout->addWidget(cur_tc_lbl_);
lower_left_layout->addStretch();
@@ -67,12 +68,12 @@ PlaybackControls::PlaybackControls(QWidget *parent) :
// Go To Start Button
go_to_start_btn_ = new QPushButton();
lower_middle_layout->addWidget(go_to_start_btn_);
connect(go_to_start_btn_, SIGNAL(clicked(bool)), this, SIGNAL(BeginClicked()));
connect(go_to_start_btn_, &QPushButton::clicked, this, &PlaybackControls::BeginClicked);
// Prev Frame Button
prev_frame_btn_ = new QPushButton();
lower_middle_layout->addWidget(prev_frame_btn_);
connect(prev_frame_btn_, SIGNAL(clicked(bool)), this, SIGNAL(PrevFrameClicked()));
connect(prev_frame_btn_, &QPushButton::clicked, this, &PlaybackControls::PrevFrameClicked);
// Play/Pause Button
playpause_stack_ = new QStackedWidget();
@@ -80,11 +81,11 @@ PlaybackControls::PlaybackControls(QWidget *parent) :
play_btn_ = new QPushButton();
playpause_stack_->addWidget(play_btn_);
connect(play_btn_, SIGNAL(clicked(bool)), this, SIGNAL(PlayClicked()));
connect(play_btn_, &QPushButton::clicked, this, &PlaybackControls::PlayClicked);
pause_btn_ = new QPushButton();
playpause_stack_->addWidget(pause_btn_);
connect(pause_btn_, SIGNAL(clicked(bool)), this, SIGNAL(PauseClicked()));
connect(pause_btn_, &QPushButton::clicked, this, &PlaybackControls::PauseClicked);
// Default to showing play button
playpause_stack_->setCurrentWidget(play_btn_);
@@ -93,12 +94,12 @@ PlaybackControls::PlaybackControls(QWidget *parent) :
// Next Frame Button
next_frame_btn_ = new QPushButton();
lower_middle_layout->addWidget(next_frame_btn_);
connect(next_frame_btn_, SIGNAL(clicked(bool)), this, SIGNAL(NextFrameClicked()));
connect(next_frame_btn_, &QPushButton::clicked, this, &PlaybackControls::NextFrameClicked);
// Go To End Button
go_to_end_btn_ = new QPushButton();
lower_middle_layout->addWidget(go_to_end_btn_);
connect(go_to_end_btn_, SIGNAL(clicked(bool)), this, SIGNAL(EndClicked()));
connect(go_to_end_btn_, &QPushButton::clicked, this, &PlaybackControls::EndClicked);
lower_middle_layout->addStretch();
@@ -117,6 +118,8 @@ PlaybackControls::PlaybackControls(QWidget *parent) :
lower_right_layout->addWidget(end_tc_lbl_);
UpdateIcons();
SetTimebase(0);
}
void PlaybackControls::SetTimecodeEnabled(bool enabled)
@@ -128,16 +131,25 @@ void PlaybackControls::SetTimecodeEnabled(bool enabled)
void PlaybackControls::SetTimebase(const rational &r)
{
time_base_ = r;
cur_tc_lbl_->SetTimebase(r);
cur_tc_lbl_->setEnabled(!r.isNull());
}
void PlaybackControls::SetTime(const int64_t &r)
{
SetTimeLabelInternal(cur_tc_lbl_, r);
cur_tc_lbl_->SetValue(r);
}
void PlaybackControls::SetEndTime(const int64_t &r)
{
SetTimeLabelInternal(end_tc_lbl_, r);
if (time_base_.isNull()) {
return;
}
end_tc_lbl_->setText(Timecode::timestamp_to_timecode(r,
time_base_,
Timecode::CurrentDisplay()));
}
void PlaybackControls::ShowPauseButton()
@@ -169,14 +181,3 @@ void PlaybackControls::UpdateIcons()
next_frame_btn_->setIcon(icon::NextFrame);
go_to_end_btn_->setIcon(icon::GoToEnd);
}
void PlaybackControls::SetTimeLabelInternal(QLabel* label, const int64_t& time)
{
if (time_base_.isNull()) {
return;
}
label->setText(Timecode::timestamp_to_timecode(time,
time_base_,
Timecode::CurrentDisplay()));
}
@@ -27,6 +27,7 @@
#include <QStackedWidget>
#include "common/rational.h"
#include "widget/slider/timeslider.h"
/**
* @brief A playback controls widget providing buttons for navigating media
@@ -86,18 +87,18 @@ signals:
*/
void EndClicked();
void TimeChanged(const int64_t& t);
protected:
virtual void changeEvent(QEvent *) override;
private:
void UpdateIcons();
void SetTimeLabelInternal(QLabel *label, const int64_t &time);
QWidget* lower_left_container_;
QWidget* lower_right_container_;
QLabel* cur_tc_lbl_;
TimeSlider* cur_tc_lbl_;
QLabel* end_tc_lbl_;
rational time_base_;
+2 -2
View File
@@ -149,10 +149,10 @@ double FloatSlider::AdjustDragDistanceInternal(const double &start, const double
current_db += drag;
qreal adjusted_linear = QAudio::convertVolume(current_db, QAudio::DecibelVolumeScale, QAudio::LinearVolumeScale);
return adjusted_linear - start;
return adjusted_linear;
}
case kPercentage:
return drag * 0.01;
return SliderBase::AdjustDragDistanceInternal(start, drag * 0.01);
}
return SliderBase::AdjustDragDistanceInternal(start, drag);
+2 -2
View File
@@ -26,9 +26,9 @@ IntegerSlider::IntegerSlider(QWidget* parent) :
connect(this, SIGNAL(ValueChanged(QVariant)), this, SLOT(ConvertValue(QVariant)));
}
int IntegerSlider::GetValue()
int64_t IntegerSlider::GetValue()
{
return Value().toInt();
return Value().toLongLong();
}
void IntegerSlider::SetValue(const int64_t &v)
+1 -1
View File
@@ -29,7 +29,7 @@ class IntegerSlider : public SliderBase
public:
IntegerSlider(QWidget* parent = nullptr);
int GetValue();
int64_t GetValue();
void SetValue(const int64_t& v);
+10 -13
View File
@@ -119,6 +119,10 @@ const QVariant &SliderBase::Value()
void SliderBase::SetValue(const QVariant &v)
{
if (IsDragging()) {
return;
}
value_ = ClampValue(v);
// Disable tristate
@@ -185,8 +189,7 @@ void SliderBase::UpdateLabel(const QVariant &v)
double SliderBase::AdjustDragDistanceInternal(const double &start, const double &drag)
{
Q_UNUSED(start)
return drag;
return start + drag;
}
QString SliderBase::ValueToString(const QVariant &v)
@@ -203,16 +206,13 @@ QVariant SliderBase::StringToValue(const QString &s, bool *ok)
void SliderBase::LabelPressed()
{
dragged_ = false;
if (mode_ != kString) {
dragged_diff_ = 0;
}
}
void SliderBase::LabelClicked()
{
if (dragged_) {
double drag_val = value_.toDouble() + AdjustDragDistanceInternal(value_.toDouble(), dragged_diff_);
dragged_ = false;
// This was a drag
switch (mode_) {
@@ -220,14 +220,13 @@ void SliderBase::LabelClicked()
// No-op
break;
case kInteger:
SetValue(qRound(drag_val));
SetValue(temp_dragged_value_.toInt());
break;
case kFloat:
SetValue(drag_val);
SetValue(temp_dragged_value_.toDouble());
break;
}
dragged_ = false;
emit ValueChanged(value_);
} else {
// This was a simple click
@@ -255,11 +254,9 @@ void SliderBase::LabelDragged(int i)
case kInteger:
case kFloat:
{
double real_drag = static_cast<double>(i) * drag_multiplier_;
dragged_diff_ += static_cast<double>(i) * drag_multiplier_;
dragged_diff_ += real_drag;
double drag_val = value_.toDouble() + AdjustDragDistanceInternal(value_.toDouble(), dragged_diff_);
double drag_val = AdjustDragDistanceInternal(value_.toDouble(), dragged_diff_);
// Update temporary value
if (mode_ == kInteger) {
+22
View File
@@ -0,0 +1,22 @@
# Olive - Non-Linear Video Editor
# Copyright (C) 2019 Olive Team
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
set(OLIVE_SOURCES
${OLIVE_SOURCES}
widget/timebased/timebased.h
widget/timebased/timebased.cpp
PARENT_SCOPE
)
+201
View File
@@ -0,0 +1,201 @@
#include "timebased.h"
#include "common/timecodefunctions.h"
TimeBasedWidget::TimeBasedWidget(bool ruler_text_visible, bool ruler_cache_status_visible, QWidget *parent) :
QWidget(parent),
viewer_node_(nullptr)
{
ruler_ = new TimeRuler(ruler_text_visible, ruler_cache_status_visible, this);
connect(ruler_, &TimeRuler::TimeChanged, this, &TimeBasedWidget::SetTimeAndSignal);
scrollbar_ = new QScrollBar(Qt::Horizontal, this);
}
rational TimeBasedWidget::GetTime() const
{
return Timecode::timestamp_to_time(ruler()->GetTime(), timebase());
}
const int64_t &TimeBasedWidget::GetTimestamp() const
{
return ruler_->GetTime();
}
ViewerOutput *TimeBasedWidget::GetConnectedNode() const
{
return viewer_node_;
}
void TimeBasedWidget::ConnectViewerNode(ViewerOutput *node)
{
if (viewer_node_) {
DisconnectNodeInternal(viewer_node_);
}
viewer_node_ = node;
ConnectedNodeChanged(viewer_node_);
if (viewer_node_) {
ConnectNodeInternal(viewer_node_);
}
}
TimeRuler *TimeBasedWidget::ruler() const
{
return ruler_;
}
QScrollBar *TimeBasedWidget::scrollbar() const
{
return scrollbar_;
}
void TimeBasedWidget::TimebaseChangedEvent(const rational &timebase)
{
TimelineScaledObject::TimebaseChangedEvent(timebase);
ruler_->SetTimebase(timebase);
emit TimebaseChanged(timebase);
}
void TimeBasedWidget::ScaleChangedEvent(const double &scale)
{
TimelineScaledObject::ScaleChangedEvent(scale);
ruler_->SetScale(scale);
}
void TimeBasedWidget::resizeEvent(QResizeEvent *event)
{
QWidget::resizeEvent(event);
// Update horizontal scrollbar's page step to the width of the panel
scrollbar()->setPageStep(scrollbar()->width());
}
void TimeBasedWidget::SetTime(int64_t timestamp)
{
ruler_->SetTime(timestamp);
TimeChangedEvent(timestamp);
}
void TimeBasedWidget::SetTimebase(const rational &timebase)
{
TimelineScaledObject::SetTimebase(timebase);
}
void TimeBasedWidget::SetScale(const double &scale)
{
TimelineScaledObject::SetScale(scale);
}
void TimeBasedWidget::ZoomIn()
{
SetScale(GetScale() * 2);
}
void TimeBasedWidget::ZoomOut()
{
SetScale(GetScale() * 0.5);
}
void TimeBasedWidget::GoToPrevCut()
{
if (!GetConnectedNode()) {
return;
}
if (GetTimestamp() == 0) {
return;
}
int64_t closest_cut = 0;
foreach (TrackOutput* track, viewer_node_->Tracks()) {
int64_t this_track_closest_cut = 0;
foreach (Block* block, track->Blocks()) {
int64_t block_out_ts = Timecode::time_to_timestamp(block->out(), timebase());
if (block_out_ts < GetTimestamp()) {
this_track_closest_cut = block_out_ts;
} else {
break;
}
}
closest_cut = qMax(closest_cut, this_track_closest_cut);
}
SetTimeAndSignal(closest_cut);
}
void TimeBasedWidget::GoToNextCut()
{
if (!GetConnectedNode()) {
return;
}
int64_t closest_cut = INT64_MAX;
foreach (TrackOutput* track, GetConnectedNode()->Tracks()) {
int64_t this_track_closest_cut = Timecode::time_to_timestamp(track->track_length(), timebase());
if (this_track_closest_cut <= GetTimestamp()) {
this_track_closest_cut = INT64_MAX;
}
foreach (Block* block, track->Blocks()) {
int64_t block_in_ts = Timecode::time_to_timestamp(block->in(), timebase());
if (block_in_ts > GetTimestamp()) {
this_track_closest_cut = block_in_ts;
break;
}
}
closest_cut = qMin(closest_cut, this_track_closest_cut);
}
if (closest_cut < INT64_MAX) {
SetTimeAndSignal(closest_cut);
}
}
void TimeBasedWidget::GoToStart()
{
if (viewer_node_) {
SetTimeAndSignal(0);
}
}
void TimeBasedWidget::PrevFrame()
{
if (viewer_node_) {
SetTimeAndSignal(qMax(static_cast<int64_t>(0), ruler()->GetTime() - 1));
}
}
void TimeBasedWidget::NextFrame()
{
if (viewer_node_) {
SetTimeAndSignal(ruler()->GetTime() + 1);
}
}
void TimeBasedWidget::GoToEnd()
{
if (viewer_node_) {
SetTimeAndSignal(Timecode::time_to_timestamp(viewer_node_->Length(), timebase()));
}
}
void TimeBasedWidget::SetTimeAndSignal(const int64_t &t)
{
SetTime(t);
emit TimeChanged(t);
}
+85
View File
@@ -0,0 +1,85 @@
#ifndef TIMEBASEDWIDGET_H
#define TIMEBASEDWIDGET_H
#include <QScrollBar>
#include <QWidget>
#include "node/output/viewer/viewer.h"
#include "widget/timelinewidget/timelinescaledobject.h"
#include "widget/timeruler/timeruler.h"
class TimeBasedWidget : public QWidget, public TimelineScaledObject
{
Q_OBJECT
public:
TimeBasedWidget(bool ruler_text_visible = true, bool ruler_cache_status_visible = false, QWidget* parent = nullptr);
rational GetTime() const;
const int64_t& GetTimestamp() const;
void ZoomIn();
void ZoomOut();
ViewerOutput* GetConnectedNode() const;
void ConnectViewerNode(ViewerOutput *node);
public slots:
// FIXME: Rename this to SetTimestamp to reduce confusion
void SetTime(int64_t timestamp);
void SetTimebase(const rational& timebase);
void SetScale(const double& scale);
void GoToStart();
void PrevFrame();
void NextFrame();
void GoToEnd();
void GoToPrevCut();
void GoToNextCut();
protected slots:
void SetTimeAndSignal(const int64_t& t);
protected:
TimeRuler* ruler() const;
QScrollBar* scrollbar() const;
virtual void TimebaseChangedEvent(const rational&) override;
virtual void TimeChangedEvent(const int64_t&){}
virtual void ScaleChangedEvent(const double &) override;
virtual void ConnectedNodeChanged(ViewerOutput*){}
virtual void ConnectNodeInternal(ViewerOutput*){}
virtual void DisconnectNodeInternal(ViewerOutput*){}
virtual void resizeEvent(QResizeEvent *event) override;
signals:
void TimeChanged(const int64_t&);
void TimebaseChanged(const rational&);
private:
ViewerOutput* viewer_node_;
TimeRuler* ruler_;
QScrollBar* scrollbar_;
};
#endif // TIMEBASEDWIDGET_H
@@ -3,11 +3,20 @@
#include <QtMath>
TimelineScaledObject::TimelineScaledObject() :
scale_(1.0)
scale_(1.0),
max_scale_(DBL_MAX)
{
}
void TimelineScaledObject::SetTimebase(const rational &timebase)
{
timebase_ = timebase;
timebase_dbl_ = timebase_.toDouble();
TimebaseChangedEvent(timebase);
}
const rational &TimelineScaledObject::timebase() const
{
return timebase_;
@@ -45,8 +54,23 @@ rational TimelineScaledObject::SceneToTime(const double &x, bool round)
return SceneToTime(x, scale_, timebase_, round);
}
void TimelineScaledObject::SetTimebaseInternal(const rational &timebase)
void TimelineScaledObject::SetMaximumScale(const double &max)
{
timebase_ = timebase;
timebase_dbl_ = timebase_.toDouble();
max_scale_ = max;
if (GetScale() > max_scale_) {
SetScale(max_scale_);
}
}
const double& TimelineScaledObject::GetScale() const
{
return scale_;
}
void TimelineScaledObject::SetScale(const double& scale)
{
scale_ = scale;
ScaleChangedEvent(scale_);
}
@@ -7,25 +7,38 @@ class TimelineScaledObject
{
public:
TimelineScaledObject();
virtual ~TimelineScaledObject() = default;
void SetTimebase(const rational &timebase);
const rational& timebase() const;
const double& timebase_dbl() const;
static rational SceneToTime(const double &x, const double& x_scale, const rational& timebase, bool round = false);
const double& GetScale() const;
void SetScale(const double& scale);
protected:
double TimeToScene(const rational& time);
rational SceneToTime(const double &x, bool round = false);
void SetTimebaseInternal(const rational& timebase);
virtual void TimebaseChangedEvent(const rational&){}
double scale_;
virtual void ScaleChangedEvent(const double&){}
void SetMaximumScale(const double& max);
private:
rational timebase_;
double timebase_dbl_;
double scale_;
double max_scale_;
};
#endif // TIMELINESCALEDOBJECT_H
+121 -229
View File
@@ -14,11 +14,9 @@
#include "widget/nodeview/nodeviewundo.h"
TimelineWidget::TimelineWidget(QWidget *parent) :
QWidget(parent),
TimeBasedWidget(true, true, parent),
rubberband_(QRubberBand::Rectangle, this),
active_tool_(nullptr),
timeline_node_(nullptr),
playhead_(0)
active_tool_(nullptr)
{
QVBoxLayout* vert_layout = new QVBoxLayout(this);
vert_layout->setSpacing(0);
@@ -30,14 +28,10 @@ TimelineWidget::TimelineWidget(QWidget *parent) :
timecode_label_ = new TimeSlider();
timecode_label_->SetAlignment(Qt::AlignCenter);
timecode_label_->setVisible(false);
connect(timecode_label_, SIGNAL(ValueChanged(int64_t)), this, SIGNAL(TimeChanged(const int64_t&)));
connect(timecode_label_, SIGNAL(ValueChanged(int64_t)), this, SLOT(UpdateInternalTime(const int64_t&)));
connect(timecode_label_, &TimeSlider::ValueChanged, this, &TimelineWidget::SetTimeAndSignal);
ruler_and_time_layout->addWidget(timecode_label_);
ruler_ = new TimeRuler(true, true);
connect(ruler_, SIGNAL(TimeChanged(const int64_t&)), this, SIGNAL(TimeChanged(const int64_t&)));
connect(ruler_, SIGNAL(TimeChanged(const int64_t&)), this, SLOT(UpdateInternalTime(const int64_t&)));
ruler_and_time_layout->addWidget(ruler_);
ruler_and_time_layout->addWidget(ruler());
// Create list of TimelineViews - these MUST correspond to the ViewType enum
@@ -74,10 +68,9 @@ TimelineWidget::TimelineWidget(QWidget *parent) :
tools_.append(import_tool_);
// Global scrollbar
horizontal_scroll_ = new QScrollBar(Qt::Horizontal);
connect(horizontal_scroll_, SIGNAL(valueChanged(int)), ruler_, SLOT(SetScroll(int)));
connect(views_.first()->view()->horizontalScrollBar(), SIGNAL(rangeChanged(int, int)), horizontal_scroll_, SLOT(setRange(int, int)));
vert_layout->addWidget(horizontal_scroll_);
connect(scrollbar(), &QScrollBar::valueChanged, ruler(), &TimeRuler::SetScroll);
connect(views_.first()->view()->horizontalScrollBar(), &QScrollBar::rangeChanged, scrollbar(), &QScrollBar::setRange);
vert_layout->addWidget(scrollbar());
foreach (TimelineAndTrackView* tview, views_) {
TimelineView* view = tview->view();
@@ -87,32 +80,32 @@ TimelineWidget::TimelineWidget(QWidget *parent) :
view_splitter->addWidget(tview);
connect(view->horizontalScrollBar(), SIGNAL(valueChanged(int)), ruler_, SLOT(SetScroll(int)));
connect(view, SIGNAL(ScaleChanged(double)), this, SLOT(SetScale(double)));
connect(ruler_, SIGNAL(TimeChanged(const int64_t&)), view, SLOT(SetTime(const int64_t&)));
connect(view, SIGNAL(TimeChanged(const int64_t&)), ruler_, SLOT(SetTime(const int64_t&)));
connect(view, SIGNAL(TimeChanged(const int64_t&)), this, SIGNAL(TimeChanged(const int64_t&)));
connect(view, SIGNAL(customContextMenuRequested(const QPoint &)), this, SLOT(ShowContextMenu()));
connect(horizontal_scroll_, SIGNAL(valueChanged(int)), view->horizontalScrollBar(), SLOT(setValue(int)));
connect(view->horizontalScrollBar(), SIGNAL(valueChanged(int)), horizontal_scroll_, SLOT(setValue(int)));
connect(view->horizontalScrollBar(), &QScrollBar::valueChanged, ruler(), &TimeRuler::SetScroll);
connect(view, &TimelineView::ScaleChanged, this, &TimelineWidget::SetScale);
connect(ruler(), &TimeRuler::TimeChanged, view, &TimelineView::SetTime);
connect(view, &TimelineView::TimeChanged, ruler(), &TimeRuler::SetTime);
connect(view, &TimelineView::TimeChanged, this, &TimelineWidget::TimeChanged);
connect(view, &TimelineView::customContextMenuRequested, this, &TimelineWidget::ShowContextMenu);
connect(scrollbar(), &QScrollBar::valueChanged, view->horizontalScrollBar(), &QScrollBar::setValue);
connect(view->horizontalScrollBar(), &QScrollBar::valueChanged, scrollbar(), &QScrollBar::setValue);
connect(view, SIGNAL(MousePressed(TimelineViewMouseEvent*)), this, SLOT(ViewMousePressed(TimelineViewMouseEvent*)));
connect(view, SIGNAL(MouseMoved(TimelineViewMouseEvent*)), this, SLOT(ViewMouseMoved(TimelineViewMouseEvent*)));
connect(view, SIGNAL(MouseReleased(TimelineViewMouseEvent*)), this, SLOT(ViewMouseReleased(TimelineViewMouseEvent*)));
connect(view, SIGNAL(MouseDoubleClicked(TimelineViewMouseEvent*)), this, SLOT(ViewMouseDoubleClicked(TimelineViewMouseEvent*)));
connect(view, SIGNAL(DragEntered(TimelineViewMouseEvent*)), this, SLOT(ViewDragEntered(TimelineViewMouseEvent*)));
connect(view, SIGNAL(DragMoved(TimelineViewMouseEvent*)), this, SLOT(ViewDragMoved(TimelineViewMouseEvent*)));
connect(view, SIGNAL(DragLeft(QDragLeaveEvent*)), this, SLOT(ViewDragLeft(QDragLeaveEvent*)));
connect(view, SIGNAL(DragDropped(TimelineViewMouseEvent*)), this, SLOT(ViewDragDropped(TimelineViewMouseEvent*)));
connect(view, &TimelineView::MousePressed, this, &TimelineWidget::ViewMousePressed);
connect(view, &TimelineView::MouseMoved, this, &TimelineWidget::ViewMouseMoved);
connect(view, &TimelineView::MouseReleased, this, &TimelineWidget::ViewMouseReleased);
connect(view, &TimelineView::MouseDoubleClicked, this, &TimelineWidget::ViewMouseDoubleClicked);
connect(view, &TimelineView::DragEntered, this, &TimelineWidget::ViewDragEntered);
connect(view, &TimelineView::DragMoved, this, &TimelineWidget::ViewDragMoved);
connect(view, &TimelineView::DragLeft, this, &TimelineWidget::ViewDragLeft);
connect(view, &TimelineView::DragDropped, this, &TimelineWidget::ViewDragDropped);
connect(tview->splitter(), SIGNAL(splitterMoved(int, int)), this, SLOT(UpdateHorizontalSplitters()));
connect(tview->splitter(), &QSplitter::splitterMoved, this, &TimelineWidget::UpdateHorizontalSplitters);
// Connect each view's scroll to each other
foreach (TimelineAndTrackView* other_tview, views_) {
TimelineView* other_view = other_tview->view();
if (view != other_view) {
connect(view->horizontalScrollBar(), SIGNAL(valueChanged(int)), other_view->horizontalScrollBar(), SLOT(setValue(int)));
connect(view->horizontalScrollBar(), &QScrollBar::valueChanged, other_view->horizontalScrollBar(), &QScrollBar::setValue);
}
}
}
@@ -121,6 +114,7 @@ TimelineWidget::TimelineWidget(QWidget *parent) :
view_splitter->setSizes({INT_MAX, INT_MAX});
// FIXME: Magic number
SetMaximumScale(TimelineViewBase::kMaximumScale);
SetScale(90.0);
}
@@ -146,11 +140,10 @@ void TimelineWidget::Clear()
block_items_.clear();
}
void TimelineWidget::SetTimebase(const rational &timebase)
void TimelineWidget::TimebaseChangedEvent(const rational &timebase)
{
SetTimebaseInternal(timebase);
TimeBasedWidget::TimebaseChangedEvent(timebase);
ruler_->SetTimebase(timebase);
timecode_label_->SetTimebase(timebase);
timecode_label_->setVisible(!timebase.isNull());
@@ -162,36 +155,82 @@ void TimelineWidget::SetTimebase(const rational &timebase)
void TimelineWidget::resizeEvent(QResizeEvent *event)
{
QWidget::resizeEvent(event);
// Update horizontal scrollbar's page step to the width of the panel
horizontal_scroll_->setPageStep(horizontal_scroll_->width());
TimeBasedWidget::resizeEvent(event);
// Update timecode label size
UpdateTimecodeWidthFromSplitters(views_.first()->splitter());
}
void TimelineWidget::SetTime(int64_t timestamp)
void TimelineWidget::TimeChangedEvent(const int64_t& timestamp)
{
ruler_->SetTime(timestamp);
foreach (TimelineAndTrackView* view, views_) {
view->view()->SetTime(timestamp);
}
UpdateInternalTime(timestamp);
timecode_label_->SetValue(timestamp);
}
void TimelineWidget::ConnectTimelineNode(ViewerOutput *node)
void TimelineWidget::ScaleChangedEvent(const double &scale)
{
if (timeline_node_ != nullptr) {
disconnect(timeline_node_, &ViewerOutput::LengthChanged, this, &TimelineWidget::UpdateTimelineLength);
disconnect(timeline_node_, &ViewerOutput::BlockAdded, this, &TimelineWidget::AddBlock);
disconnect(timeline_node_, &ViewerOutput::BlockRemoved, this, &TimelineWidget::RemoveBlock);
disconnect(timeline_node_, &ViewerOutput::TrackAdded, this, &TimelineWidget::AddTrack);
disconnect(timeline_node_, &ViewerOutput::TrackRemoved, this, &TimelineWidget::RemoveTrack);
disconnect(timeline_node_, &ViewerOutput::TimebaseChanged, this, &TimelineWidget::SetTimebase);
disconnect(timeline_node_, &ViewerOutput::TrackHeightChanged, this, &TimelineWidget::TrackHeightChanged);
TimeBasedWidget::ScaleChangedEvent(scale);
QMapIterator<Block*, TimelineViewBlockItem*> iterator(block_items_);
while (iterator.hasNext()) {
iterator.next();
if (iterator.value() != nullptr) {
iterator.value()->SetScale(scale);
}
}
foreach (TimelineViewGhostItem* ghost, ghost_items_) {
ghost->SetScale(scale);
}
foreach (TimelineAndTrackView* view, views_) {
view->view()->SetScale(scale);
}
}
void TimelineWidget::ConnectNodeInternal(ViewerOutput *n)
{
connect(n, &ViewerOutput::LengthChanged, this, &TimelineWidget::UpdateTimelineLength);
connect(n, &ViewerOutput::BlockAdded, this, &TimelineWidget::AddBlock);
connect(n, &ViewerOutput::BlockRemoved, this, &TimelineWidget::RemoveBlock);
connect(n, &ViewerOutput::TrackAdded, this, &TimelineWidget::AddTrack);
connect(n, &ViewerOutput::TrackRemoved, this, &TimelineWidget::RemoveTrack);
connect(n, &ViewerOutput::TimebaseChanged, this, &TimelineWidget::SetTimebase);
connect(n, &ViewerOutput::TrackHeightChanged, this, &TimelineWidget::TrackHeightChanged);
SetTimebase(n->video_params().time_base());
for (int i=0;i<views_.size();i++) {
Timeline::TrackType track_type = static_cast<Timeline::TrackType>(i);
TimelineView* view = views_.at(i)->view();
TrackList* track_list = n->track_list(track_type);
TrackView* track_view = views_.at(i)->track_view();
track_view->ConnectTrackList(track_list);
view->ConnectTrackList(track_list);
view->SetEndTime(n->Length());
// Defer to the track to make all the block UI items necessary
foreach (TrackOutput* track, n->track_list(track_type)->Tracks()) {
AddTrack(track, track_type);
}
}
}
void TimelineWidget::DisconnectNodeInternal(ViewerOutput *n)
{
disconnect(n, &ViewerOutput::LengthChanged, this, &TimelineWidget::UpdateTimelineLength);
disconnect(n, &ViewerOutput::BlockAdded, this, &TimelineWidget::AddBlock);
disconnect(n, &ViewerOutput::BlockRemoved, this, &TimelineWidget::RemoveBlock);
disconnect(n, &ViewerOutput::TrackAdded, this, &TimelineWidget::AddTrack);
disconnect(n, &ViewerOutput::TrackRemoved, this, &TimelineWidget::RemoveTrack);
disconnect(n, &ViewerOutput::TimebaseChanged, this, &TimelineWidget::SetTimebase);
disconnect(n, &ViewerOutput::TrackHeightChanged, this, &TimelineWidget::TrackHeightChanged);
SetTimebase(0);
@@ -203,52 +242,6 @@ void TimelineWidget::ConnectTimelineNode(ViewerOutput *node)
}
}
timeline_node_ = node;
if (timeline_node_ != nullptr) {
connect(timeline_node_, &ViewerOutput::LengthChanged, this, &TimelineWidget::UpdateTimelineLength);
connect(timeline_node_, &ViewerOutput::BlockAdded, this, &TimelineWidget::AddBlock);
connect(timeline_node_, &ViewerOutput::BlockRemoved, this, &TimelineWidget::RemoveBlock);
connect(timeline_node_, &ViewerOutput::TrackAdded, this, &TimelineWidget::AddTrack);
connect(timeline_node_, &ViewerOutput::TrackRemoved, this, &TimelineWidget::RemoveTrack);
connect(timeline_node_, &ViewerOutput::TimebaseChanged, this, &TimelineWidget::SetTimebase);
connect(timeline_node_, &ViewerOutput::TrackHeightChanged, this, &TimelineWidget::TrackHeightChanged);
SetTimebase(timeline_node_->video_params().time_base());
for (int i=0;i<views_.size();i++) {
Timeline::TrackType track_type = static_cast<Timeline::TrackType>(i);
TimelineView* view = views_.at(i)->view();
TrackList* track_list = timeline_node_->track_list(track_type);
TrackView* track_view = views_.at(i)->track_view();
track_view->ConnectTrackList(track_list);
view->ConnectTrackList(track_list);
view->SetEndTime(timeline_node_->Length());
// Defer to the track to make all the block UI items necessary
foreach (TrackOutput* track, timeline_node_->track_list(track_type)->Tracks()) {
AddTrack(track, track_type);
}
}
}
}
void TimelineWidget::DisconnectTimelineNode()
{
ConnectTimelineNode(nullptr);
}
void TimelineWidget::ZoomIn()
{
SetScale(scale_ * 2);
}
void TimelineWidget::ZoomOut()
{
SetScale(scale_ * 0.5);
}
void TimelineWidget::SelectAll()
{
foreach (TimelineAndTrackView* view, views_) {
@@ -283,72 +276,13 @@ void TimelineWidget::EditToOut()
RippleEditTo(Timeline::kTrimOut, true);
}
void TimelineWidget::GoToPrevCut()
{
if (timeline_node_ == nullptr) {
return;
}
if (playhead_ == 0) {
return;
}
int64_t closest_cut = 0;
foreach (TrackOutput* track, timeline_node_->Tracks()) {
int64_t this_track_closest_cut = 0;
foreach (Block* block, track->Blocks()) {
int64_t block_out_ts = Timecode::time_to_timestamp(block->out(), timebase());
if (block_out_ts < playhead_) {
this_track_closest_cut = block_out_ts;
} else {
break;
}
}
closest_cut = qMax(closest_cut, this_track_closest_cut);
}
SetTimeAndSignal(closest_cut);
}
void TimelineWidget::GoToNextCut()
{
if (timeline_node_ == nullptr) {
return;
}
int64_t closest_cut = INT64_MAX;
foreach (TrackOutput* track, timeline_node_->Tracks()) {
int64_t this_track_closest_cut = Timecode::time_to_timestamp(track->track_length(), timebase());
if (this_track_closest_cut <= playhead_) {
this_track_closest_cut = INT64_MAX;
}
foreach (Block* block, track->Blocks()) {
int64_t block_in_ts = Timecode::time_to_timestamp(block->in(), timebase());
if (block_in_ts > playhead_) {
this_track_closest_cut = block_in_ts;
break;
}
}
closest_cut = qMin(closest_cut, this_track_closest_cut);
}
if (closest_cut < INT64_MAX) {
SetTimeAndSignal(closest_cut);
}
}
void TimelineWidget::SplitAtPlayhead()
{
rational playhead_time = Timecode::timestamp_to_time(playhead_, timebase());
if (!GetConnectedNode()) {
return;
}
rational playhead_time = Timecode::timestamp_to_time(GetTimestamp(), timebase());
QList<TimelineViewBlockItem *> selected_blocks = GetSelectedBlocks();
@@ -359,7 +293,7 @@ void TimelineWidget::SplitAtPlayhead()
bool some_blocks_are_selected = false;
// Get all blocks at the playhead
foreach (TrackOutput* track, timeline_node_->Tracks()) {
foreach (TrackOutput* track, GetConnectedNode()->Tracks()) {
Block* b = track->BlockContainingTime(playhead_time);
if (b && b->type() == Block::kClip) {
@@ -470,7 +404,7 @@ void TimelineWidget::DeleteSelected()
// Clean each track
foreach (const TrackReference& track, tracks_affected) {
new TrackCleanGapsCommand(timeline_node_->track_list(track.type()),
new TrackCleanGapsCommand(GetConnectedNode()->track_list(track.type()),
track.index(),
command);
}
@@ -480,11 +414,11 @@ void TimelineWidget::DeleteSelected()
void TimelineWidget::IncreaseTrackHeight()
{
if (!timeline_node_) {
if (!GetConnectedNode()) {
return;
}
QVector<TrackOutput*> all_tracks = timeline_node_->Tracks();
QVector<TrackOutput*> all_tracks = GetConnectedNode()->Tracks();
// Increase the height of each track by one "unit"
foreach (TrackOutput* t, all_tracks) {
@@ -494,11 +428,11 @@ void TimelineWidget::IncreaseTrackHeight()
void TimelineWidget::DecreaseTrackHeight()
{
if (!timeline_node_) {
if (!GetConnectedNode()) {
return;
}
QVector<TrackOutput*> all_tracks = timeline_node_->Tracks();
QVector<TrackOutput*> all_tracks = GetConnectedNode()->Tracks();
// Decrease the height of each track by one "unit"
foreach (TrackOutput* t, all_tracks) {
@@ -517,7 +451,7 @@ QList<TimelineViewBlockItem *> TimelineWidget::GetSelectedBlocks()
TimelineViewBlockItem* item = iterator.value();
if (item != nullptr && item->isSelected()) {
if (item && item->isSelected()) {
list.append(item);
}
}
@@ -525,14 +459,9 @@ QList<TimelineViewBlockItem *> TimelineWidget::GetSelectedBlocks()
return list;
}
ViewerOutput *TimelineWidget::GetConnectedNode() const
{
return timeline_node_;
}
void TimelineWidget::RippleEditTo(Timeline::MovementMode mode, bool insert_gaps)
{
rational playhead_time = Timecode::timestamp_to_time(playhead_, timebase());
rational playhead_time = GetTime();
rational closest_point_to_playhead;
if (mode == Timeline::kTrimIn) {
@@ -541,7 +470,7 @@ void TimelineWidget::RippleEditTo(Timeline::MovementMode mode, bool insert_gaps)
closest_point_to_playhead = RATIONAL_MAX;
}
foreach (TrackOutput* track, timeline_node_->Tracks()) {
foreach (TrackOutput* track, GetConnectedNode()->Tracks()) {
Block* b = track->NearestBlockBefore(playhead_time);
if (b != nullptr) {
@@ -568,7 +497,7 @@ void TimelineWidget::RippleEditTo(Timeline::MovementMode mode, bool insert_gaps)
rational out_ripple = qMax(closest_point_to_playhead, playhead_time);
rational ripple_length = out_ripple - in_ripple;
foreach (TrackOutput* track, timeline_node_->Tracks()) {
foreach (TrackOutput* track, GetConnectedNode()->Tracks()) {
GapBlock* gap = nullptr;
if (insert_gaps) {
gap = new GapBlock();
@@ -595,15 +524,9 @@ void TimelineWidget::RippleEditTo(Timeline::MovementMode mode, bool insert_gaps)
}
}
void TimelineWidget::SetTimeAndSignal(const int64_t &t)
{
SetTime(t);
emit TimeChanged(t);
}
TrackOutput *TimelineWidget::GetTrackFromReference(const TrackReference &ref)
{
return timeline_node_->track_list(ref.type())->TrackAt(ref.index());
return GetConnectedNode()->track_list(ref.type())->TrackAt(ref.index());
}
int TimelineWidget::GetTrackY(const TrackReference &ref)
@@ -618,32 +541,7 @@ int TimelineWidget::GetTrackHeight(const TrackReference &ref)
void TimelineWidget::CenterOn(qreal scene_pos)
{
horizontal_scroll_->setValue(qRound(scene_pos - horizontal_scroll_->width()/2));
}
void TimelineWidget::SetScale(double scale, bool center_on_playhead)
{
scale_ = qMin(scale, TimelineViewBase::kMaximumScale);
ruler_->SetScale(scale_);
QMapIterator<Block*, TimelineViewBlockItem*> iterator(block_items_);
while (iterator.hasNext()) {
iterator.next();
if (iterator.value() != nullptr) {
iterator.value()->SetScale(scale_);
}
}
foreach (TimelineViewGhostItem* ghost, ghost_items_) {
ghost->SetScale(scale_);
}
foreach (TimelineAndTrackView* view, views_) {
view->view()->SetScale(scale_, center_on_playhead);
}
scrollbar()->setValue(qRound(scene_pos - scrollbar()->width()/2));
}
void TimelineWidget::ClearGhosts()
@@ -662,12 +560,6 @@ bool TimelineWidget::HasGhosts()
return !ghost_items_.isEmpty();
}
void TimelineWidget::UpdateInternalTime(const int64_t &timestamp)
{
playhead_ = timestamp;
timecode_label_->SetValue(timestamp);
}
void TimelineWidget::UpdateTimelineLength(const rational &length)
{
foreach (TimelineAndTrackView* view, views_) {
@@ -684,14 +576,14 @@ void TimelineWidget::ViewMousePressed(TimelineViewMouseEvent *event)
{
active_tool_ = GetActiveTool();
if (timeline_node_ != nullptr && active_tool_ != nullptr) {
if (GetConnectedNode() && active_tool_ != nullptr) {
active_tool_->MousePress(event);
}
}
void TimelineWidget::ViewMouseMoved(TimelineViewMouseEvent *event)
{
if (timeline_node_) {
if (GetConnectedNode()) {
if (active_tool_) {
active_tool_->MouseMove(event);
} else {
@@ -707,7 +599,7 @@ void TimelineWidget::ViewMouseMoved(TimelineViewMouseEvent *event)
void TimelineWidget::ViewMouseReleased(TimelineViewMouseEvent *event)
{
if (timeline_node_ != nullptr && active_tool_ != nullptr) {
if (GetConnectedNode() && active_tool_ != nullptr) {
active_tool_->MouseRelease(event);
active_tool_ = nullptr;
}
@@ -715,7 +607,7 @@ void TimelineWidget::ViewMouseReleased(TimelineViewMouseEvent *event)
void TimelineWidget::ViewMouseDoubleClicked(TimelineViewMouseEvent *event)
{
if (timeline_node_ != nullptr && active_tool_ != nullptr) {
if (GetConnectedNode() && active_tool_ != nullptr) {
active_tool_->MouseDoubleClick(event);
active_tool_ = nullptr;
}
@@ -723,28 +615,28 @@ void TimelineWidget::ViewMouseDoubleClicked(TimelineViewMouseEvent *event)
void TimelineWidget::ViewDragEntered(TimelineViewMouseEvent *event)
{
if (timeline_node_ != nullptr) {
if (GetConnectedNode()) {
import_tool_->DragEnter(event);
}
}
void TimelineWidget::ViewDragMoved(TimelineViewMouseEvent *event)
{
if (timeline_node_ != nullptr) {
if (GetConnectedNode()) {
import_tool_->DragMove(event);
}
}
void TimelineWidget::ViewDragLeft(QDragLeaveEvent *event)
{
if (timeline_node_ != nullptr) {
if (GetConnectedNode()) {
import_tool_->DragLeave(event);
}
}
void TimelineWidget::ViewDragDropped(TimelineViewMouseEvent *event)
{
if (timeline_node_ != nullptr) {
if (GetConnectedNode()) {
import_tool_->DragDrop(event);
}
}
@@ -761,7 +653,7 @@ void TimelineWidget::AddBlock(Block *block, TrackReference track)
// Set up clip with view parameters (clip item will automatically size its rect accordingly)
item->SetBlock(block);
item->SetYCoords(GetTrackY(track), GetTrackHeight(track));
item->SetScale(scale_);
item->SetScale(GetScale());
item->SetTrack(track);
// Add to list of clip items that can be iterated through
@@ -770,7 +662,7 @@ void TimelineWidget::AddBlock(Block *block, TrackReference track)
// Add item to graphics scene
views_.at(track.type())->view()->scene()->addItem(item);
connect(block, SIGNAL(Refreshed()), this, SLOT(BlockChanged()));
connect(block, &Block::Refreshed, this, &TimelineWidget::BlockChanged);
break;
}
}
@@ -854,7 +746,7 @@ void TimelineWidget::ShowContextMenu()
if (!selected.isEmpty()) {
QAction* speed_duration_action = menu.addAction(tr("Speed/Duration"));
connect(speed_duration_action, SIGNAL(triggered(bool)), this, SLOT(ShowSpeedDurationDialog()));
connect(speed_duration_action, &QAction::triggered, this, &TimelineWidget::ShowSpeedDurationDialog);
}
menu.exec(QCursor::pos());
@@ -882,12 +774,12 @@ void TimelineWidget::ShowSpeedDurationDialog()
void TimelineWidget::DeferredScrollAction()
{
horizontal_scroll_->setValue(deferred_scroll_value_);
scrollbar()->setValue(deferred_scroll_value_);
}
void TimelineWidget::AddGhost(TimelineViewGhostItem *ghost)
{
ghost->SetScale(scale_);
ghost->SetScale(GetScale());
ghost_items_.append(ghost);
views_.at(ghost->Track().type())->view()->scene()->addItem(ghost);
}
+8 -38
View File
@@ -9,15 +9,14 @@
#include "timelineandtrackview.h"
#include "node/output/viewer/viewer.h"
#include "widget/slider/timeslider.h"
#include "widget/timelinewidget/timelinescaledobject.h"
#include "widget/timeruler/timeruler.h"
#include "widget/timebased/timebased.h"
/**
* @brief Full widget for working with TimelineOutput nodes
*
* Encapsulates TimelineViews, TimeRulers, and scrollbars for a complete widget to manipulate Timelines
*/
class TimelineWidget : public QWidget, public TimelineScaledObject
class TimelineWidget : public TimeBasedWidget
{
Q_OBJECT
public:
@@ -27,16 +26,6 @@ public:
void Clear();
void SetTime(int64_t timestamp);
void ConnectTimelineNode(ViewerOutput *node);
void DisconnectTimelineNode();
void ZoomIn();
void ZoomOut();
void SelectAll();
void DeselectAll();
@@ -49,10 +38,6 @@ public:
void EditToOut();
void GoToPrevCut();
void GoToNextCut();
void SplitAtPlayhead();
void DeleteSelected();
@@ -63,16 +48,15 @@ public:
QList<TimelineViewBlockItem*> GetSelectedBlocks();
ViewerOutput* GetConnectedNode() const;
public slots:
void SetTimebase(const rational& timebase);
protected:
virtual void resizeEvent(QResizeEvent *event) override;
signals:
void TimeChanged(const int64_t& time);
virtual void TimebaseChangedEvent(const rational &) override;
virtual void TimeChangedEvent(const int64_t &) override;
virtual void ScaleChangedEvent(const double &) override;
virtual void ConnectNodeInternal(ViewerOutput* n) override;
virtual void DisconnectNodeInternal(ViewerOutput* n) override;
private:
class Tool
@@ -364,20 +348,10 @@ private:
void RippleEditTo(Timeline::MovementMode mode, bool insert_gaps);
void SetTimeAndSignal(const int64_t& t);
TrackOutput* GetTrackFromReference(const TrackReference& ref);
QList<TimelineAndTrackView*> views_;
TimeRuler* ruler_;
ViewerOutput* timeline_node_;
int64_t playhead_;
QScrollBar* horizontal_scroll_;
TimeSlider* timecode_label_;
int deferred_scroll_value_;
@@ -390,10 +364,6 @@ private:
void AddGhost(TimelineViewGhostItem* ghost);
private slots:
void SetScale(double scale, bool center_on_playhead = true);
void UpdateInternalTime(const int64_t& timestamp);
void UpdateTimelineLength(const rational& length);
void ViewMousePressed(TimelineViewMouseEvent* event);
+2 -2
View File
@@ -51,11 +51,11 @@ void TimelineWidget::AddTool::MouseRelease(TimelineViewMouseEvent *event)
ClipBlock* clip = new ClipBlock();
clip->set_length_and_media_out(ghost_->AdjustedLength());
new NodeAddCommand(static_cast<NodeGraph*>(parent()->timeline_node_->parent()),
new NodeAddCommand(static_cast<NodeGraph*>(parent()->GetConnectedNode()->parent()),
clip,
command);
new TrackPlaceBlockCommand(parent()->timeline_node_->track_list(track.type()),
new TrackPlaceBlockCommand(parent()->GetConnectedNode()->track_list(track.type()),
track.index(),
clip,
ghost_->GetAdjustedIn(),
+2 -2
View File
@@ -217,7 +217,7 @@ void TimelineWidget::ImportTool::DragDrop(TimelineViewMouseEvent *event)
{
if (parent()->HasGhosts()) {
QUndoCommand* command = new QUndoCommand();
NodeGraph* dst_graph = static_cast<NodeGraph*>(parent()->timeline_node_->parent());
NodeGraph* dst_graph = static_cast<NodeGraph*>(parent()->GetConnectedNode()->parent());
QVector<Block*> block_items(parent()->ghost_items_.size());
@@ -269,7 +269,7 @@ void TimelineWidget::ImportTool::DragDrop(TimelineViewMouseEvent *event)
if (event->GetModifiers() & Qt::ControlModifier) {
//emit parent()->RequestInsertBlockAtTime(clip, ghost->GetAdjustedIn());
} else {
new TrackPlaceBlockCommand(parent()->timeline_node_->track_list(ghost->GetAdjustedTrack().type()),
new TrackPlaceBlockCommand(parent()->GetConnectedNode()->track_list(ghost->GetAdjustedTrack().type()),
ghost->GetAdjustedTrack().index(),
clip,
ghost->GetAdjustedIn(),
+2 -2
View File
@@ -274,7 +274,7 @@ void TimelineWidget::PointerTool::MouseReleaseInternal(TimelineViewMouseEvent *e
command);
} else {
// Normal block placement
new TrackPlaceBlockCommand(parent()->timeline_node_->track_list(track_ref.type()),
new TrackPlaceBlockCommand(parent()->GetConnectedNode()->track_list(track_ref.type()),
track_ref.index(),
b,
ghost->GetAdjustedIn(),
@@ -284,7 +284,7 @@ void TimelineWidget::PointerTool::MouseReleaseInternal(TimelineViewMouseEvent *e
if (command->childCount() > 0) {
foreach (const TrackReference& t, tracks_affected) {
new TrackCleanGapsCommand(parent()->timeline_node_->track_list(t.type()),
new TrackCleanGapsCommand(parent()->GetConnectedNode()->track_list(t.type()),
t.index(),
command);
}
+2 -2
View File
@@ -49,7 +49,7 @@ void TimelineWidget::RippleTool::MouseReleaseInternal(TimelineViewMouseEvent *ev
if (ghost->AdjustedLength() > 0) {
GapBlock* gap = new GapBlock();
gap->set_length_and_media_out(ghost->AdjustedLength());
new NodeAddCommand(static_cast<NodeGraph*>(parent()->timeline_node_->parent()), gap, command);
new NodeAddCommand(static_cast<NodeGraph*>(parent()->GetConnectedNode()->parent()), gap, command);
Block* block_to_append_gap_to = Node::ValueToPtr<Block>(ghost->data(TimelineViewGhostItem::kReferenceBlock));
@@ -116,7 +116,7 @@ void TimelineWidget::RippleTool::InitiateGhosts(TimelineViewBlockItem *clicked_i
}
// For each track that does NOT have a ghost, we need to make one for Gaps
foreach (TrackOutput* track, parent()->timeline_node_->Tracks()) {
foreach (TrackOutput* track, parent()->GetConnectedNode()->Tracks()) {
// Determine if we've already created a ghost on this track
bool ghost_on_this_track_exists = false;
+1 -1
View File
@@ -56,7 +56,7 @@ void TimelineWidget::RollingTool::MouseReleaseInternal(TimelineViewMouseEvent *e
if (b->previous() == nullptr) {
const TrackReference& track_ref = ghost->Track();
new TrackPlaceBlockCommand(parent()->timeline_node_->track_list(track_ref.type()),
new TrackPlaceBlockCommand(parent()->GetConnectedNode()->track_list(track_ref.type()),
track_ref.index(),
b,
ghost->GetAdjustedIn(),
+3 -3
View File
@@ -157,16 +157,16 @@ bool TimelineWidget::Tool::SnapPoint(QList<rational> start_times, rational* move
QList<double> proposed_pts;
foreach (rational s, start_times) {
proposed_pts.append((s + *movement).toDouble() * parent()->scale_);
proposed_pts.append((s + *movement).toDouble() * parent()->GetScale());
}
if (snap_points & kSnapToPlayhead) {
rational playhead_abs_time = rational(parent()->playhead_ * parent()->timebase().numerator(),
rational playhead_abs_time = rational(parent()->GetTimestamp() * parent()->timebase().numerator(),
parent()->timebase().denominator());
qreal playhead_pos = playhead_abs_time.toDouble() * parent()->scale_;
qreal playhead_pos = playhead_abs_time.toDouble() * parent()->GetScale();
AttemptSnap(proposed_pts, playhead_pos, start_times, playhead_abs_time, movement, &diff);
}
@@ -94,11 +94,11 @@ void TimelineWidget::TransitionTool::MouseRelease(TimelineViewMouseEvent *event)
QUndoCommand* command = new QUndoCommand();
// Place transition in place
new NodeAddCommand(static_cast<NodeGraph*>(parent()->timeline_node_->parent()),
new NodeAddCommand(static_cast<NodeGraph*>(parent()->GetConnectedNode()->parent()),
transition,
command);
new TrackPlaceBlockCommand(parent()->timeline_node_->track_list(track.type()),
new TrackPlaceBlockCommand(parent()->GetConnectedNode()->track_list(track.type()),
track.index(),
transition,
ghost_->GetAdjustedIn(),
+5 -5
View File
@@ -59,17 +59,17 @@ void TimelineWidget::ZoomTool::MouseRelease(TimelineViewMouseEvent *event)
double scene_right = scene_bottomright.x();
// Normalize scale to 1.0 scale
double scene_width = (scene_right - scene_left) / parent()->scale_;
double scene_width = (scene_right - scene_left) / parent()->GetScale();
double new_scale = qMin(TimelineViewBase::kMaximumScale, static_cast<double>(reference_view->viewport()->width()) / scene_width);
parent()->deferred_scroll_value_ = qMax(0, qRound(scene_left / parent()->scale_ * new_scale));
parent()->deferred_scroll_value_ = qMax(0, qRound(scene_left / parent()->GetScale() * new_scale));
parent()->SetScale(new_scale, false);
parent()->SetScale(new_scale);
dragging_ = false;
} else {
// Simple zoom in/out at the cursor position
double scale = parent()->scale_;
double scale = parent()->GetScale();
if (event->GetModifiers() & Qt::AltModifier) {
// Zoom out if the user clicks while holding Alt
@@ -79,7 +79,7 @@ void TimelineWidget::ZoomTool::MouseRelease(TimelineViewMouseEvent *event)
scale *= 2.0;
}
parent()->SetScale(scale, false);
parent()->SetScale(scale);
// Adjust scroll location for new scale
double frame_x = event->GetFrame().toDouble() * scale;
@@ -267,7 +267,7 @@ TimelineViewMouseEvent TimelineView::CreateMouseEvent(const QPoint& pos, Qt::Key
QPointF scene_pt = mapToScene(pos);
TimelineViewMouseEvent timeline_event(scene_pt.x(),
scale_,
GetScale(),
timebase(),
TrackReference(ConnectedTrackType(), SceneToTrack(scene_pt.y())),
modifiers);
@@ -27,7 +27,7 @@ TimelineViewBase::TimelineViewBase(QWidget *parent) :
scene_.addItem(end_item_);
// Set default scale
SetScale(1.0, true);
SetScaleAndCenterOnPlayhead(1.0);
SetDefaultDragMode(NoDrag);
@@ -35,30 +35,12 @@ TimelineViewBase::TimelineViewBase(QWidget *parent) :
connect(&scene_, SIGNAL(changed(const QList<QRectF>&)), this, SLOT(UpdateSceneRect()));
connect(Core::instance(), &Core::ToolChanged, this, &TimelineViewBase::ApplicationToolChanged);
SetMaximumScale(kMaximumScale);
}
void TimelineViewBase::SetScale(const double &scale, bool center_on_playhead)
void TimelineViewBase::TimebaseChangedEvent(const rational &)
{
scale_ = qMin(scale, kMaximumScale);
end_item_->SetScale(scale_);
ScaleChangedEvent(scale_);
// Force redraw for playhead
viewport()->update();
if (center_on_playhead) {
// Zoom towards the playhead
// (using a hacky singleShot so the scroll occurs after the scene and its scrollbars have updated)
QTimer::singleShot(0, this, &TimelineViewBase::CenterScrollOnPlayhead);
}
}
void TimelineViewBase::SetTimebase(const rational &timebase)
{
SetTimebaseInternal(timebase);
// Timebase influences position/visibility of playhead
viewport()->update();
}
@@ -298,9 +280,23 @@ void TimelineViewBase::resizeEvent(QResizeEvent *event)
UpdateSceneRect();
}
void TimelineViewBase::ScaleChangedEvent(double scale)
void TimelineViewBase::ScaleChangedEvent(const double &scale)
{
Q_UNUSED(scale)
TimelineScaledObject::ScaleChangedEvent(scale);
end_item_->SetScale(scale);
// Force redraw for playhead
viewport()->update();
}
void TimelineViewBase::SetScaleAndCenterOnPlayhead(const double &scale)
{
SetScale(scale);
// Zoom towards the playhead
// (using a hacky singleShot so the scroll occurs after the scene and its scrollbars have updated)
QTimer::singleShot(0, this, &TimelineViewBase::CenterScrollOnPlayhead);
}
bool TimelineViewBase::HandleZoomFromScroll(QWheelEvent *event)
@@ -309,9 +305,9 @@ bool TimelineViewBase::HandleZoomFromScroll(QWheelEvent *event)
// If CTRL is held (or a preference is set to swap CTRL behavior), we zoom instead of scrolling
if (event->delta() != 0) {
if (event->delta() > 0) {
emit ScaleChanged(scale_ * 2.0);
emit ScaleChanged(GetScale() * 2.0);
} else {
emit ScaleChanged(scale_ * 0.5);
emit ScaleChanged(GetScale() * 0.5);
}
}
@@ -14,15 +14,13 @@ class TimelineViewBase : public QGraphicsView, public TimelineScaledObject
public:
TimelineViewBase(QWidget* parent = nullptr);
void SetScale(const double& scale, bool center_on_playhead);
void SetEndTime(const rational& length);
void SetScaleAndCenterOnPlayhead(const double& scale);
static const double kMaximumScale;
public slots:
void SetTimebase(const rational& timebase);
void SetTime(const int64_t time);
signals:
@@ -35,7 +33,7 @@ protected:
virtual void resizeEvent(QResizeEvent *event) override;
virtual void ScaleChangedEvent(double scale);
virtual void ScaleChangedEvent(const double& scale) override;
bool HandleZoomFromScroll(QWheelEvent* event);
@@ -58,6 +56,8 @@ protected:
virtual void ToolChangedEvent(Tool::Item tool);
virtual void TimebaseChangedEvent(const rational &) override;
private:
qreal GetPlayheadX();
@@ -46,9 +46,9 @@ void TimelineViewRect::SetTrack(const TrackReference &track)
track_ = track;
}
void TimelineViewRect::SetScale(const double &scale)
void TimelineViewRect::ScaleChangedEvent(const double &scale)
{
scale_ = scale;
TimelineScaledObject::ScaleChangedEvent(scale);
UpdateRect();
}
@@ -39,11 +39,11 @@ public:
const TrackReference& Track();
void SetTrack(const TrackReference& track);
void SetScale(const double& scale);
virtual void UpdateRect() = 0;
protected:
virtual void ScaleChangedEvent(const double &) override;
int y_;
int height_;
+2 -2
View File
@@ -58,7 +58,7 @@ TimeRuler::TimeRuler(bool text_visible, bool cache_status_visible, QWidget* pare
UpdateHeight();
}
const double &TimeRuler::scale()
const double &TimeRuler::GetScale()
{
return scale_;
}
@@ -174,7 +174,7 @@ void TimeRuler::paintEvent(QPaintEvent *)
}
if (short_interval < minimum_gap_between_lines_) {
if (long_interval == -1) {
if (long_interval <= 0) {
do {
short_interval *= 2;
} while (short_interval < minimum_gap_between_lines_);
+1 -1
View File
@@ -34,7 +34,7 @@ class TimeRuler : public QWidget
public:
TimeRuler(bool text_visible = true, bool cache_status_visible = false, QWidget* parent = nullptr);
const double& scale();
const double& GetScale();
void SetScale(const double& d);
void SetTimebase(const rational& r);
+93 -156
View File
@@ -35,11 +35,12 @@
#include "widget/menu/menu.h"
ViewerWidget::ViewerWidget(QWidget *parent) :
QWidget(parent),
viewer_node_(nullptr),
TimeBasedWidget(false, true, parent),
playback_speed_(0),
color_menu_enabled_(true),
divider_(Config::Current()["DefaultViewerDivider"].toInt())
divider_(Config::Current()["DefaultViewerDivider"].toInt()),
override_color_manager_(nullptr),
time_changed_from_timer_(false)
{
// Set up main layout
QVBoxLayout* layout = new QVBoxLayout(this);
@@ -54,15 +55,11 @@ ViewerWidget::ViewerWidget(QWidget *parent) :
sizer_->SetWidget(gl_widget_);
// Create time ruler
ruler_ = new TimeRuler(false, true);
layout->addWidget(ruler_);
connect(ruler_, &TimeRuler::TimeChanged, this, &ViewerWidget::RulerTimeChange);
layout->addWidget(ruler());
// Create scrollbar
scrollbar_ = new QScrollBar(Qt::Horizontal);
layout->addWidget(scrollbar_);
connect(scrollbar_, &QScrollBar::valueChanged, ruler_, &TimeRuler::SetScroll);
scrollbar_->setPageStep(ruler_->width());
layout->addWidget(scrollbar());
connect(scrollbar(), &QScrollBar::valueChanged, ruler(), &TimeRuler::SetScroll);
// Create lower controls
controls_ = new PlaybackControls();
@@ -74,58 +71,87 @@ ViewerWidget::ViewerWidget(QWidget *parent) :
connect(controls_, &PlaybackControls::NextFrameClicked, this, &ViewerWidget::NextFrame);
connect(controls_, &PlaybackControls::BeginClicked, this, &ViewerWidget::GoToStart);
connect(controls_, &PlaybackControls::EndClicked, this, &ViewerWidget::GoToEnd);
connect(controls_, &PlaybackControls::TimeChanged, this, &ViewerWidget::SetTimeAndSignal);
layout->addWidget(controls_);
// Connect timer
connect(&playback_timer_, &QTimer::timeout, this, &ViewerWidget::PlaybackTimerUpdate);
// FIXME: Magic number
ruler_->SetScale(48.0);
ruler()->SetScale(48.0);
// Start background renderers
video_renderer_ = new OpenGLBackend(this);
connect(video_renderer_, &VideoRenderBackend::CachedFrameReady, this, &ViewerWidget::RendererCachedFrame);
connect(video_renderer_, &VideoRenderBackend::CachedTimeReady, this, &ViewerWidget::RendererCachedTime);
connect(video_renderer_, &VideoRenderBackend::CachedTimeReady, ruler_, &TimeRuler::CacheTimeReady);
connect(video_renderer_, &VideoRenderBackend::RangeInvalidated, ruler_, &TimeRuler::CacheInvalidatedRange);
connect(video_renderer_, &VideoRenderBackend::CachedTimeReady, ruler(), &TimeRuler::CacheTimeReady);
connect(video_renderer_, &VideoRenderBackend::RangeInvalidated, ruler(), &TimeRuler::CacheInvalidatedRange);
audio_renderer_ = new AudioBackend(this);
connect(PixelService::instance(), &PixelService::FormatChanged, this, &ViewerWidget::UpdateRendererParameters);
}
void ViewerWidget::SetTimebase(const rational &r)
void ViewerWidget::TimeChangedEvent(const int64_t &i)
{
time_base_ = r;
time_base_dbl_ = r.toDouble();
ruler_->SetTimebase(r);
controls_->SetTimebase(r);
controls_->SetTime(ruler_->GetTime());
LengthChangedSlot(viewer_node_ ? viewer_node_->Length() : 0);
playback_timer_.setInterval(qFloor(r.toDouble()));
if (!time_changed_from_timer_) {
Pause();
}
const double &ViewerWidget::scale() const
{
return ruler_->scale();
controls_->SetTime(i);
if (GetConnectedNode() && last_time_ != i) {
rational time_set = Timecode::timestamp_to_time(i, timebase());
UpdateTextureFromNode(time_set);
PushScrubbedAudio();
}
rational ViewerWidget::GetTime() const
{
return Timecode::timestamp_to_time(ruler_->GetTime(), time_base_);
last_time_ = i;
}
void ViewerWidget::SetScale(const double &scale_)
void ViewerWidget::ConnectNodeInternal(ViewerOutput *n)
{
ruler_->SetScale(scale_);
SetTimebase(n->video_params().time_base());
connect(n, &ViewerOutput::TimebaseChanged, this, &ViewerWidget::SetTimebase);
connect(n, &ViewerOutput::SizeChanged, this, &ViewerWidget::SizeChangedSlot);
connect(n, &ViewerOutput::LengthChanged, this, &ViewerWidget::LengthChangedSlot);
connect(n, &ViewerOutput::VisibleInvalidated, this, &ViewerWidget::InvalidateVisible);
SizeChangedSlot(n->video_params().width(), n->video_params().height());
LengthChangedSlot(n->Length());
if (override_color_manager_) {
gl_widget_->ConnectColorManager(override_color_manager_);
} else if (n->parent()) {
gl_widget_->ConnectColorManager(static_cast<Sequence*>(n->parent())->project()->color_manager());
} else {
qWarning() << "Failed to find a suitable color manager for the connected viewer node";
}
void ViewerWidget::SetTime(const int64_t &time)
UpdateRendererParameters();
}
void ViewerWidget::DisconnectNodeInternal(ViewerOutput *n)
{
ruler_->SetTime(time);
UpdateTimeInternal(time);
SetTimebase(0);
disconnect(n, &ViewerOutput::TimebaseChanged, this, &ViewerWidget::SetTimebase);
disconnect(n, &ViewerOutput::SizeChanged, this, &ViewerWidget::SizeChangedSlot);
disconnect(n, &ViewerOutput::LengthChanged, this, &ViewerWidget::LengthChangedSlot);
disconnect(n, &ViewerOutput::VisibleInvalidated, this, &ViewerWidget::InvalidateVisible);
// Effectively disables the viewer and clears the state
SizeChangedSlot(0, 0);
gl_widget_->DisconnectColorManager();
}
void ViewerWidget::ConnectedNodeChanged(ViewerOutput *n)
{
video_renderer_->SetViewerNode(n);
audio_renderer_->SetViewerNode(n);
}
void ViewerWidget::TogglePlayPause()
@@ -144,54 +170,12 @@ bool ViewerWidget::IsPlaying() const
void ViewerWidget::ConnectViewerNode(ViewerOutput *node, ColorManager* color_manager)
{
if (viewer_node_ != nullptr) {
SetTimebase(0);
override_color_manager_ = color_manager;
disconnect(viewer_node_, &ViewerOutput::TimebaseChanged, this, &ViewerWidget::SetTimebase);
disconnect(viewer_node_, &ViewerOutput::SizeChanged, this, &ViewerWidget::SizeChangedSlot);
disconnect(viewer_node_, &ViewerOutput::LengthChanged, this, &ViewerWidget::LengthChangedSlot);
disconnect(viewer_node_, &ViewerOutput::VisibleInvalidated, this, &ViewerWidget::InvalidateVisible);
// Effectively disables the viewer and clears the state
SizeChangedSlot(0, 0);
gl_widget_->DisconnectColorManager();
}
viewer_node_ = node;
video_renderer_->SetViewerNode(viewer_node_);
audio_renderer_->SetViewerNode(viewer_node_);
TimeBasedWidget::ConnectViewerNode(node);
// Set texture to new texture (or null if no viewer node is available)
UpdateTextureFromNode(GetTime());
if (viewer_node_ != nullptr) {
SetTimebase(viewer_node_->video_params().time_base());
connect(viewer_node_, &ViewerOutput::TimebaseChanged, this, &ViewerWidget::SetTimebase);
connect(viewer_node_, &ViewerOutput::SizeChanged, this, &ViewerWidget::SizeChangedSlot);
connect(viewer_node_, &ViewerOutput::LengthChanged, this, &ViewerWidget::LengthChangedSlot);
connect(viewer_node_, &ViewerOutput::VisibleInvalidated, this, &ViewerWidget::InvalidateVisible);
SizeChangedSlot(viewer_node_->video_params().width(), viewer_node_->video_params().height());
LengthChangedSlot(viewer_node_->Length());
if (color_manager) {
gl_widget_->ConnectColorManager(color_manager);
} else if (viewer_node_->parent()) {
gl_widget_->ConnectColorManager(static_cast<Sequence*>(viewer_node_->parent())->project()->color_manager());
} else {
qWarning() << "Failed to find a suitable color manager for the connected viewer node";
}
UpdateRendererParameters();
}
}
ViewerOutput *ViewerWidget::GetConnectedViewer() const
{
return viewer_node_;
}
void ViewerWidget::SetColorMenuEnabled(bool enabled)
@@ -219,26 +203,9 @@ void ViewerWidget::SetTexture(OpenGLTexturePtr tex)
gl_widget_->SetTexture(tex);
}
void ViewerWidget::UpdateTimeInternal(int64_t i)
{
rational time_set = rational(i) * time_base_;
controls_->SetTime(i);
if (viewer_node_ != nullptr && last_time_ != i) {
UpdateTextureFromNode(time_set);
PushScrubbedAudio();
}
last_time_ = i;
emit TimeChanged(i);
}
void ViewerWidget::UpdateTextureFromNode(const rational& time)
{
if (viewer_node_ == nullptr) {
if (!GetConnectedNode()) {
SetTexture(nullptr);
} else {
SetTexture(video_renderer_->GetCachedFrameAsTexture(time));
@@ -249,7 +216,7 @@ void ViewerWidget::PlayInternal(int speed)
{
Q_ASSERT(speed != 0);
if (time_base_.isNull()) {
if (timebase().isNull()) {
qWarning() << "ViewerWidget can't play with an invalid timebase";
return;
}
@@ -264,7 +231,7 @@ void ViewerWidget::PlayInternal(int speed)
}
start_msec_ = QDateTime::currentMSecsSinceEpoch();
start_timestamp_ = ruler_->GetTime();
start_timestamp_ = ruler()->GetTime();
playback_timer_.start();
@@ -273,13 +240,13 @@ void ViewerWidget::PlayInternal(int speed)
void ViewerWidget::PushScrubbedAudio()
{
if (Config::Current()["AudioScrubbing"].toBool() && !IsPlaying()) {
if (!IsPlaying() && Config::Current()["AudioScrubbing"].toBool()) {
// Get audio src device from renderer
QIODevice* audio_src = audio_renderer_->GetAudioPullDevice();
if (audio_src != nullptr && audio_src->open(QFile::ReadOnly)) {
if (audio_src && audio_src->open(QFile::ReadOnly)) {
// Try to get one "frame" of audio
int size_of_sample = audio_renderer_->params().time_to_bytes(time_base_);
int size_of_sample = audio_renderer_->params().time_to_bytes(timebase());
// Push audio
audio_src->seek(audio_renderer_->params().time_to_bytes(GetTime()));
@@ -294,20 +261,20 @@ void ViewerWidget::PushScrubbedAudio()
void ViewerWidget::UpdateRendererParameters()
{
if (!viewer_node_) {
if (!GetConnectedNode()) {
return;
}
RenderMode::Mode render_mode = RenderMode::kOffline;
video_renderer_->SetParameters(VideoRenderingParams(viewer_node_->video_params(),
video_renderer_->SetParameters(VideoRenderingParams(GetConnectedNode()->video_params(),
PixelService::instance()->GetConfiguredFormatForMode(render_mode),
render_mode,
divider_));
audio_renderer_->SetParameters(AudioRenderingParams(viewer_node_->audio_params(),
audio_renderer_->SetParameters(AudioRenderingParams(GetConnectedNode()->audio_params(),
SampleFormat::GetConfiguredFormatForMode(render_mode)));
video_renderer_->InvalidateCache(0, viewer_node_->Length());
video_renderer_->InvalidateCache(0, GetConnectedNode()->Length());
}
void ViewerWidget::ShowContextMenu(const QPoint &pos)
@@ -371,13 +338,6 @@ void ViewerWidget::ShowContextMenu(const QPoint &pos)
menu.exec(mapToGlobal(pos));
}
void ViewerWidget::RulerTimeChange(int64_t i)
{
Pause();
UpdateTimeInternal(i);
}
void ViewerWidget::Play()
{
PlayInternal(1);
@@ -393,36 +353,6 @@ void ViewerWidget::Pause()
}
}
void ViewerWidget::GoToStart()
{
Pause();
SetTime(0);
}
void ViewerWidget::PrevFrame()
{
Pause();
SetTime(qMax(static_cast<int64_t>(0), ruler_->GetTime() - 1));
}
void ViewerWidget::NextFrame()
{
Pause();
SetTime(ruler_->GetTime() + 1);
}
void ViewerWidget::GoToEnd()
{
if (viewer_node_ != nullptr) {
Pause();
SetTime(Timecode::time_to_timestamp(viewer_node_->Length(), time_base_));
}
}
void ViewerWidget::ShuttleLeft()
{
int current_speed = playback_speed_;
@@ -478,20 +408,33 @@ void ViewerWidget::SetOCIOLook(const QString &look)
gl_widget_->SetOCIOLook(look);
}
void ViewerWidget::TimebaseChangedEvent(const rational &timebase)
{
TimeBasedWidget::TimebaseChangedEvent(timebase);
controls_->SetTimebase(timebase);
controls_->SetTime(ruler()->GetTime());
LengthChangedSlot(GetConnectedNode() ? GetConnectedNode()->Length() : 0);
playback_timer_.setInterval(qFloor(timebase.toDouble()));
}
void ViewerWidget::PlaybackTimerUpdate()
{
int64_t real_time = QDateTime::currentMSecsSinceEpoch() - start_msec_;
int64_t frames_since_start = qRound(static_cast<double>(real_time) / (time_base_dbl_ * 1000));
int64_t frames_since_start = qRound(static_cast<double>(real_time) / (timebase_dbl() * 1000));
int64_t current_time = start_timestamp_ + frames_since_start * playback_speed_;
if (current_time < 0) {
current_time = 0;
Pause();
SetTimeAndSignal(0);
} else {
time_changed_from_timer_ = true;
SetTimeAndSignal(current_time);
time_changed_from_timer_ = false;
}
SetTime(current_time);
}
void ViewerWidget::RendererCachedFrame(const rational &time, QVariant value, qint64 job_time)
@@ -519,14 +462,8 @@ void ViewerWidget::SizeChangedSlot(int width, int height)
void ViewerWidget::LengthChangedSlot(const rational &length)
{
controls_->SetEndTime(Timecode::time_to_timestamp(length, time_base_));
ruler_->SetCacheStatusLength(length);
}
void ViewerWidget::resizeEvent(QResizeEvent *event)
{
// Set scrollbar page step to the width
scrollbar_->setPageStep(event->size().width());
controls_->SetEndTime(Timecode::time_to_timestamp(length, timebase()));
ruler()->SetCacheStatusLength(length);
}
void ViewerWidget::ColorDisplayChanged(QAction* action)
+12 -38
View File
@@ -36,12 +36,12 @@
#include "viewerglwidget.h"
#include "viewersizer.h"
#include "widget/playbackcontrols/playbackcontrols.h"
#include "widget/timeruler/timeruler.h"
#include "widget/timebased/timebased.h"
/**
* @brief An OpenGL-based viewer widget with playback controls (a PlaybackControls widget).
*/
class ViewerWidget : public QWidget
class ViewerWidget : public TimeBasedWidget
{
Q_OBJECT
public:
@@ -51,22 +51,12 @@ public:
void SetTimeRulerEnabled(bool enabled);
const double& scale() const;
rational GetTime() const;
void SetScale(const double& scale_);
void SetTime(const int64_t& time);
void TogglePlayPause();
bool IsPlaying() const;
void ConnectViewerNode(ViewerOutput* node, ColorManager *color_manager = nullptr);
ViewerOutput* GetConnectedViewer() const;
/**
* @brief Enable or disable the color management menu
*
@@ -91,20 +81,10 @@ public slots:
*/
void SetTexture(OpenGLTexturePtr tex);
void SetTimebase(const rational& r);
void GoToStart();
void PrevFrame();
void Play();
void Pause();
void NextFrame();
void GoToEnd();
void ShuttleLeft();
void ShuttleStop();
@@ -134,11 +114,13 @@ public slots:
*/
void SetOCIOLook(const QString& look);
signals:
void TimeChanged(const int64_t&);
protected:
virtual void resizeEvent(QResizeEvent *event) override;
virtual void TimebaseChangedEvent(const rational &) override;
virtual void TimeChangedEvent(const int64_t &) override;
virtual void ConnectNodeInternal(ViewerOutput *) override;
virtual void DisconnectNodeInternal(ViewerOutput *) override;
virtual void ConnectedNodeChanged(ViewerOutput*n) override;
OpenGLBackend* video_renderer_;
AudioBackend* audio_renderer_;
@@ -158,21 +140,11 @@ private:
PlaybackControls* controls_;
TimeRuler* ruler_;
QScrollBar* scrollbar_;
rational time_base_;
double time_base_dbl_;
QTimer playback_timer_;
qint64 start_msec_;
int64_t start_timestamp_;
ViewerOutput* viewer_node_;
int playback_speed_;
qint64 frame_cache_job_time_;
@@ -183,9 +155,11 @@ private:
int divider_;
private slots:
void RulerTimeChange(int64_t);
ColorManager* override_color_manager_;
bool time_changed_from_timer_;
private slots:
void PlaybackTimerUpdate();
void RendererCachedFrame(const rational& time, QVariant value, qint64 job_time);
+4
View File
@@ -90,6 +90,10 @@ MainWindow::MainWindow(QWidget *parent) :
connect(curve_panel_, &CurvePanel::TimeChanged, viewer_panel_, &ViewerPanel::SetTime);
connect(curve_panel_, &CurvePanel::TimeChanged, timeline_panel_, &TimelinePanel::SetTime);
connect(curve_panel_, &CurvePanel::TimeChanged, param_panel_, &ParamPanel::SetTime);
viewer_panel_->ConnectTimeBasedPanel(timeline_panel_);
viewer_panel_->ConnectTimeBasedPanel(param_panel_);
viewer_panel_->ConnectTimeBasedPanel(curve_panel_);
}
void MainWindow::SetFullscreen(bool fullscreen)