From 7edbad3cd131b115ead713482308508da8f172bc Mon Sep 17 00:00:00 2001 From: Paul Licameli Date: Wed, 18 Nov 2020 15:01:02 -0500 Subject: [PATCH] Bug2570 residual: Compact should not change last saved state... ... So that if you save, edit, compact, close without saving, then reopen, you recover the saved state as expected, not the compacted state. Implications: Do not push an undo state for compaction. Discard redo states instead. Do not purge undo states after the last saved. The database still needs them. So we might reclaim less space than before. --- src/ProjectFileManager.cpp | 38 +++++++++++++++++++------------------- src/UndoManager.cpp | 19 ++++++++++++++----- src/UndoManager.h | 2 ++ 3 files changed, 35 insertions(+), 24 deletions(-) diff --git a/src/ProjectFileManager.cpp b/src/ProjectFileManager.cpp index 2c5c63454..d2a122125 100644 --- a/src/ProjectFileManager.cpp +++ b/src/ProjectFileManager.cpp @@ -1231,15 +1231,23 @@ void ProjectFileManager::Compact() // Purpose of this is to remove the -wal file. projectFileIO.ReopenProject(); - auto currentTracks = TrackList::Create( nullptr ); - auto &tracks = TrackList::Get( project ); - for (auto t : tracks.Any()) - { - currentTracks->Add(t->Duplicate()); + auto savedState = undoManager.GetSavedState(); + if (savedState < 0) { + undoManager.StateSaved(); + savedState = undoManager.GetSavedState(); + if (savedState < 0) { + wxASSERT(false); + savedState = 0; + } } + std::vector trackLists; + undoManager.VisitStates( + [&](auto& elem){ trackLists.push_back(elem.state.tracks.get()); }, + savedState, + undoManager.GetCurrentState() + 1); int64_t total = projectFileIO.GetTotalUsage(); - int64_t used = projectFileIO.GetCurrentUsage({currentTracks.get()}); + int64_t used = projectFileIO.GetCurrentUsage(trackLists); auto before = wxFileName::GetSize(projectFileIO.GetFileName()); @@ -1256,27 +1264,21 @@ void ProjectFileManager::Compact() Internat::FormatSize(total - used))); if (isBatch || dlg.ShowModal() == wxYES) { - // Want to do this before removing the states so that it becomes the - // current state. - ProjectHistory::Get(project) - .PushState(XO("Compacted project file"), XO("Compact"), UndoPush::CONSOLIDATE); + // We can remove redo states. + undoManager.AbandonRedo(); - // Now we can remove all previous states. - auto numStates = undoManager.GetNumStates(); - undoManager.RemoveStates(0, numStates - 1); + // We can remove all states before the last saved. + undoManager.RemoveStates(0, savedState); // And clear the clipboard, if needed if (&mProject == clipboard.Project().lock().get()) clipboard.Clear(); - // This may also decrease some reference counts on blocks - mLastSavedTracks.reset(); - // Refresh the before space usage since it may have changed due to the // above actions. auto before = wxFileName::GetSize(projectFileIO.GetFileName()); - projectFileIO.Compact( { currentTracks.get() }, true); + projectFileIO.Compact(trackLists, true); auto after = wxFileName::GetSize(projectFileIO.GetFileName()); @@ -1288,6 +1290,4 @@ void ProjectFileManager::Compact() XO("Compact Project")); } } - - mLastSavedTracks = currentTracks; } diff --git a/src/UndoManager.cpp b/src/UndoManager.cpp index b9c4b2bf9..61f899083 100644 --- a/src/UndoManager.cpp +++ b/src/UndoManager.cpp @@ -321,11 +321,7 @@ void UndoManager::PushState(const TrackList * l, mayConsolidate = true; - // Abandon redo states - if (saved >= current) { - saved = -1; - } - RemoveStates( current + 1, stack.size() ); + AbandonRedo(); // Assume tags was duplicated before any changes. // Just save a NEW shared_ptr to it. @@ -343,6 +339,14 @@ void UndoManager::PushState(const TrackList * l, mProject.QueueEvent( safenew wxCommandEvent{ EVT_UNDO_PUSHED } ); } +void UndoManager::AbandonRedo() +{ + if (saved > current) { + saved = -1; + } + RemoveStates( current + 1, stack.size() ); +} + void UndoManager::SetStateTo(unsigned int n, const Consumer &consumer) { wxASSERT(n < stack.size()); @@ -438,6 +442,11 @@ void UndoManager::StateSaved() saved = current; } +int UndoManager::GetSavedState() const +{ + return saved; +} + // currently unused //void UndoManager::Debug() //{ diff --git a/src/UndoManager.h b/src/UndoManager.h index 9a1c57148..841d5788e 100644 --- a/src/UndoManager.h +++ b/src/UndoManager.h @@ -148,6 +148,7 @@ class AUDACITY_DLL_API UndoManager final UndoPush flags = UndoPush::NONE); void ModifyState(const TrackList * l, const SelectedRegion &selectedRegion, const std::shared_ptr &tags); + void AbandonRedo(); void ClearStates(); void RemoveStates( size_t begin, //!< inclusive start of range @@ -183,6 +184,7 @@ class AUDACITY_DLL_API UndoManager final bool RedoAvailable(); bool UnsavedChanges() const; + int GetSavedState() const; void StateSaved(); // Return value must first be calculated by CalculateSpaceUsage():