fix undo for multi-non-contiguous region cut/delete (#9295)

Defer all ripples till after cut/delete. Then perform them
from the latest to the earliest.
This commit is contained in:
Paul Davis 2023-04-12 10:14:57 -06:00
parent e575d5c6dc
commit 117c751293

View File

@ -32,6 +32,7 @@
#include <unistd.h>
#include <algorithm>
#include <cstdlib>
#include <cmath>
#include <string>
@ -4886,7 +4887,6 @@ Editor::cut_copy_regions (CutCopyOp op, RegionSelection& rs)
timepos_t first_position = timepos_t::max (Temporal::AudioTime);
PlaylistSet freezelist;
RegionList exclude;
/* get ordering correct before we cut/copy */
@ -4932,6 +4932,16 @@ Editor::cut_copy_regions (CutCopyOp op, RegionSelection& rs)
}
}
struct Ripple {
std::shared_ptr<Playlist> playlist;
timepos_t position;
timecnt_t length;
Ripple (std::shared_ptr<Playlist> pl, timepos_t const & pos, timecnt_t const & len) : playlist (pl), position (pos), length (len) {}
};
std::vector<Ripple> ripple_list;
for (RegionSelection::iterator x = rs.begin(); x != rs.end(); ) {
std::shared_ptr<Playlist> pl = (*x)->region()->playlist();
@ -4981,7 +4991,7 @@ Editor::cut_copy_regions (CutCopyOp op, RegionSelection& rs)
case Delete:
pl->remove_region (r);
if (should_ripple()) {
do_ripple (pl, r->position(), -r->length(), &exclude, freezelist, false);
ripple_list.push_back (Ripple (pl, r->position(), -r->length()));
}
break;
@ -4990,7 +5000,7 @@ Editor::cut_copy_regions (CutCopyOp op, RegionSelection& rs)
npl->add_region (_xx, timepos_t (first_position.distance (r->position())));
pl->remove_region (r);
if (should_ripple()) {
do_ripple (pl, r->position(), -r->length(), &exclude, freezelist, false);
ripple_list.push_back (Ripple (pl, r->position(), -r->length()));
}
break;
@ -5002,7 +5012,7 @@ Editor::cut_copy_regions (CutCopyOp op, RegionSelection& rs)
case Clear:
pl->remove_region (r);
if (should_ripple()) {
do_ripple (pl, r->position(), -r->length(), &exclude, freezelist, false);
ripple_list.push_back (Ripple (pl, r->position(), -r->length()));
}
break;
}
@ -5010,6 +5020,23 @@ Editor::cut_copy_regions (CutCopyOp op, RegionSelection& rs)
x = tmp;
}
if (!ripple_list.empty()) {
/* The regions were sorted into (track, position) order. We
* need to run the rippling in reverse order, so that later
* cut/delete operations cause rippling further down the
* timeline and then work towards zero.
*/
std::reverse (ripple_list.begin(), ripple_list.end());
for (auto const & ripple : ripple_list) {
do_ripple (ripple.playlist, ripple.position, ripple.length, nullptr, freezelist, false);
}
ripple_list.clear ();
}
if (op != Delete) {
list<std::shared_ptr<Playlist> > foo;