change: change code style to Linux style except indent.

This commit is contained in:
Mike Solar
2025-08-03 03:09:40 +08:00
parent 65ab76edc8
commit 74f73ab3be
789 changed files with 77113 additions and 68888 deletions
+166 -150
View File
@@ -29,202 +29,218 @@
#include "timeline/timelineundopointer.h"
#include "widget/timelinewidget/timelinewidget.h"
namespace olive {
namespace olive
{
AddTool::AddTool(TimelineWidget *parent) :
BeamTool(parent),
ghost_(nullptr)
AddTool::AddTool(TimelineWidget *parent)
: BeamTool(parent)
, ghost_(nullptr)
{
}
void AddTool::MousePress(TimelineViewMouseEvent *event)
{
const Track::Reference& track = event->GetTrack();
const Track::Reference &track = event->GetTrack();
// Check if track is locked
Track* t = parent()->GetTrackFromReference(track);
if (t && t->IsLocked()) {
return;
}
// Check if track is locked
Track *t = parent()->GetTrackFromReference(track);
if (t && t->IsLocked()) {
return;
}
Track::Type add_type = Track::kNone;
Track::Type add_type = Track::kNone;
switch (Core::instance()->GetSelectedAddableObject()) {
case Tool::kAddableBars:
case Tool::kAddableSolid:
case Tool::kAddableTitle:
case Tool::kAddableShape:
add_type = Track::kVideo;
break;
case Tool::kAddableTone:
add_type = Track::kAudio;
break;
case Tool::kAddableSubtitle:
add_type = Track::kSubtitle;
break;
case Tool::kAddableEmpty:
// Leave as "none", which means this block can be placed on any track
break;
case Tool::kAddableCount:
// Return so we do nothing
return;
}
switch (Core::instance()->GetSelectedAddableObject()) {
case Tool::kAddableBars:
case Tool::kAddableSolid:
case Tool::kAddableTitle:
case Tool::kAddableShape:
add_type = Track::kVideo;
break;
case Tool::kAddableTone:
add_type = Track::kAudio;
break;
case Tool::kAddableSubtitle:
add_type = Track::kSubtitle;
break;
case Tool::kAddableEmpty:
// Leave as "none", which means this block can be placed on any track
break;
case Tool::kAddableCount:
// Return so we do nothing
return;
}
if (add_type == Track::kNone
|| add_type == track.type()) {
drag_start_point_ = ValidatedCoordinate(event->GetCoordinates(true)).GetFrame();
if (add_type == Track::kNone || add_type == track.type()) {
drag_start_point_ =
ValidatedCoordinate(event->GetCoordinates(true)).GetFrame();
ghost_ = new TimelineViewGhostItem();
ghost_->SetIn(drag_start_point_);
ghost_->SetOut(drag_start_point_);
ghost_->SetTrack(track);
parent()->AddGhost(ghost_);
ghost_ = new TimelineViewGhostItem();
ghost_->SetIn(drag_start_point_);
ghost_->SetOut(drag_start_point_);
ghost_->SetTrack(track);
parent()->AddGhost(ghost_);
snap_points_.push_back(drag_start_point_);
}
snap_points_.push_back(drag_start_point_);
}
}
void AddTool::MouseMove(TimelineViewMouseEvent *event)
{
if (!ghost_) {
return;
}
if (!ghost_) {
return;
}
MouseMoveInternal(event->GetFrame(), event->GetModifiers() & Qt::AltModifier);
MouseMoveInternal(event->GetFrame(),
event->GetModifiers() & Qt::AltModifier);
}
void AddTool::MouseRelease(TimelineViewMouseEvent *event)
{
if (ghost_) {
if (!ghost_->GetAdjustedLength().isNull()) {
MultiUndoCommand* command = new MultiUndoCommand();
if (ghost_) {
if (!ghost_->GetAdjustedLength().isNull()) {
MultiUndoCommand *command = new MultiUndoCommand();
if (MultiUndoCommand *subtitle_section_command = parent()->TakeSubtitleSectionCommand()) {
command->add_child(subtitle_section_command);
}
if (MultiUndoCommand *subtitle_section_command =
parent()->TakeSubtitleSectionCommand()) {
command->add_child(subtitle_section_command);
}
Sequence *s = parent()->sequence();
Sequence *s = parent()->sequence();
QRectF r;
if (Core::instance()->GetSelectedAddableObject() == Tool::kAddableTitle) {
VideoParams svp = s->GetVideoParams();
r = QRectF(0, 0, svp.width(), svp.height());
r.adjust(svp.width()/10, svp.height()/10, -svp.width()/10, -svp.height()/10);
}
QRectF r;
if (Core::instance()->GetSelectedAddableObject() ==
Tool::kAddableTitle) {
VideoParams svp = s->GetVideoParams();
r = QRectF(0, 0, svp.width(), svp.height());
r.adjust(svp.width() / 10, svp.height() / 10, -svp.width() / 10,
-svp.height() / 10);
}
CreateAddableClip(command, s, ghost_->GetTrack(), ghost_->GetAdjustedIn(), ghost_->GetAdjustedLength(), r);
CreateAddableClip(command, s, ghost_->GetTrack(),
ghost_->GetAdjustedIn(),
ghost_->GetAdjustedLength(), r);
Core::instance()->undo_stack()->push(command, qApp->translate("AddTool", "Added Clip"));
}
Core::instance()->undo_stack()->push(
command, qApp->translate("AddTool", "Added Clip"));
}
parent()->ClearGhosts();
snap_points_.clear();
ghost_ = nullptr;
}
parent()->ClearGhosts();
snap_points_.clear();
ghost_ = nullptr;
}
}
Node *AddTool::CreateAddableClip(MultiUndoCommand *command, Sequence *sequence, const Track::Reference &track, const rational &in, const rational &length, const QRectF &rect)
Node *AddTool::CreateAddableClip(MultiUndoCommand *command, Sequence *sequence,
const Track::Reference &track,
const rational &in, const rational &length,
const QRectF &rect)
{
ClipBlock* clip;
if (Core::instance()->GetSelectedAddableObject() == Tool::kAddableSubtitle) {
clip = new SubtitleBlock();
} else {
clip = new ClipBlock();
clip->SetLabel(olive::Tool::GetAddableObjectName(Core::instance()->GetSelectedAddableObject()));
}
clip->set_length_and_media_out(length);
ClipBlock *clip;
if (Core::instance()->GetSelectedAddableObject() ==
Tool::kAddableSubtitle) {
clip = new SubtitleBlock();
} else {
clip = new ClipBlock();
clip->SetLabel(olive::Tool::GetAddableObjectName(
Core::instance()->GetSelectedAddableObject()));
}
clip->set_length_and_media_out(length);
Project* graph = sequence->parent();
Project *graph = sequence->parent();
command->add_child(new NodeAddCommand(graph, clip));
command->add_child(new NodeSetPositionCommand(clip, clip, QPointF(0, 0)));
command->add_child(new TrackPlaceBlockCommand(sequence->track_list(track.type()),
track.index(),
clip,
in));
command->add_child(new NodeAddCommand(graph, clip));
command->add_child(new NodeSetPositionCommand(clip, clip, QPointF(0, 0)));
command->add_child(new TrackPlaceBlockCommand(
sequence->track_list(track.type()), track.index(), clip, in));
Node *node_to_add = nullptr;
Node *node_to_add = nullptr;
switch (Core::instance()->GetSelectedAddableObject()) {
case Tool::kAddableEmpty:
// Empty, nothing to be done
break;
case Tool::kAddableSolid:
node_to_add = new SolidGenerator();
break;
case Tool::kAddableShape:
node_to_add = new ShapeNode();
break;
case Tool::kAddableTitle:
node_to_add = new TextGeneratorV3();
break;
case Tool::kAddableBars:
case Tool::kAddableTone:
// Not implemented yet
qWarning() << "Unimplemented add object:" << Core::instance()->GetSelectedAddableObject();
break;
case Tool::kAddableSubtitle:
// The block itself is the node we want
break;
case Tool::kAddableCount:
// Invalid value, do nothing
break;
}
switch (Core::instance()->GetSelectedAddableObject()) {
case Tool::kAddableEmpty:
// Empty, nothing to be done
break;
case Tool::kAddableSolid:
node_to_add = new SolidGenerator();
break;
case Tool::kAddableShape:
node_to_add = new ShapeNode();
break;
case Tool::kAddableTitle:
node_to_add = new TextGeneratorV3();
break;
case Tool::kAddableBars:
case Tool::kAddableTone:
// Not implemented yet
qWarning() << "Unimplemented add object:"
<< Core::instance()->GetSelectedAddableObject();
break;
case Tool::kAddableSubtitle:
// The block itself is the node we want
break;
case Tool::kAddableCount:
// Invalid value, do nothing
break;
}
if (node_to_add) {
QPointF extra_node_offset(kDefaultDistanceFromOutput, 0);
command->add_child(new NodeAddCommand(graph, node_to_add));
command->add_child(new NodeEdgeAddCommand(node_to_add, NodeInput(clip, ClipBlock::kBufferIn)));
command->add_child(new NodeSetPositionCommand(node_to_add, clip, extra_node_offset));
if (node_to_add) {
QPointF extra_node_offset(kDefaultDistanceFromOutput, 0);
command->add_child(new NodeAddCommand(graph, node_to_add));
command->add_child(new NodeEdgeAddCommand(
node_to_add, NodeInput(clip, ClipBlock::kBufferIn)));
command->add_child(
new NodeSetPositionCommand(node_to_add, clip, extra_node_offset));
if (!rect.isNull()) {
if (ShapeNodeBase *shape = dynamic_cast<ShapeNodeBase*>(node_to_add)) {
shape->SetRect(rect, sequence->GetVideoParams(), command);
}
}
}
if (!rect.isNull()) {
if (ShapeNodeBase *shape =
dynamic_cast<ShapeNodeBase *>(node_to_add)) {
shape->SetRect(rect, sequence->GetVideoParams(), command);
}
}
}
return node_to_add;
return node_to_add;
}
void AddTool::MouseMoveInternal(const rational &cursor_frame, bool outwards)
{
// Calculate movement
rational movement = cursor_frame - drag_start_point_;
// Calculate movement
rational movement = cursor_frame - drag_start_point_;
// Validation: Ensure in point never goes below 0
if (movement < -ghost_->GetIn() || (outwards && -movement < -ghost_->GetIn())) {
movement = -ghost_->GetIn();
}
// Validation: Ensure in point never goes below 0
if (movement < -ghost_->GetIn() ||
(outwards && -movement < -ghost_->GetIn())) {
movement = -ghost_->GetIn();
}
// Snap movement
bool snapped;
// Snap movement
bool snapped;
if (Core::instance()->snapping()) {
snapped = parent()->SnapPoint(snap_points_, &movement);
} else {
snapped = false;
}
if (Core::instance()->snapping()) {
snapped = parent()->SnapPoint(snap_points_, &movement);
} else {
snapped = false;
}
// If alt is held, our movement goes both ways (outwards)
if (!snapped && outwards) {
// Snap backwards too
movement = -movement;
parent()->SnapPoint(snap_points_, &movement);
// We don't need to un-neg here because outwards means all future processing will be done both pos and neg
}
// If alt is held, our movement goes both ways (outwards)
if (!snapped && outwards) {
// Snap backwards too
movement = -movement;
parent()->SnapPoint(snap_points_, &movement);
// We don't need to un-neg here because outwards means all future processing will be done both pos and neg
}
// Make adjustment
if (!movement) {
ghost_->SetInAdjustment(0);
ghost_->SetOutAdjustment(0);
} else if (movement > 0) {
ghost_->SetInAdjustment(outwards ? -movement : 0);
ghost_->SetOutAdjustment(movement);
} else if (movement < 0) {
ghost_->SetInAdjustment(movement);
ghost_->SetOutAdjustment(outwards ? -movement : 0);
}
// Make adjustment
if (!movement) {
ghost_->SetInAdjustment(0);
ghost_->SetOutAdjustment(0);
} else if (movement > 0) {
ghost_->SetInAdjustment(outwards ? -movement : 0);
ghost_->SetOutAdjustment(movement);
} else if (movement < 0) {
ghost_->SetInAdjustment(movement);
ghost_->SetOutAdjustment(outwards ? -movement : 0);
}
}
}
+15 -11
View File
@@ -23,25 +23,29 @@
#include "beam.h"
namespace olive {
class AddTool : public BeamTool
namespace olive
{
class AddTool : public BeamTool {
public:
AddTool(TimelineWidget* parent);
AddTool(TimelineWidget *parent);
virtual void MousePress(TimelineViewMouseEvent *event) override;
virtual void MouseMove(TimelineViewMouseEvent *event) override;
virtual void MouseRelease(TimelineViewMouseEvent *event) override;
virtual void MousePress(TimelineViewMouseEvent *event) override;
virtual void MouseMove(TimelineViewMouseEvent *event) override;
virtual void MouseRelease(TimelineViewMouseEvent *event) override;
static Node *CreateAddableClip(MultiUndoCommand *command, Sequence *sequence, const Track::Reference &track, const rational &in, const rational &length, const QRectF &rect = QRectF());
static Node *CreateAddableClip(MultiUndoCommand *command,
Sequence *sequence,
const Track::Reference &track,
const rational &in, const rational &length,
const QRectF &rect = QRectF());
protected:
void MouseMoveInternal(const rational& cursor_frame, bool outwards);
void MouseMoveInternal(const rational &cursor_frame, bool outwards);
TimelineViewGhostItem* ghost_;
TimelineViewGhostItem *ghost_;
rational drag_start_point_;
rational drag_start_point_;
};
}
+14 -12
View File
@@ -21,29 +21,31 @@
#include "beam.h"
#include "widget/timelinewidget/timelinewidget.h"
namespace olive {
namespace olive
{
BeamTool::BeamTool(TimelineWidget *parent) :
TimelineTool(parent)
BeamTool::BeamTool(TimelineWidget *parent)
: TimelineTool(parent)
{
}
void BeamTool::HoverMove(TimelineViewMouseEvent *event)
{
parent()->SetViewBeamCursor(ValidatedCoordinate(event->GetCoordinates(true)));
parent()->SetViewBeamCursor(
ValidatedCoordinate(event->GetCoordinates(true)));
}
TimelineCoordinate BeamTool::ValidatedCoordinate(TimelineCoordinate coord)
{
if (Core::instance()->snapping()) {
rational movement;
parent()->SnapPoint({coord.GetFrame()}, &movement);
if (!movement.isNull()) {
coord.SetFrame(coord.GetFrame() + movement);
}
}
if (Core::instance()->snapping()) {
rational movement;
parent()->SnapPoint({ coord.GetFrame() }, &movement);
if (!movement.isNull()) {
coord.SetFrame(coord.GetFrame() + movement);
}
}
return coord;
return coord;
}
}
+7 -8
View File
@@ -23,18 +23,17 @@
#include "tool.h"
namespace olive {
class BeamTool : public TimelineTool
namespace olive
{
public:
BeamTool(TimelineWidget *parent);
virtual void HoverMove(TimelineViewMouseEvent *event) override;
class BeamTool : public TimelineTool {
public:
BeamTool(TimelineWidget *parent);
virtual void HoverMove(TimelineViewMouseEvent *event) override;
protected:
TimelineCoordinate ValidatedCoordinate(TimelineCoordinate coord);
TimelineCoordinate ValidatedCoordinate(TimelineCoordinate coord);
};
}
+41 -40
View File
@@ -21,72 +21,73 @@
#include "edit.h"
#include "widget/timelinewidget/timelinewidget.h"
namespace olive {
namespace olive
{
EditTool::EditTool(TimelineWidget* parent) :
BeamTool(parent)
EditTool::EditTool(TimelineWidget *parent)
: BeamTool(parent)
{
}
void EditTool::MousePress(TimelineViewMouseEvent *event)
{
if (!(event->GetModifiers() & Qt::ShiftModifier)) {
parent()->DeselectAll();
}
if (!(event->GetModifiers() & Qt::ShiftModifier)) {
parent()->DeselectAll();
}
}
void EditTool::MouseMove(TimelineViewMouseEvent *event)
{
if (dragging_) {
rational end_frame = event->GetFrame(true);
if (dragging_) {
rational end_frame = event->GetFrame(true);
if (Core::instance()->snapping()) {
rational movement;
parent()->SnapPoint({end_frame}, &movement);
if (!movement.isNull()) {
end_frame += movement;
}
}
if (Core::instance()->snapping()) {
rational movement;
parent()->SnapPoint({ end_frame }, &movement);
if (!movement.isNull()) {
end_frame += movement;
}
}
parent()->SetSelections(start_selections_, false);
parent()->AddSelection(TimeRange(start_coord_.GetFrame(), end_frame),
start_coord_.GetTrack());
} else {
start_selections_ = parent()->GetSelections();
parent()->SetSelections(start_selections_, false);
parent()->AddSelection(TimeRange(start_coord_.GetFrame(), end_frame),
start_coord_.GetTrack());
} else {
start_selections_ = parent()->GetSelections();
dragging_ = true;
dragging_ = true;
start_coord_ = event->GetCoordinates(true);
start_coord_ = event->GetCoordinates(true);
// Snap if we're snapping
if (Core::instance()->snapping()) {
rational movement;
parent()->SnapPoint({start_coord_.GetFrame()}, &movement);
if (!movement.isNull()) {
start_coord_.SetFrame(start_coord_.GetFrame() + movement);
}
}
// Snap if we're snapping
if (Core::instance()->snapping()) {
rational movement;
parent()->SnapPoint({ start_coord_.GetFrame() }, &movement);
if (!movement.isNull()) {
start_coord_.SetFrame(start_coord_.GetFrame() + movement);
}
}
dragging_ = true;
}
dragging_ = true;
}
}
void EditTool::MouseRelease(TimelineViewMouseEvent *event)
{
auto current_sel = parent()->GetSelections();
parent()->SetSelections(start_selections_, false);
parent()->SetSelections(current_sel, true);
auto current_sel = parent()->GetSelections();
parent()->SetSelections(start_selections_, false);
parent()->SetSelections(current_sel, true);
dragging_ = false;
dragging_ = false;
}
void EditTool::MouseDoubleClick(TimelineViewMouseEvent *event)
{
Block* item = parent()->GetItemAtScenePos(event->GetCoordinates());
Block *item = parent()->GetItemAtScenePos(event->GetCoordinates());
if (item && !item->track()->IsLocked()) {
parent()->AddSelection(item);
}
if (item && !item->track()->IsLocked()) {
parent()->AddSelection(item);
}
}
}
+11 -12
View File
@@ -25,23 +25,22 @@
#include "tool.h"
#include "widget/timelinewidget/timelinewidgetselections.h"
namespace olive {
class EditTool : public BeamTool
namespace olive
{
public:
EditTool(TimelineWidget* parent);
virtual void MousePress(TimelineViewMouseEvent *event) override;
virtual void MouseMove(TimelineViewMouseEvent *event) override;
virtual void MouseRelease(TimelineViewMouseEvent *event) override;
virtual void MouseDoubleClick(TimelineViewMouseEvent *event) override;
class EditTool : public BeamTool {
public:
EditTool(TimelineWidget *parent);
virtual void MousePress(TimelineViewMouseEvent *event) override;
virtual void MouseMove(TimelineViewMouseEvent *event) override;
virtual void MouseRelease(TimelineViewMouseEvent *event) override;
virtual void MouseDoubleClick(TimelineViewMouseEvent *event) override;
private:
TimelineWidgetSelections start_selections_;
TimelineCoordinate start_coord_;
TimelineWidgetSelections start_selections_;
TimelineCoordinate start_coord_;
};
}
+442 -363
View File
@@ -40,509 +40,588 @@
#include "window/mainwindow/mainwindow.h"
#include "window/mainwindow/mainwindowundo.h"
namespace olive {
ImportTool::ImportTool(TimelineWidget *parent) :
TimelineTool(parent)
namespace olive
{
// Calculate width used for importing to give ghosts a slight lead-in so the ghosts aren't right on the cursor
import_pre_buffer_ = QtUtils::QFontMetricsWidth(parent->fontMetrics(), "HHHHHHHH");
ImportTool::ImportTool(TimelineWidget *parent)
: TimelineTool(parent)
{
// Calculate width used for importing to give ghosts a slight lead-in so the ghosts aren't right on the cursor
import_pre_buffer_ =
QtUtils::QFontMetricsWidth(parent->fontMetrics(), "HHHHHHHH");
}
void ImportTool::DragEnter(TimelineViewMouseEvent *event)
{
QStringList mime_formats = event->GetMimeData()->formats();
QStringList mime_formats = event->GetMimeData()->formats();
// Listen for MIME data from a ProjectViewModel
if (mime_formats.contains(Project::kItemMimeType)) {
// Listen for MIME data from a ProjectViewModel
if (mime_formats.contains(Project::kItemMimeType)) {
// Data is drag/drop data from a ProjectViewModel
QByteArray model_data =
event->GetMimeData()->data(Project::kItemMimeType);
// Data is drag/drop data from a ProjectViewModel
QByteArray model_data = event->GetMimeData()->data(Project::kItemMimeType);
// Use QDataStream to deserialize the data
QDataStream stream(&model_data, QIODevice::ReadOnly);
// Use QDataStream to deserialize the data
QDataStream stream(&model_data, QIODevice::ReadOnly);
// Variables to deserialize into
quintptr item_ptr;
QVector<Track::Reference> enabled_streams;
// Variables to deserialize into
quintptr item_ptr;
QVector<Track::Reference> enabled_streams;
// Set drag start position
drag_start_ = event->GetCoordinates();
// Set drag start position
drag_start_ = event->GetCoordinates();
snap_points_.clear();
snap_points_.clear();
while (!stream.atEnd()) {
stream >> enabled_streams >> item_ptr;
while (!stream.atEnd()) {
stream >> enabled_streams >> item_ptr;
// Get Item object
Node *item = reinterpret_cast<Node *>(item_ptr);
// Get Item object
Node* item = reinterpret_cast<Node*>(item_ptr);
// Check if Item is Footage
ViewerOutput *f = dynamic_cast<ViewerOutput *>(item);
// Check if Item is Footage
ViewerOutput* f = dynamic_cast<ViewerOutput*>(item);
if (f && f->GetTotalStreamCount()) {
// If the Item is Footage, we can create a Ghost from it
dragged_footage_.append({ f, enabled_streams });
}
}
if (f && f->GetTotalStreamCount()) {
// If the Item is Footage, we can create a Ghost from it
dragged_footage_.append({f, enabled_streams});
}
}
// Create a reasonable amount of space to inset the cursor by when importing
ghost_offset_ = drag_start_.GetFrame();
// Create a reasonable amount of space to inset the cursor by when importing
ghost_offset_ = drag_start_.GetFrame();
if (!event->GetBypassImportBuffer()) {
ghost_offset_ -= parent()->SceneToTime(import_pre_buffer_);
}
if (!event->GetBypassImportBuffer()) {
ghost_offset_ -= parent()->SceneToTime(import_pre_buffer_);
}
PrepGhosts(ghost_offset_, drag_start_.GetTrack().index());
PrepGhosts(ghost_offset_, drag_start_.GetTrack().index());
if (parent()->HasGhosts() || !parent()->GetConnectedNode()) {
// We only clear the tentative track if the mimedata is about to be destroyed (i.e. the drag
// is cancelled). If we do this in DragLeave, it leads to undesirable behavior if the cursor
// is going between views (subtitle track rapidly appearing and disappearing)
QObject::connect(event->GetMimeData(), &QObject::destroyed,
parent(),
&TimelineWidget::ClearTentativeSubtitleTrack);
if (parent()->HasGhosts() || !parent()->GetConnectedNode()) {
// We only clear the tentative track if the mimedata is about to be destroyed (i.e. the drag
// is cancelled). If we do this in DragLeave, it leads to undesirable behavior if the cursor
// is going between views (subtitle track rapidly appearing and disappearing)
QObject::connect(event->GetMimeData(), &QObject::destroyed, parent(), &TimelineWidget::ClearTentativeSubtitleTrack);
event->accept();
} else {
event->ignore();
}
} else {
// FIXME: Implement dropping from file
event->ignore();
}
event->accept();
} else {
event->ignore();
}
} else {
// FIXME: Implement dropping from file
event->ignore();
}
}
void ImportTool::DragMove(TimelineViewMouseEvent *event)
{
if (!dragged_footage_.isEmpty()) {
if (!dragged_footage_.isEmpty()) {
if (parent()->HasGhosts()) {
rational time_movement = event->GetFrame() - drag_start_.GetFrame();
if (parent()->HasGhosts()) {
rational time_movement = event->GetFrame() - drag_start_.GetFrame();
// Keep ghost offset no lower than 0
if (ghost_offset_ + time_movement < 0) {
time_movement = -ghost_offset_;
}
// Keep ghost offset no lower than 0
if (ghost_offset_ + time_movement < 0) {
time_movement = -ghost_offset_;
}
int track_movement =
event->GetTrack().index() - drag_start_.GetTrack().index();
int track_movement = event->GetTrack().index() - drag_start_.GetTrack().index();
time_movement = ValidateTimeMovement(time_movement);
track_movement = ValidateTrackMovement(track_movement,
parent()->GetGhostItems());
time_movement = ValidateTimeMovement(time_movement);
track_movement = ValidateTrackMovement(track_movement, parent()->GetGhostItems());
// If snapping is enabled, check for snap points
if (Core::instance()->snapping()) {
parent()->SnapPoint(snap_points_, &time_movement);
// If snapping is enabled, check for snap points
if (Core::instance()->snapping()) {
parent()->SnapPoint(snap_points_, &time_movement);
time_movement = ValidateTimeMovement(time_movement);
track_movement = ValidateTrackMovement(
track_movement, parent()->GetGhostItems());
}
time_movement = ValidateTimeMovement(time_movement);
track_movement = ValidateTrackMovement(track_movement, parent()->GetGhostItems());
}
rational earliest_ghost = RATIONAL_MAX;
rational earliest_ghost = RATIONAL_MAX;
// Move ghosts to the mouse cursor
foreach (TimelineViewGhostItem *ghost, parent()->GetGhostItems()) {
ghost->SetInAdjustment(time_movement);
ghost->SetOutAdjustment(time_movement);
ghost->SetTrackAdjustment(track_movement);
// Move ghosts to the mouse cursor
foreach (TimelineViewGhostItem* ghost, parent()->GetGhostItems()) {
ghost->SetInAdjustment(time_movement);
ghost->SetOutAdjustment(time_movement);
ghost->SetTrackAdjustment(track_movement);
earliest_ghost = qMin(earliest_ghost, ghost->GetAdjustedIn());
}
earliest_ghost = qMin(earliest_ghost, ghost->GetAdjustedIn());
}
// Generate tooltip (showing earliest in point of imported clip)
rational tooltip_timebase =
parent()->GetTimebaseForTrackType(event->GetTrack().type());
QString tooltip_text =
QString::fromStdString(Timecode::time_to_timecode(
earliest_ghost, tooltip_timebase,
Core::instance()->GetTimecodeDisplay()));
// Generate tooltip (showing earliest in point of imported clip)
rational tooltip_timebase = parent()->GetTimebaseForTrackType(event->GetTrack().type());
QString tooltip_text = QString::fromStdString(Timecode::time_to_timecode(earliest_ghost,
tooltip_timebase,
Core::instance()->GetTimecodeDisplay()));
// Force tooltip to update (otherwise the tooltip won't move as written in the documentation, and could get in the way
// of the cursor)
QToolTip::hideText();
QToolTip::showText(QCursor::pos(), tooltip_text, parent());
}
// Force tooltip to update (otherwise the tooltip won't move as written in the documentation, and could get in the way
// of the cursor)
QToolTip::hideText();
QToolTip::showText(QCursor::pos(),
tooltip_text,
parent());
}
event->accept();
} else {
event->ignore();
}
event->accept();
} else {
event->ignore();
}
}
void ImportTool::DragLeave(QDragLeaveEvent* event)
void ImportTool::DragLeave(QDragLeaveEvent *event)
{
if (!dragged_footage_.isEmpty()) {
parent()->ClearGhosts();
dragged_footage_.clear();
if (!dragged_footage_.isEmpty()) {
parent()->ClearGhosts();
dragged_footage_.clear();
event->accept();
} else {
event->ignore();
}
event->accept();
} else {
event->ignore();
}
}
void ImportTool::DragDrop(TimelineViewMouseEvent *event)
{
if (!dragged_footage_.isEmpty()) {
auto command = new MultiUndoCommand();
DropGhosts(event->GetModifiers() & Qt::ControlModifier, command);
Core::instance()->undo_stack()->push(command, qApp->translate("ImportTool", "Dropped Footage Into Sequence"));
if (!dragged_footage_.isEmpty()) {
auto command = new MultiUndoCommand();
DropGhosts(event->GetModifiers() & Qt::ControlModifier, command);
Core::instance()->undo_stack()->push(
command,
qApp->translate("ImportTool", "Dropped Footage Into Sequence"));
event->accept();
} else {
event->ignore();
}
event->accept();
} else {
event->ignore();
}
}
void ImportTool::PlaceAt(const QVector<ViewerOutput *> &footage, const rational &start, bool insert, MultiUndoCommand *command, int track_offset, bool jump_to_end)
void ImportTool::PlaceAt(const QVector<ViewerOutput *> &footage,
const rational &start, bool insert,
MultiUndoCommand *command, int track_offset,
bool jump_to_end)
{
DraggedFootageData refs;
DraggedFootageData refs;
foreach (ViewerOutput* f, footage) {
refs.append({f, f->GetEnabledStreamsAsReferences()});
}
foreach (ViewerOutput *f, footage) {
refs.append({ f, f->GetEnabledStreamsAsReferences() });
}
PlaceAt(refs, start, insert, command, track_offset, jump_to_end);
PlaceAt(refs, start, insert, command, track_offset, jump_to_end);
}
void ImportTool::PlaceAt(const DraggedFootageData &footage, const rational &start, bool insert, MultiUndoCommand *command, int track_offset, bool jump_to_end)
void ImportTool::PlaceAt(const DraggedFootageData &footage,
const rational &start, bool insert,
MultiUndoCommand *command, int track_offset,
bool jump_to_end)
{
dragged_footage_ = footage;
dragged_footage_ = footage;
if (dragged_footage_.isEmpty()) {
return;
}
if (dragged_footage_.isEmpty()) {
return;
}
PrepGhosts(start, track_offset);
PrepGhosts(start, track_offset);
rational max(0);
if (jump_to_end) {
for (TimelineViewGhostItem* ghost : parent()->GetGhostItems()) {
max = std::max(max, ghost->GetAdjustedOut());
}
}
rational max(0);
if (jump_to_end) {
for (TimelineViewGhostItem *ghost : parent()->GetGhostItems()) {
max = std::max(max, ghost->GetAdjustedOut());
}
}
DropGhosts(insert, command);
DropGhosts(insert, command);
if (jump_to_end) {
this->sequence()->SetPlayhead(max);
}
if (jump_to_end) {
this->sequence()->SetPlayhead(max);
}
}
void ImportTool::FootageToGhosts(rational ghost_start, const DraggedFootageData &sorted, const rational& dest_tb, const int& track_start)
void ImportTool::FootageToGhosts(rational ghost_start,
const DraggedFootageData &sorted,
const rational &dest_tb,
const int &track_start)
{
for (auto it=sorted.cbegin(); it!=sorted.cend(); it++) {
ViewerOutput* footage = it->first;
for (auto it = sorted.cbegin(); it != sorted.cend(); it++) {
ViewerOutput *footage = it->first;
if (footage == sequence() || (sequence() && footage->InputsFrom(sequence(), true))) {
// Prevent cyclical dependency
continue;
}
if (footage == sequence() ||
(sequence() && footage->InputsFrom(sequence(), true))) {
// Prevent cyclical dependency
continue;
}
// Each stream is offset by one track per track "type", we keep track of them in this vector
QVector<int> track_offsets(Track::kCount);
track_offsets.fill(track_start);
// Each stream is offset by one track per track "type", we keep track of them in this vector
QVector<int> track_offsets(Track::kCount);
track_offsets.fill(track_start);
rational footage_duration;
rational ghost_in;
rational footage_duration;
rational ghost_in;
TimelineWorkArea* wk = footage->GetWorkArea();
if (wk->enabled()) {
footage_duration = wk->length();
ghost_in = wk->in();
} else {
footage_duration = footage->GetLength();
TimelineWorkArea *wk = footage->GetWorkArea();
if (wk->enabled()) {
footage_duration = wk->length();
ghost_in = wk->in();
} else {
footage_duration = footage->GetLength();
if (footage_duration.isNull()) {
// Fallback to still length if legngth was 0
footage_duration = OLIVE_CONFIG("DefaultStillLength").value<rational>();
}
}
if (footage_duration.isNull()) {
// Fallback to still length if legngth was 0
footage_duration =
OLIVE_CONFIG("DefaultStillLength").value<rational>();
}
}
// Snap footage duration to timebase
rational snap_mvmt = SnapMovementToTimebase(footage_duration, 0, dest_tb);
if (!snap_mvmt.isNull()) {
footage_duration += snap_mvmt;
}
// Snap footage duration to timebase
rational snap_mvmt =
SnapMovementToTimebase(footage_duration, 0, dest_tb);
if (!snap_mvmt.isNull()) {
footage_duration += snap_mvmt;
}
// Create ghosts
foreach (const Track::Reference& ref, it->second) {
Track::Type track_type = ref.type();
Track::Reference dest_track(track_type, track_offsets.at(track_type));
// Create ghosts
foreach (const Track::Reference &ref, it->second) {
Track::Type track_type = ref.type();
Track::Reference dest_track(track_type,
track_offsets.at(track_type));
if (track_type == Track::kVideo || track_type == Track::kAudio) {
auto ghost = CreateGhost(TimeRange(ghost_start, ghost_start + footage_duration), ghost_in, dest_track);
if (track_type == Track::kVideo || track_type == Track::kAudio) {
auto ghost = CreateGhost(
TimeRange(ghost_start, ghost_start + footage_duration),
ghost_in, dest_track);
// Increment track count for this track type
track_offsets[track_type]++;
// Increment track count for this track type
track_offsets[track_type]++;
TimelineViewGhostItem::AttachedFootage af = {it->first, ref.ToString()};
ghost->SetData(TimelineViewGhostItem::kAttachedFootage, QVariant::fromValue(af));
} else if (track_type == Track::kSubtitle) {
SubtitleParams sp = footage->GetSubtitleParams(ref.index());
TimelineViewGhostItem::AttachedFootage af = { it->first,
ref.ToString() };
ghost->SetData(TimelineViewGhostItem::kAttachedFootage,
QVariant::fromValue(af));
} else if (track_type == Track::kSubtitle) {
SubtitleParams sp = footage->GetSubtitleParams(ref.index());
for (const Subtitle &sub : sp) {
auto ghost = CreateGhost(sub.time() + ghost_start, 0, dest_track);
for (const Subtitle &sub : sp) {
auto ghost =
CreateGhost(sub.time() + ghost_start, 0, dest_track);
ghost->SetData(TimelineViewGhostItem::kAttachedFootage, QVariant::fromValue(sub));
}
ghost->SetData(TimelineViewGhostItem::kAttachedFootage,
QVariant::fromValue(sub));
}
parent()->AddTentativeSubtitleTrack();
}
}
parent()->AddTentativeSubtitleTrack();
}
}
// Stack each ghost one after the other
ghost_start += footage_duration;
}
// Stack each ghost one after the other
ghost_start += footage_duration;
}
}
void ImportTool::PrepGhosts(const rational& frame, const int& track_index)
void ImportTool::PrepGhosts(const rational &frame, const int &track_index)
{
if (parent()->GetConnectedNode()) {
FootageToGhosts(frame,
dragged_footage_,
parent()->GetConnectedNode()->GetVideoParams().time_base(),
track_index);
}
if (parent()->GetConnectedNode()) {
FootageToGhosts(
frame, dragged_footage_,
parent()->GetConnectedNode()->GetVideoParams().time_base(),
track_index);
}
}
void ImportTool::DropGhosts(bool insert, MultiUndoCommand *parent_command)
{
auto command = new MultiUndoCommand();
auto command = new MultiUndoCommand();
if (MultiUndoCommand *c = parent()->TakeSubtitleSectionCommand()) {
command->add_child(c);
}
if (MultiUndoCommand *c = parent()->TakeSubtitleSectionCommand()) {
command->add_child(c);
}
Project* dst_graph = nullptr;
Sequence* sequence = this->sequence();
bool open_sequence = false;
Project *dst_graph = nullptr;
Sequence *sequence = this->sequence();
bool open_sequence = false;
if (sequence) {
dst_graph = sequence->parent();
} else {
// There's no active timeline here, ask the user what to do
if (sequence) {
dst_graph = sequence->parent();
} else {
// There's no active timeline here, ask the user what to do
DropWithoutSequenceBehavior behavior = static_cast<DropWithoutSequenceBehavior>(OLIVE_CONFIG("DropWithoutSequenceBehavior").toInt());
DropWithoutSequenceBehavior behavior =
static_cast<DropWithoutSequenceBehavior>(
OLIVE_CONFIG("DropWithoutSequenceBehavior").toInt());
if (behavior == kDWSAsk) {
QCheckBox* dont_ask_again_box = new QCheckBox(QCoreApplication::translate("ImportTool", "Don't ask me again"));
if (behavior == kDWSAsk) {
QCheckBox *dont_ask_again_box = new QCheckBox(
QCoreApplication::translate("ImportTool",
"Don't ask me again"));
QMessageBox mbox(parent());
QMessageBox mbox(parent());
mbox.setIcon(QMessageBox::Question);
mbox.setWindowTitle(QCoreApplication::translate("ImportTool", "No Active Sequence"));
mbox.setText(QCoreApplication::translate("ImportTool", "No sequence is currently open. Would you like to create one?"));
mbox.setCheckBox(dont_ask_again_box);
mbox.setIcon(QMessageBox::Question);
mbox.setWindowTitle(QCoreApplication::translate(
"ImportTool", "No Active Sequence"));
mbox.setText(QCoreApplication::translate(
"ImportTool",
"No sequence is currently open. Would you like to create one?"));
mbox.setCheckBox(dont_ask_again_box);
QPushButton* auto_params_btn = mbox.addButton(QCoreApplication::translate("ImportTool", "Automatically Detect Parameters From Footage"), QMessageBox::YesRole);
QPushButton* manual_params_btn = mbox.addButton(QCoreApplication::translate("ImportTool", "Set Parameters Manually"), QMessageBox::NoRole);
mbox.addButton(QMessageBox::Cancel);
QPushButton *auto_params_btn = mbox.addButton(
QCoreApplication::translate(
"ImportTool",
"Automatically Detect Parameters From Footage"),
QMessageBox::YesRole);
QPushButton *manual_params_btn =
mbox.addButton(QCoreApplication::translate(
"ImportTool", "Set Parameters Manually"),
QMessageBox::NoRole);
mbox.addButton(QMessageBox::Cancel);
mbox.exec();
mbox.exec();
if (mbox.clickedButton() == auto_params_btn) {
behavior = kDWSAuto;
} else if (mbox.clickedButton() == manual_params_btn) {
behavior = kDWSManual;
} else {
behavior = kDWSDisable;
}
if (mbox.clickedButton() == auto_params_btn) {
behavior = kDWSAuto;
} else if (mbox.clickedButton() == manual_params_btn) {
behavior = kDWSManual;
} else {
behavior = kDWSDisable;
}
if (behavior != kDWSDisable && dont_ask_again_box->isChecked()) {
OLIVE_CONFIG("DropWithoutSequenceBehavior") = behavior;
}
}
if (behavior != kDWSDisable && dont_ask_again_box->isChecked()) {
OLIVE_CONFIG("DropWithoutSequenceBehavior") = behavior;
}
}
if (behavior != kDWSDisable) {
Project* active_project = Core::instance()->GetActiveProject();
if (behavior != kDWSDisable) {
Project *active_project = Core::instance()->GetActiveProject();
if (active_project) {
Sequence* new_sequence = Core::instance()->CreateNewSequenceForProject(active_project);
if (active_project) {
Sequence *new_sequence =
Core::instance()->CreateNewSequenceForProject(
active_project);
new_sequence->set_default_parameters();
new_sequence->set_default_parameters();
bool sequence_is_valid = true;
bool sequence_is_valid = true;
// Even if the user selected manual, set from footage anyway so the user has a useful
// starting point
QVector<ViewerOutput*> footage_only;
// Even if the user selected manual, set from footage anyway so the user has a useful
// starting point
QVector<ViewerOutput *> footage_only;
for (auto it=dragged_footage_.cbegin(); it!=dragged_footage_.cend(); it++) {
if (!footage_only.contains(it->first)) {
footage_only.append(it->first);
}
}
for (auto it = dragged_footage_.cbegin();
it != dragged_footage_.cend(); it++) {
if (!footage_only.contains(it->first)) {
footage_only.append(it->first);
}
}
new_sequence->set_parameters_from_footage(footage_only);
new_sequence->set_parameters_from_footage(footage_only);
// If the user selected manual, show them a dialog with parameters
if (behavior == kDWSManual) {
// If the user selected manual, show them a dialog with parameters
if (behavior == kDWSManual) {
SequenceDialog sd(new_sequence, SequenceDialog::kNew,
parent());
sd.SetUndoable(false);
SequenceDialog sd(new_sequence, SequenceDialog::kNew, parent());
sd.SetUndoable(false);
if (sd.exec() != QDialog::Accepted) {
sequence_is_valid = false;
}
}
if (sd.exec() != QDialog::Accepted) {
sequence_is_valid = false;
}
if (sequence_is_valid) {
dst_graph = Core::instance()->GetActiveProject();
}
command->add_child(
new NodeAddCommand(dst_graph, new_sequence));
command->add_child(new FolderAddChild(
Core::instance()->GetSelectedFolderInActiveProject(),
new_sequence));
command->add_child(new NodeSetPositionCommand(
new_sequence, new_sequence, QPointF(0, 0)));
new_sequence->add_default_nodes(command);
if (sequence_is_valid) {
dst_graph = Core::instance()->GetActiveProject();
FootageToGhosts(0, dragged_footage_,
new_sequence->GetVideoParams().time_base(),
0);
command->add_child(new NodeAddCommand(dst_graph, new_sequence));
command->add_child(new FolderAddChild(Core::instance()->GetSelectedFolderInActiveProject(), new_sequence));
command->add_child(new NodeSetPositionCommand(new_sequence, new_sequence, QPointF(0, 0)));
new_sequence->add_default_nodes(command);
if (MultiUndoCommand *c =
parent()->TakeSubtitleSectionCommand()) {
command->add_child(c);
}
FootageToGhosts(0, dragged_footage_, new_sequence->GetVideoParams().time_base(), 0);
sequence = new_sequence;
if (MultiUndoCommand *c = parent()->TakeSubtitleSectionCommand()) {
command->add_child(c);
}
// Set this as the sequence to open
open_sequence = true;
} else {
// If the sequence is valid, ownership is passed to AddItemCommand.
// Otherwise, we're responsible for deleting it.
delete new_sequence;
}
}
}
}
sequence = new_sequence;
std::list<ClipBlock *> imported_clips;
// Set this as the sequence to open
open_sequence = true;
} else {
// If the sequence is valid, ownership is passed to AddItemCommand.
// Otherwise, we're responsible for deleting it.
delete new_sequence;
}
}
}
}
if (dst_graph) {
QVector<Block *> block_items(parent()->GetGhostItems().size());
std::list<ClipBlock*> imported_clips;
// Check if we're inserting (only valid if we're not creating this sequence ourselves)
if (insert && !open_sequence) {
InsertGapsAtGhostDestination(command);
}
if (dst_graph) {
for (int i = 0; i < parent()->GetGhostItems().size(); i++) {
TimelineViewGhostItem *ghost = parent()->GetGhostItems().at(i);
Block *block = nullptr;
QVector<Block*> block_items(parent()->GetGhostItems().size());
Track::Type track_type = ghost->GetAdjustedTrack().type();
if (track_type == Track::kVideo || track_type == Track::kAudio) {
TimelineViewGhostItem::AttachedFootage footage_stream =
ghost->GetData(TimelineViewGhostItem::kAttachedFootage)
.value<TimelineViewGhostItem::AttachedFootage>();
// Check if we're inserting (only valid if we're not creating this sequence ourselves)
if (insert && !open_sequence) {
InsertGapsAtGhostDestination(command);
}
ClipBlock *clip = new ClipBlock();
block = clip;
clip->set_media_in(ghost->GetMediaIn());
command->add_child(new NodeAddCommand(dst_graph, clip));
for (int i=0;i<parent()->GetGhostItems().size();i++) {
TimelineViewGhostItem* ghost = parent()->GetGhostItems().at(i);
Block* block = nullptr;
// Position clip in its own context
command->add_child(
new NodeSetPositionCommand(clip, clip, QPointF(0, 0)));
Track::Type track_type = ghost->GetAdjustedTrack().type();
if (track_type == Track::kVideo || track_type == Track::kAudio) {
TimelineViewGhostItem::AttachedFootage footage_stream = ghost->GetData(TimelineViewGhostItem::kAttachedFootage).value<TimelineViewGhostItem::AttachedFootage>();
int dep_pos = kDefaultDistanceFromOutput;
ClipBlock* clip = new ClipBlock();
block = clip;
clip->set_media_in(ghost->GetMediaIn());
command->add_child(new NodeAddCommand(dst_graph, clip));
// Position footage in its context
command->add_child(new NodeSetPositionCommand(
footage_stream.footage, clip, QPointF(dep_pos, 0)));
// Position clip in its own context
command->add_child(new NodeSetPositionCommand(clip, clip, QPointF(0, 0)));
dep_pos++;
int dep_pos = kDefaultDistanceFromOutput;
switch (
Track::Reference::TypeFromString(footage_stream.output)) {
case Track::kVideo: {
TransformDistortNode *transform =
new TransformDistortNode();
command->add_child(
new NodeAddCommand(dst_graph, transform));
// Position footage in its context
command->add_child(new NodeSetPositionCommand(footage_stream.footage, clip, QPointF(dep_pos, 0)));
command->add_child(new NodeSetValueHintCommand(
transform, TransformDistortNode::kTextureInput, -1,
Node::ValueHint({ NodeValue::kTexture },
footage_stream.output)));
dep_pos++;
command->add_child(new NodeEdgeAddCommand(
footage_stream.footage,
NodeInput(transform,
TransformDistortNode::kTextureInput)));
command->add_child(new NodeEdgeAddCommand(
transform, NodeInput(clip, ClipBlock::kBufferIn)));
command->add_child(new NodeSetPositionCommand(
transform, clip, QPointF(dep_pos, 0)));
break;
}
case Track::kAudio: {
VolumeNode *volume_node = new VolumeNode();
command->add_child(
new NodeAddCommand(dst_graph, volume_node));
switch (Track::Reference::TypeFromString(footage_stream.output)) {
case Track::kVideo:
{
TransformDistortNode* transform = new TransformDistortNode();
command->add_child(new NodeAddCommand(dst_graph, transform));
command->add_child(new NodeSetValueHintCommand(
volume_node, VolumeNode::kSamplesInput, -1,
Node::ValueHint({ NodeValue::kSamples },
footage_stream.output)));
command->add_child(new NodeSetValueHintCommand(transform, TransformDistortNode::kTextureInput, -1, Node::ValueHint({NodeValue::kTexture}, footage_stream.output)));
command->add_child(new NodeEdgeAddCommand(
footage_stream.footage,
NodeInput(volume_node, VolumeNode::kSamplesInput)));
command->add_child(new NodeEdgeAddCommand(
volume_node, NodeInput(clip, ClipBlock::kBufferIn)));
command->add_child(new NodeSetPositionCommand(
volume_node, clip, QPointF(dep_pos, 0)));
break;
}
default:
break;
}
command->add_child(new NodeEdgeAddCommand(footage_stream.footage, NodeInput(transform, TransformDistortNode::kTextureInput)));
command->add_child(new NodeEdgeAddCommand(transform, NodeInput(clip, ClipBlock::kBufferIn)));
command->add_child(new NodeSetPositionCommand(transform, clip, QPointF(dep_pos, 0)));
break;
}
case Track::kAudio:
{
VolumeNode* volume_node = new VolumeNode();
command->add_child(new NodeAddCommand(dst_graph, volume_node));
// Link any clips so far that share the same Footage with this one
for (int j = 0; j < i; j++) {
TimelineViewGhostItem::AttachedFootage footage_compare =
parent()
->GetGhostItems()
.at(j)
->GetData(TimelineViewGhostItem::kAttachedFootage)
.value<TimelineViewGhostItem::AttachedFootage>();
command->add_child(new NodeSetValueHintCommand(volume_node, VolumeNode::kSamplesInput, -1, Node::ValueHint({NodeValue::kSamples}, footage_stream.output)));
if (footage_compare.footage == footage_stream.footage) {
Block::Link(block_items.at(j), clip);
}
}
command->add_child(new NodeEdgeAddCommand(footage_stream.footage, NodeInput(volume_node, VolumeNode::kSamplesInput)));
command->add_child(new NodeEdgeAddCommand(volume_node, NodeInput(clip, ClipBlock::kBufferIn)));
command->add_child(new NodeSetPositionCommand(volume_node, clip, QPointF(dep_pos, 0)));
break;
}
default:
break;
}
imported_clips.push_back(clip);
} else if (track_type == Track::kSubtitle) {
Subtitle src =
ghost->GetData(TimelineViewGhostItem::kAttachedFootage)
.value<Subtitle>();
SubtitleBlock *sub = new SubtitleBlock();
sub->SetText(src.text());
block = sub;
// Link any clips so far that share the same Footage with this one
for (int j=0;j<i;j++) {
TimelineViewGhostItem::AttachedFootage footage_compare = parent()->GetGhostItems().at(j)->GetData(TimelineViewGhostItem::kAttachedFootage).value<TimelineViewGhostItem::AttachedFootage>();
command->add_child(new NodeAddCommand(dst_graph, sub));
command->add_child(
new NodeSetPositionCommand(sub, sub, QPointF(0, 0)));
}
if (footage_compare.footage == footage_stream.footage) {
Block::Link(block_items.at(j), clip);
}
}
block->set_length_and_media_out(ghost->GetLength());
imported_clips.push_back(clip);
} else if (track_type == Track::kSubtitle) {
Subtitle src = ghost->GetData(TimelineViewGhostItem::kAttachedFootage).value<Subtitle>();
SubtitleBlock *sub = new SubtitleBlock();
sub->SetText(src.text());
block = sub;
command->add_child(new TrackPlaceBlockCommand(
sequence->track_list(ghost->GetAdjustedTrack().type()),
ghost->GetAdjustedTrack().index(), block,
ghost->GetAdjustedIn()));
command->add_child(new NodeAddCommand(dst_graph, sub));
command->add_child(new NodeSetPositionCommand(sub, sub, QPointF(0, 0)));
}
block_items.replace(i, block);
}
}
block->set_length_and_media_out(ghost->GetLength());
if (open_sequence) {
command->add_child(new OpenSequenceCommand(sequence));
}
command->add_child(new TrackPlaceBlockCommand(sequence->track_list(ghost->GetAdjustedTrack().type()),
ghost->GetAdjustedTrack().index(),
block,
ghost->GetAdjustedIn()));
// Do command now because RequestInvalidatedFromConnected relies on track type, which will be
// "none" before this command is done because it won't be connected to any track
command->redo_now();
parent_command->add_child(command);
block_items.replace(i, block);
}
}
while (!imported_clips.empty()) {
imported_clips.front()->RequestInvalidatedFromConnected();
imported_clips.pop_front();
}
if (open_sequence) {
command->add_child(new OpenSequenceCommand(sequence));
}
// Do command now because RequestInvalidatedFromConnected relies on track type, which will be
// "none" before this command is done because it won't be connected to any track
command->redo_now();
parent_command->add_child(command);
while (!imported_clips.empty()) {
imported_clips.front()->RequestInvalidatedFromConnected();
imported_clips.pop_front();
}
parent()->ClearGhosts();
dragged_footage_.clear();
parent()->ClearGhosts();
dragged_footage_.clear();
}
TimelineViewGhostItem* ImportTool::CreateGhost(const TimeRange &range, const rational &media_in, const Track::Reference &track)
TimelineViewGhostItem *ImportTool::CreateGhost(const TimeRange &range,
const rational &media_in,
const Track::Reference &track)
{
TimelineViewGhostItem* ghost = new TimelineViewGhostItem();
TimelineViewGhostItem *ghost = new TimelineViewGhostItem();
ghost->SetIn(range.in());
ghost->SetOut(range.out());
ghost->SetMediaIn(media_in);
ghost->SetTrack(track);
ghost->SetIn(range.in());
ghost->SetOut(range.out());
ghost->SetMediaIn(media_in);
ghost->SetTrack(track);
snap_points_.push_back(ghost->GetIn());
snap_points_.push_back(ghost->GetOut());
snap_points_.push_back(ghost->GetIn());
snap_points_.push_back(ghost->GetOut());
ghost->SetMode(Timeline::kMove);
ghost->SetMode(Timeline::kMove);
parent()->AddGhost(ghost);
parent()->AddGhost(ghost);
return ghost;
return ghost;
}
}
+33 -25
View File
@@ -23,45 +23,53 @@
#include "tool.h"
namespace olive {
class ImportTool : public TimelineTool
namespace olive
{
class ImportTool : public TimelineTool {
public:
ImportTool(TimelineWidget* parent);
ImportTool(TimelineWidget *parent);
virtual void DragEnter(TimelineViewMouseEvent *event) override;
virtual void DragMove(TimelineViewMouseEvent *event) override;
virtual void DragLeave(QDragLeaveEvent *event) override;
virtual void DragDrop(TimelineViewMouseEvent *event) override;
virtual void DragEnter(TimelineViewMouseEvent *event) override;
virtual void DragMove(TimelineViewMouseEvent *event) override;
virtual void DragLeave(QDragLeaveEvent *event) override;
virtual void DragDrop(TimelineViewMouseEvent *event) override;
using DraggedFootageData = QVector<QPair<ViewerOutput*, QVector<Track::Reference> > >;
using DraggedFootageData =
QVector<QPair<ViewerOutput *, QVector<Track::Reference>>>;
void PlaceAt(const QVector<ViewerOutput *> &footage, const rational& start, bool insert, MultiUndoCommand *command, int track_offset = 0, bool jump_to_end = false);
void PlaceAt(const DraggedFootageData &footage, const rational& start, bool insert, MultiUndoCommand *command, int track_offset = 0, bool jump_to_end = false);
void PlaceAt(const QVector<ViewerOutput *> &footage, const rational &start,
bool insert, MultiUndoCommand *command, int track_offset = 0,
bool jump_to_end = false);
void PlaceAt(const DraggedFootageData &footage, const rational &start,
bool insert, MultiUndoCommand *command, int track_offset = 0,
bool jump_to_end = false);
enum DropWithoutSequenceBehavior {
kDWSAsk,
kDWSAuto,
kDWSManual,
kDWSDisable
};
enum DropWithoutSequenceBehavior {
kDWSAsk,
kDWSAuto,
kDWSManual,
kDWSDisable
};
private:
void FootageToGhosts(rational ghost_start, const DraggedFootageData &footage, const rational &dest_tb, const int &track_start);
void FootageToGhosts(rational ghost_start,
const DraggedFootageData &footage,
const rational &dest_tb, const int &track_start);
void PrepGhosts(const rational &frame, const int &track_index);
void PrepGhosts(const rational &frame, const int &track_index);
void DropGhosts(bool insert, MultiUndoCommand *parent_command);
void DropGhosts(bool insert, MultiUndoCommand *parent_command);
TimelineViewGhostItem* CreateGhost(const TimeRange &range, const rational &media_in, const Track::Reference &track);
TimelineViewGhostItem *CreateGhost(const TimeRange &range,
const rational &media_in,
const Track::Reference &track);
DraggedFootageData dragged_footage_;
DraggedFootageData dragged_footage_;
int import_pre_buffer_;
rational ghost_offset_;
int import_pre_buffer_;
rational ghost_offset_;
};
}
File diff suppressed because it is too large Load Diff
+77 -64
View File
@@ -23,111 +23,124 @@
#include "tool.h"
namespace olive {
class PointerTool : public TimelineTool
namespace olive
{
class PointerTool : public TimelineTool {
public:
PointerTool(TimelineWidget* parent);
PointerTool(TimelineWidget *parent);
virtual void MousePress(TimelineViewMouseEvent *event) override;
virtual void MouseMove(TimelineViewMouseEvent *event) override;
virtual void MouseRelease(TimelineViewMouseEvent *event) override;
virtual void MousePress(TimelineViewMouseEvent *event) override;
virtual void MouseMove(TimelineViewMouseEvent *event) override;
virtual void MouseRelease(TimelineViewMouseEvent *event) override;
virtual void HoverMove(TimelineViewMouseEvent *event) override;
virtual void HoverMove(TimelineViewMouseEvent *event) override;
protected:
virtual void FinishDrag(TimelineViewMouseEvent *event);
virtual void FinishDrag(TimelineViewMouseEvent *event);
virtual void InitiateDrag(Block* clicked_item, Timeline::MovementMode trim_mode, Qt::KeyboardModifiers modifiers);
virtual void InitiateDrag(Block *clicked_item,
Timeline::MovementMode trim_mode,
Qt::KeyboardModifiers modifiers);
TimelineViewGhostItem *GetExistingGhostFromBlock(Block *block);
TimelineViewGhostItem *GetExistingGhostFromBlock(Block *block);
TimelineViewGhostItem* AddGhostFromBlock(Block *block, Timeline::MovementMode mode, bool check_if_exists = false);
TimelineViewGhostItem *AddGhostFromBlock(Block *block,
Timeline::MovementMode mode,
bool check_if_exists = false);
TimelineViewGhostItem* AddGhostFromNull(const rational& in, const rational& out, const Track::Reference& track, Timeline::MovementMode mode);
TimelineViewGhostItem *AddGhostFromNull(const rational &in,
const rational &out,
const Track::Reference &track,
Timeline::MovementMode mode);
/**
/**
* @brief Validates Ghosts that are getting their in points trimmed
*
* Assumes ghost->data() is a Block. Ensures no Ghost's in point becomes a negative timecode. Also ensures no
* Ghost's length becomes 0 or negative.
*/
rational ValidateInTrimming(rational movement);
rational ValidateInTrimming(rational movement);
/**
/**
* @brief Validates Ghosts that are getting their out points trimmed
*
* Assumes ghost->data() is a Block. Ensures no Ghost's in point becomes a negative timecode. Also ensures no
* Ghost's length becomes 0 or negative.
*/
rational ValidateOutTrimming(rational movement);
rational ValidateOutTrimming(rational movement);
virtual void ProcessDrag(const TimelineCoordinate &mouse_pos);
virtual void ProcessDrag(const TimelineCoordinate &mouse_pos);
void InitiateDragInternal(Block* clicked_item,
Timeline::MovementMode trim_mode,
Qt::KeyboardModifiers modifiers,
bool dont_roll_trims,
bool allow_nongap_rolling, bool slide_instead_of_moving);
void InitiateDragInternal(Block *clicked_item,
Timeline::MovementMode trim_mode,
Qt::KeyboardModifiers modifiers,
bool dont_roll_trims, bool allow_nongap_rolling,
bool slide_instead_of_moving);
const Timeline::MovementMode& drag_movement_mode() const { return drag_movement_mode_; }
void set_drag_movement_mode(const Timeline::MovementMode &d) { drag_movement_mode_ = d; }
const Timeline::MovementMode &drag_movement_mode() const
{
return drag_movement_mode_;
}
void set_drag_movement_mode(const Timeline::MovementMode &d)
{
drag_movement_mode_ = d;
}
static bool CanTransitionMove(TransitionBlock *transit, const QVector<Block*> &clips);
static bool CanTransitionMove(TransitionBlock *transit,
const QVector<Block *> &clips);
void SetMovementAllowed(bool e)
{
movement_allowed_ = e;
}
void SetMovementAllowed(bool e)
{
movement_allowed_ = e;
}
void SetTrimmingAllowed(bool e)
{
trimming_allowed_ = e;
}
void SetTrimmingAllowed(bool e)
{
trimming_allowed_ = e;
}
void SetTrackMovementAllowed(bool e)
{
track_movement_allowed_ = e;
}
void SetTrackMovementAllowed(bool e)
{
track_movement_allowed_ = e;
}
void SetGapTrimmingAllowed(bool e)
{
gap_trimming_allowed_ = e;
}
void SetGapTrimmingAllowed(bool e)
{
gap_trimming_allowed_ = e;
}
void SetClickedItem(Block *b)
{
clicked_item_ = b;
}
void SetClickedItem(Block *b)
{
clicked_item_ = b;
}
private:
Timeline::MovementMode IsCursorInTrimHandle(Block* block, qreal cursor_x);
Timeline::MovementMode IsCursorInTrimHandle(Block *block, qreal cursor_x);
void AddGhostInternal(TimelineViewGhostItem* ghost, Timeline::MovementMode mode);
void AddGhostInternal(TimelineViewGhostItem *ghost,
Timeline::MovementMode mode);
bool IsClipTrimmable(Block* clip,
const QVector<Block*> &items,
const Timeline::MovementMode& mode);
bool IsClipTrimmable(Block *clip, const QVector<Block *> &items,
const Timeline::MovementMode &mode);
void ProcessGhostsForSliding();
void ProcessGhostsForSliding();
void ProcessGhostsForRolling();
void ProcessGhostsForRolling();
bool movement_allowed_;
bool trimming_allowed_;
bool track_movement_allowed_;
bool gap_trimming_allowed_;
bool can_rubberband_select_;
bool rubberband_selecting_;
bool movement_allowed_;
bool trimming_allowed_;
bool track_movement_allowed_;
bool gap_trimming_allowed_;
bool can_rubberband_select_;
bool rubberband_selecting_;
Track::Type drag_track_type_;
Timeline::MovementMode drag_movement_mode_;
Track::Type drag_track_type_;
Timeline::MovementMode drag_movement_mode_;
Block* clicked_item_;
QPoint drag_global_start_;
Block *clicked_item_;
QPoint drag_global_start_;
};
}
+49 -46
View File
@@ -24,79 +24,82 @@
#include "timeline/timelineundosplit.h"
#include "widget/timelinewidget/timelinewidget.h"
namespace olive {
namespace olive
{
RazorTool::RazorTool(TimelineWidget* parent) :
BeamTool(parent)
RazorTool::RazorTool(TimelineWidget *parent)
: BeamTool(parent)
{
}
void RazorTool::MousePress(TimelineViewMouseEvent *event)
{
split_tracks_.clear();
split_tracks_.clear();
MouseMove(event);
MouseMove(event);
}
void RazorTool::MouseMove(TimelineViewMouseEvent *event)
{
if (!dragging_) {
drag_start_ = ValidatedCoordinate(event->GetCoordinates(true));
dragging_ = true;
}
if (!dragging_) {
drag_start_ = ValidatedCoordinate(event->GetCoordinates(true));
dragging_ = true;
}
// Split at the current cursor track
Track::Reference split_track = event->GetTrack();
// Split at the current cursor track
Track::Reference split_track = event->GetTrack();
if (!split_tracks_.contains(split_track)) {
split_tracks_.append(split_track);
}
if (!split_tracks_.contains(split_track)) {
split_tracks_.append(split_track);
}
}
void RazorTool::MouseRelease(TimelineViewMouseEvent *event)
{
Q_UNUSED(event)
Q_UNUSED(event)
// Always split at the same time
rational split_time = drag_start_.GetFrame();
// Always split at the same time
rational split_time = drag_start_.GetFrame();
QVector<Block*> blocks_to_split;
QVector<Block *> blocks_to_split;
foreach (const Track::Reference& track_ref, split_tracks_) {
Track* track = parent()->GetTrackFromReference(track_ref);
foreach (const Track::Reference &track_ref, split_tracks_) {
Track *track = parent()->GetTrackFromReference(track_ref);
if (track == nullptr || track->IsLocked()) {
continue;
}
if (track == nullptr || track->IsLocked()) {
continue;
}
Block* block_at_time = track->NearestBlockBefore(split_time);
Block *block_at_time = track->NearestBlockBefore(split_time);
// Ensure there's a valid block here
ClipBlock *clip_at_time;
if (block_at_time
&& block_at_time->out() != split_time
&& (clip_at_time = dynamic_cast<ClipBlock*>(block_at_time))
&& !blocks_to_split.contains(block_at_time)) {
blocks_to_split.append(block_at_time);
// Ensure there's a valid block here
ClipBlock *clip_at_time;
if (block_at_time && block_at_time->out() != split_time &&
(clip_at_time = dynamic_cast<ClipBlock *>(block_at_time)) &&
!blocks_to_split.contains(block_at_time)) {
blocks_to_split.append(block_at_time);
// Add links if no alt is held
if (!(event->GetModifiers() & Qt::AltModifier)) {
foreach (Block* link, clip_at_time->block_links()) {
if (!blocks_to_split.contains(link)) {
blocks_to_split.append(link);
}
}
}
}
}
// Add links if no alt is held
if (!(event->GetModifiers() & Qt::AltModifier)) {
foreach (Block *link, clip_at_time->block_links()) {
if (!blocks_to_split.contains(link)) {
blocks_to_split.append(link);
}
}
}
}
}
split_tracks_.clear();
split_tracks_.clear();
if (!blocks_to_split.isEmpty()) {
Core::instance()->undo_stack()->push(new BlockSplitPreservingLinksCommand(blocks_to_split, {split_time}), qApp->translate("RazorTool", "Split Clips"));
}
if (!blocks_to_split.isEmpty()) {
Core::instance()->undo_stack()->push(
new BlockSplitPreservingLinksCommand(blocks_to_split,
{ split_time }),
qApp->translate("RazorTool", "Split Clips"));
}
dragging_ = false;
dragging_ = false;
}
}
+9 -9
View File
@@ -23,19 +23,19 @@
#include "beam.h"
namespace olive {
class RazorTool : public BeamTool
namespace olive
{
public:
RazorTool(TimelineWidget* parent);
virtual void MousePress(TimelineViewMouseEvent *event) override;
virtual void MouseMove(TimelineViewMouseEvent *event) override;
virtual void MouseRelease(TimelineViewMouseEvent *event) override;
class RazorTool : public BeamTool {
public:
RazorTool(TimelineWidget *parent);
virtual void MousePress(TimelineViewMouseEvent *event) override;
virtual void MouseMove(TimelineViewMouseEvent *event) override;
virtual void MouseRelease(TimelineViewMouseEvent *event) override;
private:
QVector<Track::Reference> split_tracks_;
QVector<Track::Reference> split_tracks_;
};
}
+59 -56
View File
@@ -2,87 +2,90 @@
#include "widget/timelinewidget/timelinewidget.h"
namespace olive {
RecordTool::RecordTool(TimelineWidget *parent) :
BeamTool(parent),
ghost_(nullptr)
namespace olive
{
RecordTool::RecordTool(TimelineWidget *parent)
: BeamTool(parent)
, ghost_(nullptr)
{
}
void RecordTool::MousePress(TimelineViewMouseEvent *event)
{
const Track::Reference& track = event->GetTrack();
const Track::Reference &track = event->GetTrack();
// Check if track is locked
Track* t = parent()->GetTrackFromReference(track);
if (t && t->IsLocked()) {
return;
}
// Check if track is locked
Track *t = parent()->GetTrackFromReference(track);
if (t && t->IsLocked()) {
return;
}
if (t && t->type() != Track::kAudio) {
// We only support audio tracks here
return;
}
if (t && t->type() != Track::kAudio) {
// We only support audio tracks here
return;
}
drag_start_point_ = ValidatedCoordinate(event->GetCoordinates(true)).GetFrame();
drag_start_point_ =
ValidatedCoordinate(event->GetCoordinates(true)).GetFrame();
ghost_ = new TimelineViewGhostItem();
ghost_->SetIn(drag_start_point_);
ghost_->SetOut(drag_start_point_);
ghost_->SetTrack(track);
parent()->AddGhost(ghost_);
ghost_ = new TimelineViewGhostItem();
ghost_->SetIn(drag_start_point_);
ghost_->SetOut(drag_start_point_);
ghost_->SetTrack(track);
parent()->AddGhost(ghost_);
snap_points_.push_back(drag_start_point_);
snap_points_.push_back(drag_start_point_);
}
void RecordTool::MouseMove(TimelineViewMouseEvent *event)
{
if (!ghost_) {
return;
}
if (!ghost_) {
return;
}
// Calculate movement
rational movement = event->GetFrame() - drag_start_point_;
// Calculate movement
rational movement = event->GetFrame() - drag_start_point_;
// Validation: Ensure in point never goes below 0
if (movement < -ghost_->GetIn()) {
movement = -ghost_->GetIn();
}
// Validation: Ensure in point never goes below 0
if (movement < -ghost_->GetIn()) {
movement = -ghost_->GetIn();
}
// Snap movement
bool snapped;
// Snap movement
bool snapped;
if (Core::instance()->snapping()) {
snapped = parent()->SnapPoint(snap_points_, &movement);
} else {
snapped = false;
}
if (Core::instance()->snapping()) {
snapped = parent()->SnapPoint(snap_points_, &movement);
} else {
snapped = false;
}
// Make adjustment
if (!movement) {
ghost_->SetInAdjustment(0);
ghost_->SetOutAdjustment(0);
} else if (movement > 0) {
ghost_->SetInAdjustment(0);
ghost_->SetOutAdjustment(movement);
} else if (movement < 0) {
ghost_->SetInAdjustment(movement);
ghost_->SetOutAdjustment(0);
}
// Make adjustment
if (!movement) {
ghost_->SetInAdjustment(0);
ghost_->SetOutAdjustment(0);
} else if (movement > 0) {
ghost_->SetInAdjustment(0);
ghost_->SetOutAdjustment(movement);
} else if (movement < 0) {
ghost_->SetInAdjustment(movement);
ghost_->SetOutAdjustment(0);
}
Q_UNUSED(snapped)
Q_UNUSED(snapped)
}
void RecordTool::MouseRelease(TimelineViewMouseEvent *event)
{
if (ghost_) {
emit parent()->RequestCaptureStart(TimeRange(ghost_->GetAdjustedIn(), ghost_->GetAdjustedOut()), ghost_->GetTrack());
parent()->ClearGhosts();
snap_points_.clear();
ghost_ = nullptr;
}
if (ghost_) {
emit parent() -> RequestCaptureStart(
TimeRange(ghost_->GetAdjustedIn(), ghost_->GetAdjustedOut()),
ghost_->GetTrack());
parent()->ClearGhosts();
snap_points_.clear();
ghost_ = nullptr;
}
}
}
+11 -12
View File
@@ -23,24 +23,23 @@
#include "beam.h"
namespace olive {
class RecordTool : public BeamTool
namespace olive
{
public:
RecordTool(TimelineWidget* parent);
virtual void MousePress(TimelineViewMouseEvent *event) override;
virtual void MouseMove(TimelineViewMouseEvent *event) override;
virtual void MouseRelease(TimelineViewMouseEvent *event) override;
class RecordTool : public BeamTool {
public:
RecordTool(TimelineWidget *parent);
virtual void MousePress(TimelineViewMouseEvent *event) override;
virtual void MouseMove(TimelineViewMouseEvent *event) override;
virtual void MouseRelease(TimelineViewMouseEvent *event) override;
protected:
void MouseMoveInternal(const rational& cursor_frame, bool outwards);
void MouseMoveInternal(const rational &cursor_frame, bool outwards);
TimelineViewGhostItem* ghost_;
rational drag_start_point_;
TimelineViewGhostItem *ghost_;
rational drag_start_point_;
};
}
+131 -117
View File
@@ -24,156 +24,170 @@
#include "timeline/timelineundoripple.h"
#include "ripple.h"
namespace olive {
RippleTool::RippleTool(TimelineWidget* parent) :
PointerTool(parent)
namespace olive
{
SetMovementAllowed(false);
SetGapTrimmingAllowed(true);
RippleTool::RippleTool(TimelineWidget *parent)
: PointerTool(parent)
{
SetMovementAllowed(false);
SetGapTrimmingAllowed(true);
}
void RippleTool::InitiateDrag(Block *clicked_item, Timeline::MovementMode trim_mode, Qt::KeyboardModifiers modifiers)
void RippleTool::InitiateDrag(Block *clicked_item,
Timeline::MovementMode trim_mode,
Qt::KeyboardModifiers modifiers)
{
InitiateDragInternal(clicked_item, trim_mode, modifiers, true, true, false);
InitiateDragInternal(clicked_item, trim_mode, modifiers, true, true, false);
if (!parent()->HasGhosts()) {
return;
}
if (!parent()->HasGhosts()) {
return;
}
// Find the earliest ripple
rational earliest_ripple = RATIONAL_MAX;
// Find the earliest ripple
rational earliest_ripple = RATIONAL_MAX;
foreach (TimelineViewGhostItem* ghost, parent()->GetGhostItems()) {
rational ghost_ripple_point;
foreach (TimelineViewGhostItem *ghost, parent()->GetGhostItems()) {
rational ghost_ripple_point;
if (trim_mode == Timeline::kTrimIn) {
ghost_ripple_point = ghost->GetIn();
} else {
ghost_ripple_point = ghost->GetOut();
}
if (trim_mode == Timeline::kTrimIn) {
ghost_ripple_point = ghost->GetIn();
} else {
ghost_ripple_point = ghost->GetOut();
}
earliest_ripple = qMin(earliest_ripple, ghost_ripple_point);
}
earliest_ripple = qMin(earliest_ripple, ghost_ripple_point);
}
// For each track that does NOT have a ghost, we need to make one for Gaps
foreach (Track* track, sequence()->GetTracks()) {
if (track->IsLocked()) {
continue;
}
// For each track that does NOT have a ghost, we need to make one for Gaps
foreach (Track *track, sequence()->GetTracks()) {
if (track->IsLocked()) {
continue;
}
// Determine if we've already created a ghost on this track
bool ghost_on_this_track_exists = false;
// Determine if we've already created a ghost on this track
bool ghost_on_this_track_exists = false;
foreach (TimelineViewGhostItem* ghost, parent()->GetGhostItems()) {
if (parent()->GetTrackFromReference(ghost->GetTrack()) == track) {
ghost_on_this_track_exists = true;
break;
}
}
foreach (TimelineViewGhostItem *ghost, parent()->GetGhostItems()) {
if (parent()->GetTrackFromReference(ghost->GetTrack()) == track) {
ghost_on_this_track_exists = true;
break;
}
}
// If there's no ghost on this track, create one
if (!ghost_on_this_track_exists) {
// Find the block that starts just after or at the ripple point
Block* block_after_ripple = track->NearestBlockAfterOrAt(earliest_ripple);
// If there's no ghost on this track, create one
if (!ghost_on_this_track_exists) {
// Find the block that starts just after or at the ripple point
Block *block_after_ripple =
track->NearestBlockAfterOrAt(earliest_ripple);
// Exception for out-transitions, do not create a gap between them
if (block_after_ripple) {
if (ClipBlock *prev_clip = dynamic_cast<ClipBlock*>(block_after_ripple->previous())) {
if (prev_clip->out_transition() == block_after_ripple) {
block_after_ripple = block_after_ripple->next();
}
}
}
// Exception for out-transitions, do not create a gap between them
if (block_after_ripple) {
if (ClipBlock *prev_clip = dynamic_cast<ClipBlock *>(
block_after_ripple->previous())) {
if (prev_clip->out_transition() == block_after_ripple) {
block_after_ripple = block_after_ripple->next();
}
}
}
// If block is null, there will be no blocks after to ripple
if (block_after_ripple) {
TimelineViewGhostItem* ghost;
// If block is null, there will be no blocks after to ripple
if (block_after_ripple) {
TimelineViewGhostItem *ghost;
if (dynamic_cast<GapBlock*>(block_after_ripple)) {
// If this Block is already a Gap, ghost it now
ghost = AddGhostFromBlock(block_after_ripple, trim_mode);
} else {
// Well we need to ripple SOMETHING, it'll either be the previous block if it's a gap
// or we'll have to create a new gap ourselves
Block* previous = block_after_ripple->previous();
if (dynamic_cast<GapBlock *>(block_after_ripple)) {
// If this Block is already a Gap, ghost it now
ghost = AddGhostFromBlock(block_after_ripple, trim_mode);
} else {
// Well we need to ripple SOMETHING, it'll either be the previous block if it's a gap
// or we'll have to create a new gap ourselves
Block *previous = block_after_ripple->previous();
if (dynamic_cast<GapBlock*>(previous)) {
// Previous is a gap, that'll make a fine substitute
ghost = AddGhostFromBlock(previous, trim_mode);
} else {
// Previous is not a gap, we'll have to insert one there ourselves
ghost = AddGhostFromNull(block_after_ripple->in(), block_after_ripple->in(), track->ToReference(), trim_mode);
ghost->SetData(TimelineViewGhostItem::kReferenceBlock, QtUtils::PtrToValue(block_after_ripple));
}
}
}
}
}
if (dynamic_cast<GapBlock *>(previous)) {
// Previous is a gap, that'll make a fine substitute
ghost = AddGhostFromBlock(previous, trim_mode);
} else {
// Previous is not a gap, we'll have to insert one there ourselves
ghost = AddGhostFromNull(block_after_ripple->in(),
block_after_ripple->in(),
track->ToReference(),
trim_mode);
ghost->SetData(TimelineViewGhostItem::kReferenceBlock,
QtUtils::PtrToValue(block_after_ripple));
}
}
}
}
}
}
void RippleTool::FinishDrag(TimelineViewMouseEvent *event)
{
Q_UNUSED(event)
Q_UNUSED(event)
if (parent()->HasGhosts()) {
QVector< QHash<Track*, TrackListRippleToolCommand::RippleInfo> > info_list(Track::kCount);
if (parent()->HasGhosts()) {
QVector<QHash<Track *, TrackListRippleToolCommand::RippleInfo>>
info_list(Track::kCount);
foreach (TimelineViewGhostItem* ghost, parent()->GetGhostItems()) {
if (!ghost->HasBeenAdjusted()) {
continue;
}
foreach (TimelineViewGhostItem *ghost, parent()->GetGhostItems()) {
if (!ghost->HasBeenAdjusted()) {
continue;
}
Track* track = parent()->GetTrackFromReference(ghost->GetTrack());
Track *track = parent()->GetTrackFromReference(ghost->GetTrack());
TrackListRippleToolCommand::RippleInfo info;
Block* b = QtUtils::ValueToPtr<Block>(ghost->GetData(TimelineViewGhostItem::kAttachedBlock));
TrackListRippleToolCommand::RippleInfo info;
Block *b = QtUtils::ValueToPtr<Block>(
ghost->GetData(TimelineViewGhostItem::kAttachedBlock));
if (b) {
info.block = b;
info.append_gap = false;
} else {
info.block = QtUtils::ValueToPtr<Block>(ghost->GetData(TimelineViewGhostItem::kReferenceBlock));
info.append_gap = true;
}
if (b) {
info.block = b;
info.append_gap = false;
} else {
info.block = QtUtils::ValueToPtr<Block>(
ghost->GetData(TimelineViewGhostItem::kReferenceBlock));
info.append_gap = true;
}
info_list[track->type()].insert(track, info);
}
info_list[track->type()].insert(track, info);
}
MultiUndoCommand* command = new MultiUndoCommand();
MultiUndoCommand *command = new MultiUndoCommand();
rational movement;
rational movement;
if (drag_movement_mode() == Timeline::kTrimOut) {
movement = parent()->GetGhostItems().first()->GetOutAdjustment();
} else {
movement = parent()->GetGhostItems().first()->GetInAdjustment();
}
if (drag_movement_mode() == Timeline::kTrimOut) {
movement = parent()->GetGhostItems().first()->GetOutAdjustment();
} else {
movement = parent()->GetGhostItems().first()->GetInAdjustment();
}
for (int i=0;i<info_list.size();i++) {
if (!info_list.at(i).isEmpty()) {
command->add_child(new TrackListRippleToolCommand(sequence()->track_list(static_cast<Track::Type>(i)),
info_list.at(i),
movement,
drag_movement_mode()));
}
}
for (int i = 0; i < info_list.size(); i++) {
if (!info_list.at(i).isEmpty()) {
command->add_child(new TrackListRippleToolCommand(
sequence()->track_list(static_cast<Track::Type>(i)),
info_list.at(i), movement, drag_movement_mode()));
}
}
if (command->child_count() > 0) {
TimelineWidgetSelections new_sel = parent()->GetSelections();
TimelineViewGhostItem* reference_ghost = parent()->GetGhostItems().first();
if (drag_movement_mode() == Timeline::kTrimIn) {
new_sel.TrimOut(-reference_ghost->GetInAdjustment());
} else {
new_sel.TrimOut(reference_ghost->GetOutAdjustment());
}
command->add_child(new TimelineWidget::SetSelectionsCommand(parent(), new_sel, parent()->GetSelections(), false));
if (command->child_count() > 0) {
TimelineWidgetSelections new_sel = parent()->GetSelections();
TimelineViewGhostItem *reference_ghost =
parent()->GetGhostItems().first();
if (drag_movement_mode() == Timeline::kTrimIn) {
new_sel.TrimOut(-reference_ghost->GetInAdjustment());
} else {
new_sel.TrimOut(reference_ghost->GetOutAdjustment());
}
command->add_child(new TimelineWidget::SetSelectionsCommand(
parent(), new_sel, parent()->GetSelections(), false));
Core::instance()->undo_stack()->push(command, qApp->translate("RippleTool", "Rippled Clips"));
} else {
delete command;
}
}
Core::instance()->undo_stack()->push(
command, qApp->translate("RippleTool", "Rippled Clips"));
} else {
delete command;
}
}
}
}
+11 -8
View File
@@ -23,16 +23,19 @@
#include "pointer.h"
namespace olive {
class RippleTool : public PointerTool
namespace olive
{
public:
RippleTool(TimelineWidget* parent);
protected:
virtual void FinishDrag(TimelineViewMouseEvent *event) override;
virtual void InitiateDrag(Block* clicked_item, Timeline::MovementMode trim_mode, Qt::KeyboardModifiers modifiers) override;
class RippleTool : public PointerTool {
public:
RippleTool(TimelineWidget *parent);
protected:
virtual void FinishDrag(TimelineViewMouseEvent *event) override;
virtual void InitiateDrag(Block *clicked_item,
Timeline::MovementMode trim_mode,
Qt::KeyboardModifiers modifiers) override;
};
}
+13 -9
View File
@@ -24,18 +24,22 @@
#include "node/nodeundo.h"
#include "rolling.h"
namespace olive {
RollingTool::RollingTool(TimelineWidget* parent) :
PointerTool(parent)
namespace olive
{
SetMovementAllowed(false);
SetGapTrimmingAllowed(true);
}
void RollingTool::InitiateDrag(Block *clicked_item, Timeline::MovementMode trim_mode, Qt::KeyboardModifiers modifiers)
RollingTool::RollingTool(TimelineWidget *parent)
: PointerTool(parent)
{
InitiateDragInternal(clicked_item, trim_mode, modifiers, false, true, false);
SetMovementAllowed(false);
SetGapTrimmingAllowed(true);
}
void RollingTool::InitiateDrag(Block *clicked_item,
Timeline::MovementMode trim_mode,
Qt::KeyboardModifiers modifiers)
{
InitiateDragInternal(clicked_item, trim_mode, modifiers, false, true,
false);
}
}
+7 -5
View File
@@ -23,15 +23,17 @@
#include "pointer.h"
namespace olive {
class RollingTool : public PointerTool
namespace olive
{
class RollingTool : public PointerTool {
public:
RollingTool(TimelineWidget* parent);
RollingTool(TimelineWidget *parent);
protected:
virtual void InitiateDrag(Block* clicked_item, Timeline::MovementMode trim_mode, Qt::KeyboardModifiers modifiers) override;
virtual void InitiateDrag(Block *clicked_item,
Timeline::MovementMode trim_mode,
Qt::KeyboardModifiers modifiers) override;
};
}
+13 -10
View File
@@ -24,19 +24,22 @@
#include "node/nodeundo.h"
#include "slide.h"
namespace olive {
SlideTool::SlideTool(TimelineWidget* parent) :
PointerTool(parent)
namespace olive
{
SetTrimmingAllowed(false);
SetTrackMovementAllowed(false);
SetGapTrimmingAllowed(true);
}
void SlideTool::InitiateDrag(Block *clicked_item, Timeline::MovementMode trim_mode, Qt::KeyboardModifiers modifiers)
SlideTool::SlideTool(TimelineWidget *parent)
: PointerTool(parent)
{
InitiateDragInternal(clicked_item, trim_mode, modifiers, false, true, true);
SetTrimmingAllowed(false);
SetTrackMovementAllowed(false);
SetGapTrimmingAllowed(true);
}
void SlideTool::InitiateDrag(Block *clicked_item,
Timeline::MovementMode trim_mode,
Qt::KeyboardModifiers modifiers)
{
InitiateDragInternal(clicked_item, trim_mode, modifiers, false, true, true);
}
}
+7 -6
View File
@@ -23,16 +23,17 @@
#include "pointer.h"
namespace olive {
class SlideTool : public PointerTool
namespace olive
{
class SlideTool : public PointerTool {
public:
SlideTool(TimelineWidget* parent);
SlideTool(TimelineWidget *parent);
protected:
virtual void InitiateDrag(Block* clicked_item, Timeline::MovementMode trim_mode, Qt::KeyboardModifiers modifiers) override;
virtual void InitiateDrag(Block *clicked_item,
Timeline::MovementMode trim_mode,
Qt::KeyboardModifiers modifiers) override;
};
}
+44 -39
View File
@@ -26,61 +26,66 @@
#include "timeline/timelineundogeneral.h"
#include "widget/timelinewidget/timelinewidget.h"
namespace olive {
SlipTool::SlipTool(TimelineWidget *parent) :
PointerTool(parent)
namespace olive
{
SetTrimmingAllowed(false);
SetTrackMovementAllowed(false);
SlipTool::SlipTool(TimelineWidget *parent)
: PointerTool(parent)
{
SetTrimmingAllowed(false);
SetTrackMovementAllowed(false);
}
void SlipTool::ProcessDrag(const TimelineCoordinate &mouse_pos)
{
// Determine frame movement
rational time_movement = drag_start_.GetFrame() - mouse_pos.GetFrame();
// Determine frame movement
rational time_movement = drag_start_.GetFrame() - mouse_pos.GetFrame();
// Validate slip (enforce all ghosts moving in legal ways)
foreach (TimelineViewGhostItem* ghost, parent()->GetGhostItems()) {
if (ghost->GetMediaIn() + time_movement < 0) {
time_movement = -ghost->GetMediaIn();
}
}
// Validate slip (enforce all ghosts moving in legal ways)
foreach (TimelineViewGhostItem *ghost, parent()->GetGhostItems()) {
if (ghost->GetMediaIn() + time_movement < 0) {
time_movement = -ghost->GetMediaIn();
}
}
// Perform slip
foreach (TimelineViewGhostItem* ghost, parent()->GetGhostItems()) {
ghost->SetMediaInAdjustment(time_movement);
}
// Perform slip
foreach (TimelineViewGhostItem *ghost, parent()->GetGhostItems()) {
ghost->SetMediaInAdjustment(time_movement);
}
// Generate tooltip and force it to to update (otherwise the tooltip won't move as written in the
// documentation, and could get in the way of the cursor)
rational tooltip_timebase = parent()->GetTimebaseForTrackType(drag_start_.GetTrack().type());
QToolTip::hideText();
QToolTip::showText(QCursor::pos(),
QString::fromStdString(Timecode::time_to_timecode(time_movement,
tooltip_timebase,
Core::instance()->GetTimecodeDisplay(),
true)),
parent());
// Generate tooltip and force it to to update (otherwise the tooltip won't move as written in the
// documentation, and could get in the way of the cursor)
rational tooltip_timebase =
parent()->GetTimebaseForTrackType(drag_start_.GetTrack().type());
QToolTip::hideText();
QToolTip::showText(QCursor::pos(),
QString::fromStdString(Timecode::time_to_timecode(
time_movement, tooltip_timebase,
Core::instance()->GetTimecodeDisplay(), true)),
parent());
}
void SlipTool::FinishDrag(TimelineViewMouseEvent *event)
{
Q_UNUSED(event)
Q_UNUSED(event)
MultiUndoCommand* command = new MultiUndoCommand();
MultiUndoCommand *command = new MultiUndoCommand();
// Find earliest point to ripple around
foreach (TimelineViewGhostItem* ghost, parent()->GetGhostItems()) {
Block* b = QtUtils::ValueToPtr<Block>(ghost->GetData(TimelineViewGhostItem::kAttachedBlock));
// Find earliest point to ripple around
foreach (TimelineViewGhostItem *ghost, parent()->GetGhostItems()) {
Block *b = QtUtils::ValueToPtr<Block>(
ghost->GetData(TimelineViewGhostItem::kAttachedBlock));
ClipBlock *cb = dynamic_cast<ClipBlock*>(b);
if (cb) {
command->add_child(new BlockSetMediaInCommand(cb, ghost->GetAdjustedMediaIn()));
}
}
ClipBlock *cb = dynamic_cast<ClipBlock *>(b);
if (cb) {
command->add_child(
new BlockSetMediaInCommand(cb, ghost->GetAdjustedMediaIn()));
}
}
Core::instance()->undo_stack()->push(command, qApp->translate("SlipTool", "Slipped %1 Clip(s)").arg(parent()->GetGhostItems().size()));
Core::instance()->undo_stack()->push(
command, qApp->translate("SlipTool", "Slipped %1 Clip(s)")
.arg(parent()->GetGhostItems().size()));
}
}
+6 -6
View File
@@ -23,16 +23,16 @@
#include "pointer.h"
namespace olive {
class SlipTool : public PointerTool
namespace olive
{
class SlipTool : public PointerTool {
public:
SlipTool(TimelineWidget* parent);
SlipTool(TimelineWidget *parent);
protected:
virtual void ProcessDrag(const TimelineCoordinate &mouse_pos) override;
virtual void FinishDrag(TimelineViewMouseEvent *event) override;
virtual void ProcessDrag(const TimelineCoordinate &mouse_pos) override;
virtual void FinishDrag(TimelineViewMouseEvent *event) override;
};
}
+75 -68
View File
@@ -22,13 +22,14 @@
#include "node/block/transition/transition.h"
namespace olive {
namespace olive
{
const int TimelineTool::kDefaultDistanceFromOutput = -4;
TimelineTool::TimelineTool(TimelineWidget *parent) :
dragging_(false),
parent_(parent)
TimelineTool::TimelineTool(TimelineWidget *parent)
: dragging_(false)
, parent_(parent)
{
}
@@ -38,110 +39,116 @@ TimelineTool::~TimelineTool()
TimelineWidget *TimelineTool::parent()
{
return parent_;
return parent_;
}
Sequence *TimelineTool::sequence()
{
return parent_->sequence();
return parent_->sequence();
}
Timeline::MovementMode TimelineTool::FlipTrimMode(const Timeline::MovementMode &trim_mode)
Timeline::MovementMode
TimelineTool::FlipTrimMode(const Timeline::MovementMode &trim_mode)
{
if (trim_mode == Timeline::kTrimIn) {
return Timeline::kTrimOut;
}
if (trim_mode == Timeline::kTrimIn) {
return Timeline::kTrimOut;
}
if (trim_mode == Timeline::kTrimOut) {
return Timeline::kTrimIn;
}
if (trim_mode == Timeline::kTrimOut) {
return Timeline::kTrimIn;
}
return trim_mode;
return trim_mode;
}
rational TimelineTool::SnapMovementToTimebase(const rational &start, rational movement, const rational &timebase)
rational TimelineTool::SnapMovementToTimebase(const rational &start,
rational movement,
const rational &timebase)
{
rational proposed_position = start + movement;
rational snapped = Timecode::snap_time_to_timebase(proposed_position, timebase);
rational proposed_position = start + movement;
rational snapped =
Timecode::snap_time_to_timebase(proposed_position, timebase);
if (proposed_position != snapped) {
movement += snapped - proposed_position;
}
if (proposed_position != snapped) {
movement += snapped - proposed_position;
}
return movement;
return movement;
}
rational TimelineTool::ValidateTimeMovement(rational movement)
{
bool first_ghost = true;
bool first_ghost = true;
foreach (TimelineViewGhostItem* ghost, parent()->GetGhostItems()) {
if (ghost->GetMode() != Timeline::kMove) {
continue;
}
foreach (TimelineViewGhostItem *ghost, parent()->GetGhostItems()) {
if (ghost->GetMode() != Timeline::kMove) {
continue;
}
// Prevents any ghosts from going below 0:00:00 time
if (ghost->GetIn() + movement < 0) {
movement = -ghost->GetIn();
} else if (first_ghost) {
// Ensure ghost is snapped to a grid
movement = SnapMovementToTimebase(ghost->GetIn(), movement, parent()->GetTimebaseForTrackType(ghost->GetTrack().type()));
// Prevents any ghosts from going below 0:00:00 time
if (ghost->GetIn() + movement < 0) {
movement = -ghost->GetIn();
} else if (first_ghost) {
// Ensure ghost is snapped to a grid
movement = SnapMovementToTimebase(
ghost->GetIn(), movement,
parent()->GetTimebaseForTrackType(ghost->GetTrack().type()));
first_ghost = false;
}
}
first_ghost = false;
}
}
return movement;
return movement;
}
int TimelineTool::ValidateTrackMovement(int movement, const QVector<TimelineViewGhostItem*>& ghosts)
int TimelineTool::ValidateTrackMovement(
int movement, const QVector<TimelineViewGhostItem *> &ghosts)
{
foreach (TimelineViewGhostItem* ghost, ghosts) {
if (ghost->GetMode() != Timeline::kMove) {
continue;
}
foreach (TimelineViewGhostItem *ghost, ghosts) {
if (ghost->GetMode() != Timeline::kMove) {
continue;
}
if (!ghost->GetCanMoveTracks()) {
if (!ghost->GetCanMoveTracks()) {
return 0;
return 0;
} else if (ghost->GetTrack().index() + movement < 0) {
// Prevents any ghosts from going to a non-existent negative track
movement = -ghost->GetTrack().index();
}
}
} else if (ghost->GetTrack().index() + movement < 0) {
// Prevents any ghosts from going to a non-existent negative track
movement = -ghost->GetTrack().index();
}
}
return movement;
return movement;
}
void TimelineTool::GetGhostData(rational *earliest_point, rational *latest_point)
void TimelineTool::GetGhostData(rational *earliest_point,
rational *latest_point)
{
rational ep = RATIONAL_MAX;
rational lp = RATIONAL_MIN;
rational ep = RATIONAL_MAX;
rational lp = RATIONAL_MIN;
foreach (TimelineViewGhostItem* ghost, parent()->GetGhostItems()) {
ep = qMin(ep, ghost->GetAdjustedIn());
lp = qMax(lp, ghost->GetAdjustedOut());
}
foreach (TimelineViewGhostItem *ghost, parent()->GetGhostItems()) {
ep = qMin(ep, ghost->GetAdjustedIn());
lp = qMax(lp, ghost->GetAdjustedOut());
}
if (earliest_point) {
*earliest_point = ep;
}
if (earliest_point) {
*earliest_point = ep;
}
if (latest_point) {
*latest_point = lp;
}
if (latest_point) {
*latest_point = lp;
}
}
void TimelineTool::InsertGapsAtGhostDestination(olive::MultiUndoCommand *command)
{
rational earliest_point, latest_point;
rational earliest_point, latest_point;
GetGhostData(&earliest_point, &latest_point);
GetGhostData(&earliest_point, &latest_point);
parent()->InsertGapsAt(earliest_point, latest_point - earliest_point, command);
parent()->InsertGapsAt(earliest_point, latest_point - earliest_point,
command);
}
}
+51 -30
View File
@@ -26,67 +26,88 @@
#include "widget/timelinewidget/view/timelineviewghostitem.h"
#include "widget/timelinewidget/view/timelineviewmouseevent.h"
namespace olive {
namespace olive
{
class TimelineWidget;
class TimelineTool
{
class TimelineTool {
public:
TimelineTool(TimelineWidget* parent);
virtual ~TimelineTool();
TimelineTool(TimelineWidget *parent);
virtual ~TimelineTool();
virtual void MousePress(TimelineViewMouseEvent *){}
virtual void MouseMove(TimelineViewMouseEvent *){}
virtual void MouseRelease(TimelineViewMouseEvent *){}
virtual void MouseDoubleClick(TimelineViewMouseEvent *){}
virtual void MousePress(TimelineViewMouseEvent *)
{
}
virtual void MouseMove(TimelineViewMouseEvent *)
{
}
virtual void MouseRelease(TimelineViewMouseEvent *)
{
}
virtual void MouseDoubleClick(TimelineViewMouseEvent *)
{
}
virtual void HoverMove(TimelineViewMouseEvent *){}
virtual void HoverMove(TimelineViewMouseEvent *)
{
}
virtual void DragEnter(TimelineViewMouseEvent *){}
virtual void DragMove(TimelineViewMouseEvent *){}
virtual void DragLeave(QDragLeaveEvent *){}
virtual void DragDrop(TimelineViewMouseEvent *){}
virtual void DragEnter(TimelineViewMouseEvent *)
{
}
virtual void DragMove(TimelineViewMouseEvent *)
{
}
virtual void DragLeave(QDragLeaveEvent *)
{
}
virtual void DragDrop(TimelineViewMouseEvent *)
{
}
TimelineWidget* parent();
TimelineWidget *parent();
Sequence* sequence();
Sequence *sequence();
static Timeline::MovementMode FlipTrimMode(const Timeline::MovementMode& trim_mode);
static Timeline::MovementMode
FlipTrimMode(const Timeline::MovementMode &trim_mode);
static rational SnapMovementToTimebase(const rational& start, rational movement, const rational& timebase);
static rational SnapMovementToTimebase(const rational &start,
rational movement,
const rational &timebase);
protected:
/**
/**
* @brief Validates Ghosts that are moving horizontally (time-based)
*
* Validation is the process of ensuring that whatever movements the user is making are "valid" and "legal". This
* function's validation ensures that no Ghost's in point ends up in a negative timecode.
*/
rational ValidateTimeMovement(rational movement);
rational ValidateTimeMovement(rational movement);
/**
/**
* @brief Validates Ghosts that are moving vertically (track-based)
*
* This function's validation ensures that no Ghost's track ends up in a negative (non-existent) track.
*/
int ValidateTrackMovement(int movement, const QVector<TimelineViewGhostItem *> &ghosts);
int ValidateTrackMovement(int movement,
const QVector<TimelineViewGhostItem *> &ghosts);
void GetGhostData(rational *earliest_point, rational *latest_point);
void GetGhostData(rational *earliest_point, rational *latest_point);
void InsertGapsAtGhostDestination(MultiUndoCommand* command);
void InsertGapsAtGhostDestination(MultiUndoCommand *command);
std::vector<rational> snap_points_;
std::vector<rational> snap_points_;
bool dragging_;
bool dragging_;
TimelineCoordinate drag_start_;
TimelineCoordinate drag_start_;
static const int kDefaultDistanceFromOutput;
static const int kDefaultDistanceFromOutput;
private:
TimelineWidget* parent_;
TimelineWidget *parent_;
};
}
+55 -51
View File
@@ -24,73 +24,77 @@
#include "node/output/track/track.h"
#include "widget/timelinewidget/timelinewidget.h"
namespace olive {
namespace olive
{
TrackSelectTool::TrackSelectTool(TimelineWidget *parent) :
PointerTool(parent)
TrackSelectTool::TrackSelectTool(TimelineWidget *parent)
: PointerTool(parent)
{
}
void TrackSelectTool::MousePress(TimelineViewMouseEvent *event)
{
QVector<Block*> blocks;
bool forward = !(event->GetModifiers() & Qt::ControlModifier);
QVector<Block *> blocks;
bool forward = !(event->GetModifiers() & Qt::ControlModifier);
parent()->DeselectAll();
parent()->DeselectAll();
if (event->GetModifiers() & Qt::ShiftModifier) {
// Track only
Track *track = parent()->GetTrackFromReference(event->GetTrack());
if (track) {
SelectBlocksOnTrack(track, event, &blocks, forward);
}
} else {
// All tracks
foreach (Track *track, parent()->sequence()->GetTracks()) {
SelectBlocksOnTrack(track, event, &blocks, forward);
}
}
if (event->GetModifiers() & Qt::ShiftModifier) {
// Track only
Track *track = parent()->GetTrackFromReference(event->GetTrack());
if (track) {
SelectBlocksOnTrack(track, event, &blocks, forward);
}
} else {
// All tracks
foreach (Track *track, parent()->sequence()->GetTracks()) {
SelectBlocksOnTrack(track, event, &blocks, forward);
}
}
if (!blocks.isEmpty()) {
parent()->SignalSelectedBlocks(blocks);
set_drag_movement_mode(Timeline::kMove);
SetClickedItem(blocks.first());
drag_start_ = event->GetCoordinates();
} else {
set_drag_movement_mode(Timeline::kNone);
}
if (!blocks.isEmpty()) {
parent()->SignalSelectedBlocks(blocks);
set_drag_movement_mode(Timeline::kMove);
SetClickedItem(blocks.first());
drag_start_ = event->GetCoordinates();
} else {
set_drag_movement_mode(Timeline::kNone);
}
}
void TrackSelectTool::SelectBlocksOnTrack(Track *track, TimelineViewMouseEvent *event, QVector<Block*> *blocks, bool forward)
void TrackSelectTool::SelectBlocksOnTrack(Track *track,
TimelineViewMouseEvent *event,
QVector<Block *> *blocks,
bool forward)
{
Block *b = track->NearestBlockBeforeOrAt(event->GetFrame());
Block *b = track->NearestBlockBeforeOrAt(event->GetFrame());
if (!b && !track->Blocks().isEmpty() && !forward) {
// Fallback to first or last block in track
b = track->Blocks().last();
}
if (!b && !track->Blocks().isEmpty() && !forward) {
// Fallback to first or last block in track
b = track->Blocks().last();
}
while (b) {
if (!dynamic_cast<GapBlock*>(b)) {
if (!blocks->contains(b)) {
parent()->AddSelection(b);
blocks->append(b);
}
while (b) {
if (!dynamic_cast<GapBlock *>(b)) {
if (!blocks->contains(b)) {
parent()->AddSelection(b);
blocks->append(b);
}
if (!(event->GetModifiers() & Qt::AltModifier)) {
if (ClipBlock *clip = dynamic_cast<ClipBlock*>(b)) {
foreach (Block *link, clip->block_links()) {
if (!blocks->contains(link)) {
parent()->AddSelection(link);
blocks->append(link);
}
}
}
}
}
if (!(event->GetModifiers() & Qt::AltModifier)) {
if (ClipBlock *clip = dynamic_cast<ClipBlock *>(b)) {
foreach (Block *link, clip->block_links()) {
if (!blocks->contains(link)) {
parent()->AddSelection(link);
blocks->append(link);
}
}
}
}
}
b = forward ? b->next() : b->previous();
}
b = forward ? b->next() : b->previous();
}
}
}
+8 -8
View File
@@ -23,18 +23,18 @@
#include "pointer.h"
namespace olive {
class TrackSelectTool : public PointerTool
namespace olive
{
public:
TrackSelectTool(TimelineWidget *parent);
virtual void MousePress(TimelineViewMouseEvent *event) override;
class TrackSelectTool : public PointerTool {
public:
TrackSelectTool(TimelineWidget *parent);
virtual void MousePress(TimelineViewMouseEvent *event) override;
private:
void SelectBlocksOnTrack(Track *track, TimelineViewMouseEvent *event, QVector<Block *> *blocks, bool forward);
void SelectBlocksOnTrack(Track *track, TimelineViewMouseEvent *event,
QVector<Block *> *blocks, bool forward);
};
}
+172 -143
View File
@@ -27,209 +27,238 @@
#include "timeline/timelineundopointer.h"
#include "transition.h"
namespace olive {
namespace olive
{
TransitionTool::TransitionTool(TimelineWidget *parent) :
AddTool(parent)
TransitionTool::TransitionTool(TimelineWidget *parent)
: AddTool(parent)
{
}
void TransitionTool::HoverMove(TimelineViewMouseEvent *event)
{
ClipBlock *primary = nullptr;
ClipBlock *secondary = nullptr;
Timeline::MovementMode trim_mode = Timeline::kNone;
rational transition_start_point;
ClipBlock *primary = nullptr;
ClipBlock *secondary = nullptr;
Timeline::MovementMode trim_mode = Timeline::kNone;
rational transition_start_point;
GetBlocksAtCoord(event->GetCoordinates(), &primary, &secondary, &trim_mode, &transition_start_point);
GetBlocksAtCoord(event->GetCoordinates(), &primary, &secondary, &trim_mode,
&transition_start_point);
if (trim_mode == Timeline::kTrimIn) {
std::swap(primary, secondary);
}
if (trim_mode == Timeline::kTrimIn) {
std::swap(primary, secondary);
}
parent()->SetViewTransitionOverlay(primary, secondary);
parent()->SetViewTransitionOverlay(primary, secondary);
}
void TransitionTool::MousePress(TimelineViewMouseEvent *event)
{
ClipBlock *primary, *secondary;
Timeline::MovementMode trim_mode;
rational transition_start_point;
if (!GetBlocksAtCoord(event->GetCoordinates(), &primary, &secondary, &trim_mode, &transition_start_point)) {
return;
}
ClipBlock *primary, *secondary;
Timeline::MovementMode trim_mode;
rational transition_start_point;
if (!GetBlocksAtCoord(event->GetCoordinates(), &primary, &secondary,
&trim_mode, &transition_start_point)) {
return;
}
// Create ghost
ghost_ = new TimelineViewGhostItem();
ghost_->SetTrack(event->GetTrack());
ghost_->SetIn(transition_start_point);
ghost_->SetOut(transition_start_point);
ghost_->SetMode(trim_mode);
ghost_->SetData(TimelineViewGhostItem::kAttachedBlock, QtUtils::PtrToValue(primary));
// Create ghost
ghost_ = new TimelineViewGhostItem();
ghost_->SetTrack(event->GetTrack());
ghost_->SetIn(transition_start_point);
ghost_->SetOut(transition_start_point);
ghost_->SetMode(trim_mode);
ghost_->SetData(TimelineViewGhostItem::kAttachedBlock,
QtUtils::PtrToValue(primary));
dual_transition_ = (secondary);
if (secondary)
ghost_->SetData(TimelineViewGhostItem::kReferenceBlock, QtUtils::PtrToValue(secondary));
dual_transition_ = (secondary);
if (secondary)
ghost_->SetData(TimelineViewGhostItem::kReferenceBlock,
QtUtils::PtrToValue(secondary));
parent()->AddGhost(ghost_);
parent()->AddGhost(ghost_);
snap_points_.push_back(transition_start_point);
snap_points_.push_back(transition_start_point);
// Set the drag start point
drag_start_point_ = event->GetFrame();
// Set the drag start point
drag_start_point_ = event->GetFrame();
}
void TransitionTool::MouseMove(TimelineViewMouseEvent *event)
{
if (!ghost_) {
return;
}
if (!ghost_) {
return;
}
MouseMoveInternal(event->GetFrame(), dual_transition_);
MouseMoveInternal(event->GetFrame(), dual_transition_);
}
void TransitionTool::MouseRelease(TimelineViewMouseEvent *event)
{
const Track::Reference& track = ghost_->GetTrack();
const Track::Reference &track = ghost_->GetTrack();
if (ghost_) {
if (!ghost_->GetAdjustedLength().isNull()) {
TransitionBlock* transition;
if (ghost_) {
if (!ghost_->GetAdjustedLength().isNull()) {
TransitionBlock *transition;
if (Core::instance()->GetSelectedTransition().isEmpty()) {
// Fallback if the user hasn't selected one yet
transition = new CrossDissolveTransition();
} else {
transition = static_cast<TransitionBlock*>(NodeFactory::CreateFromID(Core::instance()->GetSelectedTransition()));
}
if (Core::instance()->GetSelectedTransition().isEmpty()) {
// Fallback if the user hasn't selected one yet
transition = new CrossDissolveTransition();
} else {
transition =
static_cast<TransitionBlock *>(NodeFactory::CreateFromID(
Core::instance()->GetSelectedTransition()));
}
// Set transition length
rational len = ghost_->GetAdjustedLength();
transition->set_length_and_media_out(len);
// Set transition length
rational len = ghost_->GetAdjustedLength();
transition->set_length_and_media_out(len);
MultiUndoCommand* command = new MultiUndoCommand();
MultiUndoCommand *command = new MultiUndoCommand();
// Place transition in place
command->add_child(new NodeAddCommand(parent()->GetConnectedNode()->parent(),
transition));
// Place transition in place
command->add_child(new NodeAddCommand(
parent()->GetConnectedNode()->parent(), transition));
command->add_child(new NodeSetPositionCommand(transition, transition, QPointF(0, 0)));
command->add_child(new NodeSetPositionCommand(
transition, transition, QPointF(0, 0)));
command->add_child(new TrackPlaceBlockCommand(sequence()->track_list(track.type()),
track.index(),
transition,
ghost_->GetAdjustedIn()));
command->add_child(new TrackPlaceBlockCommand(
sequence()->track_list(track.type()), track.index(), transition,
ghost_->GetAdjustedIn()));
if (dual_transition_) {
// Block mouse is hovering over
Block* active_block = QtUtils::ValueToPtr<Block>(ghost_->GetData(TimelineViewGhostItem::kAttachedBlock));
if (dual_transition_) {
// Block mouse is hovering over
Block *active_block = QtUtils::ValueToPtr<Block>(
ghost_->GetData(TimelineViewGhostItem::kAttachedBlock));
// Block mouse is next to
Block* friend_block = QtUtils::ValueToPtr<Block>(ghost_->GetData(TimelineViewGhostItem::kReferenceBlock));
// Block mouse is next to
Block *friend_block = QtUtils::ValueToPtr<Block>(
ghost_->GetData(TimelineViewGhostItem::kReferenceBlock));
// Use ghost mode to determine which block is which
Block* out_block = (ghost_->GetMode() == Timeline::kTrimIn) ? friend_block : active_block;
Block* in_block = (ghost_->GetMode() == Timeline::kTrimIn) ? active_block : friend_block;
// Use ghost mode to determine which block is which
Block *out_block = (ghost_->GetMode() == Timeline::kTrimIn) ?
friend_block :
active_block;
Block *in_block = (ghost_->GetMode() == Timeline::kTrimIn) ?
active_block :
friend_block;
// Connect block to transition
command->add_child(new NodeEdgeAddCommand(out_block,
NodeInput(transition, TransitionBlock::kOutBlockInput)));
// Connect block to transition
command->add_child(new NodeEdgeAddCommand(
out_block,
NodeInput(transition, TransitionBlock::kOutBlockInput)));
command->add_child(new NodeEdgeAddCommand(in_block,
NodeInput(transition, TransitionBlock::kInBlockInput)));
command->add_child(new NodeEdgeAddCommand(
in_block,
NodeInput(transition, TransitionBlock::kInBlockInput)));
command->add_child(new NodeSetPositionCommand(out_block, transition, QPointF(-1, -0.5)));
command->add_child(new NodeSetPositionCommand(in_block, transition, QPointF(-1, 0.5)));
} else {
Block* block_to_transition = QtUtils::ValueToPtr<Block>(ghost_->GetData(TimelineViewGhostItem::kAttachedBlock));
QString transition_input_to_connect;
command->add_child(new NodeSetPositionCommand(
out_block, transition, QPointF(-1, -0.5)));
command->add_child(new NodeSetPositionCommand(
in_block, transition, QPointF(-1, 0.5)));
} else {
Block *block_to_transition = QtUtils::ValueToPtr<Block>(
ghost_->GetData(TimelineViewGhostItem::kAttachedBlock));
QString transition_input_to_connect;
if (ghost_->GetMode() == Timeline::kTrimIn) {
transition_input_to_connect = TransitionBlock::kInBlockInput;
} else {
transition_input_to_connect = TransitionBlock::kOutBlockInput;
}
if (ghost_->GetMode() == Timeline::kTrimIn) {
transition_input_to_connect =
TransitionBlock::kInBlockInput;
} else {
transition_input_to_connect =
TransitionBlock::kOutBlockInput;
}
// Connect block to transition
command->add_child(new NodeEdgeAddCommand(block_to_transition,
NodeInput(transition, transition_input_to_connect)));
// Connect block to transition
command->add_child(new NodeEdgeAddCommand(
block_to_transition,
NodeInput(transition, transition_input_to_connect)));
command->add_child(new NodeSetPositionCommand(block_to_transition, transition, QPointF(-1, 0)));
}
command->add_child(new NodeSetPositionCommand(
block_to_transition, transition, QPointF(-1, 0)));
}
Core::instance()->undo_stack()->push(command, qApp->translate("TransitionTool", "Created Transition"));
Core::instance()->undo_stack()->push(
command,
qApp->translate("TransitionTool", "Created Transition"));
parent()->SetViewTransitionOverlay(nullptr, nullptr);
}
parent()->SetViewTransitionOverlay(nullptr, nullptr);
}
parent()->ClearGhosts();
snap_points_.clear();
ghost_ = nullptr;
}
parent()->ClearGhosts();
snap_points_.clear();
ghost_ = nullptr;
}
}
bool TransitionTool::GetBlocksAtCoord(const TimelineCoordinate &coord, ClipBlock **primary, ClipBlock **secondary, Timeline::MovementMode *ptrim_mode, rational *start_point)
bool TransitionTool::GetBlocksAtCoord(const TimelineCoordinate &coord,
ClipBlock **primary,
ClipBlock **secondary,
Timeline::MovementMode *ptrim_mode,
rational *start_point)
{
const Track::Reference& track = coord.GetTrack();
Track* t = parent()->GetTrackFromReference(track);
rational cursor_frame = coord.GetFrame();
const Track::Reference &track = coord.GetTrack();
Track *t = parent()->GetTrackFromReference(track);
rational cursor_frame = coord.GetFrame();
if (!t || t->IsLocked()) {
return false;
}
if (!t || t->IsLocked()) {
return false;
}
Block* block_at_time = t->NearestBlockBeforeOrAt(coord.GetFrame());
if (!dynamic_cast<ClipBlock*>(block_at_time)) {
return false;
}
Block *block_at_time = t->NearestBlockBeforeOrAt(coord.GetFrame());
if (!dynamic_cast<ClipBlock *>(block_at_time)) {
return false;
}
// Determine which side of the clip the transition belongs to
rational transition_start_point;
Timeline::MovementMode trim_mode;
rational tenth_point = block_at_time->length() / 10;
Block* other_block = nullptr;
if (cursor_frame < (block_at_time->in() + block_at_time->length() / 2)) {
if (static_cast<ClipBlock*>(block_at_time)->in_transition()) {
// This clip already has a transition here
return false;
}
// Determine which side of the clip the transition belongs to
rational transition_start_point;
Timeline::MovementMode trim_mode;
rational tenth_point = block_at_time->length() / 10;
Block *other_block = nullptr;
if (cursor_frame < (block_at_time->in() + block_at_time->length() / 2)) {
if (static_cast<ClipBlock *>(block_at_time)->in_transition()) {
// This clip already has a transition here
return false;
}
ClipBlock *adjacent = dynamic_cast<ClipBlock*>(block_at_time->previous());
if (adjacent) {
tenth_point = std::min(tenth_point, adjacent->length()/10);
}
ClipBlock *adjacent =
dynamic_cast<ClipBlock *>(block_at_time->previous());
if (adjacent) {
tenth_point = std::min(tenth_point, adjacent->length() / 10);
}
transition_start_point = block_at_time->in();
trim_mode = Timeline::kTrimIn;
transition_start_point = block_at_time->in();
trim_mode = Timeline::kTrimIn;
if (cursor_frame < (block_at_time->in() + tenth_point) && adjacent) {
other_block = adjacent;
}
} else {
if (static_cast<ClipBlock*>(block_at_time)->out_transition()) {
// This clip already has a transition here
return false;
}
if (cursor_frame < (block_at_time->in() + tenth_point) && adjacent) {
other_block = adjacent;
}
} else {
if (static_cast<ClipBlock *>(block_at_time)->out_transition()) {
// This clip already has a transition here
return false;
}
ClipBlock *adjacent = dynamic_cast<ClipBlock*>(block_at_time->next());
if (adjacent) {
tenth_point = std::min(tenth_point, adjacent->length()/10);
}
ClipBlock *adjacent = dynamic_cast<ClipBlock *>(block_at_time->next());
if (adjacent) {
tenth_point = std::min(tenth_point, adjacent->length() / 10);
}
transition_start_point = block_at_time->out();
trim_mode = Timeline::kTrimOut;
transition_start_point = block_at_time->out();
trim_mode = Timeline::kTrimOut;
if (cursor_frame > block_at_time->out() - tenth_point && adjacent) {
other_block = block_at_time->next();
}
}
if (cursor_frame > block_at_time->out() - tenth_point && adjacent) {
other_block = block_at_time->next();
}
}
*primary = static_cast<ClipBlock*>(block_at_time);
*secondary = static_cast<ClipBlock*>(other_block);
*ptrim_mode = trim_mode;
*start_point = transition_start_point;
*primary = static_cast<ClipBlock *>(block_at_time);
*secondary = static_cast<ClipBlock *>(other_block);
*ptrim_mode = trim_mode;
*start_point = transition_start_point;
return true;
return true;
}
}
+13 -11
View File
@@ -23,24 +23,26 @@
#include "add.h"
namespace olive {
class TransitionTool : public AddTool
namespace olive
{
class TransitionTool : public AddTool {
public:
TransitionTool(TimelineWidget* parent);
TransitionTool(TimelineWidget *parent);
virtual void HoverMove(TimelineViewMouseEvent *event) override;
virtual void HoverMove(TimelineViewMouseEvent *event) override;
virtual void MousePress(TimelineViewMouseEvent *event) override;
virtual void MouseMove(TimelineViewMouseEvent *event) override;
virtual void MouseRelease(TimelineViewMouseEvent *event) override;
virtual void MousePress(TimelineViewMouseEvent *event) override;
virtual void MouseMove(TimelineViewMouseEvent *event) override;
virtual void MouseRelease(TimelineViewMouseEvent *event) override;
private:
bool GetBlocksAtCoord(const TimelineCoordinate &coord, ClipBlock **primary, ClipBlock **secondary, Timeline::MovementMode *trim_mode, rational *start_point);
bool dual_transition_;
bool GetBlocksAtCoord(const TimelineCoordinate &coord, ClipBlock **primary,
ClipBlock **secondary,
Timeline::MovementMode *trim_mode,
rational *start_point);
bool dual_transition_;
};
}
+53 -43
View File
@@ -21,81 +21,91 @@
#include "widget/timelinewidget/timelinewidget.h"
#include "zoom.h"
namespace olive {
namespace olive
{
ZoomTool::ZoomTool(TimelineWidget *parent) :
TimelineTool(parent)
ZoomTool::ZoomTool(TimelineWidget *parent)
: TimelineTool(parent)
{
}
void ZoomTool::MousePress(TimelineViewMouseEvent *event)
{
Q_UNUSED(event)
Q_UNUSED(event)
drag_global_start_ = QCursor::pos();
drag_global_start_ = QCursor::pos();
}
void ZoomTool::MouseMove(TimelineViewMouseEvent *event)
{
Q_UNUSED(event)
Q_UNUSED(event)
if (!dragging_) {
parent()->StartRubberBandSelect(drag_global_start_);
if (!dragging_) {
parent()->StartRubberBandSelect(drag_global_start_);
dragging_ = true;
}
dragging_ = true;
}
parent()->MoveRubberBandSelect(false, false);
parent()->MoveRubberBandSelect(false, false);
}
void ZoomTool::MouseRelease(TimelineViewMouseEvent *event)
{
int scroll_value;
int scroll_value;
if (dragging_) {
// Zoom into the rubberband selection
QRect screen_coords = parent()->GetRubberBandGeometry();
if (dragging_) {
// Zoom into the rubberband selection
QRect screen_coords = parent()->GetRubberBandGeometry();
parent()->EndRubberBandSelect();
parent()->EndRubberBandSelect();
TimelineView* reference_view = parent()->GetFirstTimelineView();
QPointF scene_topleft = reference_view->mapToScene(reference_view->mapFrom(parent(), screen_coords.topLeft()));
QPointF scene_bottomright = reference_view->mapToScene(reference_view->mapFrom(parent(), screen_coords.bottomRight()));
TimelineView *reference_view = parent()->GetFirstTimelineView();
QPointF scene_topleft = reference_view->mapToScene(
reference_view->mapFrom(parent(), screen_coords.topLeft()));
QPointF scene_bottomright = reference_view->mapToScene(
reference_view->mapFrom(parent(), screen_coords.bottomRight()));
double scene_left = scene_topleft.x();
double scene_right = scene_bottomright.x();
double scene_left = scene_topleft.x();
double scene_right = scene_bottomright.x();
// Normalize scale to 1.0 scale
double scene_width = (scene_right - scene_left) / parent()->GetScale();
// Normalize scale to 1.0 scale
double scene_width = (scene_right - scene_left) / parent()->GetScale();
double new_scale = qMin(parent()->GetFirstTimelineView()->GetMaximumScale(), static_cast<double>(reference_view->viewport()->width()) / scene_width);
double new_scale =
qMin(parent()->GetFirstTimelineView()->GetMaximumScale(),
static_cast<double>(reference_view->viewport()->width()) /
scene_width);
parent()->SetScale(new_scale);
parent()->SetScale(new_scale);
scroll_value = qMax(0, qRound(scene_left / parent()->GetScale() * new_scale));
scroll_value =
qMax(0, qRound(scene_left / parent()->GetScale() * new_scale));
dragging_ = false;
} else {
// Simple zoom in/out at the cursor position
double scale = parent()->GetScale();
dragging_ = false;
} else {
// Simple zoom in/out at the cursor position
double scale = parent()->GetScale();
if (event->GetModifiers() & Qt::AltModifier) {
// Zoom out if the user clicks while holding Alt
scale *= 0.5;
} else {
// Otherwise zoom in
scale *= 2.0;
}
if (event->GetModifiers() & Qt::AltModifier) {
// Zoom out if the user clicks while holding Alt
scale *= 0.5;
} else {
// Otherwise zoom in
scale *= 2.0;
}
parent()->SetScale(scale);
parent()->SetScale(scale);
// Adjust scroll location for new scale
double frame_x = event->GetFrame().toDouble() * scale;
// Adjust scroll location for new scale
double frame_x = event->GetFrame().toDouble() * scale;
scroll_value = qMax(0, qRound(frame_x - parent()->GetFirstTimelineView()->viewport()->width()/2));
}
scroll_value = qMax(
0,
qRound(frame_x -
parent()->GetFirstTimelineView()->viewport()->width() / 2));
}
parent()->QueueScroll(scroll_value);
parent()->QueueScroll(scroll_value);
}
}
+9 -10
View File
@@ -23,20 +23,19 @@
#include "tool.h"
namespace olive {
class ZoomTool : public TimelineTool
namespace olive
{
public:
ZoomTool(TimelineWidget* parent);
virtual void MousePress(TimelineViewMouseEvent *event) override;
virtual void MouseMove(TimelineViewMouseEvent *event) override;
virtual void MouseRelease(TimelineViewMouseEvent *event) override;
class ZoomTool : public TimelineTool {
public:
ZoomTool(TimelineWidget *parent);
virtual void MousePress(TimelineViewMouseEvent *event) override;
virtual void MouseMove(TimelineViewMouseEvent *event) override;
virtual void MouseRelease(TimelineViewMouseEvent *event) override;
private:
QPoint drag_global_start_;
QPoint drag_global_start_;
};
}