/*** Olive - Non-Linear Video Editor Copyright (C) 2022 Olive Team Modifications Copyright (C) 2025 mikesolar 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 OAK_TIMELINEUNDORIPPLE_H #define OAK_TIMELINEUNDORIPPLE_H #include "node/block/gap/gap.h" #include "node/output/track/track.h" #include "node/output/track/tracklist.h" #include "node/project/sequence/sequence.h" #include "timelineundogeneral.h" #include "timelineundosplit.h" #include "timelineundotrack.h" namespace olive { /** * @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, const TimeRange &range); virtual ~TrackRippleRemoveAreaCommand() override; virtual Project *get_relevant_project() const override { return track_->project(); } /** * @brief Block to insert after if you want to insert something between this ripple */ Block *get_insertion_index() const { return insert_previous_; } Block *get_spliced_block() const { if (splice_split_command_) { return splice_split_command_->new_block(); } return nullptr; } void set_allow_splitting_gaps(bool e) { allow_splitting_gaps_ = e; } protected: virtual void prepare() override; virtual void redo() override; virtual void undo() override; private: struct TrimOperation { Block *block; Rational old_length; Rational new_length; }; struct RemoveOperation { Block *block; Block *before; }; Track *track_; TimeRange range_; TrimOperation trim_out_; QVector removals_; TrimOperation trim_in_; Block *insert_previous_; bool allow_splitting_gaps_; BlockSplitCommand *splice_split_command_; QVector remove_block_commands_; }; class TrackListRippleRemoveAreaCommand : public UndoCommand { public: TrackListRippleRemoveAreaCommand(TrackList *list, Rational in, Rational out) : list_(list) , range_(in, out) { } virtual ~TrackListRippleRemoveAreaCommand() override { qDeleteAll(commands_); } virtual Project *get_relevant_project() const override { return list_->parent()->project(); } protected: virtual void prepare() override; virtual void redo() override; virtual void undo() override; private: TrackList *list_; QList working_tracks_; TimeRange range_; QVector commands_; }; class TimelineRippleRemoveAreaCommand : public MultiUndoCommand { public: TimelineRippleRemoveAreaCommand(Sequence *timeline, Rational in, Rational out); virtual Project *get_relevant_project() const override { return timeline_->project(); } private: Sequence *timeline_; }; class TrackListRippleToolCommand : public UndoCommand { public: struct RippleInfo { Block *block; bool append_gap; }; TrackListRippleToolCommand(TrackList *track_list, const QHash &info, const Rational &ripple_movement, const Timeline::MovementMode &movement_mode); virtual Project *get_relevant_project() const override { return track_list_->parent()->project(); } protected: virtual void redo() override { ripple(true); } virtual void undo() override { ripple(false); } private: void ripple(bool redo); TrackList *track_list_; QHash info_; Rational ripple_movement_; Timeline::MovementMode movement_mode_; struct WorkingData { GapBlock *created_gap = nullptr; Block *removed_gap_after; Rational old_length; Rational earliest_point_of_change; }; QHash working_data_; QObject memory_manager_; }; class TimelineRippleDeleteGapsAtRegionsCommand : public UndoCommand { public: using RangeList = QVector>; TimelineRippleDeleteGapsAtRegionsCommand(Sequence *vo, const RangeList ®ions) : timeline_(vo) , regions_(regions) { } virtual ~TimelineRippleDeleteGapsAtRegionsCommand() override { qDeleteAll(commands_); } virtual Project *get_relevant_project() const override { return timeline_->project(); } bool has_commands() const { return !commands_.isEmpty(); } protected: virtual void prepare() override; virtual void redo() override; virtual void undo() override; private: Sequence *timeline_; RangeList regions_; QVector commands_; struct RemovalRequest { GapBlock *gap; TimeRange range; }; }; } #endif // OAK_TIMELINEUNDORIPPLE_H