|
|
|
@@ -1,7 +1,7 @@
|
|
|
|
|
/***
|
|
|
|
|
|
|
|
|
|
Olive - Non-Linear Video Editor
|
|
|
|
|
Copyright (C) 2021 Olive Team
|
|
|
|
|
Copyright (C) 2022 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
|
|
|
|
@@ -90,19 +90,21 @@ void SeekableWidget::ConnectTimelinePoints(TimelinePoints *points)
|
|
|
|
|
|
|
|
|
|
void SeekableWidget::DeleteSelected()
|
|
|
|
|
{
|
|
|
|
|
MultiUndoCommand* command = new MultiUndoCommand();
|
|
|
|
|
if (!selection_manager_.IsDragging()) {
|
|
|
|
|
MultiUndoCommand* command = new MultiUndoCommand();
|
|
|
|
|
|
|
|
|
|
foreach (TimelineMarker *marker, selection_manager_.GetSelectedObjects()) {
|
|
|
|
|
command->add_child(new MarkerRemoveCommand(marker));
|
|
|
|
|
foreach (TimelineMarker *marker, selection_manager_.GetSelectedObjects()) {
|
|
|
|
|
command->add_child(new MarkerRemoveCommand(marker));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Core::instance()->undo_stack()->pushIfHasChildren(command);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Core::instance()->undo_stack()->pushIfHasChildren(command);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool SeekableWidget::CopySelected(bool cut)
|
|
|
|
|
{
|
|
|
|
|
if (!selection_manager_.GetSelectedObjects().empty()) {
|
|
|
|
|
ProjectSerializer::SaveData sdata(Project::GetProjectFromObject(timeline_points_));
|
|
|
|
|
ProjectSerializer::SaveData sdata;
|
|
|
|
|
sdata.SetOnlySerializeMarkers(selection_manager_.GetSelectedObjects());
|
|
|
|
|
|
|
|
|
|
ProjectSerializer::Copy(sdata, QStringLiteral("markers"));
|
|
|
|
@@ -117,7 +119,7 @@ bool SeekableWidget::CopySelected(bool cut)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool SeekableWidget::PasteMarkers(bool insert, rational insert_time)
|
|
|
|
|
bool SeekableWidget::PasteMarkers()
|
|
|
|
|
{
|
|
|
|
|
ProjectSerializer::Result res = ProjectSerializer::Paste(QStringLiteral("markers"));
|
|
|
|
|
if (res == ProjectSerializer::kSuccess) {
|
|
|
|
@@ -128,29 +130,18 @@ bool SeekableWidget::PasteMarkers(bool insert, rational insert_time)
|
|
|
|
|
// Normalize markers to start at playhead
|
|
|
|
|
rational min = RATIONAL_MAX;
|
|
|
|
|
for (auto it=markers.cbegin(); it!=markers.cend(); it++) {
|
|
|
|
|
min = qMin(min, (*it)->time());
|
|
|
|
|
min = std::min(min, (*it)->time().in());
|
|
|
|
|
}
|
|
|
|
|
min -= GetTime();
|
|
|
|
|
|
|
|
|
|
// Avoid duplicates
|
|
|
|
|
bool loop;
|
|
|
|
|
do {
|
|
|
|
|
loop = false;
|
|
|
|
|
for (auto it=markers.cbegin(); it!=markers.cend(); it++) {
|
|
|
|
|
rational proposed_time = (*it)->time() - min;
|
|
|
|
|
|
|
|
|
|
if (timeline_points_->markers()->GetMarkerAtTime(proposed_time)) {
|
|
|
|
|
min -= timebase();
|
|
|
|
|
loop = true;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} while (loop);
|
|
|
|
|
|
|
|
|
|
for (auto it=markers.cbegin(); it!=markers.cend(); it++) {
|
|
|
|
|
TimelineMarker *m = *it;
|
|
|
|
|
|
|
|
|
|
m->set_time(m->time() - min);
|
|
|
|
|
m->set_time(m->time().in() - min);
|
|
|
|
|
|
|
|
|
|
if (TimelineMarker *existing = timeline_points_->markers()->GetMarkerAtTime(m->time().in())) {
|
|
|
|
|
command->add_child(new MarkerRemoveCommand(existing));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
command->add_child(new MarkerAddCommand(timeline_points_->markers(), m));
|
|
|
|
|
}
|
|
|
|
@@ -198,7 +189,11 @@ void SeekableWidget::mouseMoveEvent(QMouseEvent *event)
|
|
|
|
|
}
|
|
|
|
|
} else if (timeline_points_) {
|
|
|
|
|
// Look for resize points
|
|
|
|
|
setCursor(FindResizeHandle(event) ? Qt::SizeHorCursor : Qt::ArrowCursor);
|
|
|
|
|
if (FindResizeHandle(event)) {
|
|
|
|
|
setCursor(Qt::SizeHorCursor);
|
|
|
|
|
} else {
|
|
|
|
|
unsetCursor();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@@ -344,12 +339,12 @@ void SeekableWidget::DrawTimelinePoints(QPainter* p, int marker_bottom)
|
|
|
|
|
for (auto it=GetTimelinePoints()->markers()->cbegin(); it!=GetTimelinePoints()->markers()->cend(); it++) {
|
|
|
|
|
TimelineMarker* marker = *it;
|
|
|
|
|
|
|
|
|
|
int marker_right = TimeToScene(marker->time_range().out());
|
|
|
|
|
int marker_right = TimeToScene(marker->time().out());
|
|
|
|
|
if (marker_right < lim_left) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int marker_left = TimeToScene(marker->time_range().in());
|
|
|
|
|
int marker_left = TimeToScene(marker->time().in());
|
|
|
|
|
if (marker_left >= lim_right) {
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
@@ -441,16 +436,16 @@ bool SeekableWidget::FindResizeHandle(QMouseEvent *event)
|
|
|
|
|
// Check for markers
|
|
|
|
|
for (auto it=timeline_points_->markers()->cbegin(); it!=timeline_points_->markers()->cend(); it++) {
|
|
|
|
|
TimelineMarker *m = *it;
|
|
|
|
|
if (m->time_range().in() != m->time_range().out()) {
|
|
|
|
|
if (m->time_range().in() >= min && m->time_range().in() < max) {
|
|
|
|
|
if (m->time().in() != m->time().out()) {
|
|
|
|
|
if (m->time().in() >= min && m->time().in() < max) {
|
|
|
|
|
resize_mode_ = kResizeIn;
|
|
|
|
|
} else if (m->time_range().out() >= min && m->time_range().out() < max) {
|
|
|
|
|
} else if (m->time().out() >= min && m->time().out() < max) {
|
|
|
|
|
resize_mode_ = kResizeOut;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (resize_mode_ != kResizeNone) {
|
|
|
|
|
resize_item_ = m;
|
|
|
|
|
resize_item_range_ = m->time_range();
|
|
|
|
|
resize_item_range_ = m->time();
|
|
|
|
|
resize_snap_mask_ = TimeBasedWidget::kSnapAll;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
@@ -519,7 +514,7 @@ void SeekableWidget::CommitResizeHandle()
|
|
|
|
|
MultiUndoCommand *command = new MultiUndoCommand();
|
|
|
|
|
|
|
|
|
|
if (TimelineMarker *marker = dynamic_cast<TimelineMarker*>(resize_item_)) {
|
|
|
|
|
command->add_child(new MarkerChangeTimeCommand(marker, marker->time_range(), resize_item_range_));
|
|
|
|
|
command->add_child(new MarkerChangeTimeCommand(marker, marker->time(), resize_item_range_));
|
|
|
|
|
} else if (TimelineWorkArea *workarea = dynamic_cast<TimelineWorkArea*>(resize_item_)) {
|
|
|
|
|
command->add_child(new WorkareaSetRangeCommand(workarea, workarea->range(), resize_item_range_));
|
|
|
|
|
}
|
|
|
|
|