1
0
mirror of https://github.com/cookiengineer/audacity synced 2025-08-01 08:29:27 +02:00

Bug 2700 - "Failed to open the project database"

This commit is contained in:
Leland Lucius 2021-04-01 01:13:15 -05:00
parent 1ee130a92f
commit 392a060389
9 changed files with 124 additions and 38 deletions

View File

@ -31,6 +31,7 @@ Provides thread-safe logging based on the wxWidgets log facility.
#include <wx/icon.h> #include <wx/icon.h>
#include <wx/settings.h> #include <wx/settings.h>
#include <wx/textctrl.h> #include <wx/textctrl.h>
#include <wx/tokenzr.h>
#include "../images/AudacityLogoAlpha.xpm" #include "../images/AudacityLogoAlpha.xpm"
#include "widgets/AudacityMessageBox.h" #include "widgets/AudacityMessageBox.h"
@ -237,12 +238,23 @@ void AudacityLogger::Show(bool show)
Flush(); Flush();
} }
#if defined(EXPERIMENTAL_CRASH_REPORT) wxString AudacityLogger::GetLog(int count)
wxString AudacityLogger::GetLog()
{ {
return mBuffer; if (count == 0)
{
return mBuffer;
}
wxString buffer;
auto lines = wxStringTokenize(mBuffer, wxT("\r\n"), wxTOKEN_RET_DELIMS);
for (int index = lines.size() - 1; index >= 0 && count > 0; --index, --count)
{
buffer.Prepend(lines[index]);
}
return buffer;
} }
#endif
void AudacityLogger::OnCloseWindow(wxCloseEvent & WXUNUSED(e)) void AudacityLogger::OnCloseWindow(wxCloseEvent & WXUNUSED(e))
{ {

View File

@ -40,9 +40,7 @@ class AudacityLogger final : public wxEvtHandler,
bool SaveLog(const wxString &fileName) const; bool SaveLog(const wxString &fileName) const;
bool ClearLog(); bool ClearLog();
#if defined(EXPERIMENTAL_CRASH_REPORT) wxString GetLog(int count = 0);
wxString GetLog();
#endif
protected: protected:
void Flush() override; void Flush() override;

View File

@ -16,6 +16,7 @@ Paul Licameli -- split from ProjectFileIO.cpp
#include <wx/progdlg.h> #include <wx/progdlg.h>
#include <wx/string.h> #include <wx/string.h>
#include "AudacityLogger.h"
#include "FileNames.h" #include "FileNames.h"
#include "Internat.h" #include "Internat.h"
#include "Project.h" #include "Project.h"
@ -66,13 +67,23 @@ void DBConnection::SetError(
const TranslatableString &msg, const TranslatableString &libraryError, int errorCode) const TranslatableString &msg, const TranslatableString &libraryError, int errorCode)
{ {
wxLogMessage(wxT("Connection msg: %s"), msg.Debug()); wxLogMessage(wxT("Connection msg: %s"), msg.Debug());
printf("Connection msg: %s", msg.Debug().mb_str().data());
if (!libraryError.empty()) if (!libraryError.empty())
{
wxLogMessage(wxT("Connection error: %s"), libraryError.Debug()); wxLogMessage(wxT("Connection error: %s"), libraryError.Debug());
printf("Connection error: %s", libraryError.Debug().mb_str().data());
}
mpErrors->mLastError = msg; mpErrors->mLastError = msg;
mpErrors->mLibraryError = libraryError; mpErrors->mLibraryError = libraryError;
mpErrors->mErrorCode = errorCode; mpErrors->mErrorCode = errorCode;
auto logger = AudacityLogger::Get();
if (logger)
{
mpErrors->mLog = logger->GetLog(10);
}
} }
void DBConnection::SetDBError( void DBConnection::SetDBError(
@ -96,6 +107,12 @@ void DBConnection::SetDBError(
wxLogMessage(wxT(" Lib error: %s"), mpErrors->mLibraryError.Debug()); wxLogMessage(wxT(" Lib error: %s"), mpErrors->mLibraryError.Debug());
printf(" Lib error: %s", mpErrors->mLibraryError.Debug().mb_str().data()); printf(" Lib error: %s", mpErrors->mLibraryError.Debug().mb_str().data());
auto logger = AudacityLogger::Get();
if (logger)
{
mpErrors->mLog = logger->GetLog(10);
}
} }
bool DBConnection::Open(const FilePath fileName) bool DBConnection::Open(const FilePath fileName)

View File

@ -32,6 +32,7 @@ struct DBConnectionErrors
TranslatableString mLastError; TranslatableString mLastError;
TranslatableString mLibraryError; TranslatableString mLibraryError;
int mErrorCode { 0 }; int mErrorCode { 0 };
wxString mLog;
}; };
class DBConnection class DBConnection

View File

@ -1132,7 +1132,7 @@ bool ProjectFileIO::RenameOrWarn(const FilePath &src, const FilePath &dst)
if (!success) if (!success)
{ {
ShowErrorDialog( ShowError(
&window, &window,
XO("Error Writing to File"), XO("Error Writing to File"),
XO("Audacity failed to write file %s.\n" XO("Audacity failed to write file %s.\n"
@ -1538,7 +1538,7 @@ bool ProjectFileIO::HandleXMLTag(const wxChar *tag, const wxChar **attrs)
auto msg = XO("This file was saved using Audacity %s.\nYou are using Audacity %s. You may need to upgrade to a newer version to open this file.") auto msg = XO("This file was saved using Audacity %s.\nYou are using Audacity %s. You may need to upgrade to a newer version to open this file.")
.Format(audacityVersion, AUDACITY_VERSION_STRING); .Format(audacityVersion, AUDACITY_VERSION_STRING);
ShowErrorDialog( ShowError(
&window, &window,
XO("Can't open project file"), XO("Can't open project file"),
msg, msg,
@ -1926,7 +1926,7 @@ bool ProjectFileIO::SaveProject(
if (!reopened) { if (!reopened) {
wxTheApp->CallAfter([this]{ wxTheApp->CallAfter([this]{
ShowErrorDialog(nullptr, ShowError(nullptr,
XO("Warning"), XO("Warning"),
XO( XO(
"The project's database failed to reopen, " "The project's database failed to reopen, "
@ -1950,7 +1950,7 @@ bool ProjectFileIO::SaveProject(
// after we switch to the new file. // after we switch to the new file.
if (!CopyTo(fileName, XO("Saving project"), false)) if (!CopyTo(fileName, XO("Saving project"), false))
{ {
ShowErrorDialog( ShowError(
nullptr, nullptr,
XO("Error Saving Project"), XO("Error Saving Project"),
FileException::WriteFailureMessage(fileName), FileException::WriteFailureMessage(fileName),
@ -2001,7 +2001,7 @@ bool ProjectFileIO::SaveProject(
if (!success) if (!success)
{ {
// Additional help via a Help button links to the manual. // Additional help via a Help button links to the manual.
ShowErrorDialog(nullptr, ShowError(nullptr,
XO("Error Saving Project"), XO("Error Saving Project"),
XO("The project failed to open, possibly due to limited space\n" XO("The project failed to open, possibly due to limited space\n"
"on the storage device.\n\n%s").Format(GetLastError()), "on the storage device.\n\n%s").Format(GetLastError()),
@ -2020,7 +2020,7 @@ bool ProjectFileIO::SaveProject(
if (!AutoSaveDelete()) if (!AutoSaveDelete())
{ {
// Additional help via a Help button links to the manual. // Additional help via a Help button links to the manual.
ShowErrorDialog(nullptr, ShowError(nullptr,
XO("Error Saving Project"), XO("Error Saving Project"),
XO("Unable to remove autosave information, possibly due to limited space\n" XO("Unable to remove autosave information, possibly due to limited space\n"
"on the storage device.\n\n%s").Format(GetLastError()), "on the storage device.\n\n%s").Format(GetLastError()),
@ -2059,7 +2059,7 @@ bool ProjectFileIO::SaveProject(
else else
{ {
if ( !UpdateSaved( nullptr ) ) { if ( !UpdateSaved( nullptr ) ) {
ShowErrorDialog( ShowError(
nullptr, nullptr,
XO("Error Saving Project"), XO("Error Saving Project"),
FileException::WriteFailureMessage(fileName), FileException::WriteFailureMessage(fileName),
@ -2182,6 +2182,15 @@ wxLongLong ProjectFileIO::GetFreeDiskSpace() const
return -1; return -1;
} }
/// Displays an error dialog with a button that offers help
void ProjectFileIO::ShowError(wxWindow *parent,
const TranslatableString &dlogTitle,
const TranslatableString &message,
const wxString &helpPage)
{
ShowErrorDialog(parent, dlogTitle, message, helpPage, true, GetLastLog());
}
const TranslatableString &ProjectFileIO::GetLastError() const const TranslatableString &ProjectFileIO::GetLastError() const
{ {
return mpErrors->mLastError; return mpErrors->mLastError;
@ -2197,6 +2206,11 @@ int ProjectFileIO::GetLastErrorCode() const
return mpErrors->mErrorCode; return mpErrors->mErrorCode;
} }
const wxString &ProjectFileIO::GetLastLog() const
{
return mpErrors->mLog;
}
void ProjectFileIO::SetError( void ProjectFileIO::SetError(
const TranslatableString& msg, const TranslatableString& libraryError, int errorCode) const TranslatableString& msg, const TranslatableString& libraryError, int errorCode)
{ {

View File

@ -114,9 +114,15 @@ public:
// specific database. This is the workhorse for the above 3 methods. // specific database. This is the workhorse for the above 3 methods.
static int64_t GetDiskUsage(DBConnection &conn, SampleBlockID blockid); static int64_t GetDiskUsage(DBConnection &conn, SampleBlockID blockid);
// Displays an error dialog with a button that offers help
void ShowError(wxWindow *parent,
const TranslatableString &dlogTitle,
const TranslatableString &message,
const wxString &helpPage);
const TranslatableString &GetLastError() const; const TranslatableString &GetLastError() const;
const TranslatableString &GetLibraryError() const; const TranslatableString &GetLibraryError() const;
int GetLastErrorCode() const; int GetLastErrorCode() const;
const wxString &GetLastLog() const;
// Provides a means to bypass "DELETE"s at shutdown if the database // Provides a means to bypass "DELETE"s at shutdown if the database
// is just going to be deleted anyway. This prevents a noticeable // is just going to be deleted anyway. This prevents a noticeable

View File

@ -1021,7 +1021,7 @@ void ProjectFileManager::OpenFile(const FilePath &fileNameArg, bool addtohistory
wxLogError(wxT("Could not parse file \"%s\". \nError: %s"), fileName, errorStr.Debug()); wxLogError(wxT("Could not parse file \"%s\". \nError: %s"), fileName, errorStr.Debug());
ShowErrorDialog( projectFileIO.ShowError(
&window, &window,
XO("Error Opening Project"), XO("Error Opening Project"),
errorStr, errorStr,

View File

@ -19,6 +19,7 @@
#include <wx/app.h> #include <wx/app.h>
#include <wx/button.h> #include <wx/button.h>
#include <wx/collpane.h>
#include <wx/icon.h> #include <wx/icon.h>
#include <wx/dialog.h> #include <wx/dialog.h>
#include <wx/intl.h> #include <wx/intl.h>
@ -38,6 +39,7 @@
#include "HelpSystem.h" #include "HelpSystem.h"
BEGIN_EVENT_TABLE(ErrorDialog, wxDialogWrapper) BEGIN_EVENT_TABLE(ErrorDialog, wxDialogWrapper)
EVT_COLLAPSIBLEPANE_CHANGED( wxID_ANY, ErrorDialog::OnPane )
EVT_BUTTON( wxID_OK, ErrorDialog::OnOk) EVT_BUTTON( wxID_OK, ErrorDialog::OnOk)
EVT_BUTTON( wxID_HELP, ErrorDialog::OnHelp) EVT_BUTTON( wxID_HELP, ErrorDialog::OnHelp)
END_EVENT_TABLE() END_EVENT_TABLE()
@ -47,8 +49,11 @@ ErrorDialog::ErrorDialog(
const TranslatableString & dlogTitle, const TranslatableString & dlogTitle,
const TranslatableString & message, const TranslatableString & message,
const wxString & helpPage, const wxString & helpPage,
const bool Close, const bool modal): const wxString & log,
wxDialogWrapper(parent, (wxWindowID)-1, dlogTitle) const bool Close, const bool modal)
: wxDialogWrapper(parent, wxID_ANY, dlogTitle,
wxDefaultPosition, wxDefaultSize,
wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER)
{ {
SetName(); SetName();
@ -62,31 +67,58 @@ ErrorDialog::ErrorDialog(
ShuttleGui S(this, eIsCreating); ShuttleGui S(this, eIsCreating);
S.StartHorizontalLay(); S.SetBorder(2);
S.StartHorizontalLay(wxEXPAND, 0);
{ {
// wxART_ERROR and wxART_INFORMATION are other possibilities. S.SetBorder(20);
// S.AddIcon( &wxArtProvider::GetBitmap( wxART_WARNING));
S.SetBorder( 20 );
wxBitmap bitmap = wxArtProvider::GetBitmap(wxART_WARNING); wxBitmap bitmap = wxArtProvider::GetBitmap(wxART_WARNING);
auto icon = safenew wxStaticBitmap(S.GetParent(), -1, bitmap); S.AddWindow(safenew wxStaticBitmap(S.GetParent(), -1, bitmap));
S.AddWindow( icon );
S.StartVerticalLay(); S.SetBorder(20);
{ S.AddFixedText(message, false, 500);
S.SetBorder(20);
S.AddFixedText(message, false, 500);
S.SetBorder(2);
S.AddStandardButtons(buttonMask);
}
S.EndVerticalLay();
} }
S.EndHorizontalLay(); S.EndHorizontalLay();
S.SetBorder(2);
if (!log.empty())
{
S.StartHorizontalLay(wxEXPAND, 1);
{
S.SetBorder(5);
auto pane = safenew wxCollapsiblePane(S.GetParent(),
wxID_ANY,
XO("Show &Log...").Translation());
S.Style(wxEXPAND | wxALIGN_LEFT);
S.Prop(1);
S.AddWindow(pane);
ShuttleGui SI(pane->GetPane(), eIsCreating);
auto text = SI.AddTextWindow(log);
text->SetInsertionPointEnd();
text->ShowPosition(text->GetLastPosition());
text->SetMinSize(wxSize(700, 250));
}
S.EndHorizontalLay();
}
S.SetBorder(2);
S.AddStandardButtons(buttonMask);
Layout(); Layout();
GetSizer()->Fit(this); GetSizer()->Fit(this);
SetMinSize(GetSize()); SetMinSize(GetSize());
Center(); Center();
} }
void ErrorDialog::OnPane(wxCollapsiblePaneEvent & event)
{
if (!event.GetCollapsed())
{
Center();
}
}
void ErrorDialog::OnOk(wxCommandEvent & WXUNUSED(event)) void ErrorDialog::OnOk(wxCommandEvent & WXUNUSED(event))
{ {
if (dModal) if (dModal)
@ -95,7 +127,6 @@ void ErrorDialog::OnOk(wxCommandEvent & WXUNUSED(event))
Destroy(); Destroy();
} }
void ErrorDialog::OnHelp(wxCommandEvent & WXUNUSED(event)) void ErrorDialog::OnHelp(wxCommandEvent & WXUNUSED(event))
{ {
if( dhelpPage.StartsWith(wxT("innerlink:")) ) if( dhelpPage.StartsWith(wxT("innerlink:")) )
@ -118,9 +149,10 @@ void ShowErrorDialog(wxWindow *parent,
const TranslatableString &dlogTitle, const TranslatableString &dlogTitle,
const TranslatableString &message, const TranslatableString &message,
const wxString &helpPage, const wxString &helpPage,
const bool Close) const bool Close,
const wxString &log)
{ {
ErrorDialog dlog(parent, dlogTitle, message, helpPage, Close); ErrorDialog dlog(parent, dlogTitle, message, helpPage, log, Close);
dlog.CentreOnParent(); dlog.CentreOnParent();
dlog.ShowModal(); dlog.ShowModal();
} }
@ -131,13 +163,14 @@ void ShowModelessErrorDialog(wxWindow *parent,
const TranslatableString &dlogTitle, const TranslatableString &dlogTitle,
const TranslatableString &message, const TranslatableString &message,
const wxString &helpPage, const wxString &helpPage,
const bool Close) const bool Close,
const wxString &log)
{ {
// ensure it has some parent. // ensure it has some parent.
if( !parent ) if( !parent )
parent = wxTheApp->GetTopWindow(); parent = wxTheApp->GetTopWindow();
wxASSERT(parent); wxASSERT(parent);
ErrorDialog *dlog = safenew ErrorDialog(parent, dlogTitle, message, helpPage, Close, false); ErrorDialog *dlog = safenew ErrorDialog(parent, dlogTitle, message, helpPage, log, Close, false);
dlog->CentreOnParent(); dlog->CentreOnParent();
dlog->Show(); dlog->Show();
// ANSWER-ME: Vigilant Sentry flagged this method as not deleting dlog, so // ANSWER-ME: Vigilant Sentry flagged this method as not deleting dlog, so

View File

@ -19,6 +19,7 @@
#include "wxPanelWrapper.h" // to inherit #include "wxPanelWrapper.h" // to inherit
class AudacityProject; class AudacityProject;
class wxCollapsiblePaneEvent;
class ErrorDialog /* not final */ : public wxDialogWrapper class ErrorDialog /* not final */ : public wxDialogWrapper
{ {
@ -28,6 +29,7 @@ public:
const TranslatableString & dlogTitle, const TranslatableString & dlogTitle,
const TranslatableString & message, const TranslatableString & message,
const wxString & helpPage, const wxString & helpPage,
const wxString & log,
const bool Close = true, const bool modal = true); const bool Close = true, const bool modal = true);
virtual ~ErrorDialog(){} virtual ~ErrorDialog(){}
@ -37,6 +39,7 @@ private:
bool dClose; bool dClose;
bool dModal; bool dModal;
void OnPane( wxCollapsiblePaneEvent &event );
void OnOk( wxCommandEvent &event ); void OnOk( wxCommandEvent &event );
void OnHelp( wxCommandEvent &event ); void OnHelp( wxCommandEvent &event );
DECLARE_EVENT_TABLE() DECLARE_EVENT_TABLE()
@ -47,14 +50,16 @@ void ShowErrorDialog(wxWindow *parent,
const TranslatableString &dlogTitle, const TranslatableString &dlogTitle,
const TranslatableString &message, const TranslatableString &message,
const wxString &helpPage, const wxString &helpPage,
bool Close = true); bool Close = true,
const wxString &log = {});
/// Displays a modeless error dialog with a button that offers help /// Displays a modeless error dialog with a button that offers help
void ShowModelessErrorDialog(wxWindow *parent, void ShowModelessErrorDialog(wxWindow *parent,
const TranslatableString &dlogTitle, const TranslatableString &dlogTitle,
const TranslatableString &message, const TranslatableString &message,
const wxString &helpPage, const wxString &helpPage,
bool Close = true); bool Close = true,
const wxString &log = {});
#include <wx/textdlg.h> // to inherit #include <wx/textdlg.h> // to inherit