Use ShowExceptionDialog when we want to show ErrorReportDialog

This commit is contained in:
Dmitry Vedenko 2021-06-08 13:40:52 +03:00 committed by Dmitry Vedenko
parent bbb9ca14a2
commit 690772ccb0
18 changed files with 61 additions and 24 deletions

View File

@ -23,8 +23,10 @@ AudacityException::~AudacityException()
wxAtomicInt sOutstandingMessages {}; wxAtomicInt sOutstandingMessages {};
MessageBoxException::MessageBoxException( const TranslatableString &caption_ ) MessageBoxException::MessageBoxException(
: caption{ caption_ } ExceptionType exceptionType_, const TranslatableString& caption_)
: caption { caption_ }
, exceptionType { exceptionType_ }
{ {
if (!caption.empty()) if (!caption.empty())
wxAtomicInc( sOutstandingMessages ); wxAtomicInc( sOutstandingMessages );
@ -42,6 +44,7 @@ MessageBoxException::MessageBoxException( const MessageBoxException& that )
caption = that.caption; caption = that.caption;
moved = that.moved; moved = that.moved;
helpUrl = that.helpUrl; helpUrl = that.helpUrl;
exceptionType = that.exceptionType;
that.moved = true; that.moved = true;
} }
@ -73,21 +76,27 @@ void MessageBoxException::DelayedHandlerAction()
// give the user no useful added information. // give the user no useful added information.
if ( wxAtomicDec( sOutstandingMessages ) == 0 ) { if ( wxAtomicDec( sOutstandingMessages ) == 0 ) {
if (ErrorHelpUrl().IsEmpty()) if (exceptionType == ExceptionType::Internal)
{
ShowExceptionDialog(
nullptr,
(caption.empty() ? AudacityMessageBoxCaptionStr() : caption),
ErrorMessage(), ErrorHelpUrl());
}
// We show BadEnvironment and BadUserAction in a similar way
else if (ErrorHelpUrl().IsEmpty())
{ {
::AudacityMessageBox( ::AudacityMessageBox(
ErrorMessage(), ErrorMessage(),
(caption.empty() ? AudacityMessageBoxCaptionStr() : caption), (caption.empty() ? AudacityMessageBoxCaptionStr() : caption),
wxICON_ERROR wxICON_ERROR);
);
} }
else else
{ {
ShowErrorDialog( ShowErrorDialog(
nullptr, nullptr,
(caption.empty() ? AudacityMessageBoxCaptionStr() : caption), (caption.empty() ? AudacityMessageBoxCaptionStr() : caption),
ErrorMessage(), ErrorMessage(), ErrorHelpUrl());
ErrorHelpUrl());
} }
} }

View File

@ -17,6 +17,14 @@
#include "Internat.h" #include "Internat.h"
//! A type of an exception
enum class ExceptionType
{
Internal, //!< Indicates internal failure from Audacity.
BadUserAction, //!< Indicates that the user performed an action that is not allowed.
BadEnvironment, //!< Indicates problems with environment, such as a full disk
};
//! Base class for exceptions specially processed by the application //! Base class for exceptions specially processed by the application
/*! Objects of this type can be thrown and caught in any thread, stored, and then used by the main /*! Objects of this type can be thrown and caught in any thread, stored, and then used by the main
thread in later idle time to explain the error condition to the user. thread in later idle time to explain the error condition to the user.
@ -57,7 +65,8 @@ class AUDACITY_DLL_API MessageBoxException /* not final */
protected: protected:
//! If default-constructed with empty caption, it makes no message box. //! If default-constructed with empty caption, it makes no message box.
explicit MessageBoxException( explicit MessageBoxException(
const TranslatableString &caption = {} //!< Shown in message box's frame; not the actual message ExceptionType exceptionType, //!< Exception type
const TranslatableString &caption //!< Shown in message box's frame; not the actual message
); );
~MessageBoxException() override; ~MessageBoxException() override;
@ -69,6 +78,8 @@ protected:
private: private:
TranslatableString caption; //!< Stored caption TranslatableString caption; //!< Stored caption
ExceptionType exceptionType; //!< Exception type
mutable bool moved { false }; //!< Whether @c *this has been the source of a copy mutable bool moved { false }; //!< Whether @c *this has been the source of a copy
protected: protected:
mutable wxString helpUrl{ "" }; mutable wxString helpUrl{ "" };
@ -80,11 +91,12 @@ class AUDACITY_DLL_API SimpleMessageBoxException /* not final */
{ {
public: public:
explicit SimpleMessageBoxException( explicit SimpleMessageBoxException(
ExceptionType exceptionType, //!< Exception type
const TranslatableString &message_, //<! Message to show const TranslatableString &message_, //<! Message to show
const TranslatableString &caption = XO("Message"), //<! Short caption in frame around message const TranslatableString &caption = XO("Message"), //<! Short caption in frame around message
const wxString &helpUrl_ = "" // Optional URL for help. const wxString &helpUrl_ = "" // Optional URL for help.
) )
: MessageBoxException{ caption } : MessageBoxException { exceptionType, caption }
, message{ message_ } , message{ message_ }
{ {
helpUrl = helpUrl_; helpUrl = helpUrl_;

View File

@ -1463,7 +1463,7 @@ void AudioIO::StartMonitoring( const AudioIOStartStreamOptions &options )
if (!success) { if (!success) {
auto msg = XO("Error opening recording device.\nError code: %s") auto msg = XO("Error opening recording device.\nError code: %s")
.Format( Get()->LastPaErrorString() ); .Format( Get()->LastPaErrorString() );
ShowErrorDialog( FindProjectFrame( mOwningProject ), ShowExceptionDialog( FindProjectFrame( mOwningProject ),
XO("Error"), msg, wxT("Error_opening_sound_device")); XO("Error"), msg, wxT("Error_opening_sound_device"));
return; return;
} }

View File

@ -494,8 +494,8 @@ void DBConnection::CheckpointThread(sqlite3 *db, const FilePath &fileName)
// Stop the audio. // Stop the audio.
GuardedCall( GuardedCall(
[&message] { [&message, rc] {
throw SimpleMessageBoxException{ throw SimpleMessageBoxException{ rc != SQLITE_FULL ? ExceptionType::Internal : ExceptionType::BadEnvironment,
message, XO("Warning"), "Error:_Disk_full_or_not_writable" }; }, message, XO("Warning"), "Error:_Disk_full_or_not_writable" }; },
SimpleGuard<void>{}, SimpleGuard<void>{},
[this](AudacityException * e) { [this](AudacityException * e) {
@ -596,7 +596,7 @@ TransactionScope::TransactionScope(
mInTrans = TransactionStart(mName); mInTrans = TransactionStart(mName);
if ( !mInTrans ) if ( !mInTrans )
// To do, improve the message // To do, improve the message
throw SimpleMessageBoxException( throw SimpleMessageBoxException( ExceptionType::Internal,
XO("Database error. Sorry, but we don't have more details."), XO("Database error. Sorry, but we don't have more details."),
XO("Warning"), XO("Warning"),
"Error:_Disk_full_or_not_writable" "Error:_Disk_full_or_not_writable"

View File

@ -32,7 +32,11 @@ public:
const TranslatableString &caption = XO("File Error"), //!< Shown in message box frame, not the main message const TranslatableString &caption = XO("File Error"), //!< Shown in message box frame, not the main message
const wxFileName &renameTarget_ = {} //!< A second file name, only for renaming failure const wxFileName &renameTarget_ = {} //!< A second file name, only for renaming failure
) )
: MessageBoxException{ caption } // DV: We consider a FileException to be internal for now.
// We used to have some odd cases related to the read-only folder in 3.0.0,
// so it is good to have a full picture here.
// In case we see to many - we will tweak this behavior in the next release.
: MessageBoxException{ ExceptionType::Internal, caption }
, cause{ cause_ }, fileName{ fileName_ }, renameTarget{ renameTarget_ } , cause{ cause_ }, fileName{ fileName_ }, renameTarget{ renameTarget_ }
{} {}

View File

@ -23,7 +23,9 @@
class AUDACITY_DLL_API InconsistencyException final : public MessageBoxException class AUDACITY_DLL_API InconsistencyException final : public MessageBoxException
{ {
public: public:
InconsistencyException() {} InconsistencyException ()
: MessageBoxException{ ExceptionType::Internal, XO ("Internal Error") }
{}
//! Don't call this directly but use @ref CONSTRUCT_INCONSISTENCY_EXCEPTION or @ref THROW_INCONSISTENCY_EXCEPTION //! Don't call this directly but use @ref CONSTRUCT_INCONSISTENCY_EXCEPTION or @ref THROW_INCONSISTENCY_EXCEPTION
explicit InconsistencyException( explicit InconsistencyException(
@ -31,8 +33,8 @@ public:
const char *f, //!< function name supplied by preprocessor const char *f, //!< function name supplied by preprocessor
unsigned l //!< line number supplied by preprocessor unsigned l //!< line number supplied by preprocessor
) )
: MessageBoxException{ XO("Internal Error") } : MessageBoxException { ExceptionType::Internal, XO("Internal Error") }
, func { fn }, file { f }, line { l } , func { fn }, file { f }, line { l }
{} {}
InconsistencyException(InconsistencyException&& that) InconsistencyException(InconsistencyException&& that)

View File

@ -264,7 +264,7 @@ int ProjectAudioManager::PlayPlayRegion(const SelectedRegion &selectedRegion,
auto &window = GetProjectFrame( mProject ); auto &window = GetProjectFrame( mProject );
window.CallAfter( [&]{ window.CallAfter( [&]{
// Show error message if stream could not be opened // Show error message if stream could not be opened
ShowErrorDialog(&window, XO("Error"), ShowExceptionDialog(&window, XO("Error"),
XO("Error opening sound device.\nTry changing the audio host, playback device and the project sample rate."), XO("Error opening sound device.\nTry changing the audio host, playback device and the project sample rate."),
wxT("Error_opening_sound_device")); wxT("Error_opening_sound_device"));
}); });
@ -757,7 +757,7 @@ bool ProjectAudioManager::DoRecord(AudacityProject &project,
// Show error message if stream could not be opened // Show error message if stream could not be opened
auto msg = XO("Error opening recording device.\nError code: %s") auto msg = XO("Error opening recording device.\nError code: %s")
.Format( gAudioIO->LastPaErrorString() ); .Format( gAudioIO->LastPaErrorString() );
ShowErrorDialog(&GetProjectFrame( mProject ), ShowExceptionDialog(&GetProjectFrame( mProject ),
XO("Error"), msg, wxT("Error_opening_sound_device")); XO("Error"), msg, wxT("Error_opening_sound_device"));
} }
} }

View File

@ -307,6 +307,7 @@ DBConnection &ProjectFileIO::GetConnection()
{ {
throw SimpleMessageBoxException throw SimpleMessageBoxException
{ {
ExceptionType::Internal,
XO("Failed to open the project's database"), XO("Failed to open the project's database"),
XO("Warning"), XO("Warning"),
"Error:_Disk_full_or_not_writable" "Error:_Disk_full_or_not_writable"

View File

@ -341,7 +341,7 @@ bool ProjectFileManager::DoSave(const FilePath & fileName, const bool fromSaveAs
// Show this error only if we didn't fail reconnection in SaveProject // Show this error only if we didn't fail reconnection in SaveProject
// REVIEW: Could HasConnection() be true but SaveProject() still have failed? // REVIEW: Could HasConnection() be true but SaveProject() still have failed?
if (!projectFileIO.HasConnection()) if (!projectFileIO.HasConnection())
ShowErrorDialog( ShowExceptionDialog(
&window, &window,
XO("Error Saving Project"), XO("Error Saving Project"),
FileException::WriteFailureMessage(fileName), FileException::WriteFailureMessage(fileName),
@ -770,7 +770,7 @@ bool ProjectFileManager::OpenNewProject()
bool bOK = OpenProject(); bool bOK = OpenProject();
if( !bOK ) if( !bOK )
{ {
ShowErrorDialog( ShowExceptionDialog(
nullptr, nullptr,
XO("Can't open new empty project"), XO("Can't open new empty project"),
XO("Error opening a new empty project"), XO("Error opening a new empty project"),

View File

@ -79,6 +79,7 @@ namespace {
{ {
if ( !projectFileIO.AutoSave() ) if ( !projectFileIO.AutoSave() )
throw SimpleMessageBoxException{ throw SimpleMessageBoxException{
ExceptionType::Internal,
XO("Automatic database backup failed."), XO("Automatic database backup failed."),
XO("Warning"), XO("Warning"),
"Error:_Disk_full_or_not_writable" "Error:_Disk_full_or_not_writable"

View File

@ -341,6 +341,7 @@ DBConnection *SqliteSampleBlock::Conn() const
if (!pConnection) { if (!pConnection) {
throw SimpleMessageBoxException throw SimpleMessageBoxException
{ {
ExceptionType::Internal,
XO("Connection to project file is null"), XO("Connection to project file is null"),
XO("Warning"), XO("Warning"),
"Error:_Disk_full_or_not_writable" "Error:_Disk_full_or_not_writable"

View File

@ -1739,6 +1739,7 @@ void WaveClip::Resample(int rate, ProgressDialog *progress)
if (error) if (error)
throw SimpleMessageBoxException{ throw SimpleMessageBoxException{
ExceptionType::Internal,
XO("Resampling failed."), XO("Resampling failed."),
XO("Warning"), XO("Warning"),
"Error:_Resampling" "Error:_Resampling"

View File

@ -1284,6 +1284,7 @@ void WaveTrack::Paste(double t0, const Track *src)
// Strong-guarantee in case of this path // Strong-guarantee in case of this path
// not that it matters. // not that it matters.
throw SimpleMessageBoxException{ throw SimpleMessageBoxException{
ExceptionType::BadUserAction,
XO("There is not enough room available to paste the selection"), XO("There is not enough room available to paste the selection"),
XO("Warning"), XO("Warning"),
"Error:_Insufficient_space_in_track" "Error:_Insufficient_space_in_track"
@ -1306,6 +1307,7 @@ void WaveTrack::Paste(double t0, const Track *src)
// Strong-guarantee in case of this path // Strong-guarantee in case of this path
// not that it matters. // not that it matters.
throw SimpleMessageBoxException{ throw SimpleMessageBoxException{
ExceptionType::BadUserAction,
XO("There is not enough room available to paste the selection"), XO("There is not enough room available to paste the selection"),
XO("Warning"), XO("Warning"),
"Error:_Insufficient_space_in_track" "Error:_Insufficient_space_in_track"
@ -2422,6 +2424,7 @@ void WaveTrack::ExpandCutLine(double cutLinePosition, double* cutlineStart,
clip->GetEndTime() + end - start > clip2->GetStartTime()) clip->GetEndTime() + end - start > clip2->GetStartTime())
// Strong-guarantee in case of this path // Strong-guarantee in case of this path
throw SimpleMessageBoxException{ throw SimpleMessageBoxException{
ExceptionType::BadUserAction,
XO("There is not enough room available to expand the cut line"), XO("There is not enough room available to expand the cut line"),
XO("Warning"), XO("Warning"),
"Error:_Insufficient_space_in_track" "Error:_Insufficient_space_in_track"

View File

@ -2468,7 +2468,7 @@ void Effect::Preview(bool dryOnly)
} }
} }
else { else {
ShowErrorDialog(FocusDialog, XO("Error"), ShowExceptionDialog(FocusDialog, XO("Error"),
XO("Error opening sound device.\nTry changing the audio host, playback device and the project sample rate."), XO("Error opening sound device.\nTry changing the audio host, playback device and the project sample rate."),
wxT("Error_opening_sound_device")); wxT("Error_opening_sound_device"));
} }

View File

@ -1519,7 +1519,7 @@ void ShowExportErrorDialog(wxString ErrorCode,
TranslatableString message, TranslatableString message,
const TranslatableString& caption) const TranslatableString& caption)
{ {
ShowErrorDialog(nullptr, ShowExceptionDialog(nullptr,
caption, caption,
message.Format( ErrorCode ), message.Format( ErrorCode ),
"Error:_Unable_to_export" // URL. "Error:_Unable_to_export" // URL.

View File

@ -210,6 +210,7 @@ static void Extract(bool bits16,
if( dataSizeIn < 1 ) if( dataSizeIn < 1 )
throw SimpleMessageBoxException{ throw SimpleMessageBoxException{
ExceptionType::BadUserAction,
XO("Bad data size. Could not import audio"), XO("Bad data size. Could not import audio"),
XO("Warning"), XO("Warning"),
"Error:_Importing_raw_audio" "Error:_Importing_raw_audio"

View File

@ -447,6 +447,7 @@ void OnPaste(const CommandContext &context)
// Throw, so that any previous changes to the project in this loop // Throw, so that any previous changes to the project in this loop
// are discarded. // are discarded.
throw SimpleMessageBoxException{ throw SimpleMessageBoxException{
ExceptionType::BadUserAction,
XO("Pasting one type of track into another is not allowed."), XO("Pasting one type of track into another is not allowed."),
XO("Warning"), XO("Warning"),
"Error:_Copying_or_Pasting" "Error:_Copying_or_Pasting"
@ -477,6 +478,7 @@ void OnPaste(const CommandContext &context)
// Throw, so that any previous changes to the project in this // Throw, so that any previous changes to the project in this
// loop are discarded. // loop are discarded.
throw SimpleMessageBoxException{ throw SimpleMessageBoxException{
ExceptionType::BadUserAction,
XO("Copying stereo audio into a mono track is not allowed."), XO("Copying stereo audio into a mono track is not allowed."),
XO("Warning"), XO("Warning"),
"Error:_Copying_or_Pasting" "Error:_Copying_or_Pasting"

View File

@ -699,7 +699,7 @@ namespace {
[[noreturn]] void MigrationFailure() { [[noreturn]] void MigrationFailure() {
// Tracks may be in an inconsistent state; throw to the application // Tracks may be in an inconsistent state; throw to the application
// handler which restores consistency from undo history // handler which restores consistency from undo history
throw SimpleMessageBoxException{ throw SimpleMessageBoxException{ ExceptionType::Internal,
XO("Could not shift between tracks")}; XO("Could not shift between tracks")};
} }