Merge branch 'master' into transition-offsets
This commit is contained in:
@@ -30,6 +30,7 @@
|
||||
#include "common/timecodefunctions.h"
|
||||
#include "dialog/nodeproperties/nodepropertiesdialog.h"
|
||||
#include "dialog/sequence/sequence.h"
|
||||
#include "dialog/speedduration/speeddurationdialog.h"
|
||||
#include "node/block/transition/transition.h"
|
||||
#include "tool/add.h"
|
||||
#include "tool/beam.h"
|
||||
@@ -70,10 +71,11 @@ TimelineWidget::TimelineWidget(QWidget *parent) :
|
||||
QHBoxLayout* ruler_and_time_layout = new QHBoxLayout();
|
||||
vert_layout->addLayout(ruler_and_time_layout);
|
||||
|
||||
timecode_label_ = new TimeSlider();
|
||||
timecode_label_ = new RationalSlider();
|
||||
timecode_label_->SetAlignment(Qt::AlignCenter);
|
||||
timecode_label_->SetDisplayType(RationalSlider::kTime);
|
||||
timecode_label_->setVisible(false);
|
||||
connect(timecode_label_, &TimeSlider::ValueChanged, this, &TimelineWidget::SetTimeAndSignal);
|
||||
connect(timecode_label_, &RationalSlider::ValueChanged, this, &TimelineWidget::SetTimeAndSignal);
|
||||
ruler_and_time_layout->addWidget(timecode_label_);
|
||||
|
||||
ruler_and_time_layout->addWidget(ruler());
|
||||
@@ -135,7 +137,7 @@ TimelineWidget::TimelineWidget(QWidget *parent) :
|
||||
|
||||
connect(view->horizontalScrollBar(), &QScrollBar::valueChanged, ruler(), &TimeRuler::SetScroll);
|
||||
connect(view, &TimelineView::ScaleChanged, this, &TimelineWidget::SetScale);
|
||||
connect(view, &TimelineView::TimeChanged, this, &TimelineWidget::ViewTimestampChanged);
|
||||
connect(view, &TimelineView::TimeChanged, this, &TimelineWidget::SetTimeAndSignal);
|
||||
connect(view, &TimelineView::customContextMenuRequested, this, &TimelineWidget::ShowContextMenu);
|
||||
connect(scrollbar(), &QScrollBar::valueChanged, view->horizontalScrollBar(), &QScrollBar::setValue);
|
||||
connect(view->horizontalScrollBar(), &QScrollBar::valueChanged, scrollbar(), &QScrollBar::setValue);
|
||||
@@ -221,13 +223,13 @@ void TimelineWidget::resizeEvent(QResizeEvent *event)
|
||||
UpdateTimecodeWidthFromSplitters(views_.first()->splitter());
|
||||
}
|
||||
|
||||
void TimelineWidget::TimeChangedEvent(const int64_t& timestamp)
|
||||
void TimelineWidget::TimeChangedEvent(const rational &time)
|
||||
{
|
||||
super::TimeChangedEvent(timestamp);
|
||||
super::TimeChangedEvent(time);
|
||||
|
||||
SetViewTimestamp(timestamp);
|
||||
SetViewTime(time);
|
||||
|
||||
timecode_label_->SetValue(timestamp);
|
||||
timecode_label_->SetValue(time);
|
||||
}
|
||||
|
||||
void TimelineWidget::ScaleChangedEvent(const double &scale)
|
||||
@@ -399,7 +401,7 @@ void TimelineWidget::SplitAtPlayhead()
|
||||
return;
|
||||
}
|
||||
|
||||
rational playhead_time = Timecode::timestamp_to_time(GetTimestamp(), timebase());
|
||||
const rational &playhead_time = GetTime();
|
||||
|
||||
QVector<Block*> selected_blocks = GetSelectedBlocks();
|
||||
|
||||
@@ -692,8 +694,7 @@ void TimelineWidget::DeleteInToOut(bool ripple)
|
||||
false));
|
||||
|
||||
if (ripple) {
|
||||
SetTimeAndSignal(Timecode::time_to_timestamp(GetConnectedNode()->GetTimelinePoints()->workarea()->in(),
|
||||
timebase()));
|
||||
SetTimeAndSignal(GetConnectedNode()->GetTimelinePoints()->workarea()->in());
|
||||
}
|
||||
|
||||
Core::instance()->undo_stack()->push(command);
|
||||
@@ -738,6 +739,33 @@ void TimelineWidget::NudgeRight()
|
||||
}
|
||||
}
|
||||
|
||||
void TimelineWidget::MoveInToPlayhead()
|
||||
{
|
||||
MoveToPlayheadInternal(false);
|
||||
}
|
||||
|
||||
void TimelineWidget::MoveOutToPlayhead()
|
||||
{
|
||||
MoveToPlayheadInternal(true);
|
||||
}
|
||||
|
||||
void TimelineWidget::ShowSpeedDurationDialogForSelectedClips()
|
||||
{
|
||||
QVector<ClipBlock*> clips;
|
||||
|
||||
foreach (Block *b, selected_blocks_) {
|
||||
ClipBlock *c = dynamic_cast<ClipBlock*>(b);
|
||||
if (c) {
|
||||
clips.append(c);
|
||||
}
|
||||
}
|
||||
|
||||
if (!clips.isEmpty()) {
|
||||
SpeedDurationDialog sdd(clips, timebase(), this);
|
||||
sdd.exec();
|
||||
}
|
||||
}
|
||||
|
||||
void TimelineWidget::InsertGapsAt(const rational &earliest_point, const rational &insert_length, MultiUndoCommand *command)
|
||||
{
|
||||
for (int i=0;i<Track::kCount;i++) {
|
||||
@@ -1057,39 +1085,16 @@ void TimelineWidget::SetUseAudioTimeUnits(bool use)
|
||||
|
||||
// Update timebases
|
||||
UpdateViewTimebases();
|
||||
|
||||
// Force update of the viewer timestamps
|
||||
SetViewTimestamp(GetTimestamp());
|
||||
}
|
||||
|
||||
void TimelineWidget::SetViewTimestamp(const int64_t &ts)
|
||||
void TimelineWidget::SetViewTime(const rational &time)
|
||||
{
|
||||
for (int i=0;i<views_.size();i++) {
|
||||
TimelineAndTrackView* view = views_.at(i);
|
||||
|
||||
if (GetConnectedNode() && use_audio_time_units_ && i == Track::kAudio) {
|
||||
view->view()->SetTime(Timecode::rescale_timestamp(ts,
|
||||
timebase(),
|
||||
GetConnectedNode()->GetAudioParams().sample_rate_as_time_base()));
|
||||
} else {
|
||||
view->view()->SetTime(ts);
|
||||
}
|
||||
view->view()->SetTime(time);
|
||||
}
|
||||
}
|
||||
|
||||
void TimelineWidget::ViewTimestampChanged(int64_t ts)
|
||||
{
|
||||
if (GetConnectedNode() && use_audio_time_units_ && sender() == views_.at(Track::kAudio)) {
|
||||
ts = Timecode::rescale_timestamp(ts,
|
||||
GetConnectedNode()->GetAudioParams().sample_rate_as_time_base(),
|
||||
timebase());
|
||||
}
|
||||
|
||||
// Update all other views
|
||||
SetTimestamp(ts);
|
||||
emit TimeChanged(ts);
|
||||
}
|
||||
|
||||
void TimelineWidget::ToolChanged()
|
||||
{
|
||||
HideSnaps();
|
||||
@@ -1161,19 +1166,73 @@ void TimelineWidget::UpdateViewTimebases()
|
||||
|
||||
void TimelineWidget::NudgeInternal(const rational &amount)
|
||||
{
|
||||
MultiUndoCommand *command = new MultiUndoCommand();
|
||||
if (!selected_blocks_.isEmpty()) {
|
||||
MultiUndoCommand *command = new MultiUndoCommand();
|
||||
|
||||
foreach (Block* b, selected_blocks_) {
|
||||
command->add_child(new TrackReplaceBlockWithGapCommand(b->track(), b, false));
|
||||
command->add_child(new TrackPlaceBlockCommand(sequence()->track_list(b->track()->type()), b->track()->Index(), b, b->in() + amount));
|
||||
foreach (Block* b, selected_blocks_) {
|
||||
command->add_child(new TrackReplaceBlockWithGapCommand(b->track(), b, false));
|
||||
command->add_child(new TrackPlaceBlockCommand(sequence()->track_list(b->track()->type()), b->track()->Index(), b, b->in() + amount));
|
||||
}
|
||||
|
||||
// Nudge selections
|
||||
TimelineWidgetSelections new_sel = GetSelections();
|
||||
new_sel.ShiftTime(amount);
|
||||
command->add_child(new TimelineWidget::SetSelectionsCommand(this, new_sel, GetSelections(), true));
|
||||
|
||||
Core::instance()->undo_stack()->push(command);
|
||||
}
|
||||
}
|
||||
|
||||
// Nudge selections
|
||||
TimelineWidgetSelections new_sel = GetSelections();
|
||||
new_sel.ShiftTime(amount);
|
||||
command->add_child(new TimelineWidget::SetSelectionsCommand(this, new_sel, GetSelections(), true));
|
||||
void TimelineWidget::MoveToPlayheadInternal(bool out)
|
||||
{
|
||||
if (GetConnectedNode() && !selected_blocks_.isEmpty()) {
|
||||
MultiUndoCommand *command = new MultiUndoCommand();
|
||||
|
||||
Core::instance()->undo_stack()->pushIfHasChildren(command);
|
||||
// Remove each block from the graph
|
||||
QHash<Track*, rational> earliest_pts;
|
||||
foreach (Block *b, selected_blocks_) {
|
||||
command->add_child(new TrackReplaceBlockWithGapCommand(b->track(), b, false));
|
||||
|
||||
rational r = earliest_pts.value(b->track(), out ? RATIONAL_MIN : RATIONAL_MAX);
|
||||
rational compare = out ? b->out() : b->in();
|
||||
if ((compare < r) == !out) {
|
||||
earliest_pts.insert(b->track(), compare);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (Block *b, selected_blocks_) {
|
||||
rational shift_amt = GetTime() - earliest_pts.value(b->track());
|
||||
rational new_in = b->in() + shift_amt;
|
||||
bool can_shift = true;
|
||||
|
||||
if (new_in < 0) {
|
||||
// Handle clips threatening to go below 0
|
||||
rational new_out = new_in + b->length();
|
||||
if (new_out <= 0) {
|
||||
can_shift = false;
|
||||
} else {
|
||||
command->add_child(new BlockResizeWithMediaInCommand(b, new_out));
|
||||
new_in = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (can_shift) {
|
||||
command->add_child(new TrackPlaceBlockCommand(sequence()->track_list(b->track()->type()), b->track()->Index(), b, new_in));
|
||||
}
|
||||
}
|
||||
|
||||
// Shift selections
|
||||
TimelineWidgetSelections new_sel = GetSelections();
|
||||
for (auto it=new_sel.begin(); it!=new_sel.end(); it++) {
|
||||
rational track_adj = GetTime() - earliest_pts.value(GetTrackFromReference(it.key()), GetTime());
|
||||
if (!track_adj.isNull()) {
|
||||
it.value().shift(track_adj);
|
||||
}
|
||||
}
|
||||
command->add_child(new SetSelectionsCommand(this, new_sel, GetSelections(), true));
|
||||
|
||||
Core::instance()->undo_stack()->push(command);
|
||||
}
|
||||
}
|
||||
|
||||
void TimelineWidget::SetViewBeamCursor(const TimelineCoordinate &coord)
|
||||
@@ -1359,9 +1418,9 @@ void TimelineWidget::RippleTo(Timeline::MovementMode mode)
|
||||
|
||||
// If we rippled, ump to where new cut is if applicable
|
||||
if (mode == Timeline::kTrimIn) {
|
||||
SetTimeAndSignal(Timecode::time_to_timestamp(closest_point_to_playhead, timebase()));
|
||||
SetTimeAndSignal(closest_point_to_playhead);
|
||||
} else if (mode == Timeline::kTrimOut && closest_point_to_playhead == GetTime()) {
|
||||
SetTimeAndSignal(Timecode::time_to_timestamp(playhead_time, timebase()));
|
||||
SetTimeAndSignal(playhead_time);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1603,6 +1662,10 @@ void TimelineWidget::RemoveSelection(Block *item)
|
||||
|
||||
void TimelineWidget::SetSelections(const TimelineWidgetSelections &s, bool process_block_changes)
|
||||
{
|
||||
if (selections_ == s) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (process_block_changes) {
|
||||
SignalDeselectedBlocks(GetBlocksInSelection(selections_.Subtracted(s)));
|
||||
SignalSelectedBlocks(GetBlocksInSelection(s.Subtracted(selections_)));
|
||||
|
||||
Reference in New Issue
Block a user