From 14c300c672957becf0dd8ab68ca4ef7e91811eae Mon Sep 17 00:00:00 2001 From: Paul Licameli Date: Thu, 19 Nov 2020 13:01:52 -0500 Subject: [PATCH] Bug2542: Discard button of auto recovery should work with UP --- src/AutoRecoveryDialog.cpp | 58 ++++++++++++++++++++++++++++++-------- src/ProjectFileIO.cpp | 5 ++-- src/ProjectFileIO.h | 2 +- src/ProjectFileManager.cpp | 26 ++++++++++++++--- src/ProjectFileManager.h | 6 +++- 5 files changed, 78 insertions(+), 19 deletions(-) diff --git a/src/AutoRecoveryDialog.cpp b/src/AutoRecoveryDialog.cpp index 3dbd41e64..dafb2001f 100644 --- a/src/AutoRecoveryDialog.cpp +++ b/src/AutoRecoveryDialog.cpp @@ -14,6 +14,7 @@ Paul Licameli split from AutoRecovery.cpp #include "FileNames.h" #include "ProjectManager.h" #include "ProjectFileIO.h" +#include "ProjectFileManager.h" #include "ShuttleGui.h" #include "widgets/AudacityMessageBox.h" #include "widgets/wxPanelWrapper.h" @@ -235,18 +236,36 @@ void AutoRecoveryDialog::OnDiscardSelected(wxCommandEvent &WXUNUSED(evt)) return; } - int ret = AudacityMessageBox( - XO("Are you sure you want to discard the selected projects?\n\n" - "Choosing \"Yes\" permanently deletes the selected projects immediately."), - XO("Automatic Crash Recovery"), - wxICON_QUESTION | wxYES_NO | wxNO_DEFAULT, this); - - if (ret == wxNO) + long item = -1; + bool selectedTemporary = false; + while (!selectedTemporary) { - return; + item = mFileList->GetNextItem(item, wxLIST_NEXT_ALL, wxLIST_STATE_DONTCARE); + if (item == wxNOT_FOUND) + break; + if (!mFileList->IsItemChecked(item)) + continue; + FilePath fileName = mFiles[item]; + wxFileName file(fileName); + if (file.GetExt().IsSameAs(FileNames::UnsavedProjectExtension())) + selectedTemporary = true; } - long item = -1; + // Don't give this warning message if all of the checked items are + // previously saved, non-temporary projects. + if (selectedTemporary) { + int ret = AudacityMessageBox( + XO("Are you sure you want to discard the selected projects?\n\n" + "Choosing \"Yes\" permanently deletes the selected projects immediately."), + XO("Automatic Crash Recovery"), + wxICON_QUESTION | wxYES_NO | wxNO_DEFAULT, this); + + if (ret == wxNO) + return; + } + + item = -1; + FilePaths files; while (true) { item = mFileList->GetNextItem(item, wxLIST_NEXT_ALL, wxLIST_STATE_DONTCARE); @@ -288,6 +307,10 @@ void AutoRecoveryDialog::OnDiscardSelected(wxCommandEvent &WXUNUSED(evt)) } } } + else + // Don't remove from disk, but do (later) open the database + // of this saved file, and discard edits + files.push_back(fileName); // Forget all about it ActiveProjects::Remove(fileName); @@ -295,6 +318,8 @@ void AutoRecoveryDialog::OnDiscardSelected(wxCommandEvent &WXUNUSED(evt)) PopulateList(); + mFiles = files; + if (mFileList->GetItemCount() == 0) { EndModal(ID_DISCARD_SELECTED); @@ -409,7 +434,7 @@ static bool RecoverAllProjects(const FilePaths &files, // Open a project window for each auto save file wxString filename; - for (int i = 0, cnt = files.size(); i < cnt; ++i) + for (auto &file: files) { AudacityProject *proj = nullptr; if (*pproj) @@ -420,7 +445,7 @@ static bool RecoverAllProjects(const FilePaths &files, } // Open project. - if (ProjectManager::OpenProject(proj, files[i], false) == nullptr) + if (ProjectManager::OpenProject(proj, file, false) == nullptr) { return false; } @@ -429,6 +454,13 @@ static bool RecoverAllProjects(const FilePaths &files, return true; } +static void DiscardAllProjects(const FilePaths &files) +{ + // Open and close each file, invisibly, removing its Autosave blob + for (auto &file: files) + ProjectFileManager::DiscardAutosave(file); +} + bool ShowAutoRecoveryDialogIfNeeded(AudacityProject **pproj, bool *didRecoverAnything) { if (didRecoverAnything) @@ -461,7 +493,11 @@ bool ShowAutoRecoveryDialogIfNeeded(AudacityProject **pproj, bool *didRecoverAny switch (ret) { case ID_SKIP: + success = true; + break; + case ID_DISCARD_SELECTED: + DiscardAllProjects(dialog.GetRecoverables()); success = true; break; diff --git a/src/ProjectFileIO.cpp b/src/ProjectFileIO.cpp index 3a1f4b4b7..1c6e3e2fd 100644 --- a/src/ProjectFileIO.cpp +++ b/src/ProjectFileIO.cpp @@ -1723,7 +1723,7 @@ bool ProjectFileIO::ImportProject(const FilePath &fileName) return true; } -bool ProjectFileIO::LoadProject(const FilePath &fileName) +bool ProjectFileIO::LoadProject(const FilePath &fileName, bool ignoreAutosave) { bool success = false; @@ -1748,7 +1748,8 @@ bool ProjectFileIO::LoadProject(const FilePath &fileName) bool usedAutosave = true; // Get the autosave doc, if any - if (!GetBlob("SELECT dict || doc FROM autosave WHERE id = 1;", buffer)) + if (!ignoreAutosave && + !GetBlob("SELECT dict || doc FROM autosave WHERE id = 1;", buffer)) { // Error already set return false; diff --git a/src/ProjectFileIO.h b/src/ProjectFileIO.h index 7d151df21..d12ebf5e7 100644 --- a/src/ProjectFileIO.h +++ b/src/ProjectFileIO.h @@ -82,7 +82,7 @@ public: bool ReopenProject(); bool ImportProject(const FilePath &fileName); - bool LoadProject(const FilePath &fileName); + bool LoadProject(const FilePath &fileName, bool ignoreAutosave); bool UpdateSaved(const TrackList *tracks = nullptr); bool SaveProject(const FilePath &fileName, const TrackList *lastSaved); bool SaveCopy(const FilePath& fileName); diff --git a/src/ProjectFileManager.cpp b/src/ProjectFileManager.cpp index 0d04fb6c7..4b8168ddb 100644 --- a/src/ProjectFileManager.cpp +++ b/src/ProjectFileManager.cpp @@ -71,6 +71,22 @@ const ProjectFileManager &ProjectFileManager::Get( const AudacityProject &projec return Get( const_cast< AudacityProject & >( project ) ); } +void ProjectFileManager::DiscardAutosave(const FilePath &filename) +{ + InvisibleTemporaryProject tempProject; + auto &project = tempProject.Project(); + auto &projectFileManager = Get(project); + // Read the project, discarding autosave + projectFileManager.ReadProjectFile(filename, true); + + for (auto wt : projectFileManager.mLastSavedTracks->Any()) + wt->CloseLock(); + projectFileManager.mLastSavedTracks.reset(); + + // Side-effect on database is done, and destructor of tempProject + // closes the temporary project properly +} + ProjectFileManager::ProjectFileManager( AudacityProject &project ) : mProject{ project } { @@ -126,7 +142,8 @@ wxString FindHelpUrl( const TranslatableString &libraryError ) } -auto ProjectFileManager::ReadProjectFile( const FilePath &fileName ) +auto ProjectFileManager::ReadProjectFile( + const FilePath &fileName, bool discardAutosave ) -> ReadProjectResults { auto &project = mProject; @@ -136,14 +153,15 @@ auto ProjectFileManager::ReadProjectFile( const FilePath &fileName ) /// /// Parse project file /// - bool bParseSuccess = projectFileIO.LoadProject(fileName); + bool bParseSuccess = projectFileIO.LoadProject(fileName, discardAutosave); bool err = false; if (bParseSuccess) { - if (projectFileIO.IsRecovered()) - { + if (discardAutosave) + projectFileIO.AutoSaveDelete(); + else if (projectFileIO.IsRecovered()) { bool resaved = false; if (!projectFileIO.IsTemporary()) diff --git a/src/ProjectFileManager.h b/src/ProjectFileManager.h index 0c0392de7..2465256e0 100644 --- a/src/ProjectFileManager.h +++ b/src/ProjectFileManager.h @@ -36,6 +36,9 @@ public: static ProjectFileManager &Get( AudacityProject &project ); static const ProjectFileManager &Get( const AudacityProject &project ); + // Open and close a file, invisibly, removing its Autosave blob + static void DiscardAutosave(const FilePath &filename); + explicit ProjectFileManager( AudacityProject &project ); ProjectFileManager( const ProjectFileManager & ) PROHIBITED; ProjectFileManager &operator=( const ProjectFileManager & ) PROHIBITED; @@ -48,7 +51,8 @@ public: const TranslatableString errorString; wxString helpUrl; }; - ReadProjectResults ReadProjectFile( const FilePath &fileName ); + ReadProjectResults ReadProjectFile( + const FilePath &fileName, bool discardAutosave = false ); bool OpenProject(); void CloseProject();