1
0
mirror of https://github.com/cookiengineer/audacity synced 2025-09-16 16:20:50 +02:00

Detect failure to reconnect to temp project when first saving it

This commit is contained in:
Paul Licameli 2020-12-06 22:14:54 -05:00
parent 41eb66fccf
commit aa0b33dc8f
5 changed files with 62 additions and 15 deletions

View File

@ -44,6 +44,7 @@ Paul Licameli split from AudacityProject.cpp
wxDEFINE_EVENT(EVT_PROJECT_TITLE_CHANGE, wxCommandEvent); wxDEFINE_EVENT(EVT_PROJECT_TITLE_CHANGE, wxCommandEvent);
wxDEFINE_EVENT( EVT_CHECKPOINT_FAILURE, wxCommandEvent); wxDEFINE_EVENT( EVT_CHECKPOINT_FAILURE, wxCommandEvent);
wxDEFINE_EVENT( EVT_RECONNECTION_FAILURE, wxCommandEvent);
static const int ProjectFileID = ('A' << 24 | 'U' << 16 | 'D' << 8 | 'Y'); static const int ProjectFileID = ('A' << 24 | 'U' << 16 | 'D' << 8 | 'Y');
static const int ProjectFileVersion = 1; static const int ProjectFileVersion = 1;
@ -263,6 +264,12 @@ ProjectFileIO::~ProjectFileIO()
{ {
} }
bool ProjectFileIO::HasConnection() const
{
auto &connectionPtr = ConnectionPtr::Get( mProject );
return connectionPtr.mpConnection != nullptr;
}
DBConnection &ProjectFileIO::GetConnection() DBConnection &ProjectFileIO::GetConnection()
{ {
auto &curConn = CurrConn(); auto &curConn = CurrConn();
@ -2045,20 +2052,38 @@ bool ProjectFileIO::SaveProject(
FilePath savedName = mFileName; FilePath savedName = mFileName;
if (CloseConnection()) if (CloseConnection())
{ {
if (MoveProject(savedName, fileName)) bool reopened = false;
bool moved = false;
if (true == (moved = MoveProject(savedName, fileName)))
{ {
if (!OpenConnection(fileName)) if (OpenConnection(fileName))
{ reopened = true;
else {
MoveProject(fileName, savedName); MoveProject(fileName, savedName);
OpenConnection(savedName); reopened = OpenConnection(savedName);
} }
} }
else { else {
// Rename can fail -- if it's to a different device, requiring // Rename can fail -- if it's to a different device, requiring
// real copy of contents, which might exhaust space // real copy of contents, which might exhaust space
OpenConnection(savedName); reopened = OpenConnection(savedName);
return false;
} }
if (!reopened)
wxTheApp->CallAfter([this]{
ShowErrorDialog(nullptr,
XO("Warning"),
XO(
"The project's database failed to reopen, "
"possibly because of limited space on the storage device."),
"Error:_Disk_full_or_not_writable"
);
wxCommandEvent evt{ EVT_RECONNECTION_FAILURE };
mProject.ProcessEvent(evt);
});
if (!moved)
return false;
} }
} }

View File

@ -45,6 +45,11 @@ using BlockIDs = std::unordered_set<SampleBlockID>;
wxDECLARE_EXPORTED_EVENT( AUDACITY_DLL_API, wxDECLARE_EXPORTED_EVENT( AUDACITY_DLL_API,
EVT_CHECKPOINT_FAILURE, wxCommandEvent ); EVT_CHECKPOINT_FAILURE, wxCommandEvent );
// An event processed by the project in the main thread after failure to
// reconnect to the database, after temporary close and attempted file movement
wxDECLARE_EXPORTED_EVENT( AUDACITY_DLL_API,
EVT_RECONNECTION_FAILURE, wxCommandEvent );
///\brief Object associated with a project that manages reading and writing ///\brief Object associated with a project that manages reading and writing
/// of Audacity project file formats, and autosave /// of Audacity project file formats, and autosave
class ProjectFileIO final class ProjectFileIO final
@ -179,6 +184,10 @@ public:
// 0 for success or non-zero to stop the query // 0 for success or non-zero to stop the query
using ExecCB = std::function<int(int cols, char **vals, char **names)>; using ExecCB = std::function<int(int cols, char **vals, char **names)>;
//! Return true if a connetion is now open
bool HasConnection() const;
//! Return a reference to a connection, creating it as needed on demand; throw on failure
DBConnection &GetConnection(); DBConnection &GetConnection();
private: private:

View File

@ -302,15 +302,17 @@ bool ProjectFileManager::DoSave(const FilePath & fileName, const bool fromSaveAs
bool success = projectFileIO.SaveProject(fileName, mLastSavedTracks.get()); bool success = projectFileIO.SaveProject(fileName, mLastSavedTracks.get());
if (!success) if (!success)
{ {
ShowErrorDialog( // Show this error only if we didn't fail reconnection in SaveProject
&window, if (projectFileIO.HasConnection())
XO("Error Saving Project"), ShowErrorDialog(
XO("Could not save project. Perhaps %s \n" &window,
"is not writable or the disk is full.\n" XO("Error Saving Project"),
"For tips on freeing up space, click the help button.") XO("Could not save project. Perhaps %s \n"
.Format(fileName), "is not writable or the disk is full.\n"
"Error:_Disk_full_or_not_writable" "For tips on freeing up space, click the help button.")
); .Format(fileName),
"Error:_Disk_full_or_not_writable"
);
return false; return false;
} }

View File

@ -82,6 +82,8 @@ ProjectManager::ProjectManager( AudacityProject &project )
window.Bind( wxEVT_CLOSE_WINDOW, &ProjectManager::OnCloseWindow, this ); window.Bind( wxEVT_CLOSE_WINDOW, &ProjectManager::OnCloseWindow, this );
mProject.Bind(EVT_PROJECT_STATUS_UPDATE, mProject.Bind(EVT_PROJECT_STATUS_UPDATE,
&ProjectManager::OnStatusChange, this); &ProjectManager::OnStatusChange, this);
project.Bind( EVT_RECONNECTION_FAILURE,
&ProjectManager::OnReconnectionFailure, this );
} }
ProjectManager::~ProjectManager() = default; ProjectManager::~ProjectManager() = default;
@ -589,6 +591,14 @@ AudacityProject *ProjectManager::New()
return p; return p;
} }
void ProjectManager::OnReconnectionFailure(wxCommandEvent & event)
{
event.Skip();
wxTheApp->CallAfter([this]{
ProjectWindow::Get(mProject).Close(true);
});
}
void ProjectManager::OnCloseWindow(wxCloseEvent & event) void ProjectManager::OnCloseWindow(wxCloseEvent & event)
{ {
auto &project = mProject; auto &project = mProject;

View File

@ -65,6 +65,7 @@ public:
void SetSkipSavePrompt(bool bSkip) { sbSkipPromptingForSave = bSkip; }; void SetSkipSavePrompt(bool bSkip) { sbSkipPromptingForSave = bSkip; };
private: private:
void OnReconnectionFailure(wxCommandEvent & event);
void OnCloseWindow(wxCloseEvent & event); void OnCloseWindow(wxCloseEvent & event);
void OnTimer(wxTimerEvent & event); void OnTimer(wxTimerEvent & event);
void OnOpenAudioFile(wxCommandEvent & event); void OnOpenAudioFile(wxCommandEvent & event);