From 02e7c68104c7bceb45aa8cc5a47d8dfea52d4222 Mon Sep 17 00:00:00 2001 From: itsmattkc Date: Sun, 15 Mar 2020 13:41:46 +1100 Subject: [PATCH] timeline: reimplemented linking/unlinking functionality --- app/node/block/block.cpp | 26 ++++++++++++---- app/node/block/block.h | 6 ++-- app/panel/timeline/timeline.cpp | 5 ++++ app/panel/timeline/timeline.h | 2 ++ app/widget/menu/menushared.cpp | 7 ++++- app/widget/menu/menushared.h | 2 ++ app/widget/panel/panel.h | 2 ++ app/widget/timelinewidget/timelinewidget.cpp | 25 ++++++++++++++++ app/widget/timelinewidget/timelinewidget.h | 2 ++ app/widget/timelinewidget/undo/undo.cpp | 31 +++++++++++++++----- app/widget/timelinewidget/undo/undo.h | 13 ++++++-- 11 files changed, 102 insertions(+), 19 deletions(-) diff --git a/app/node/block/block.cpp b/app/node/block/block.cpp index 6228dcec2..69cda6126 100644 --- a/app/node/block/block.cpp +++ b/app/node/block/block.cpp @@ -202,20 +202,25 @@ void Block::LengthInputChanged() emit LengthChanged(length()); } -void Block::Link(Block *a, Block *b) +bool Block::Link(Block *a, Block *b) { if (a == b || !a || !b) { - return; + return false; } // Prevent duplicate link entries (assume that we only need to check one clip since this should be the only function // that adds to the linked array) - if (a->linked_clips_.contains(b)) { - return; + if (Block::AreLinked(a, b)) { + return false; } a->linked_clips_.append(b); b->linked_clips_.append(a); + + emit a->LinksChanged(); + emit b->LinksChanged(); + + return true; } void Block::Link(const QList& blocks) @@ -227,14 +232,23 @@ void Block::Link(const QList& blocks) } } -void Block::Unlink(Block *a, Block *b) +bool Block::Unlink(Block *a, Block *b) { if (a == b || !a || !b) { - return; + return false; + } + + if (!Block::AreLinked(a, b)) { + return false; } a->linked_clips_.removeOne(b); b->linked_clips_.removeOne(a); + + emit a->LinksChanged(); + emit b->LinksChanged(); + + return true; } void Block::Unlink(const QList &blocks) diff --git a/app/node/block/block.h b/app/node/block/block.h index 3cf16d46e..cb9ea4e93 100644 --- a/app/node/block/block.h +++ b/app/node/block/block.h @@ -76,9 +76,9 @@ public: QString block_name() const; void set_block_name(const QString& name); - static void Link(Block* a, Block* b); + static bool Link(Block* a, Block* b); static void Link(const QList& blocks); - static void Unlink(Block* a, Block* b); + static bool Unlink(Block* a, Block* b); static void Unlink(const QList& blocks); static bool AreLinked(Block* a, Block* b); const QVector& linked_clips(); @@ -104,6 +104,8 @@ signals: void LengthChanged(const rational& length); + void LinksChanged(); + protected: rational SequenceToMediaTime(const rational& sequence_time) const; diff --git a/app/panel/timeline/timeline.cpp b/app/panel/timeline/timeline.cpp index 95dfdbb7d..53fd6116c 100644 --- a/app/panel/timeline/timeline.cpp +++ b/app/panel/timeline/timeline.cpp @@ -115,6 +115,11 @@ void TimelinePanel::Overwrite() } } +void TimelinePanel::ToggleLinks() +{ + static_cast(GetTimeBasedWidget())->ToggleLinksOnSelected(); +} + void TimelinePanel::InsertFootageAtPlayhead(const QList &footage) { static_cast(GetTimeBasedWidget())->InsertFootageAtPlayhead(footage); diff --git a/app/panel/timeline/timeline.h b/app/panel/timeline/timeline.h index 02c09d1e5..3d5c1dd91 100644 --- a/app/panel/timeline/timeline.h +++ b/app/panel/timeline/timeline.h @@ -61,6 +61,8 @@ public: virtual void Overwrite() override; + virtual void ToggleLinks() override; + void InsertFootageAtPlayhead(const QList &footage); void OverwriteFootageAtPlayhead(const QList &footage); diff --git a/app/widget/menu/menushared.cpp b/app/widget/menu/menushared.cpp index 84419b8cc..d128017ac 100644 --- a/app/widget/menu/menushared.cpp +++ b/app/widget/menu/menushared.cpp @@ -52,7 +52,7 @@ MenuShared::MenuShared() // "Clip Edit" menu shared items clip_add_default_transition_item_ = Menu::CreateItem(this, "deftransition", nullptr, nullptr, "Ctrl+Shift+D"); - clip_link_unlink_item_ = Menu::CreateItem(this, "linkunlink", nullptr, nullptr, "Ctrl+L"); + clip_link_unlink_item_ = Menu::CreateItem(this, "linkunlink", this, SLOT(ToggleLinksTriggered()), "Ctrl+L"); clip_enable_disable_item_ = Menu::CreateItem(this, "enabledisable", nullptr, nullptr, "Shift+E"); clip_nest_item_ = Menu::CreateItem(this, "nest", nullptr, nullptr); @@ -156,6 +156,11 @@ void MenuShared::ClearInOutTriggered() PanelManager::instance()->CurrentlyFocused()->ClearInOut(); } +void MenuShared::ToggleLinksTriggered() +{ + PanelManager::instance()->CurrentlyFocused()->ToggleLinks(); +} + void MenuShared::Retranslate() { // "New" menu shared items diff --git a/app/widget/menu/menushared.h b/app/widget/menu/menushared.h index 6269aa2bb..d15408f57 100644 --- a/app/widget/menu/menushared.h +++ b/app/widget/menu/menushared.h @@ -91,6 +91,8 @@ private slots: void ClearInOutTriggered(); + void ToggleLinksTriggered(); + }; #endif // MENUSHARED_H diff --git a/app/widget/panel/panel.h b/app/widget/panel/panel.h index 0ea111e45..8e447a948 100644 --- a/app/widget/panel/panel.h +++ b/app/widget/panel/panel.h @@ -130,6 +130,8 @@ public: virtual void SetMarker(){} + virtual void ToggleLinks(){} + protected: /** * @brief paintEvent diff --git a/app/widget/timelinewidget/timelinewidget.cpp b/app/widget/timelinewidget/timelinewidget.cpp index 28359e0fc..2a19176a7 100644 --- a/app/widget/timelinewidget/timelinewidget.cpp +++ b/app/widget/timelinewidget/timelinewidget.cpp @@ -472,6 +472,30 @@ void TimelineWidget::OverwriteFootageAtPlayhead(const QList &footage) import_tool_->PlaceAt(footage, GetTime(), false); } +void TimelineWidget::ToggleLinksOnSelected() +{ + QList sel = GetSelectedBlocks(); + + // Prioritize unlinking + + QList blocks; + bool link = true; + + foreach (TimelineViewBlockItem* item, sel) { + if (link && item->block()->HasLinks()) { + link = false; + } + + blocks.append(item->block()); + } + + if (link) { + Core::instance()->undo_stack()->push(new BlockLinkManyCommand(blocks, true)); + } else { + Core::instance()->undo_stack()->push(new BlockLinkManyCommand(blocks, false)); + } +} + QList TimelineWidget::GetSelectedBlocks() { QList list; @@ -687,6 +711,7 @@ void TimelineWidget::AddBlock(Block *block, TrackReference track) views_.at(track.type())->view()->scene()->addItem(item); connect(block, &Block::Refreshed, this, &TimelineWidget::BlockChanged); + connect(block, &Block::LinksChanged, this, &TimelineWidget::PreviewUpdated); if (block->type() == Block::kClip) { connect(static_cast(block), &ClipBlock::PreviewUpdated, this, &TimelineWidget::PreviewUpdated); diff --git a/app/widget/timelinewidget/timelinewidget.h b/app/widget/timelinewidget/timelinewidget.h index ca51db637..86534a45a 100644 --- a/app/widget/timelinewidget/timelinewidget.h +++ b/app/widget/timelinewidget/timelinewidget.h @@ -57,6 +57,8 @@ public: void OverwriteFootageAtPlayhead(const QList &footage); + void ToggleLinksOnSelected(); + QList GetSelectedBlocks(); signals: diff --git a/app/widget/timelinewidget/undo/undo.cpp b/app/widget/timelinewidget/undo/undo.cpp index 4eb3e66af..d9b875c0e 100644 --- a/app/widget/timelinewidget/undo/undo.cpp +++ b/app/widget/timelinewidget/undo/undo.cpp @@ -716,9 +716,10 @@ void WorkareaSetRangeCommand::undo_internal() points_->workarea()->set_range(old_range_); } -BlockLinkCommand::BlockLinkCommand(const QList &blocks, bool link, QUndoCommand *parent) : +BlockLinkCommand::BlockLinkCommand(Block *a, Block *b, bool link, QUndoCommand *parent) : UndoCommand(parent), - blocks_(blocks), + a_(a), + b_(b), link_(link) { } @@ -726,18 +727,20 @@ BlockLinkCommand::BlockLinkCommand(const QList &blocks, bool link, QUnd void BlockLinkCommand::redo_internal() { if (link_) { - Block::Link(blocks_); + done_ = Block::Link(a_, b_); } else { - Block::Unlink(blocks_); + done_ = Block::Unlink(a_, b_); } } void BlockLinkCommand::undo_internal() { - if (link_) { - Block::Unlink(blocks_); - } else { - Block::Link(blocks_); + if (done_) { + if (link_) { + Block::Unlink(a_, b_); + } else { + Block::Link(a_, b_); + } } } @@ -764,3 +767,15 @@ void BlockUnlinkAllCommand::undo_internal() unlinked_.clear(); } + +BlockLinkManyCommand::BlockLinkManyCommand(const QList blocks, bool link, QUndoCommand *parent) : + UndoCommand(parent) +{ + foreach (Block* a, blocks) { + foreach (Block* b, blocks) { + if (a != b) { + new BlockLinkCommand(a, b, link, this); + } + } + } +} diff --git a/app/widget/timelinewidget/undo/undo.h b/app/widget/timelinewidget/undo/undo.h index ce2d82285..3756fe217 100644 --- a/app/widget/timelinewidget/undo/undo.h +++ b/app/widget/timelinewidget/undo/undo.h @@ -331,19 +331,28 @@ private: }; +class BlockLinkManyCommand : public UndoCommand { +public: + BlockLinkManyCommand(const QList blocks, bool link, QUndoCommand* parent = nullptr); +}; + class BlockLinkCommand : public UndoCommand { public: - BlockLinkCommand(const QList& blocks, bool link, QUndoCommand* parent = nullptr); + BlockLinkCommand(Block* a, Block* b, bool link, QUndoCommand* parent = nullptr); protected: virtual void redo_internal() override; virtual void undo_internal() override; private: - QList blocks_; + Block* a_; + + Block* b_; bool link_; + bool done_; + }; class BlockUnlinkAllCommand : public UndoCommand {