From fbdda3d6d4c210c47b9537c72dac8b98403ce08a Mon Sep 17 00:00:00 2001 From: itsmattkc Date: Wed, 13 Jan 2021 12:05:05 +1100 Subject: [PATCH] various code cleanups --- app/node/block/block.cpp | 6 +- app/node/block/clip/clip.cpp | 14 +- app/node/block/clip/clip.h | 4 +- app/node/block/transition/transition.cpp | 2 +- app/node/node.cpp | 12 +- app/node/node.h | 4 +- app/node/output/track/track.cpp | 34 +- app/node/output/track/track.h | 15 +- app/node/output/viewer/viewer.h | 5 + app/node/traverser.cpp | 27 +- app/undo/undocommand.h | 4 +- app/widget/nodeview/nodeviewundo.h | 1 - app/widget/projectexplorer/CMakeLists.txt | 1 - .../projectexplorer/projectexplorerundo.cpp | 54 - .../projectexplorer/projectexplorerundo.h | 29 +- app/widget/timebased/timebasedwidget.cpp | 1 - app/widget/timelinewidget/CMakeLists.txt | 2 +- app/widget/timelinewidget/undo/CMakeLists.txt | 22 - app/widget/timelinewidget/undo/undo.cpp | 1790 ----------------- app/widget/timelinewidget/undo/undo.h | 639 ------ app/widget/timelinewidget/view/timelineview.h | 2 - 21 files changed, 111 insertions(+), 2557 deletions(-) delete mode 100644 app/widget/projectexplorer/projectexplorerundo.cpp delete mode 100644 app/widget/timelinewidget/undo/CMakeLists.txt delete mode 100644 app/widget/timelinewidget/undo/undo.cpp delete mode 100644 app/widget/timelinewidget/undo/undo.h diff --git a/app/node/block/block.cpp b/app/node/block/block.cpp index 1ab79d179..797de34c4 100644 --- a/app/node/block/block.cpp +++ b/app/node/block/block.cpp @@ -104,7 +104,7 @@ void Block::set_length_and_media_in(const rational &length) } // Calculate media_in adjustment - set_media_in(SequenceToMediaTime(in() + (this->length() - length))); + set_media_in(SequenceToMediaTime(this->length() - length)); // Set the length without setting media out set_length_internal(length); @@ -164,7 +164,7 @@ rational Block::SequenceToMediaTime(const rational &sequence_time) const return sequence_time; } - rational local_time = sequence_time - in(); + rational local_time = sequence_time; // FIXME: Doesn't handle reversing if (speed_input_->IsKeyframing() || speed_input_->IsConnected()) { @@ -208,7 +208,7 @@ rational Block::MediaToSequenceTime(const rational &media_time) const } } - return sequence_time + in(); + return sequence_time; } void Block::LoadInternal(QXmlStreamReader *reader, XMLNodeData &xml_node_data) diff --git a/app/node/block/clip/clip.cpp b/app/node/block/clip/clip.cpp index 2b915e60b..41d0a81de 100644 --- a/app/node/block/clip/clip.cpp +++ b/app/node/block/clip/clip.cpp @@ -73,22 +73,26 @@ void ClipBlock::InvalidateCache(const TimeRange& range, const InputConnection& f } } -TimeRange ClipBlock::InputTimeAdjustment(NodeInput *input, const TimeRange &input_time) const +TimeRange ClipBlock::InputTimeAdjustment(NodeInput *input, int element, const TimeRange &input_time) const { + Q_UNUSED(element) + if (input == texture_input_) { return TimeRange(SequenceToMediaTime(input_time.in()), SequenceToMediaTime(input_time.out())); } - return Block::InputTimeAdjustment(input, input_time); + return Block::InputTimeAdjustment(input, element, input_time); } -TimeRange ClipBlock::OutputTimeAdjustment(NodeInput *input, const TimeRange &input_time) const +TimeRange ClipBlock::OutputTimeAdjustment(NodeInput *input, int element, const TimeRange &input_time) const { + Q_UNUSED(element) + if (input == texture_input_) { return TimeRange(MediaToSequenceTime(input_time.in()), MediaToSequenceTime(input_time.out())); } - return Block::InputTimeAdjustment(input, input_time); + return Block::OutputTimeAdjustment(input, element, input_time); } NodeValueTable ClipBlock::Value(NodeValueDatabase &value) const @@ -113,7 +117,7 @@ void ClipBlock::Retranslate() void ClipBlock::Hash(QCryptographicHash &hash, const rational &time) const { if (texture_input_->IsConnected()) { - rational t = InputTimeAdjustment(texture_input_, TimeRange(time, time)).in(); + rational t = InputTimeAdjustment(texture_input_, -1, TimeRange(time, time)).in(); texture_input_->GetConnectedNode()->Hash(hash, t); } diff --git a/app/node/block/clip/clip.h b/app/node/block/clip/clip.h index e4f376f14..5ed962e92 100644 --- a/app/node/block/clip/clip.h +++ b/app/node/block/clip/clip.h @@ -46,9 +46,9 @@ public: virtual void InvalidateCache(const TimeRange& range, const InputConnection& from) override; - virtual TimeRange InputTimeAdjustment(NodeInput* input, const TimeRange& input_time) const override; + virtual TimeRange InputTimeAdjustment(NodeInput* input, int element, const TimeRange& input_time) const override; - virtual TimeRange OutputTimeAdjustment(NodeInput* input, const TimeRange& input_time) const override; + virtual TimeRange OutputTimeAdjustment(NodeInput* input, int element, const TimeRange& input_time) const override; virtual NodeValueTable Value(NodeValueDatabase& value) const override; diff --git a/app/node/block/transition/transition.cpp b/app/node/block/transition/transition.cpp index ab54c068d..2a154ba44 100644 --- a/app/node/block/transition/transition.cpp +++ b/app/node/block/transition/transition.cpp @@ -151,7 +151,7 @@ void TransitionBlock::Hash(QCryptographicHash &hash, const rational &time) const double TransitionBlock::GetInternalTransitionTime(const double &time) const { - return time - in().toDouble(); + return time; } void TransitionBlock::InsertTransitionTimes(AcceleratedJob *job, const double &time) const diff --git a/app/node/node.cpp b/app/node/node.cpp index c5af5d02e..825230987 100644 --- a/app/node/node.cpp +++ b/app/node/node.cpp @@ -203,13 +203,13 @@ void Node::EndOperation() } } -TimeRange Node::InputTimeAdjustment(NodeInput *, const TimeRange &input_time) const +TimeRange Node::InputTimeAdjustment(NodeInput *, int, const TimeRange &input_time) const { // Default behavior is no time adjustment at all return input_time; } -TimeRange Node::OutputTimeAdjustment(NodeInput *, const TimeRange &input_time) const +TimeRange Node::OutputTimeAdjustment(NodeInput *, int, const TimeRange &input_time) const { // Default behavior is no time adjustment at all return input_time; @@ -398,7 +398,7 @@ void Node::HashInputElement(QCryptographicHash &hash, NodeInput *input, int elem { // Get time adjustment // For a single frame, we only care about one of the times - rational input_time = InputTimeAdjustment(input, TimeRange(time, time)).in(); + rational input_time = InputTimeAdjustment(input, element, TimeRange(time, time)).in(); if (input->IsConnected(element)) { // Traverse down this edge @@ -661,8 +661,8 @@ QVector Node::TransformTimeTo(const TimeRange &time, Node *target, bo // If this input is connected, traverse it to see if we stumble across the specified `node` foreach (NodeInput* input, inputs_) { for (auto it=input->edges().cbegin(); it!=input->edges().cend(); it++) { - TimeRange input_adjustment = InputTimeAdjustment(input, time); - Node* connected = input->GetConnectedNode(it.key()); + TimeRange input_adjustment = InputTimeAdjustment(input, it.key(), time); + Node* connected = it.value(); if (connected == target) { // We found the target, no need to keep traversing @@ -680,7 +680,7 @@ QVector Node::TransformTimeTo(const TimeRange &time, Node *target, bo foreach (const InputConnection& conn, edges()) { Node* input_node = conn.input->parent(); - TimeRange output_adjustment = input_node->OutputTimeAdjustment(conn.input, time); + TimeRange output_adjustment = input_node->OutputTimeAdjustment(conn.input, conn.element, time); if (input_node == target) { paths_found.append(output_adjustment); diff --git a/app/node/node.h b/app/node/node.h index 269914814..00d98dc70 100644 --- a/app/node/node.h +++ b/app/node/node.h @@ -329,12 +329,12 @@ public: * If this node modifies the `time` (i.e. a clip converting sequence time to media time), this function should be * overridden to do so. Also make sure to override OutputTimeAdjustment() to provide the inverse function. */ - virtual TimeRange InputTimeAdjustment(NodeInput* input, const TimeRange& input_time) const; + virtual TimeRange InputTimeAdjustment(NodeInput* input, int element, const TimeRange& input_time) const; /** * @brief The inverse of InputTimeAdjustment() */ - virtual TimeRange OutputTimeAdjustment(NodeInput* input, const TimeRange& input_time) const; + virtual TimeRange OutputTimeAdjustment(NodeInput* input, int element, const TimeRange& input_time) const; /** * @brief Copies inputs from from Node to another including connections diff --git a/app/node/output/track/track.cpp b/app/node/output/track/track.cpp index 5a0b89b55..cec91c459 100644 --- a/app/node/output/track/track.cpp +++ b/app/node/output/track/track.cpp @@ -96,6 +96,30 @@ QString Track::Description() const "a Sequence."); } +TimeRange Track::InputTimeAdjustment(NodeInput *input, int element, const TimeRange &input_time) const +{ + if (input == block_input_ && element >= 0) { + int cache_index = GetCacheIndexFromArrayIndex(element); + const rational& block_in = blocks_.at(cache_index).range.in(); + + return input_time - block_in; + } + + return Node::InputTimeAdjustment(input, element, input_time); +} + +TimeRange Track::OutputTimeAdjustment(NodeInput *input, int element, const TimeRange &input_time) const +{ + if (input == block_input_ && element >= 0) { + int cache_index = GetCacheIndexFromArrayIndex(element); + const rational& block_in = blocks_.at(cache_index).range.in(); + + return input_time + block_in; + } + + return Node::OutputTimeAdjustment(input, element, input_time); +} + const double &Track::GetTrackHeight() const { return track_height_; @@ -435,15 +459,15 @@ void Track::UpdateInOutFrom(int index) SetLengthInternal(last_out); } -int Track::GetInputIndexFromCacheIndex(int cache_index) +int Track::GetArrayIndexFromCacheIndex(int index) const { - return GetInputIndexFromCacheIndex(block_cache_.at(cache_index)); + return blocks_.at(index).array_index; } -int Track::GetInputIndexFromCacheIndex(Block *block) +int Track::GetCacheIndexFromArrayIndex(int index) const { - for (int i=0; iArraySize(); i++) { - if (block_input_->GetConnectedNode(i) == block) { + for (int i=0; i Category() const override; virtual QString Description() const override; + virtual TimeRange InputTimeAdjustment(NodeInput* input, int element, const TimeRange& input_time) const override; + + virtual TimeRange OutputTimeAdjustment(NodeInput* input, int element, const TimeRange& input_time) const override; + const double& GetTrackHeight() const; void SetTrackHeight(const double& height); @@ -277,8 +281,9 @@ protected: private: void UpdateInOutFrom(int index); - int GetInputIndexFromCacheIndex(int cache_index); - int GetInputIndexFromCacheIndex(Block* block); + int GetArrayIndexFromCacheIndex(int index) const; + + int GetCacheIndexFromArrayIndex(int index) const; void SetLengthInternal(const rational& r, bool invalidate = true); @@ -313,4 +318,4 @@ private slots: } -#endif // TRACKOUTPUT_H +#endif // TRACK_H diff --git a/app/node/output/viewer/viewer.h b/app/node/output/viewer/viewer.h index 01beb2dd6..4933d0f92 100644 --- a/app/node/output/viewer/viewer.h +++ b/app/node/output/viewer/viewer.h @@ -97,6 +97,11 @@ public: return track_cache_; } + Track* GetTrackFromReference(const TrackReference& track_ref) const + { + return track_lists_.at(track_ref.type())->GetTrackAt(track_ref.index()); + } + /** * @brief Same as GetTracks() but omits tracks that are locked. */ diff --git a/app/node/traverser.cpp b/app/node/traverser.cpp index 814ebc9ac..1e419cc69 100644 --- a/app/node/traverser.cpp +++ b/app/node/traverser.cpp @@ -34,9 +34,7 @@ NodeValueDatabase NodeTraverser::GenerateDatabase(const Node* node, const TimeRa return NodeValueDatabase(); } - TimeRange input_time = node->InputTimeAdjustment(input, range); - - database.Insert(input, ProcessInput(input, input_time)); + database.Insert(input, ProcessInput(input, range)); } AddGlobalsToDatabase(database, range); @@ -47,16 +45,18 @@ NodeValueDatabase NodeTraverser::GenerateDatabase(const Node* node, const TimeRa NodeValueTable NodeTraverser::ProcessInput(NodeInput* input, const TimeRange& range) { // If input is connected, retrieve value directly + Node* node = input->parent(); + if (input->IsConnected()) { + TimeRange adjusted_range = node->InputTimeAdjustment(input, -1, range); + // Value will equal something from the connected node, follow it - return GenerateTable(input->GetConnectedNode(), range); + return GenerateTable(input->GetConnectedNode(), adjusted_range); } else { // Store node - Node* node = static_cast(input->parent()); - QVariant return_val; if (input->IsArray()) { @@ -66,11 +66,12 @@ NodeValueTable NodeTraverser::ProcessInput(NodeInput* input, const TimeRange& ra for (int i=0; iInputTimeAdjustment(input, i, range); if (input->IsConnected(i)) { - sub_tbl = GenerateTable(input->GetConnectedNode(i), range); + sub_tbl = GenerateTable(input->GetConnectedNode(i), adjusted_range); } else { - QVariant input_value = input->GetValueAtTime(range.in(), i); + QVariant input_value = input->GetValueAtTime(adjusted_range.in(), i); sub_tbl.Push(input->GetDataType(), input_value, node); } } @@ -80,7 +81,9 @@ NodeValueTable NodeTraverser::ProcessInput(NodeInput* input, const TimeRange& ra } else { // Not connected or an array, just pull the immediate - return_val = input->GetValueAtTime(range.in()); + TimeRange adjusted_range = node->InputTimeAdjustment(input, -1, range); + + return_val = input->GetValueAtTime(adjusted_range.in()); } @@ -120,12 +123,12 @@ NodeValueTable NodeTraverser::GenerateTable(const Node *n, const rational &in, c NodeValueTable NodeTraverser::GenerateBlockTable(const Track *track, const TimeRange &range) { // By default, just follow the in point - Block* active_block = track->BlockAtTime(range.in()); + int active_block = track->BlockAtTime(range.in()); NodeValueTable table; - if (active_block) { - table = GenerateTable(active_block, range); + if (active_block >= 0) { + table = GenerateTable(track->Blocks().at(active_block).block, range); } return table; diff --git a/app/undo/undocommand.h b/app/undo/undocommand.h index ff71174d1..4a4844c05 100644 --- a/app/undo/undocommand.h +++ b/app/undo/undocommand.h @@ -24,10 +24,12 @@ #include #include "common/define.h" -#include "project/project.h" +#include "node/graph.h" namespace olive { +class Project; + class UndoCommand : public QUndoCommand { public: diff --git a/app/widget/nodeview/nodeviewundo.h b/app/widget/nodeview/nodeviewundo.h index 5d7aeba59..aa5ee9b87 100644 --- a/app/widget/nodeview/nodeviewundo.h +++ b/app/widget/nodeview/nodeviewundo.h @@ -26,7 +26,6 @@ #include "node/graph.h" #include "node/node.h" #include "undo/undocommand.h" -#include "widget/timelinewidget/undo/undo.h" namespace olive { diff --git a/app/widget/projectexplorer/CMakeLists.txt b/app/widget/projectexplorer/CMakeLists.txt index 86d399e66..9fd45f85c 100644 --- a/app/widget/projectexplorer/CMakeLists.txt +++ b/app/widget/projectexplorer/CMakeLists.txt @@ -33,6 +33,5 @@ set(OLIVE_SOURCES widget/projectexplorer/projectexplorernavigation.h widget/projectexplorer/projectexplorernavigation.cpp widget/projectexplorer/projectexplorerundo.h - widget/projectexplorer/projectexplorerundo.cpp PARENT_SCOPE ) diff --git a/app/widget/projectexplorer/projectexplorerundo.cpp b/app/widget/projectexplorer/projectexplorerundo.cpp deleted file mode 100644 index c11950e44..000000000 --- a/app/widget/projectexplorer/projectexplorerundo.cpp +++ /dev/null @@ -1,54 +0,0 @@ -/*** - - Olive - Non-Linear Video Editor - Copyright (C) 2020 Olive Team - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - -***/ - -#include "projectexplorerundo.h" - -namespace olive { - -OfflineFootageCommand::OfflineFootageCommand(const QVector &media, QUndoCommand* parent) : - UndoCommand(parent) -{ - foreach (MediaInput* i, media) { - stream_data_.insert(i, i->stream()); - } - - project_ = static_cast(media.first()->parent())->project(); -} - -Project *OfflineFootageCommand::GetRelevantProject() const -{ - return project_; -} - -void OfflineFootageCommand::redo_internal() -{ - for (auto it=stream_data_.cbegin(); it!=stream_data_.cend(); it++) { - it.key()->SetStream(nullptr); - } -} - -void OfflineFootageCommand::undo_internal() -{ - for (auto it=stream_data_.cbegin(); it!=stream_data_.cend(); it++) { - it.key()->SetStream(it.value()); - } -} - -} diff --git a/app/widget/projectexplorer/projectexplorerundo.h b/app/widget/projectexplorer/projectexplorerundo.h index ddbafb924..ef98e4bb3 100644 --- a/app/widget/projectexplorer/projectexplorerundo.h +++ b/app/widget/projectexplorer/projectexplorerundo.h @@ -31,14 +31,35 @@ namespace olive { */ class OfflineFootageCommand : public UndoCommand { public: - OfflineFootageCommand(const QVector& media, QUndoCommand* parent = nullptr); + OfflineFootageCommand(const QVector& media, QUndoCommand* parent = nullptr) : + UndoCommand(parent) + { + foreach (MediaInput* i, media) { + stream_data_.insert(i, i->stream()); + } - virtual Project* GetRelevantProject() const override; + project_ = media.first()->parent()->project(); + } + + virtual Project* GetRelevantProject() const override + { + return project_; + } protected: - virtual void redo_internal() override; + virtual void redo_internal() override + { + for (auto it=stream_data_.cbegin(); it!=stream_data_.cend(); it++) { + it.key()->SetStream(nullptr); + } + } - virtual void undo_internal() override; + virtual void undo_internal() override + { + for (auto it=stream_data_.cbegin(); it!=stream_data_.cend(); it++) { + it.key()->SetStream(it.value()); + } + } private: QMap stream_data_; diff --git a/app/widget/timebased/timebasedwidget.cpp b/app/widget/timebased/timebasedwidget.cpp index f0e37dcd3..9bfbcc647 100644 --- a/app/widget/timebased/timebasedwidget.cpp +++ b/app/widget/timebased/timebasedwidget.cpp @@ -28,7 +28,6 @@ #include "config/config.h" #include "core.h" #include "project/item/sequence/sequence.h" -#include "widget/timelinewidget/undo/undo.h" namespace olive { diff --git a/app/widget/timelinewidget/CMakeLists.txt b/app/widget/timelinewidget/CMakeLists.txt index 563fa03dd..4028f0f78 100644 --- a/app/widget/timelinewidget/CMakeLists.txt +++ b/app/widget/timelinewidget/CMakeLists.txt @@ -16,13 +16,13 @@ add_subdirectory(trackview) add_subdirectory(tool) -add_subdirectory(undo) add_subdirectory(view) set(OLIVE_SOURCES ${OLIVE_SOURCES} widget/timelinewidget/timelineandtrackview.h widget/timelinewidget/timelineandtrackview.cpp + widget/timelinewidget/timelineundo.h widget/timelinewidget/timelinewidget.h widget/timelinewidget/timelinewidget.cpp widget/timelinewidget/timelinewidgetselections.h diff --git a/app/widget/timelinewidget/undo/CMakeLists.txt b/app/widget/timelinewidget/undo/CMakeLists.txt deleted file mode 100644 index 91cf6fa71..000000000 --- a/app/widget/timelinewidget/undo/CMakeLists.txt +++ /dev/null @@ -1,22 +0,0 @@ -# Olive - Non-Linear Video Editor -# Copyright (C) 2020 Olive Team -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . - -set(OLIVE_SOURCES - ${OLIVE_SOURCES} - widget/timelinewidget/undo/undo.h - widget/timelinewidget/undo/undo.cpp - PARENT_SCOPE -) diff --git a/app/widget/timelinewidget/undo/undo.cpp b/app/widget/timelinewidget/undo/undo.cpp deleted file mode 100644 index ae666f480..000000000 --- a/app/widget/timelinewidget/undo/undo.cpp +++ /dev/null @@ -1,1790 +0,0 @@ -/*** - - Olive - Non-Linear Video Editor - Copyright (C) 2020 Olive Team - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - -***/ - -#include "undo.h" - -#include "config/config.h" -#include "core.h" -#include "node/block/clip/clip.h" -#include "node/block/transition/transition.h" -#include "node/graph.h" -#include "widget/nodeview/nodeviewundo.h" -#include "widget/timelinewidget/timelinewidget.h" - -namespace olive { - -BlockResizeCommand::BlockResizeCommand(Block *block, rational new_length, QUndoCommand* parent) : - UndoCommand(parent), - block_(block), - old_length_(block->length()), - new_length_(new_length) -{ -} - -Project *BlockResizeCommand::GetRelevantProject() const -{ - return static_cast(block_->parent())->project(); -} - -void BlockResizeCommand::redo_internal() -{ - block_->set_length_and_media_out(new_length_); -} - -void BlockResizeCommand::undo_internal() -{ - block_->set_length_and_media_out(old_length_); -} - -BlockResizeWithMediaInCommand::BlockResizeWithMediaInCommand(Block *block, rational new_length, QUndoCommand *parent) : - UndoCommand(parent), - block_(block), - old_length_(block->length()), - new_length_(new_length) -{ -} - -Project *BlockResizeWithMediaInCommand::GetRelevantProject() const -{ - return static_cast(block_->parent())->project(); -} - -void BlockResizeWithMediaInCommand::redo_internal() -{ - block_->set_length_and_media_in(new_length_); -} - -void BlockResizeWithMediaInCommand::undo_internal() -{ - block_->set_length_and_media_in(old_length_); -} - -BlockSetMediaInCommand::BlockSetMediaInCommand(Block *block, rational new_media_in, QUndoCommand* parent) : - UndoCommand(parent), - block_(block), - old_media_in_(block->media_in()), - new_media_in_(new_media_in) -{ -} - -Project *BlockSetMediaInCommand::GetRelevantProject() const -{ - return static_cast(block_->parent())->project(); -} - -void BlockSetMediaInCommand::redo_internal() -{ - block_->set_media_in(new_media_in_); -} - -void BlockSetMediaInCommand::undo_internal() -{ - block_->set_media_in(old_media_in_); -} - -TrackRippleRemoveBlockCommand::TrackRippleRemoveBlockCommand(Track *track, Block *block, QUndoCommand *parent) : - UndoCommand(parent), - track_(track), - block_(block) -{ -} - -Project *TrackRippleRemoveBlockCommand::GetRelevantProject() const -{ - return static_cast(block_->parent())->project(); -} - -void TrackRippleRemoveBlockCommand::redo_internal() -{ - before_ = block_->previous(); - track_->RippleRemoveBlock(block_); -} - -void TrackRippleRemoveBlockCommand::undo_internal() -{ - if (before_) { - track_->InsertBlockAfter(block_, before_); - } else { - track_->PrependBlock(block_); - } -} - -TrackInsertBlockAfterCommand::TrackInsertBlockAfterCommand(Track *track, - Block *block, - Block *before, - QUndoCommand *parent) : - UndoCommand(parent), - track_(track), - block_(block), - before_(before) -{ -} - -Project *TrackInsertBlockAfterCommand::GetRelevantProject() const -{ - return static_cast(block_->parent())->project(); -} - -void TrackInsertBlockAfterCommand::redo_internal() -{ - track_->InsertBlockAfter(block_, before_); -} - -void TrackInsertBlockAfterCommand::undo_internal() -{ - track_->RippleRemoveBlock(block_); -} - -TrackRippleRemoveAreaCommand::TrackRippleRemoveAreaCommand(Track *track, rational in, rational out, QUndoCommand *parent) : - UndoCommand(parent), - track_(track), - in_(in), - out_(out), - splice_(false), - splice_split_command_(nullptr), - trim_out_(nullptr), - trim_in_(nullptr), - insert_(nullptr) -{ -} - -Project *TrackRippleRemoveAreaCommand::GetRelevantProject() const -{ - return static_cast(track_->parent())->project(); -} - -void TrackRippleRemoveAreaCommand::SetInsert(Block *insert) -{ - insert_ = insert; -} - -void TrackRippleRemoveAreaCommand::redo_internal() -{ - // Iterate through blocks determining which need trimming/removing/splitting - foreach (Block* block, track_->Blocks()) { - if (block->in() < in_ && block->out() > out_) { - // The area entirely within this Block - trim_out_ = block; - splice_ = true; - - // We don't need to do anything else here - break; - } else if (block->in() >= in_ && block->out() <= out_) { - // This Block's is entirely within the area - removed_blocks_.append(block); - } else if (block->in() < in_ && block->out() >= in_) { - // This Block's out point exceeds `in` - trim_out_ = block; - } else if (block->in() <= out_ && block->out() > out_) { - // This Block's in point exceeds `out` - trim_in_ = block; - } - } - - track_->BeginOperation(); - - // If we picked up a block to splice - if (splice_) { - - if (trim_out_->type() == Block::kGap && !insert_) { - - // Gaps shouldn't be split, just trim the difference - trim_out_->set_length_and_media_out(trim_out_->length() - (out_ - in_)); - - } else { - - // Split the block here - splice_split_command_ = new QUndoCommand(); - - if (Config::Current()[QStringLiteral("SplitClipsCopyNodes")].toBool()) { - QVector nodes_to_clone; - nodes_to_clone.append(trim_out_); - nodes_to_clone.append(trim_out_->GetDependencies()); - QVector duplicated = Node::CopyDependencyGraph(nodes_to_clone, splice_split_command_); - trim_in_ = static_cast(duplicated.first()); - } else { - trim_in_ = static_cast(trim_out_->copy()); - new NodeAddCommand(static_cast(track_->parent()), trim_in_, splice_split_command_); - new NodeCopyInputsCommand(trim_out_, trim_in_, true, splice_split_command_); - } - - splice_split_command_->redo(); - - trim_out_old_length_ = trim_out_->length(); - trim_out_->set_length_and_media_out(in_ - trim_out_->in()); - - trim_in_->set_length_and_media_in(trim_out_old_length_ - (out_ - trim_out_->in())); - - track_->InsertBlockAfter(trim_in_, trim_out_); - - } - - } else { - - // If we picked up a block to trim the in point of - if (trim_in_) { - trim_in_old_length_ = trim_in_->length(); - trim_in_new_length_ = trim_in_->out() - out_; - } - - // If we picked up a block to trim the out point of - if (trim_out_) { - trim_out_old_length_ = trim_out_->length(); - trim_out_new_length_ = in_ - trim_out_->in(); - } - - // If we picked up a block to trim the in point of - if (trim_in_old_length_ != trim_in_new_length_) { - trim_in_->set_length_and_media_in(trim_in_new_length_); - } - - // Remove all blocks that are flagged for removal - foreach (Block* remove_block, removed_blocks_) { - track_->RippleRemoveBlock(remove_block); - - QUndoCommand* remove_command = new QUndoCommand(); - Node::RemoveNodesAndExclusiveDependencies(remove_block, remove_command); - remove_command->redo(); - remove_block_commands_.append(remove_command); - } - - // If we picked up a block to trim the out point of - if (trim_out_old_length_ != trim_out_new_length_) { - trim_out_->set_length_and_media_out(trim_out_new_length_); - } - - } - - // If we were given a block to insert, insert it here - if (insert_) { - if (!trim_out_) { - // This is the start of the Sequence - track_->PrependBlock(insert_); - } else if (!trim_in_) { - // This is the end of the Sequence - track_->AppendBlock(insert_); - } else { - // This is somewhere in the middle of the Sequence - track_->InsertBlockAfter(insert_, trim_out_); - } - } - - track_->EndOperation(); - - track_->Node::InvalidateCache(TimeRange(in_, insert_ ? out_ : RATIONAL_MAX), - track_->block_input()); -} - -void TrackRippleRemoveAreaCommand::undo_internal() -{ - track_->BeginOperation(); - - // If we were given a block to insert, insert it here - if (insert_ != nullptr) { - track_->RippleRemoveBlock(insert_); - } - - if (splice_) { - - if (trim_out_->type() == Block::kGap && !insert_) { - - // Just restore the length - trim_out_->set_length_and_media_out(trim_out_->length() + (out_ - in_)); - - } else { - - // trim_in_ is our copy and trim_out_ is our original - track_->RippleRemoveBlock(trim_in_); - trim_out_->set_length_and_media_out(trim_out_old_length_); - - splice_split_command_->undo(); - - } - - } else { - - // If we picked up a block to trim the out point of - if (trim_out_old_length_ != trim_out_new_length_) { - trim_out_->set_length_and_media_out(trim_out_old_length_); - } - - // Restore blocks that were removed - for (int i=remove_block_commands_.size()-1;i>=0;i--) { - QUndoCommand* command = remove_block_commands_.at(i); - command->undo(); - delete command; - } - remove_block_commands_.clear(); - - for (int i=removed_blocks_.size()-1;i>=0;i--) { - Block* remove_block = removed_blocks_.at(i); - - if (trim_in_) { - track_->InsertBlockBefore(remove_block, trim_in_); - } else { - track_->AppendBlock(remove_block); - } - } - removed_blocks_.clear(); - - // If we picked up a block to trim the in point of - if (trim_in_old_length_ != trim_in_new_length_) { - trim_in_->set_length_and_media_in(trim_in_old_length_); - } - - } - - track_->EndOperation(); - - track_->Node::InvalidateCache(TimeRange(in_, insert_ ? out_ : RATIONAL_MAX), - track_->block_input()); - - if (splice_split_command_) { - delete splice_split_command_; - splice_split_command_ = nullptr; - } -} - -TrackPlaceBlockCommand::TrackPlaceBlockCommand(TrackList *timeline, int track, Block *block, rational in, QUndoCommand *parent) : - TrackRippleRemoveAreaCommand(nullptr, in, 0, parent), // Out gets set correctly in redo() - timeline_(timeline), - track_index_(track), - gap_(nullptr) -{ - insert_ = block; -} - -Project *TrackPlaceBlockCommand::GetRelevantProject() const -{ - return static_cast(static_cast(timeline_->parent())->parent())->project(); -} - -void TrackPlaceBlockCommand::redo_internal() -{ - // Determine if we need to add tracks - if (track_index_ >= timeline_->GetTracks().size()) { - if (added_tracks_.isEmpty()) { - // First redo, create tracks now - added_tracks_.resize(track_index_ - timeline_->GetTracks().size() + 1); - - for (int i=0; isetParent(timeline_->GetParentGraph()); - - timeline_->track_input()->ArrayAppend(); - Node::ConnectEdge(track, timeline_->track_input(), timeline_->track_input()->ArraySize() - 1); - } - } - - track_ = timeline_->GetTrackAt(track_index_); - - append_ = (in_ >= track_->track_length()); - - // Check if the placement location is past the end of the timeline - if (append_) { - if (in_ > track_->track_length()) { - // If so, insert a gap here - gap_ = new GapBlock(); - gap_->set_length_and_media_out(in_ - track_->track_length()); - gap_->setParent(track_->parent()); - track_->AppendBlock(gap_); - } - - track_->AppendBlock(insert_); - } else { - out_ = in_ + insert_->length(); - - // Place the Block at this point - TrackRippleRemoveAreaCommand::redo_internal(); - } -} - -void TrackPlaceBlockCommand::undo_internal() -{ - if (append_) { - track_->RippleRemoveBlock(insert_); - - if (gap_ != nullptr) { - track_->RippleRemoveBlock(gap_); - gap_->setParent(&memory_manager_); - } - } else { - TrackRippleRemoveAreaCommand::undo_internal(); - } - - for (int i=added_tracks_.size()-1; i>=0; i--) { - Track* track = added_tracks_.at(i); - Node::DisconnectEdge(track, timeline_->track_input(), timeline_->track_input()->ArraySize() - 1); - track->setParent(&memory_manager_); - timeline_->track_input()->ArrayRemoveLast(); - } -} - -BlockSplitCommand::BlockSplitCommand(Track* track, Block *block, rational point, QUndoCommand *parent) : - UndoCommand(parent), - track_(track), - block_(block), - new_length_(point - block->in()), - old_length_(block->length()), - point_(point) -{ - Q_ASSERT(point > block_->in() && point < block_->out() && block_->type() == Block::kClip); - - // Ensures that this block is deleted if this action is undone - new_block_ = static_cast(block_->copy()); - new_block_->setParent(&memory_manager_); - - // Determine if the block outputs to an "out" transition - TransitionBlock* transition = TransitionBlock::GetBlockOutTransition(block_); - if (transition) { - transitions_to_move_.append(transition->out_block_input()); - } -} - -Project *BlockSplitCommand::GetRelevantProject() const -{ - return static_cast(block_->parent())->project(); -} - -void BlockSplitCommand::redo_internal() -{ - track_->BeginOperation(); - - NodeGraph* graph = block_->parent(); - - add_command_ = new QUndoCommand(); - new NodeAddCommand(graph, new_block_, add_command_); - - bool copy_dependencies_too = Config::Current()[QStringLiteral("SplitClipsCopyNodes")].toBool(); - - new NodeCopyInputsCommand(block_, new_block_, !copy_dependencies_too, add_command_); - - if (copy_dependencies_too) { - - QVector src_nodes; - QVector dst_nodes; - - src_nodes.append(block_); - src_nodes.append(block_->GetDependencies()); - - dst_nodes.resize(src_nodes.size()); - dst_nodes[0] = new_block_; - for (int i=1; icopy(); - new NodeAddCommand(graph, dst_nodes[i], add_command_); - Node::CopyInputs(src_nodes[i], dst_nodes[i], false); - } - - Node::CopyDependencyGraph(src_nodes, dst_nodes, add_command_); - - } - - add_command_->redo(); - - rational new_part_length = block_->length() - (point_ - block_->in()); - - block_->set_length_and_media_out(new_length_); - - new_block_->set_length_and_media_in(new_part_length); - - track_->InsertBlockAfter(new_block_, block_); - - foreach (NodeInput* transition, transitions_to_move_) { - Node::DisconnectEdge(block_, transition); - Node::ConnectEdge(new_block_, transition); - } - - track_->EndOperation(); -} - -void BlockSplitCommand::undo_internal() -{ - track_->BeginOperation(); - - foreach (NodeInput* transition, transitions_to_move_) { - Node::DisconnectEdge(new_block_, transition); - Node::ConnectEdge(block_, transition); - } - - block_->set_length_and_media_out(old_length_); - track_->RippleRemoveBlock(new_block_); - - add_command_->undo(); - new_block_->setParent(&memory_manager_); - delete add_command_; - - track_->EndOperation(); -} - -Block *BlockSplitCommand::new_block() -{ - return new_block_; -} - -TrackSplitAtTimeCommand::TrackSplitAtTimeCommand(Track *track, rational point, QUndoCommand *parent) : - UndoCommand(parent), - track_(track) -{ - // Find Block that contains this time - foreach (Block* b, track->Blocks()) { - if (b->out() == point) { - // This time is between blocks, no split needs to occur - return; - } else if (b->in() < point && b->out() > point) { - // We found the Block, split it - new BlockSplitCommand(track_, b, point, this); - return; - } - } -} - -Project *TrackSplitAtTimeCommand::GetRelevantProject() const -{ - return static_cast(track_->parent())->project(); -} - -TrackReplaceBlockCommand::TrackReplaceBlockCommand(Track* track, Block *old, Block *replace, QUndoCommand *parent) : - UndoCommand(parent), - track_(track), - old_(old), - replace_(replace) -{ -} - -Project *TrackReplaceBlockCommand::GetRelevantProject() const -{ - return static_cast(track_->parent())->project(); -} - -void TrackReplaceBlockCommand::redo_internal() -{ - track_->ReplaceBlock(old_, replace_); -} - -void TrackReplaceBlockCommand::undo_internal() -{ - track_->ReplaceBlock(replace_, old_); -} - -TrackPrependBlockCommand::TrackPrependBlockCommand(Track *track, Block *block, QUndoCommand *parent) : - UndoCommand(parent), - track_(track), - block_(block) -{ -} - -Project *TrackPrependBlockCommand::GetRelevantProject() const -{ - return static_cast(track_->parent())->project(); -} - -void TrackPrependBlockCommand::redo_internal() -{ - track_->PrependBlock(block_); -} - -void TrackPrependBlockCommand::undo_internal() -{ - track_->RippleRemoveBlock(block_); -} - -BlockSplitPreservingLinksCommand::BlockSplitPreservingLinksCommand(const QVector &blocks, const QList ×, QUndoCommand *parent) : - UndoCommand(parent), - blocks_(blocks), - times_(times) -{ - QVector< QVector > split_blocks(times.size()); - - for (int i=0;i splits(blocks.size()); - - for (int j=0;jin() < time && b->out() > time) { - Track* track = Track::TrackFromBlock(b); - - Q_ASSERT(track); - - BlockSplitCommand* split_command = new BlockSplitCommand(track, b, time, this); - splits.replace(j, split_command->new_block()); - } else { - splits.replace(j, nullptr); - } - } - - split_blocks.replace(i, splits); - } - - // Now that we've determined all the splits, we can relink everything - for (int i=0;i& split_list, split_blocks) { - Block::Link(split_list.at(i), split_list.at(j)); - } - } - } - } -} - -Project *BlockSplitPreservingLinksCommand::GetRelevantProject() const -{ - return static_cast(blocks_.first()->parent())->project(); -} - -TimelineRippleDeleteGapsAtRegionsCommand::TimelineRippleDeleteGapsAtRegionsCommand(ViewerOutput *vo, const TimeRangeList ®ions, QUndoCommand *parent) : - UndoCommand(parent), - timeline_(vo), - regions_(regions) -{ -} - -Project *TimelineRippleDeleteGapsAtRegionsCommand::GetRelevantProject() const -{ - return static_cast(timeline_->parent())->project(); -} - -void TimelineRippleDeleteGapsAtRegionsCommand::redo_internal() -{ - foreach (const TimeRange& range, regions_) { - rational max_ripple_length = range.length(); - - QList blocks_around_range; - - foreach (Track* track, timeline_->GetTracks()) { - // Get the block from every other track that is either at or just before our block's in point - Block* block_at_time = track->NearestBlockBeforeOrAt(range.in()); - - if (block_at_time) { - if (block_at_time->type() == Block::kGap) { - max_ripple_length = qMin(block_at_time->length(), max_ripple_length); - } else { - max_ripple_length = 0; - break; - } - - blocks_around_range.append(block_at_time); - } - } - - if (max_ripple_length > 0) { - foreach (Block* resize, blocks_around_range) { - if (resize->length() == max_ripple_length) { - // Remove block entirely - TrackRippleRemoveBlockCommand* remove_command = new TrackRippleRemoveBlockCommand(Track::TrackFromBlock(resize), resize); - remove_command->redo(); - commands_.append(remove_command); - } else { - // Resize block - BlockResizeCommand* resize_command = new BlockResizeCommand(resize, resize->length() - max_ripple_length); - resize_command->redo(); - commands_.append(resize_command); - } - } - } - } -} - -void TimelineRippleDeleteGapsAtRegionsCommand::undo_internal() -{ - for (int i=commands_.size()-1;i>=0;i--) { - commands_.at(i)->undo(); - delete commands_.at(i); - } - commands_.empty(); -} - -WorkareaSetEnabledCommand::WorkareaSetEnabledCommand(Project* project, TimelinePoints *points, bool enabled, QUndoCommand *parent) : - UndoCommand(parent), - project_(project), - points_(points), - old_enabled_(points_->workarea()->enabled()), - new_enabled_(enabled) -{ -} - -Project *WorkareaSetEnabledCommand::GetRelevantProject() const -{ - return project_; -} - -void WorkareaSetEnabledCommand::redo_internal() -{ - points_->workarea()->set_enabled(new_enabled_); -} - -void WorkareaSetEnabledCommand::undo_internal() -{ - points_->workarea()->set_enabled(old_enabled_); -} - -WorkareaSetRangeCommand::WorkareaSetRangeCommand(Project* project, TimelinePoints *points, const TimeRange &range, QUndoCommand *parent) : - UndoCommand(parent), - project_(project), - points_(points), - old_range_(points_->workarea()->range()), - new_range_(range) -{ -} - -Project *WorkareaSetRangeCommand::GetRelevantProject() const -{ - return project_; -} - -void WorkareaSetRangeCommand::redo_internal() -{ - points_->workarea()->set_range(new_range_); -} - -void WorkareaSetRangeCommand::undo_internal() -{ - points_->workarea()->set_range(old_range_); -} - -BlockLinkCommand::BlockLinkCommand(Block *a, Block *b, bool link, QUndoCommand *parent) : - UndoCommand(parent), - a_(a), - b_(b), - link_(link) -{ -} - -Project *BlockLinkCommand::GetRelevantProject() const -{ - return static_cast(a_->parent())->project(); -} - -void BlockLinkCommand::redo_internal() -{ - if (link_) { - done_ = Block::Link(a_, b_); - } else { - done_ = Block::Unlink(a_, b_); - } -} - -void BlockLinkCommand::undo_internal() -{ - if (done_) { - if (link_) { - Block::Unlink(a_, b_); - } else { - Block::Link(a_, b_); - } - } -} - -BlockUnlinkAllCommand::BlockUnlinkAllCommand(Block *block, QUndoCommand *parent) : - UndoCommand(parent), - block_(block) -{ -} - -Project *BlockUnlinkAllCommand::GetRelevantProject() const -{ - return static_cast(block_->parent())->project(); -} - -void BlockUnlinkAllCommand::redo_internal() -{ - unlinked_ = block_->linked_clips(); - - foreach (Block* link, unlinked_) { - Block::Unlink(block_, link); - } -} - -void BlockUnlinkAllCommand::undo_internal() -{ - foreach (Block* link, unlinked_) { - Block::Link(block_, link); - } - - unlinked_.clear(); -} - -BlockLinkManyCommand::BlockLinkManyCommand(const QVector blocks, bool link, QUndoCommand *parent) : - UndoCommand(parent), - blocks_(blocks) -{ - foreach (Block* a, blocks_) { - foreach (Block* b, blocks_) { - if (a != b) { - new BlockLinkCommand(a, b, link, this); - } - } - } -} - -Project *BlockLinkManyCommand::GetRelevantProject() const -{ - return static_cast(blocks_.first()->parent())->project(); -} - -BlockEnableDisableCommand::BlockEnableDisableCommand(Block *block, bool enabled, QUndoCommand *parent) : - UndoCommand(parent), - block_(block), - old_enabled_(block_->is_enabled()), - new_enabled_(enabled) -{ -} - -Project *BlockEnableDisableCommand::GetRelevantProject() const -{ - return static_cast(block_->parent())->project(); -} - -void BlockEnableDisableCommand::redo_internal() -{ - block_->set_enabled(new_enabled_); -} - -void BlockEnableDisableCommand::undo_internal() -{ - block_->set_enabled(old_enabled_); -} - -BlockTrimCommand::BlockTrimCommand(Track* track, Block *block, rational new_length, Timeline::MovementMode mode, QUndoCommand *command) : - UndoCommand(command), - track_(track), - block_(block), - old_length_(block->length()), - new_length_(new_length), - mode_(mode), - adjacent_(nullptr), - we_created_adjacent_(false), - we_deleted_adjacent_(false), - trim_is_a_roll_edit_(false) -{ -} - -Project *BlockTrimCommand::GetRelevantProject() const -{ - return static_cast(block_->parent())->project(); -} - -void BlockTrimCommand::redo_internal() -{ - track_->BeginOperation(); - - // Will be POSITIVE if trimming shorter and NEGATIVE if trimming longer - rational trim_diff = old_length_ - new_length_; - - TimeRange invalidate_range; - - if (mode_ == Timeline::kTrimIn) { - invalidate_range = TimeRange(block_->in(), block_->in() + trim_diff); - block_->set_length_and_media_in(new_length_); - adjacent_ = block_->previous(); - } else { - invalidate_range = TimeRange(block_->out(), block_->out() - trim_diff); - block_->set_length_and_media_out(new_length_); - adjacent_ = block_->next(); - } - - if (trim_diff > rational()) { - // If trimming SHORTER, we'll need to create/modify a gap - if (adjacent_ && (adjacent_->type() == Block::kGap || trim_is_a_roll_edit_)) { - - // A gap (or equivalent) exists, simply increase the size of it - if (mode_ == Timeline::kTrimIn) { - adjacent_->set_length_and_media_out(adjacent_->length() + trim_diff); - } else { - adjacent_->set_length_and_media_in(adjacent_->length() + trim_diff); - } - - } else { - - // Don't create a gap if the trim was at the end of the sequence (which would be indicated by - // the mode being "trim out" and "block_->next()" being null. - if (mode_ == Timeline::kTrimIn || block_->next()) { - // We must create a gap - we_created_adjacent_ = true; - - adjacent_ = new GapBlock(); - adjacent_->set_length_and_media_out(trim_diff); - adjacent_->setParent(track_->parent()); - - if (mode_ == Timeline::kTrimIn) { - track_->InsertBlockBefore(adjacent_, block_); - } else { - track_->InsertBlockAfter(adjacent_, block_); - } - } - - } - } else { - if (adjacent_) { - // If trimming LONGER, we'll need to trim the adjacent - // (assume if there's no adjacent, we're at the end of the timeline and do nothing) - rational adjacent_length = adjacent_->length() + trim_diff; - - if (adjacent_length.isNull()) { - // Ripple remove block - track_->RippleRemoveBlock(adjacent_); - adjacent_->setParent(&memory_manager_); - we_deleted_adjacent_ = true; - } else if (mode_ == Timeline::kTrimIn) { - adjacent_->set_length_and_media_out(adjacent_length); - } else { - adjacent_->set_length_and_media_in(adjacent_length); - } - } - } - - track_->EndOperation(); - - if (block_->type() == Block::kTransition) { - // Whole transition needs to be invalidated - invalidate_range = TimeRange(block_->in(), block_->out()); - } - - track_->Node::InvalidateCache(invalidate_range, track_->block_input()); -} - -void BlockTrimCommand::undo_internal() -{ - TimeRange invalidate_range; - - if (block_->type() == Block::kTransition) { - // Whole transition needs to be invalidated - invalidate_range = TimeRange(block_->in(), block_->out()); - } - - track_->BeginOperation(); - - // Will be POSITIVE if trimming shorter and NEGATIVE if trimming longer - rational trim_diff = old_length_ - new_length_; - - if (trim_diff > rational()) { - // If trimmed SHORTER, we need to unadjust the gap - if (we_created_adjacent_) { - // If we created a gap, just remove it straight up - track_->RippleRemoveBlock(adjacent_); - adjacent_->setParent(&memory_manager_); - adjacent_ = nullptr; - we_created_adjacent_ = false; - } else if (adjacent_) { - // If we adjusted an existing gap, unadjust here - adjacent_->set_length_and_media_out(adjacent_->length() - trim_diff); - } - } else { - if (adjacent_) { - // If trimmed LONGER, we adjusted an existing block - // (assume if there's no adjacent, we're at the end of the timeline and do nothing) - if (we_deleted_adjacent_) { - adjacent_->setParent(track_->parent()); - - if (mode_ == Timeline::kTrimIn) { - track_->InsertBlockBefore(adjacent_, block_); - } else { - track_->InsertBlockAfter(adjacent_, block_); - } - - we_deleted_adjacent_ = false; - } else if (mode_ == Timeline::kTrimIn) { - adjacent_->set_length_and_media_out(adjacent_->length() - trim_diff); - } else { - adjacent_->set_length_and_media_in(adjacent_->length() - trim_diff); - } - } - } - - if (mode_ == Timeline::kTrimIn) { - block_->set_length_and_media_in(old_length_); - - if (block_->type() != Block::kTransition) { - invalidate_range = TimeRange(block_->in(), block_->in() + trim_diff); - } - } else { - block_->set_length_and_media_out(old_length_); - - if (block_->type() != Block::kTransition) { - invalidate_range = TimeRange(block_->out(), block_->out() - trim_diff); - } - } - - track_->EndOperation(); - - track_->Node::InvalidateCache(invalidate_range, track_->block_input()); -} - -TrackReplaceBlockWithGapCommand::TrackReplaceBlockWithGapCommand(Track *track, Block *block, QUndoCommand *command) : - UndoCommand(command), - track_(track), - block_(block), - existing_gap_(nullptr), - existing_merged_gap_(nullptr), - our_gap_(nullptr) -{ -} - -Project *TrackReplaceBlockWithGapCommand::GetRelevantProject() const -{ - return static_cast(block_->parent())->project(); -} - -void TrackReplaceBlockWithGapCommand::redo_internal() -{ - track_->BeginOperation(); - - // Invalidate the range inhabited by this block - TimeRange invalidate_range(block_->in(), block_->out()); - - if (block_->next()) { - // Block has a next, which means it's NOT at the end of the sequence and thus requires a gap - rational new_gap_length = block_->length(); - - Block* previous = block_->previous(); - Block* next = block_->next(); - - bool previous_is_a_gap = (previous && previous->type() == Block::kGap); - bool next_is_a_gap = (next && next->type() == Block::kGap); - - if (previous_is_a_gap && next_is_a_gap) { - // Clip is preceded and followed by a gap, so we'll merge the two - existing_gap_ = static_cast(previous); - - existing_merged_gap_ = static_cast(next); - new_gap_length += existing_merged_gap_->length(); - track_->RippleRemoveBlock(existing_merged_gap_); - existing_merged_gap_->setParent(&memory_manager_); - } else if (previous_is_a_gap) { - // Extend this gap to fill space left by block - existing_gap_ = static_cast(previous); - } else if (next_is_a_gap) { - // Extend this gap to fill space left by block - existing_gap_ = static_cast(next); - } - - if (existing_gap_) { - // Extend an existing gap - new_gap_length += existing_gap_->length(); - existing_gap_->set_length_and_media_out(new_gap_length); - track_->RippleRemoveBlock(block_); - - existing_gap_precedes_ = (existing_gap_ == previous); - } else { - // No gap exists to fill this space, create a new one and swap it in - our_gap_ = new GapBlock(); - our_gap_->set_length_and_media_out(new_gap_length); - our_gap_->setParent(track_->parent()); - track_->ReplaceBlock(block_, our_gap_); - } - - } else { - // Block is at the end of the track, simply remove it - - // Determine if it's proceeded by a gap, and remove that gap if so - Block* preceding = block_->previous(); - if (preceding && preceding->type() == Block::kGap) { - track_->RippleRemoveBlock(preceding); - preceding->setParent(&memory_manager_); - - existing_merged_gap_ = static_cast(preceding); - } - - // Remove block in question - track_->RippleRemoveBlock(block_); - } - - track_->EndOperation(); - - track_->Node::InvalidateCache(invalidate_range, track_->block_input()); -} - -void TrackReplaceBlockWithGapCommand::undo_internal() -{ - track_->BeginOperation(); - - if (our_gap_) { - - // We made this gap, simply swap our gap back - track_->ReplaceBlock(our_gap_, block_); - our_gap_->setParent(&memory_manager_); - our_gap_ = nullptr; - - } else if (existing_gap_) { - - // If we're here, assume that we extended an existing gap - rational original_gap_length = existing_gap_->length() - block_->length(); - - // If we merged two gaps together, restore the second one now - if (existing_merged_gap_) { - original_gap_length -= existing_merged_gap_->length(); - existing_merged_gap_->setParent(track_->parent()); - track_->InsertBlockAfter(existing_merged_gap_, existing_gap_); - existing_merged_gap_ = nullptr; - } - - // Restore original block - if (existing_gap_precedes_) { - track_->InsertBlockAfter(block_, existing_gap_); - } else { - track_->InsertBlockBefore(block_, existing_gap_); - } - - // Restore gap's original length - existing_gap_->set_length_and_media_out(original_gap_length); - - existing_gap_ = nullptr; - - } else { - - // Our gap and existing gap were both null, our block must have been at the end and thus - // required no gap extension/replacement - - // However, we may have removed an unnecessary gap that preceded it - if (existing_merged_gap_) { - existing_merged_gap_->setParent(track_->parent()); - track_->AppendBlock(existing_merged_gap_); - existing_merged_gap_ = nullptr; - } - - // Restore block - track_->AppendBlock(block_); - - } - - track_->EndOperation(); - - track_->Node::InvalidateCache(TimeRange(block_->in(), block_->out()), track_->block_input()); -} - -TrackSlideCommand::TrackSlideCommand(Track* track, const QList& moving_blocks, Block *in_adjacent, Block *out_adjacent, const rational& movement, QUndoCommand* parent) : - UndoCommand(parent), - track_(track), - blocks_(moving_blocks), - movement_(movement), - we_created_in_adjacent_(false), - in_adjacent_(in_adjacent), - we_created_out_adjacent_(false), - out_adjacent_(out_adjacent) -{ - Q_ASSERT(!movement_.isNull()); -} - -Project *TrackSlideCommand::GetRelevantProject() const -{ - return static_cast(track_->parent())->project(); -} - -void TrackSlideCommand::redo_internal() -{ - slide_internal(false); -} - -void TrackSlideCommand::undo_internal() -{ - slide_internal(true); -} - -void TrackSlideCommand::slide_internal(bool undo) -{ - // Make sure all movement blocks' old positions are invalidated - TimeRange invalidate_range(blocks_.first()->in(), blocks_.last()->out()); - - track_->BeginOperation(); - - if (undo) { - - // Undo code - if (we_created_in_adjacent_) { - // This is a gap we made, we can just delete it entirely - track_->RippleRemoveBlock(in_adjacent_); - in_adjacent_->setParent(&memory_manager_); - we_created_in_adjacent_ = false; - in_adjacent_ = nullptr; - } else if (in_adjacent_->parent() == &memory_manager_) { - // This is a gap we removed, we can re-insert it now - in_adjacent_->setParent(track_->parent()); - track_->InsertBlockBefore(in_adjacent_, blocks_.first()); - } else { - // We must have just resized this block - in_adjacent_->set_length_and_media_out(in_adjacent_->length() - movement_); - } - - if (we_created_out_adjacent_) { - // This is a gap we made, we can just delete it entirely - track_->RippleRemoveBlock(out_adjacent_); - out_adjacent_->setParent(&memory_manager_); - we_created_out_adjacent_ = false; - out_adjacent_ = nullptr; - } else if (out_adjacent_) { - // We may not have created an out adjacent if this was the last clip in the track so we have - // to check here - if (out_adjacent_->parent() == &memory_manager_) { - // This is a gap we removed, we can re-insert it now - out_adjacent_->setParent(track_->parent()); - track_->InsertBlockAfter(out_adjacent_, blocks_.last()); - } else { - // We must have just resized this block - out_adjacent_->set_length_and_media_in(out_adjacent_->length() + movement_); - } - } - - } else { - - // Redo code - if (!in_adjacent_) { - // For any slide operation to have occurred at all with no in_adjacent, a gap will need to - // be created - GapBlock* gap = new GapBlock(); - gap->set_length_and_media_out(movement_); - gap->setParent(track_->parent()); - track_->InsertBlockBefore(gap, blocks_.first()); - we_created_in_adjacent_ = true; - in_adjacent_ = gap; - } else if (-movement_ == in_adjacent_->length()) { - // Remove in adjacent entirely - track_->RippleRemoveBlock(in_adjacent_); - in_adjacent_->setParent(&memory_manager_); - } else { - // Resize in adjacent - in_adjacent_->set_length_and_media_out(in_adjacent_->length() + movement_); - } - - if (!out_adjacent_) { - // For any slide operation to have occurred at all with no out_adjacent, a gap will need to - // be created UNLESS this is at the end of the track already - if (blocks_.last()->next()) { - GapBlock* gap = new GapBlock(); - gap->set_length_and_media_out(-movement_); - gap->setParent(track_->parent()); - track_->InsertBlockAfter(gap, blocks_.last()); - we_created_out_adjacent_ = true; - out_adjacent_ = gap; - } - } else if (movement_ == out_adjacent_->length()) { - // Remove out adjacent entirely - track_->RippleRemoveBlock(out_adjacent_); - out_adjacent_->setParent(&memory_manager_); - } else { - // Resize out adjacent - out_adjacent_->set_length_and_media_in(out_adjacent_->length() - movement_); - } - - } - - track_->EndOperation(); - - // Make sure all movement blocks' new positions are invalidated - invalidate_range.set_range(qMin(invalidate_range.in(), blocks_.first()->in()), - qMax(invalidate_range.out(), blocks_.last()->out())); - - track_->Node::InvalidateCache(invalidate_range, track_->block_input()); -} - -TrackListRippleRemoveAreaCommand::TrackListRippleRemoveAreaCommand(TrackList *list, rational in, rational out, QUndoCommand *parent) : - UndoCommand(parent), - list_(list), - in_(in), - out_(out) -{ - all_tracks_unlocked_ = true; - - foreach (Track* track, list_->GetTracks()) { - if (track->IsLocked()) { - all_tracks_unlocked_ = false; - continue; - } - - TrackRippleRemoveAreaCommand* c = new TrackRippleRemoveAreaCommand(track, in, out); - commands_.append(c); - working_tracks_.append(track); - } -} - -TrackListRippleRemoveAreaCommand::~TrackListRippleRemoveAreaCommand() -{ - qDeleteAll(commands_); -} - -Project *TrackListRippleRemoveAreaCommand::GetRelevantProject() const -{ - return static_cast(static_cast(list_->parent())->parent())->project(); -} - -void TrackListRippleRemoveAreaCommand::redo_internal() -{ - if (all_tracks_unlocked_) { - // We can optimize here by simply shifting the whole cache forward instead of re-caching - // everything following this time - if (list_->type() == Track::kVideo) { - static_cast(list_->parent())->ShiftVideoCache(out_, in_); - } else if (list_->type() == Track::kAudio) { - static_cast(list_->parent())->ShiftAudioCache(out_, in_); - } - - foreach (Track* track, working_tracks_) { - track->BeginOperation(); - } - } - - foreach (TrackRippleRemoveAreaCommand* c, commands_) { - c->redo(); - } - - if (all_tracks_unlocked_) { - foreach (Track* track, working_tracks_) { - track->EndOperation(); - } - } -} - -void TrackListRippleRemoveAreaCommand::undo_internal() -{ - if (all_tracks_unlocked_) { - // We can optimize here by simply shifting the whole cache forward instead of re-caching - // everything following this time - if (list_->type() == Track::kVideo) { - static_cast(list_->parent())->ShiftVideoCache(in_, out_); - } else if (list_->type() == Track::kAudio) { - static_cast(list_->parent())->ShiftAudioCache(in_, out_); - } - - foreach (Track* track, working_tracks_) { - track->BeginOperation(); - } - } - - foreach (TrackRippleRemoveAreaCommand* c, commands_) { - c->undo(); - } - - if (all_tracks_unlocked_) { - foreach (Track* track, working_tracks_) { - track->EndOperation(); - } - } -} - -TimelineRippleRemoveAreaCommand::TimelineRippleRemoveAreaCommand(ViewerOutput *timeline, rational in, rational out, QUndoCommand *parent) : - UndoCommand(parent), - timeline_(timeline) -{ - for (int i=0; itrack_list(static_cast(i)), - in, - out, - this); - } -} - -Project *TimelineRippleRemoveAreaCommand::GetRelevantProject() const -{ - return static_cast(timeline_->parent())->project(); -} - -TrackListRippleToolCommand::TrackListRippleToolCommand(TrackList *track_list, const QList &info, const Timeline::MovementMode &movement_mode, QUndoCommand *parent) : - UndoCommand(parent), - track_list_(track_list), - info_(info), - movement_mode_(movement_mode) -{ - working_data_.resize(info_.size()); - - all_tracks_unlocked_ = (info_.size() == track_list_->GetTrackCount()); -} - -Project *TrackListRippleToolCommand::GetRelevantProject() const -{ - return static_cast(static_cast(track_list_->parent())->parent())->project(); -} - -void TrackListRippleToolCommand::redo_internal() -{ - rational old_latest_pt; - rational earliest_pt; - - if (all_tracks_unlocked_) { - // We can do some optimization here - foreach (const RippleInfo& info, info_) { - info.track->BeginOperation(); - } - - old_latest_pt = RATIONAL_MIN; - earliest_pt = RATIONAL_MAX; - foreach (const RippleInfo& info, info_) { - if (info.block) { - old_latest_pt = qMax(old_latest_pt, info.block->out()); - - if (movement_mode_ == Timeline::kTrimIn) { - earliest_pt = qMin(earliest_pt, info.block->in()); - } else { - earliest_pt = qMin(earliest_pt, info.block->out()); - } - } else { - old_latest_pt = qMax(old_latest_pt, info.ref_block->out()); - earliest_pt = qMin(earliest_pt, info.ref_block->out()); - } - } - } - - for (int i=0;i 0) { - if (movement_mode_ == Timeline::kTrimIn) { - // We'll need to shift the media in point too - b->set_length_and_media_in(info.new_length); - } else { - b->set_length_and_media_out(info.new_length); - } - } else { - // Assume the Block was a Gap and it was reduced to zero length, remove it here - working_data_[i].removed_gap_after = b->previous(); - info.track->RippleRemoveBlock(b); - b->setParent(&memory_manager_); - } - } else if (info.new_length > 0) { - // This is a gap we are creating - GapBlock* gap = new GapBlock(); - gap->set_length_and_media_out(info.new_length); - gap->setParent(info.ref_block->parent()); - working_data_[i].created_gap = gap; - - info.track->InsertBlockAfter(gap, info.ref_block); - } - } - - if (all_tracks_unlocked_) { - // We can do some optimization here - - rational new_latest_pt = RATIONAL_MIN; - for (int i=0;i 0) { - new_latest_pt = qMax(new_latest_pt, info.block->out()); - } else { - new_latest_pt = qMax(new_latest_pt, info.block->in()); - } - } else if (info.new_length > 0) { - new_latest_pt = qMax(new_latest_pt, working_data_.at(i).created_gap->out()); - } - } - - if (track_list_->type() == Track::kVideo) { - static_cast(track_list_->parent())->ShiftVideoCache(old_latest_pt, new_latest_pt); - } else if (track_list_->type() == Track::kAudio) { - static_cast(track_list_->parent())->ShiftAudioCache(old_latest_pt, new_latest_pt); - } - - foreach (const RippleInfo& info, info_) { - info.track->EndOperation(); - - // FIXME: Untested, is this desirable behavior? - if (earliest_pt < new_latest_pt) { - info.track->InvalidateCache(TimeRange(earliest_pt, new_latest_pt), - info.track->block_input()); - } - } - } -} - -void TrackListRippleToolCommand::undo_internal() -{ - // FIXME: Add cache shift optimization - - // Clean created gaps - for (int i=info_.size()-1; i>=0; i--) { - const RippleInfo& info = info_.at(i); - - Block* b = info.block; - - if (b) { - // This was a Block that already existed - if (info.new_length > 0) { - if (movement_mode_ == Timeline::kTrimIn) { - // We'll need to shift the media in point too - b->set_length_and_media_in(info.old_length); - } else { - b->set_length_and_media_out(info.old_length); - } - } else { - // Assume the Block was a Gap and it was reduced to zero length, remove it here - Block* previous_block = working_data_[i].removed_gap_after; - - b->setParent(info.track->parent()); - - if (previous_block) { - info.track->InsertBlockAfter(b, previous_block); - } else { - info.track->PrependBlock(b); - } - } - } else if (info.new_length > 0) { - // We created a gap here, remove it - GapBlock* gap = working_data_.at(i).created_gap; - - info.track->RippleRemoveBlock(gap); - gap->setParent(&memory_manager_); - } - } -} - -TrackListInsertGaps::TrackListInsertGaps(TrackList *track_list, const rational &point, const rational &length, QUndoCommand *parent) : - UndoCommand(parent), - track_list_(track_list), - point_(point), - length_(length), - split_command_(nullptr) -{ - all_tracks_unlocked_ = true; - - foreach (Track* track, track_list_->GetTracks()) { - if (track->IsLocked()) { - all_tracks_unlocked_ = false; - continue; - } - - working_tracks_.append(track); - } -} - -Project *TrackListInsertGaps::GetRelevantProject() const -{ - return static_cast(static_cast(track_list_->parent())->parent())->project(); -} - -void TrackListInsertGaps::redo_internal() -{ - if (all_tracks_unlocked_) { - // Optimize by shifting over since we have a constant amount of time being inserted - if (track_list_->type() == Track::kVideo) { - static_cast(track_list_->parent())->ShiftVideoCache(point_, point_ + length_); - } else if (track_list_->type() == Track::kAudio) { - static_cast(track_list_->parent())->ShiftAudioCache(point_, point_ + length_); - } - - foreach (Track* track, working_tracks_) { - track->BeginOperation(); - } - } - - QVector blocks_to_split; - QVector blocks_to_append_gap_to; - - foreach (Track* track, working_tracks_) { - foreach (Block* b, track->Blocks()) { - if (b->type() == Block::kGap && b->in() <= point_ && b->out() >= point_) { - // Found a gap at the location - gaps_to_extend_.append(b); - break; - } else if (b->type() == Block::kClip && b->out() >= point_) { - if (b->out() > point_) { - blocks_to_split.append(b); - } - - blocks_to_append_gap_to.append(b); - break; - } - } - } - - foreach (Block* gap, gaps_to_extend_) { - gap->set_length_and_media_out(gap->length() + length_); - } - - if (!blocks_to_split.isEmpty()) { - split_command_ = new BlockSplitPreservingLinksCommand(blocks_to_split, {point_}); - split_command_->redo(); - } - - foreach (Block* block, blocks_to_append_gap_to) { - GapBlock* gap = new GapBlock(); - gap->set_length_and_media_out(length_); - gap->setParent(block->parent()); - Track::TrackFromBlock(block)->InsertBlockAfter(gap, block); - gaps_added_.append(gap); - } - - if (all_tracks_unlocked_) { - foreach (Track* track, working_tracks_) { - track->EndOperation(); - } - } -} - -void TrackListInsertGaps::undo_internal() -{ - if (all_tracks_unlocked_) { - // Optimize by shifting over since we have a constant amount of time being inserted - if (track_list_->type() == Track::kVideo) { - static_cast(track_list_->parent())->ShiftVideoCache(point_ + length_, point_); - } else if (track_list_->type() == Track::kAudio) { - static_cast(track_list_->parent())->ShiftAudioCache(point_ + length_, point_); - } - - foreach (Track* track, working_tracks_) { - track->BeginOperation(); - } - } - - // Remove added gaps - foreach (GapBlock* gap, gaps_added_) { - Track::TrackFromBlock(gap)->RippleRemoveBlock(gap); - gap->setParent(&memory_manager_); - } - gaps_added_.clear(); - - // Un-split blocks - if (split_command_) { - split_command_->undo(); - delete split_command_; - split_command_ = nullptr; - } - - // Restore original length of gaps - foreach (Block* gap, gaps_to_extend_) { - gap->set_length_and_media_out(gap->length() - length_); - } - gaps_to_extend_.clear(); - - if (all_tracks_unlocked_) { - foreach (Track* track, working_tracks_) { - track->EndOperation(); - } - } -} - -TransitionRemoveCommand::TransitionRemoveCommand(Track* track, TransitionBlock *block, QUndoCommand* parent) : - UndoCommand(parent), - track_(track), - block_(block), - out_block_(block_->connected_out_block()), - in_block_(block_->connected_in_block()) -{ - // Can't remove a transition in this way unless it's connected to at least one other block - Q_ASSERT(out_block_ || in_block_); -} - -Project *TransitionRemoveCommand::GetRelevantProject() const -{ - return static_cast(track_->parent())->project(); -} - -void TransitionRemoveCommand::redo_internal() -{ - track_->BeginOperation(); - - TimeRange invalidate_range(block_->in(), block_->out()); - - if (in_block_) { - in_block_->set_length_and_media_in(in_block_->length() + block_->in_offset()); - } - - if (out_block_) { - out_block_->set_length_and_media_out(out_block_->length() + block_->out_offset()); - } - - if (in_block_) { - Node::DisconnectEdge(in_block_, block_->in_block_input()); - } - - if (out_block_) { - Node::DisconnectEdge(out_block_, block_->out_block_input()); - } - - track_->RippleRemoveBlock(block_); - - track_->EndOperation(); - - track_->Node::InvalidateCache(invalidate_range, track_->block_input()); -} - -void TransitionRemoveCommand::undo_internal() -{ - track_->BeginOperation(); - - if (in_block_) { - track_->InsertBlockBefore(block_, in_block_); - } else { - track_->InsertBlockAfter(block_, out_block_); - } - - if (in_block_) { - Node::ConnectEdge(in_block_, block_->in_block_input()); - } - - if (out_block_) { - Node::ConnectEdge(out_block_, block_->out_block_input()); - } - - // These if statements must be separated because in_offset and out_offset report different things - // if only one block is connected vs two. So we have to connect the blocks first before we have - // an accurate return value from these offset functions. - if (in_block_) { - in_block_->set_length_and_media_in(in_block_->length() - block_->in_offset()); - } - - if (out_block_) { - out_block_->set_length_and_media_out(out_block_->length() - block_->out_offset()); - } - - track_->EndOperation(); - - track_->Node::InvalidateCache(TimeRange(block_->in(), block_->out()), track_->block_input()); -} - -TimelineSetSelectionsCommand::TimelineSetSelectionsCommand(TimelineWidget *timeline, const TimelineWidgetSelections &now, const TimelineWidgetSelections &old, QUndoCommand *parent) : - QUndoCommand(parent), - timeline_(timeline), - old_(old), - now_(now) -{ -} - -void TimelineSetSelectionsCommand::redo() -{ - timeline_->SetSelections(now_); -} - -void TimelineSetSelectionsCommand::undo() -{ - timeline_->SetSelections(old_); -} - -} diff --git a/app/widget/timelinewidget/undo/undo.h b/app/widget/timelinewidget/undo/undo.h deleted file mode 100644 index 68d355af6..000000000 --- a/app/widget/timelinewidget/undo/undo.h +++ /dev/null @@ -1,639 +0,0 @@ -/*** - - Olive - Non-Linear Video Editor - Copyright (C) 2020 Olive Team - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - -***/ - -#ifndef TIMELINEUNDOABLE_H -#define TIMELINEUNDOABLE_H - -#include - -#include "node/block/block.h" -#include "node/block/gap/gap.h" -#include "node/block/transition/transition.h" -#include "node/output/track/track.h" -#include "node/output/track/tracklist.h" -#include "timeline/timelinepoints.h" -#include "undo/undocommand.h" -#include "widget/timelinewidget/timelinewidgetselections.h" - -namespace olive { - -class BlockResizeCommand : public UndoCommand { -public: - BlockResizeCommand(Block* block, rational new_length, QUndoCommand* parent = nullptr); - - virtual Project* GetRelevantProject() const override; - -protected: - virtual void redo_internal() override; - virtual void undo_internal() override; - -private: - Block* block_; - rational old_length_; - rational new_length_; -}; - -class BlockResizeWithMediaInCommand : public UndoCommand { -public: - BlockResizeWithMediaInCommand(Block* block, rational new_length, QUndoCommand* parent = nullptr); - - virtual Project* GetRelevantProject() const override; - -protected: - virtual void redo_internal() override; - virtual void undo_internal() override; - -private: - Block* block_; - rational old_length_; - rational new_length_; -}; - -class BlockTrimCommand : public UndoCommand { -public: - BlockTrimCommand(Track *track, Block* block, rational new_length, Timeline::MovementMode mode, QUndoCommand* command = nullptr); - - virtual Project* GetRelevantProject() const override; - - void SetTrimIsARollEdit(bool e) - { - trim_is_a_roll_edit_ = e; - } - -protected: - virtual void redo_internal() override; - virtual void undo_internal() override; - -private: - Track* track_; - Block* block_; - rational old_length_; - rational new_length_; - Timeline::MovementMode mode_; - - Block* adjacent_; - bool we_created_adjacent_; - bool we_deleted_adjacent_; - - bool trim_is_a_roll_edit_; - - QObject memory_manager_; - -}; - -class BlockSetMediaInCommand : public UndoCommand { -public: - BlockSetMediaInCommand(Block* block, rational new_media_in, QUndoCommand* parent = nullptr); - - virtual Project* GetRelevantProject() const override; - -protected: - virtual void redo_internal() override; - virtual void undo_internal() override; - -private: - Block* block_; - rational old_media_in_; - rational new_media_in_; -}; - -class TrackRippleRemoveBlockCommand : public UndoCommand { -public: - TrackRippleRemoveBlockCommand(Track* track, Block* block, QUndoCommand* parent = nullptr); - - virtual Project* GetRelevantProject() const override; - -protected: - virtual void redo_internal() override; - virtual void undo_internal() override; - -private: - Track* track_; - - Block* block_; - - Block* before_; -}; - -class TrackPrependBlockCommand : public UndoCommand { -public: - TrackPrependBlockCommand(Track* track, Block* block, QUndoCommand* parent = nullptr); - - virtual Project* GetRelevantProject() const override; - -protected: - virtual void redo_internal() override; - virtual void undo_internal() override; - -private: - Track* track_; - Block* block_; -}; - -class TrackInsertBlockAfterCommand : public UndoCommand { -public: - TrackInsertBlockAfterCommand(Track* track, Block* block, Block* before, QUndoCommand* parent = nullptr); - - virtual Project* GetRelevantProject() const override; - -protected: - virtual void redo_internal() override; - virtual void undo_internal() override; - -private: - Track* track_; - - Block* block_; - - Block* before_; -}; - -/** - * @brief Clears the area between in and out - * - * The area between `in` and `out` is guaranteed to be freed. BLocks are trimmed and removed to free this space. - * By default, nothing takes this area meaning all subsequent clips are pushed backward, however you can specify - * a block to insert at the `in` point. No checking is done to ensure `insert` is the same length as `in` to `out`. - */ -class TrackRippleRemoveAreaCommand : public UndoCommand { -public: - TrackRippleRemoveAreaCommand(Track* track, rational in, rational out, QUndoCommand* parent = nullptr); - - virtual Project* GetRelevantProject() const override; - - void SetInsert(Block* insert); - -protected: - virtual void redo_internal() override; - virtual void undo_internal() override; - -protected: - Project* project_; - - Track* track_; - rational in_; - rational out_; - - bool splice_; - QUndoCommand* splice_split_command_; - - Block* trim_out_; - Block* trim_in_; - QVector removed_blocks_; - - rational trim_in_old_length_; - rational trim_out_old_length_; - - rational trim_in_new_length_; - rational trim_out_new_length_; - - Block* insert_; - - QObject memory_manager_; - - QVector remove_block_commands_; - -}; - -class TrackListRippleRemoveAreaCommand : public UndoCommand { -public: - TrackListRippleRemoveAreaCommand(TrackList* list, rational in, rational out, QUndoCommand* parent = nullptr); - - virtual ~TrackListRippleRemoveAreaCommand() override; - - virtual Project* GetRelevantProject() const override; - -protected: - virtual void redo_internal() override; - virtual void undo_internal() override; - -private: - TrackList* list_; - - QList working_tracks_; - - rational in_; - - rational out_; - - bool all_tracks_unlocked_; - - QVector commands_; - -}; - -class TimelineRippleRemoveAreaCommand : public UndoCommand { -public: - TimelineRippleRemoveAreaCommand(ViewerOutput* timeline, rational in, rational out, QUndoCommand* parent = nullptr); - - virtual Project* GetRelevantProject() const override; - -private: - ViewerOutput* timeline_; - -}; - -class TrackListRippleToolCommand : public UndoCommand { -public: - struct RippleInfo { - Block* block; - Block* ref_block; - Track* track; - rational new_length; - rational old_length; - }; - - TrackListRippleToolCommand(TrackList* track_list, - const QList& info, - const Timeline::MovementMode& movement_mode, - QUndoCommand* parent = nullptr); - - virtual Project* GetRelevantProject() const override; - -protected: - virtual void redo_internal() override; - virtual void undo_internal() override; - -private: - TrackList* track_list_; - - QList info_; - Timeline::MovementMode movement_mode_; - - struct WorkingData { - GapBlock* created_gap; - Block* removed_gap_after; - }; - - QVector working_data_; - - QObject memory_manager_; - - bool all_tracks_unlocked_; - -}; - -/** - * @brief Destructively places `block` at the in point `start` - * - * The Block is guaranteed to be placed at the starting point specified. If there are Blocks in this area, they are - * either trimmed or removed to make space for this Block. Additionally, if the Block is placed beyond the end of - * the Sequence, a GapBlock is inserted to compensate. - */ -class TrackPlaceBlockCommand : public TrackRippleRemoveAreaCommand { -public: - TrackPlaceBlockCommand(TrackList *timeline, int track, Block* block, rational in, QUndoCommand* parent = nullptr); - - virtual Project* GetRelevantProject() const override; - -protected: - virtual void redo_internal() override; - virtual void undo_internal() override; - -private: - TrackList* timeline_; - int track_index_; - bool append_; - GapBlock* gap_; - QVector added_tracks_; - -}; - -class BlockSplitCommand : public UndoCommand { -public: - BlockSplitCommand(Track* track, Block* block, rational point, QUndoCommand* parent = nullptr); - - virtual Project* GetRelevantProject() const override; - - Block* new_block(); - -protected: - virtual void redo_internal() override; - virtual void undo_internal() override; - -private: - Track* track_; - Block* block_; - Block* new_block_; - - rational new_length_; - rational old_length_; - rational point_; - - QList transitions_to_move_; - - QObject memory_manager_; - - QUndoCommand* add_command_; - -}; - -class TrackSplitAtTimeCommand : public UndoCommand { -public: - TrackSplitAtTimeCommand(Track* track, rational point, QUndoCommand* parent = nullptr); - - virtual Project* GetRelevantProject() const override; - -private: - Track* track_; - -}; - -class BlockSplitPreservingLinksCommand : public UndoCommand { -public: - BlockSplitPreservingLinksCommand(const QVector &blocks, const QList& times, QUndoCommand* parent = nullptr); - - virtual Project* GetRelevantProject() const override; - -private: - QVector blocks_; - - QList times_; -}; - -/** - * @brief Replaces Block `old` with Block `replace` - * - * Both blocks must have equal lengths. - */ -class TrackReplaceBlockCommand : public UndoCommand { -public: - TrackReplaceBlockCommand(Track* track, Block* old, Block* replace, QUndoCommand* parent = nullptr); - - virtual Project* GetRelevantProject() const override; - -protected: - virtual void redo_internal() override; - virtual void undo_internal() override; - -private: - Track* track_; - Block* old_; - Block* replace_; -}; - -class TrackReplaceBlockWithGapCommand : public UndoCommand { -public: - TrackReplaceBlockWithGapCommand(Track* track, Block* block, QUndoCommand* command = nullptr); - - virtual Project* GetRelevantProject() const override; - -protected: - virtual void redo_internal() override; - virtual void undo_internal() override; - -private: - Track* track_; - Block* block_; - - GapBlock* existing_gap_; - GapBlock* existing_merged_gap_; - bool existing_gap_precedes_; - GapBlock* our_gap_; - - QObject memory_manager_; - -}; - -class TimelineRippleDeleteGapsAtRegionsCommand : public UndoCommand { -public: - TimelineRippleDeleteGapsAtRegionsCommand(ViewerOutput* vo, const TimeRangeList& regions, QUndoCommand* parent = nullptr); - - virtual Project* GetRelevantProject() const override; - -protected: - virtual void redo_internal() override; - virtual void undo_internal() override; - -private: - ViewerOutput* timeline_; - TimeRangeList regions_; - - QList commands_; - -}; - -class WorkareaSetEnabledCommand : public UndoCommand { -public: - WorkareaSetEnabledCommand(Project *project, TimelinePoints* points, bool enabled, QUndoCommand* parent = nullptr); - - virtual Project* GetRelevantProject() const override; - -protected: - virtual void redo_internal() override; - virtual void undo_internal() override; - -private: - Project* project_; - - TimelinePoints* points_; - - bool old_enabled_; - - bool new_enabled_; - -}; - -class WorkareaSetRangeCommand : public UndoCommand { -public: - WorkareaSetRangeCommand(Project *project, TimelinePoints* points, const TimeRange& range, QUndoCommand* parent = nullptr); - - virtual Project* GetRelevantProject() const override; - -protected: - virtual void redo_internal() override; - virtual void undo_internal() override; - -private: - Project* project_; - - TimelinePoints* points_; - - TimeRange old_range_; - - TimeRange new_range_; - -}; - -class BlockLinkManyCommand : public UndoCommand { -public: - BlockLinkManyCommand(const QVector blocks, bool link, QUndoCommand* parent = nullptr); - - virtual Project* GetRelevantProject() const override; - -private: - QVector blocks_; - -}; - -class BlockLinkCommand : public UndoCommand { -public: - BlockLinkCommand(Block* a, Block* b, bool link, QUndoCommand* parent = nullptr); - - virtual Project* GetRelevantProject() const override; - -protected: - virtual void redo_internal() override; - virtual void undo_internal() override; - -private: - Block* a_; - - Block* b_; - - bool link_; - - bool done_; - -}; - -class BlockUnlinkAllCommand : public UndoCommand { -public: - BlockUnlinkAllCommand(Block* block, QUndoCommand* parent = nullptr); - - virtual Project* GetRelevantProject() const override; - -protected: - virtual void redo_internal() override; - virtual void undo_internal() override; - -private: - Block* block_; - - QVector unlinked_; - -}; - -class BlockEnableDisableCommand : public UndoCommand { -public: - BlockEnableDisableCommand(Block* block, bool enabled, QUndoCommand* parent = nullptr); - - virtual Project* GetRelevantProject() const override; - -protected: - virtual void redo_internal() override; - virtual void undo_internal() override; - -private: - Block* block_; - - bool old_enabled_; - - bool new_enabled_; - -}; - -class TrackSlideCommand : public UndoCommand { -public: - TrackSlideCommand(Track* track, const QList& moving_blocks, Block* in_adjacent, Block* out_adjacent, const rational& movement, QUndoCommand* parent = nullptr); - - virtual Project* GetRelevantProject() const override; - -protected: - virtual void redo_internal() override; - virtual void undo_internal() override; - -private: - void slide_internal(bool undo); - - Track* track_; - QList blocks_; - rational movement_; - - bool we_created_in_adjacent_; - Block* in_adjacent_; - bool we_created_out_adjacent_; - Block* out_adjacent_; - - QObject memory_manager_; - -}; - -class TrackListInsertGaps : public UndoCommand { -public: - TrackListInsertGaps(TrackList* track_list, const rational& point, const rational& length, QUndoCommand* parent = nullptr); - - virtual Project* GetRelevantProject() const override; - -protected: - virtual void redo_internal() override; - virtual void undo_internal() override; - -private: - TrackList* track_list_; - - rational point_; - - rational length_; - - QList working_tracks_; - - bool all_tracks_unlocked_; - - QList gaps_to_extend_; - - QList gaps_added_; - - BlockSplitPreservingLinksCommand* split_command_; - - QObject memory_manager_; - -}; - -class TransitionRemoveCommand : public UndoCommand { -public: - TransitionRemoveCommand(Track *track, TransitionBlock* block, QUndoCommand *parent = nullptr); - - virtual Project* GetRelevantProject() const override; - -protected: - virtual void redo_internal() override; - virtual void undo_internal() override; - -private: - Track* track_; - - TransitionBlock* block_; - - Block* out_block_; - Block* in_block_; - -}; - -class TimelineWidget; - -class TimelineSetSelectionsCommand : public QUndoCommand { -public: - TimelineSetSelectionsCommand(TimelineWidget* timeline, const TimelineWidgetSelections& now, const TimelineWidgetSelections& old, QUndoCommand* parent = nullptr); - -protected: - virtual void redo() override; - virtual void undo() override; - -private: - TimelineWidget* timeline_; - TimelineWidgetSelections old_; - TimelineWidgetSelections now_; - -}; - -} - -#endif // TIMELINEUNDOABLE_H diff --git a/app/widget/timelinewidget/view/timelineview.h b/app/widget/timelinewidget/view/timelineview.h index b309d16ba..6f5671663 100644 --- a/app/widget/timelinewidget/view/timelineview.h +++ b/app/widget/timelinewidget/view/timelineview.h @@ -31,8 +31,6 @@ #include "timelineviewmouseevent.h" #include "timelineviewghostitem.h" #include "widget/timebased/timebasedview.h" -#include "widget/timelinewidget/undo/undo.h" -#include "undo/undostack.h" namespace olive {