From 36019314e91c7a2e8eae597159675091fd05c002 Mon Sep 17 00:00:00 2001 From: Alex Shvartzkop <dudesuchamazing@gmail.com> Date: Tue, 27 Aug 2024 05:49:37 +0300 Subject: [PATCH] Make simulation reporter warnings non-fatal. Adds REPORTER::HasMessageOfSeverity for WX_STRING_REPORTER, which allows us to show simulation warnings and fail only if there's errors. Also fixes a crash when SPICE_GENERATOR_KIBIS throws an IO_ERROR. Fixes https://gitlab.com/kicad/code/kicad/-/issues/18143 --- common/reporter.cpp | 34 +++++++++-- common/widgets/wx_html_report_panel.cpp | 9 ++- common/widgets/wx_html_report_panel.h | 1 + eeschema/dialogs/dialog_bom.cpp | 5 +- eeschema/dialogs/dialog_sim_model.cpp | 25 ++++---- eeschema/erc/erc.cpp | 8 +-- eeschema/files-io.cpp | 4 +- .../netlist_exporter_spice.cpp | 46 ++++++++------- eeschema/sim/sim_lib_mgr.cpp | 2 +- eeschema/sim/sim_model.cpp | 3 +- eeschema/sim/sim_model_ibis.cpp | 5 +- eeschema/sim/simulator_frame.cpp | 57 +++++++++++-------- eeschema/sim/simulator_frame.h | 2 +- eeschema/sim/simulator_frame_ui.cpp | 6 +- eeschema/tools/sch_editor_control.cpp | 5 +- eeschema/tools/simulator_control.cpp | 18 ++++-- gerbview/files.cpp | 12 ++-- gerbview/job_file_reader.cpp | 7 +-- include/reporter.h | 17 +++++- include/widgets/report_severity.h | 16 +++--- pcbnew/files.cpp | 6 +- qa/schematic_utils/eeschema_test_utils.cpp | 5 +- 22 files changed, 173 insertions(+), 120 deletions(-) diff --git a/common/reporter.cpp b/common/reporter.cpp index 859d06597e..0ec4ed264a 100644 --- a/common/reporter.cpp +++ b/common/reporter.cpp @@ -50,6 +50,13 @@ REPORTER& REPORTER::Report( const char* aText, SEVERITY aSeverity ) } +bool REPORTER::HasMessageOfSeverity( int aSeverityMask ) const +{ + wxFAIL_MSG( "HasMessageOfSeverity is not implemented in this reporter" ); + return HasMessage(); +} + + REPORTER& WX_TEXT_CTRL_REPORTER::Report( const wxString& aText, SEVERITY aSeverity ) { wxCHECK_MSG( m_textCtrl != nullptr, *this, @@ -68,17 +75,34 @@ bool WX_TEXT_CTRL_REPORTER::HasMessage() const REPORTER& WX_STRING_REPORTER::Report( const wxString& aText, SEVERITY aSeverity ) { - wxCHECK_MSG( m_string != nullptr, *this, - wxT( "No wxString object defined in WX_STRING_REPORTER." ) ); - - *m_string << aText << wxS( "\n" ); + m_severityMask |= aSeverity; + m_string << aText << wxS( "\n" ); return *this; } +const wxString& WX_STRING_REPORTER::GetMessages() const +{ + return m_string; +} + + +void WX_STRING_REPORTER::Clear() +{ + m_severityMask = 0; + m_string.clear(); +} + + bool WX_STRING_REPORTER::HasMessage() const { - return !m_string->IsEmpty(); + return !m_string.IsEmpty(); +} + + +bool WX_STRING_REPORTER::HasMessageOfSeverity( int aSeverityMask ) const +{ + return ( m_severityMask & aSeverityMask ) != 0; } diff --git a/common/widgets/wx_html_report_panel.cpp b/common/widgets/wx_html_report_panel.cpp index ebdd223649..c74aa01c0e 100644 --- a/common/widgets/wx_html_report_panel.cpp +++ b/common/widgets/wx_html_report_panel.cpp @@ -494,5 +494,12 @@ REPORTER& WX_HTML_PANEL_REPORTER::ReportHead( const wxString& aText, SEVERITY aS bool WX_HTML_PANEL_REPORTER::HasMessage() const { - return m_panel->Count( RPT_SEVERITY_ERROR | RPT_SEVERITY_WARNING ) > 0; + // Check just for errors and warnings for compatibility + return HasMessageOfSeverity( RPT_SEVERITY_ERROR | RPT_SEVERITY_WARNING ); +} + + +bool WX_HTML_PANEL_REPORTER::HasMessageOfSeverity( int aSeverityMask ) const +{ + return m_panel->Count( aSeverityMask ) > 0; } \ No newline at end of file diff --git a/common/widgets/wx_html_report_panel.h b/common/widgets/wx_html_report_panel.h index 0532551fc3..aa23d00134 100644 --- a/common/widgets/wx_html_report_panel.h +++ b/common/widgets/wx_html_report_panel.h @@ -48,6 +48,7 @@ public: SEVERITY aSeverity = RPT_SEVERITY_UNDEFINED ) override; bool HasMessage() const override; + bool HasMessageOfSeverity( int aSeverityMask ) const override; private: WX_HTML_REPORT_PANEL* m_panel; diff --git a/eeschema/dialogs/dialog_bom.cpp b/eeschema/dialogs/dialog_bom.cpp index d6a7853c3c..a4969241d4 100644 --- a/eeschema/dialogs/dialog_bom.cpp +++ b/eeschema/dialogs/dialog_bom.cpp @@ -334,8 +334,7 @@ void DIALOG_BOM::OnRunGenerator( wxCommandEvent& event ) wxString fullfilename = fn.GetFullPath(); m_parent->ClearMsgPanel(); - wxString reportmsg; - WX_STRING_REPORTER reporter( &reportmsg ); + WX_STRING_REPORTER reporter; m_parent->SetNetListerCommand( m_textCtrlCommand->GetValue() ); #ifdef __WINDOWS__ @@ -351,7 +350,7 @@ void DIALOG_BOM::OnRunGenerator( wxCommandEvent& event ) if( !status ) DisplayError( this, _( "Failed to create file." ) ); - m_Messages->SetValue( reportmsg ); + m_Messages->SetValue( reporter.GetMessages() ); // Force focus back on the dialog SetFocus(); diff --git a/eeschema/dialogs/dialog_sim_model.cpp b/eeschema/dialogs/dialog_sim_model.cpp index 8bfbde53ae..e8074a7983 100644 --- a/eeschema/dialogs/dialog_sim_model.cpp +++ b/eeschema/dialogs/dialog_sim_model.cpp @@ -171,8 +171,7 @@ bool DIALOG_SIM_MODEL<T>::TransferDataToWindow() wxString pinMap; bool storeInValue = false; - wxString msg; - WX_STRING_REPORTER reporter( &msg ); + WX_STRING_REPORTER reporter; auto setFieldValue = [&]( const wxString& aFieldName, const wxString& aValue ) @@ -220,7 +219,7 @@ bool DIALOG_SIM_MODEL<T>::TransferDataToWindow() if( !loadLibrary( libraryFilename, reporter ) ) { if( reporter.HasMessage() ) - m_infoBar->ShowMessage( msg ); + m_infoBar->ShowMessage( reporter.GetMessages() ); m_libraryPathText->ChangeValue( libraryFilename ); m_curModelType = SIM_MODEL::ReadTypeFromFields( m_fields, reporter ); @@ -303,24 +302,24 @@ bool DIALOG_SIM_MODEL<T>::TransferDataToWindow() // The model is sourced from the instance. m_rbBuiltinModel->SetValue( true ); - msg.clear(); + reporter.Clear(); m_curModelType = SIM_MODEL::ReadTypeFromFields( m_fields, reporter ); if( reporter.HasMessage() ) - DisplayErrorMessage( this, msg ); + DisplayErrorMessage( this, reporter.GetMessages() ); } for( SIM_MODEL::TYPE type : SIM_MODEL::TYPE_ITERATOR() ) { if( m_rbBuiltinModel->GetValue() && type == m_curModelType ) { - msg.clear(); + reporter.Clear(); m_builtinModelsMgr.CreateModel( m_fields, m_sortedPartPins, false, reporter ); if( reporter.HasMessage() ) { DisplayErrorMessage( this, _( "Failed to read simulation model from fields." ) - + wxT( "\n\n" ) + msg ); + + wxT( "\n\n" ) + reporter.GetMessages() ); } } else @@ -817,7 +816,7 @@ bool DIALOG_SIM_MODEL<T>::loadLibrary( const wxString& aLibraryPath, REPORTER& a m_libraryModelsMgr.SetForceFullParse(); m_libraryModelsMgr.SetLibrary( aLibraryPath, aReporter ); - if( aReporter.HasMessage() ) + if( aReporter.HasMessageOfSeverity( RPT_SEVERITY_UNDEFINED | RPT_SEVERITY_ERROR ) ) return false; std::string modelName = SIM_MODEL::GetFieldValue( &m_fields, SIM_LIBRARY::NAME_FIELD ); @@ -1182,14 +1181,13 @@ void DIALOG_SIM_MODEL<T>::onLibraryPathTextEnter( wxCommandEvent& aEvent ) { m_rbLibraryModel->SetValue( true ); - wxString msg; - WX_STRING_REPORTER reporter( &msg ); + WX_STRING_REPORTER reporter; wxString path = m_libraryPathText->GetValue(); if( loadLibrary( path, reporter, true ) || path.IsEmpty() ) m_infoBar->Hide(); else if( reporter.HasMessage() ) - m_infoBar->ShowMessage( msg ); + m_infoBar->ShowMessage( reporter.GetMessages() ); updateWidgets(); } @@ -1234,13 +1232,12 @@ void DIALOG_SIM_MODEL<T>::onBrowseButtonClick( wxCommandEvent& aEvent ) if( fn.MakeRelativeTo( Prj().GetProjectPath() ) && !fn.GetFullPath().StartsWith( wxS( ".." ) ) ) path = fn.GetFullPath(); - wxString msg; - WX_STRING_REPORTER reporter( &msg ); + WX_STRING_REPORTER reporter; if( loadLibrary( path, reporter, true ) ) m_infoBar->Hide(); else - m_infoBar->ShowMessage( msg ); + m_infoBar->ShowMessage( reporter.GetMessages() ); updateWidgets(); } diff --git a/eeschema/erc/erc.cpp b/eeschema/erc/erc.cpp index e6dc8fd573..7f937a9dc7 100644 --- a/eeschema/erc/erc.cpp +++ b/eeschema/erc/erc.cpp @@ -1572,8 +1572,7 @@ int ERC_TESTER::TestOffGridEndpoints() int ERC_TESTER::TestSimModelIssues() { - wxString msg; - WX_STRING_REPORTER reporter( &msg ); + WX_STRING_REPORTER reporter; int err_count = 0; SIM_LIB_MGR libMgr( &m_schematic->Prj() ); @@ -1594,12 +1593,13 @@ int ERC_TESTER::TestSimModelIssues() continue; // Reset for each symbol - msg.Clear(); + reporter.Clear(); SIM_LIBRARY::MODEL model = libMgr.CreateModel( &sheet, *symbol, reporter ); - if( !msg.IsEmpty() ) + if( reporter.HasMessage() ) { + wxString msg = reporter.GetMessages(); std::shared_ptr<ERC_ITEM> ercItem = ERC_ITEM::Create( ERCE_SIMULATION_MODEL ); //Remove \n and \r at e.o.l if any: diff --git a/eeschema/files-io.cpp b/eeschema/files-io.cpp index 4db18055da..fc20503741 100644 --- a/eeschema/files-io.cpp +++ b/eeschema/files-io.cpp @@ -1294,10 +1294,10 @@ bool SCH_EDIT_FRAME::SaveProject( bool aSaveAs ) if( !Kiface().IsSingle() ) { - WX_STRING_REPORTER backupReporter( &msg ); + WX_STRING_REPORTER backupReporter; if( !GetSettingsManager()->TriggerBackupIfNeeded( backupReporter ) ) - SetStatusText( msg, 0 ); + SetStatusText( backupReporter.GetMessages(), 0 ); } updateTitle(); diff --git a/eeschema/netlist_exporters/netlist_exporter_spice.cpp b/eeschema/netlist_exporters/netlist_exporter_spice.cpp index 6205f2bdd1..dffa1b1cab 100644 --- a/eeschema/netlist_exporters/netlist_exporter_spice.cpp +++ b/eeschema/netlist_exporters/netlist_exporter_spice.cpp @@ -37,6 +37,7 @@ #include <sch_screen.h> #include <sch_textbox.h> #include <string_utils.h> +#include <ki_exception.h> #include <dialogs/html_message_box.h> #include <fmt/core.h> @@ -175,31 +176,38 @@ bool NETLIST_EXPORTER_SPICE::ReadSchematicAndLibraries( unsigned aNetlistOptions if( !symbol || symbol->GetExcludedFromSim() ) continue; - SPICE_ITEM spiceItem; - std::vector<PIN_INFO> pins = CreatePinList( symbol, sheet, true ); - - for( const SCH_FIELD& field : symbol->GetFields() ) + try { - spiceItem.fields.emplace_back( VECTOR2I(), -1, symbol, field.GetName() ); + SPICE_ITEM spiceItem; + std::vector<PIN_INFO> pins = CreatePinList( symbol, sheet, true ); - if( field.GetId() == REFERENCE_FIELD ) - spiceItem.fields.back().SetText( symbol->GetRef( &sheet ) ); - else - spiceItem.fields.back().SetText( field.GetShownText( &sheet, false ) ); + for( const SCH_FIELD& field : symbol->GetFields() ) + { + spiceItem.fields.emplace_back( VECTOR2I(), -1, symbol, field.GetName() ); + + if( field.GetId() == REFERENCE_FIELD ) + spiceItem.fields.back().SetText( symbol->GetRef( &sheet ) ); + else + spiceItem.fields.back().SetText( field.GetShownText( &sheet, false ) ); + } + + readRefName( sheet, *symbol, spiceItem, refNames ); + readModel( sheet, *symbol, spiceItem, aReporter ); + readPinNumbers( *symbol, spiceItem, pins ); + readPinNetNames( *symbol, spiceItem, pins, ncCounter ); + readNodePattern( spiceItem ); + // TODO: transmission line handling? + + m_items.push_back( std::move( spiceItem ) ); + } + catch( IO_ERROR& e ) + { + aReporter.Report( e.What(), RPT_SEVERITY_ERROR ); } - - readRefName( sheet, *symbol, spiceItem, refNames ); - readModel( sheet, *symbol, spiceItem, aReporter ); - readPinNumbers( *symbol, spiceItem, pins ); - readPinNetNames( *symbol, spiceItem, pins, ncCounter ); - readNodePattern( spiceItem ); - // TODO: transmission line handling? - - m_items.push_back( std::move( spiceItem ) ); } } - return !aReporter.HasMessage(); + return !aReporter.HasMessageOfSeverity( RPT_SEVERITY_UNDEFINED | RPT_SEVERITY_ERROR ); } diff --git a/eeschema/sim/sim_lib_mgr.cpp b/eeschema/sim/sim_lib_mgr.cpp index 8a7716d007..37aae740f6 100644 --- a/eeschema/sim/sim_lib_mgr.cpp +++ b/eeschema/sim/sim_lib_mgr.cpp @@ -129,7 +129,7 @@ void SIM_LIB_MGR::SetLibrary( const wxString& aLibraryPath, REPORTER& aReporter { wxString path = ResolveLibraryPath( aLibraryPath, m_project, aReporter ); - if( aReporter.HasMessage() ) + if( aReporter.HasMessageOfSeverity( RPT_SEVERITY_UNDEFINED | RPT_SEVERITY_ERROR ) ) return; if( !wxFileName::Exists( path ) ) diff --git a/eeschema/sim/sim_model.cpp b/eeschema/sim/sim_model.cpp index 6bb60480eb..c6db410719 100644 --- a/eeschema/sim/sim_model.cpp +++ b/eeschema/sim/sim_model.cpp @@ -1706,8 +1706,7 @@ void SIM_MODEL::MigrateSimModel( T& aSymbol, const PROJECT* aProject ) if( !lib.IsEmpty() ) { - wxString msg; - WX_STRING_REPORTER reporter( &msg ); + WX_STRING_REPORTER reporter; SIM_LIB_MGR libMgr( aProject ); std::vector<SCH_FIELD> emptyFields; diff --git a/eeschema/sim/sim_model_ibis.cpp b/eeschema/sim/sim_model_ibis.cpp index 7e45c1c949..1bcd7ecb9c 100644 --- a/eeschema/sim/sim_model_ibis.cpp +++ b/eeschema/sim/sim_model_ibis.cpp @@ -61,12 +61,11 @@ std::string SPICE_GENERATOR_IBIS::IbisDevice( const SPICE_ITEM& aItem, const PRO std::string ibisModelName = SIM_MODEL::GetFieldValue( &aItem.fields, SIM_LIBRARY_IBIS::MODEL_FIELD ); bool diffMode = SIM_MODEL::GetFieldValue( &aItem.fields, SIM_LIBRARY_IBIS::DIFF_FIELD ) == "1"; - wxString msg; - WX_STRING_REPORTER reporter( &msg ); + WX_STRING_REPORTER reporter; wxString path = SIM_LIB_MGR::ResolveLibraryPath( ibisLibFilename, &aProject, reporter ); if( reporter.HasMessage() ) - THROW_IO_ERROR( msg ); + THROW_IO_ERROR( reporter.GetMessages() ); KIBIS kibis( std::string( path.c_str() ) ); kibis.m_cacheDir = std::string( aCacheDir.c_str() ); diff --git a/eeschema/sim/simulator_frame.cpp b/eeschema/sim/simulator_frame.cpp index 56062e693b..be7cdb1f4f 100644 --- a/eeschema/sim/simulator_frame.cpp +++ b/eeschema/sim/simulator_frame.cpp @@ -62,8 +62,7 @@ // Reporter is stored by pointer in KIBIS, so keep this here to avoid crashes -static wxString s_errors; -static WX_STRING_REPORTER s_reporter( &s_errors ); +static WX_STRING_REPORTER s_reporter; class SIM_THREAD_REPORTER : public SIMULATOR_REPORTER @@ -353,9 +352,12 @@ void SIMULATOR_FRAME::UpdateTitle() // Don't let the dialog grow too tall: you may not be able to get to the OK button #define MAX_MESSAGES 20 -void SIMULATOR_FRAME::showNetlistErrors( const wxString& aErrors ) +void SIMULATOR_FRAME::showNetlistErrors( const WX_STRING_REPORTER& aReporter ) { - wxArrayString lines = wxSplit( aErrors, '\n' ); + if( !aReporter.HasMessage() ) + return; + + wxArrayString lines = wxSplit( aReporter.GetMessages(), '\n' ); if( lines.size() > MAX_MESSAGES ) { @@ -363,13 +365,22 @@ void SIMULATOR_FRAME::showNetlistErrors( const wxString& aErrors ) lines.Add( wxS( "..." ) ); } - DisplayErrorMessage( this, _( "Errors during netlist generation." ), wxJoin( lines, '\n' ) ); + if( aReporter.HasMessageOfSeverity( RPT_SEVERITY_UNDEFINED | RPT_SEVERITY_ERROR ) ) + { + DisplayErrorMessage( this, _( "Errors during netlist generation." ), + wxJoin( lines, '\n' ) ); + } + else if( aReporter.HasMessageOfSeverity( RPT_SEVERITY_WARNING ) ) + { + DisplayInfoMessage( this, _( "Warnings during netlist generation." ), + wxJoin( lines, '\n' ) ); + } } bool SIMULATOR_FRAME::LoadSimulator( const wxString& aSimCommand, unsigned aSimOptions ) { - s_errors.clear(); + s_reporter.Clear(); if( !m_schematicFrame->ReadyToNetlist( _( "Simulator requires a fully annotated schematic." ) ) ) return false; @@ -378,26 +389,23 @@ bool SIMULATOR_FRAME::LoadSimulator( const wxString& aSimCommand, unsigned aSimO if( ADVANCED_CFG::GetCfg().m_IncrementalConnectivity ) m_schematicFrame->RecalculateConnections( nullptr, GLOBAL_CLEANUP ); - if( !m_simulator->Attach( m_circuitModel, aSimCommand, aSimOptions, Prj().GetProjectPath(), - s_reporter ) ) - { - showNetlistErrors( s_errors ); - return false; - } + bool success = m_simulator->Attach( m_circuitModel, aSimCommand, aSimOptions, + Prj().GetProjectPath(), s_reporter ); - return true; + showNetlistErrors( s_reporter ); + + return success; } void SIMULATOR_FRAME::ReloadSimulator( const wxString& aSimCommand, unsigned aSimOptions ) { - s_errors.clear(); + s_reporter.Clear(); - if( !m_simulator->Attach( m_circuitModel, aSimCommand, aSimOptions, Prj().GetProjectPath(), - s_reporter ) ) - { - showNetlistErrors( s_errors ); - } + m_simulator->Attach( m_circuitModel, aSimCommand, aSimOptions, Prj().GetProjectPath(), + s_reporter ); + + showNetlistErrors( s_reporter ); } @@ -583,16 +591,15 @@ bool SIMULATOR_FRAME::EditAnalysis() SIM_TAB* simTab = m_ui->GetCurrentSimTab(); DIALOG_SIM_COMMAND dlg( this, m_circuitModel, m_simulator->Settings() ); - s_errors.clear(); + s_reporter.Clear(); if( !simTab ) return false; - if( !m_circuitModel->ReadSchematicAndLibraries( NETLIST_EXPORTER_SPICE::OPTION_DEFAULT_FLAGS, - s_reporter ) ) - { - showNetlistErrors( s_errors ); - } + m_circuitModel->ReadSchematicAndLibraries( NETLIST_EXPORTER_SPICE::OPTION_DEFAULT_FLAGS, + s_reporter ); + + showNetlistErrors( s_reporter ); dlg.SetSimCommand( simTab->GetSimCommand() ); dlg.SetSimOptions( simTab->GetSimOptions() ); diff --git a/eeschema/sim/simulator_frame.h b/eeschema/sim/simulator_frame.h index 01655fb79b..c75e9fe011 100644 --- a/eeschema/sim/simulator_frame.h +++ b/eeschema/sim/simulator_frame.h @@ -196,7 +196,7 @@ private: void setupUIConditions() override; - void showNetlistErrors( const wxString& aErrors ); + void showNetlistErrors( const WX_STRING_REPORTER& aReporter ); bool canCloseWindow( wxCloseEvent& aEvent ) override; void doCloseWindow() override; diff --git a/eeschema/sim/simulator_frame_ui.cpp b/eeschema/sim/simulator_frame_ui.cpp index 6ad2eca123..d93b7da662 100644 --- a/eeschema/sim/simulator_frame_ui.cpp +++ b/eeschema/sim/simulator_frame_ui.cpp @@ -1862,8 +1862,7 @@ void SIMULATOR_FRAME_UI::applyUserDefinedSignals() void SIMULATOR_FRAME_UI::applyTuners() { - wxString errors; - WX_STRING_REPORTER reporter( &errors ); + WX_STRING_REPORTER reporter; for( const TUNER_SLIDER* tuner : m_tuners ) { @@ -1893,7 +1892,8 @@ void SIMULATOR_FRAME_UI::applyTuners() } if( reporter.HasMessage() ) - DisplayErrorMessage( this, _( "Could not apply tuned value(s):" ) + wxS( "\n" ) + errors ); + DisplayErrorMessage( this, _( "Could not apply tuned value(s):" ) + wxS( "\n" ) + + reporter.GetMessages() ); } diff --git a/eeschema/tools/sch_editor_control.cpp b/eeschema/tools/sch_editor_control.cpp index 271d460180..914600e59f 100644 --- a/eeschema/tools/sch_editor_control.cpp +++ b/eeschema/tools/sch_editor_control.cpp @@ -567,14 +567,13 @@ int SCH_EDITOR_CONTROL::SimProbe( const TOOL_EVENT& aEvent ) SCH_PIN* pin = static_cast<SCH_PIN*>( item )->GetLibPin(); SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item->GetParent() ); - wxString msg; - WX_STRING_REPORTER reporter( &msg ); + WX_STRING_REPORTER reporter; SIM_LIB_MGR mgr( &m_frame->Prj() ); SIM_MODEL& model = mgr.CreateModel( &sheet, *symbol, reporter ).model; if( reporter.HasMessage() ) - THROW_IO_ERROR( msg ); + THROW_IO_ERROR( reporter.GetMessages() ); SPICE_ITEM spiceItem; spiceItem.refName = symbol->GetRef( &sheet ).ToStdString(); diff --git a/eeschema/tools/simulator_control.cpp b/eeschema/tools/simulator_control.cpp index e214175c24..70776a22e4 100644 --- a/eeschema/tools/simulator_control.cpp +++ b/eeschema/tools/simulator_control.cpp @@ -71,14 +71,20 @@ void SIMULATOR_CONTROL::Reset( RESET_REASON aReason ) int SIMULATOR_CONTROL::NewAnalysisTab( const TOOL_EVENT& aEvent ) { DIALOG_SIM_COMMAND dlg( m_simulatorFrame, m_circuitModel, m_simulator->Settings() ); - wxString errors; - WX_STRING_REPORTER reporter( &errors ); + WX_STRING_REPORTER reporter; - if( !m_circuitModel->ReadSchematicAndLibraries( NETLIST_EXPORTER_SPICE::OPTION_DEFAULT_FLAGS, - reporter ) ) + m_circuitModel->ReadSchematicAndLibraries( NETLIST_EXPORTER_SPICE::OPTION_DEFAULT_FLAGS, + reporter ); + + if( reporter.HasMessageOfSeverity( RPT_SEVERITY_UNDEFINED | RPT_SEVERITY_ERROR ) ) { - DisplayErrorMessage( m_simulatorFrame, - _( "Errors during netlist generation.\n\n" ) + errors ); + DisplayErrorMessage( m_simulatorFrame, _( "Errors during netlist generation." ), + reporter.GetMessages() ); + } + else if( reporter.HasMessageOfSeverity( RPT_SEVERITY_WARNING ) ) + { + DisplayInfoMessage( m_simulatorFrame, _( "Warnings during netlist generation." ), + reporter.GetMessages() ); } dlg.SetSimCommand( wxS( "*" ) ); diff --git a/gerbview/files.cpp b/gerbview/files.cpp index 93eec6e937..c57b130435 100644 --- a/gerbview/files.cpp +++ b/gerbview/files.cpp @@ -259,8 +259,7 @@ bool GERBVIEW_FRAME::LoadListOfGerberAndDrillFiles( const wxString& aPath, LSET visibility = GetVisibleLayers(); // Manage errors when loading files - wxString msg; - WX_STRING_REPORTER reporter( &msg ); + WX_STRING_REPORTER reporter; // Create progress dialog (only used if more than 1 file to load std::unique_ptr<WX_PROGRESS_REPORTER> progress = nullptr; @@ -403,7 +402,7 @@ bool GERBVIEW_FRAME::LoadListOfGerberAndDrillFiles( const wxString& aPath, wxSafeYield(); // Allows slice of time to redraw the screen // to refresh widgets, before displaying messages HTML_MESSAGE_BOX mbox( this, _( "Errors" ) ); - mbox.ListSet( msg ); + mbox.ListSet( reporter.GetMessages() ); mbox.ShowModal(); } @@ -658,8 +657,7 @@ bool GERBVIEW_FRAME::LoadZipArchiveFile( const wxString& aFullFileName ) m_mruPath = currentPath; } - wxString msg; - WX_STRING_REPORTER reporter( &msg ); + WX_STRING_REPORTER reporter; if( filename.IsOk() ) unarchiveFiles( filename.GetFullPath(), &reporter ); @@ -672,12 +670,12 @@ bool GERBVIEW_FRAME::LoadZipArchiveFile( const wxString& aFullFileName ) m_LayersManager->UpdateLayerIcons(); syncLayerBox(); - if( !msg.IsEmpty() ) + if( reporter.HasMessage() ) { wxSafeYield(); // Allows slice of time to redraw the screen // to refresh widgets, before displaying messages HTML_MESSAGE_BOX mbox( this, _( "Messages" ) ); - mbox.ListSet( msg ); + mbox.ListSet( reporter.GetMessages() ); mbox.ShowModal(); } diff --git a/gerbview/job_file_reader.cpp b/gerbview/job_file_reader.cpp index d45438cb5f..01b80e1cb2 100644 --- a/gerbview/job_file_reader.cpp +++ b/gerbview/job_file_reader.cpp @@ -208,8 +208,7 @@ bool GERBVIEW_FRAME::LoadGerberJobFile( const wxString& aFullFileName ) m_mruPath = currentPath; } - wxString msg; - WX_STRING_REPORTER reporter( &msg ); + WX_STRING_REPORTER reporter; if( filename.IsOk() ) { @@ -235,12 +234,12 @@ bool GERBVIEW_FRAME::LoadGerberJobFile( const wxString& aFullFileName ) SortLayersByX2Attributes(); - if( !msg.IsEmpty() ) + if( reporter.HasMessage() ) { wxSafeYield(); // Allows slice of time to redraw the screen // to refresh widgets, before displaying messages HTML_MESSAGE_BOX mbox( this, _( "Messages" ) ); - mbox.ListSet( msg ); + mbox.ListSet( reporter.GetMessages() ); mbox.ShowModal(); } diff --git a/include/reporter.h b/include/reporter.h index 588078b90a..0ebd46ff8a 100644 --- a/include/reporter.h +++ b/include/reporter.h @@ -121,6 +121,12 @@ public: */ virtual bool HasMessage() const = 0; + /** + * Returns true if the reporter has one or more messages matching the specified + * severity mask. + */ + virtual bool HasMessageOfSeverity( int aSeverityMask ) const; + virtual EDA_UNITS GetUnits() const { return EDA_UNITS::MILLIMETRES; @@ -164,9 +170,9 @@ private: class KICOMMON_API WX_STRING_REPORTER : public REPORTER { public: - WX_STRING_REPORTER( wxString* aString ) : + WX_STRING_REPORTER() : REPORTER(), - m_string( aString ) + m_severityMask( 0 ) { } @@ -177,9 +183,14 @@ public: REPORTER& Report( const wxString& aText, SEVERITY aSeverity = RPT_SEVERITY_UNDEFINED ) override; bool HasMessage() const override; + bool HasMessageOfSeverity( int aSeverityMask ) const override; + + const wxString& GetMessages() const; + void Clear(); private: - wxString* m_string; + wxString m_string; + int m_severityMask; }; diff --git a/include/widgets/report_severity.h b/include/widgets/report_severity.h index ddfa7b33ab..8c4df164f3 100644 --- a/include/widgets/report_severity.h +++ b/include/widgets/report_severity.h @@ -24,14 +24,14 @@ // Note: On windows, SEVERITY_ERROR collides with a system declaration, // so we used RPT_SEVERITY_xxx instead of SEVERITY_xxx enum SEVERITY { - RPT_SEVERITY_UNDEFINED = 0x00, - RPT_SEVERITY_INFO = 0x01, - RPT_SEVERITY_EXCLUSION = 0x02, - RPT_SEVERITY_ACTION = 0x04, - RPT_SEVERITY_WARNING = 0x08, - RPT_SEVERITY_ERROR = 0x10, - RPT_SEVERITY_IGNORE = 0x20, - RPT_SEVERITY_DEBUG = 0x40, + RPT_SEVERITY_UNDEFINED = 0x01, + RPT_SEVERITY_INFO = 0x02, + RPT_SEVERITY_EXCLUSION = 0x04, + RPT_SEVERITY_ACTION = 0x08, + RPT_SEVERITY_WARNING = 0x10, + RPT_SEVERITY_ERROR = 0x20, + RPT_SEVERITY_IGNORE = 0x40, + RPT_SEVERITY_DEBUG = 0x80, }; #endif // REPORT_SEVERITY_H diff --git a/pcbnew/files.cpp b/pcbnew/files.cpp index c638b3e1a4..19a19dcc66 100644 --- a/pcbnew/files.cpp +++ b/pcbnew/files.cpp @@ -1079,10 +1079,10 @@ bool PCB_EDIT_FRAME::SavePcbFile( const wxString& aFileName, bool addToHistory, if( !Kiface().IsSingle() ) { - WX_STRING_REPORTER backupReporter( &upperTxt ); + WX_STRING_REPORTER backupReporter; - if( GetSettingsManager()->TriggerBackupIfNeeded( backupReporter ) ) - upperTxt.clear(); + if( !GetSettingsManager()->TriggerBackupIfNeeded( backupReporter ) ) + upperTxt = backupReporter.GetMessages(); } GetBoard()->SetFileName( pcbFileName.GetFullPath() ); diff --git a/qa/schematic_utils/eeschema_test_utils.cpp b/qa/schematic_utils/eeschema_test_utils.cpp index f6d77d5bb8..cc9f7a1dce 100644 --- a/qa/schematic_utils/eeschema_test_utils.cpp +++ b/qa/schematic_utils/eeschema_test_utils.cpp @@ -133,13 +133,12 @@ void TEST_NETLIST_EXPORTER_FIXTURE<Exporter>::WriteNetlist() if( wxFileExists( GetNetlistPath( true ) ) ) wxRemoveFile( GetNetlistPath( true ) ); - wxString errors; - WX_STRING_REPORTER reporter( &errors ); + WX_STRING_REPORTER reporter; std::unique_ptr<Exporter> exporter = std::make_unique<Exporter>( &m_schematic ); bool success = exporter->WriteNetlist( GetNetlistPath( true ), GetNetlistOptions(), reporter ); - BOOST_REQUIRE( success && errors.IsEmpty() ); + BOOST_REQUIRE( success && reporter.GetMessages().IsEmpty() ); }