Fix cli crash due to dialogs buried in the pcb parser...

Fixes sentry KICAD-Q2
This commit is contained in:
Marek Roszko 2023-03-24 19:45:56 -04:00
parent 0b54eb6edb
commit 8a8589b9db
9 changed files with 130 additions and 109 deletions

View File

@ -31,30 +31,13 @@
#include <dialogs/html_message_box.h> #include <dialogs/html_message_box.h>
#include <functional> #include <functional>
#include <unordered_map> #include <unordered_map>
#include <pgm_base.h>
#include "cli/cli_names.h" #include "cli/cli_names.h"
// Set of dialogs that have been chosen not to be shown again // Set of dialogs that have been chosen not to be shown again
static std::unordered_map<unsigned long, int> doNotShowAgainDlgs; static std::unordered_map<unsigned long, int> doNotShowAgainDlgs;
bool IsGUI()
{
if( !wxTheApp )
return false;
#if wxCHECK_VERSION( 3, 1, 6 )
return wxTheApp->IsGUI();
#else
// wxWidgets older than version 3.1.6 do not have a way to know if the app
// has a GUI or is a console application.
// So the trick is to set the App class name when starting kicad-cli, and when
// the app class name is the kicad-cli class name the app is a console app
bool run_gui = wxTheApp->GetClassName() != KICAD_CLI_APP_NAME;
return run_gui;
#endif
}
KIDIALOG::KIDIALOG( wxWindow* aParent, const wxString& aMessage, const wxString& aCaption, KIDIALOG::KIDIALOG( wxWindow* aParent, const wxString& aMessage, const wxString& aCaption,
long aStyle ) long aStyle )
: wxRichMessageDialog( aParent, aMessage, aCaption, aStyle | wxCENTRE | wxSTAY_ON_TOP ), : wxRichMessageDialog( aParent, aMessage, aCaption, aStyle | wxCENTRE | wxSTAY_ON_TOP ),
@ -305,7 +288,7 @@ void DisplayError( wxWindow* aParent, const wxString& aText, int aDisplayTime )
return; return;
} }
if( !IsGUI() ) if( !Pgm().IsGUI() )
{ {
wxFprintf( stderr, aText ); wxFprintf( stderr, aText );
return; return;
@ -330,7 +313,7 @@ void DisplayErrorMessage( wxWindow* aParent, const wxString& aText, const wxStri
return; return;
} }
if( !IsGUI() ) if( !Pgm().IsGUI() )
{ {
wxFprintf( stderr, aText ); wxFprintf( stderr, aText );
return; return;
@ -357,7 +340,7 @@ void DisplayInfoMessage( wxWindow* aParent, const wxString& aMessage, const wxSt
return; return;
} }
if( !IsGUI() ) if( !Pgm().IsGUI() )
{ {
wxFprintf( stdout, "%s %s", aMessage, aExtraInfo ); wxFprintf( stdout, "%s %s", aMessage, aExtraInfo );
return; return;

View File

@ -1231,7 +1231,7 @@ bool EDA_BASE_FRAME::IsWritable( const wxFileName& aFileName, bool aVerbose )
void EDA_BASE_FRAME::CheckForAutoSaveFile( const wxFileName& aFileName ) void EDA_BASE_FRAME::CheckForAutoSaveFile( const wxFileName& aFileName )
{ {
if( !IsGUI() ) if( !Pgm().IsGUI() )
return; return;
wxCHECK_RET( aFileName.IsOk(), wxT( "Invalid file name!" ) ); wxCHECK_RET( aFileName.IsOk(), wxT( "Invalid file name!" ) );

View File

@ -857,3 +857,21 @@ ENV_VAR_MAP& PGM_BASE::GetLocalEnvVariables() const
{ {
return GetCommonSettings()->m_Env.vars; return GetCommonSettings()->m_Env.vars;
} }
bool PGM_BASE::IsGUI()
{
if( !wxTheApp )
return false;
#if wxCHECK_VERSION( 3, 1, 6 )
return wxTheApp->IsGUI();
#else
// wxWidgets older than version 3.1.6 do not have a way to know if the app
// has a GUI or is a console application.
// So the trick is to set the App class name when starting kicad-cli, and when
// the app class name is the kicad-cli class name the app is a console app
bool run_gui = wxTheApp->GetClassName() != KICAD_CLI_APP_NAME;
return run_gui;
#endif
}

View File

@ -1400,7 +1400,7 @@ bool SCH_EDIT_FRAME::updateAutoSaveFile()
void SCH_EDIT_FRAME::CheckForAutoSaveFile( const wxFileName& aFileName ) void SCH_EDIT_FRAME::CheckForAutoSaveFile( const wxFileName& aFileName )
{ {
if( !IsGUI() ) if( !Pgm().IsGUI() )
return; return;
wxCHECK_RET( aFileName.IsOk(), wxT( "Invalid file name!" ) ); wxCHECK_RET( aFileName.IsOk(), wxT( "Invalid file name!" ) );

View File

@ -194,11 +194,4 @@ int OKOrCancelDialog( wxWindow* aParent, const wxString& aWarning, const wxStrin
int SelectSingleOption( wxWindow* aParent, const wxString& aTitle, const wxString& aMessage, int SelectSingleOption( wxWindow* aParent, const wxString& aTitle, const wxString& aMessage,
const wxArrayString& aOptions ); const wxArrayString& aOptions );
/**
* Determine if the application is running with a GUI
*
* @return true if there is a GUI and false otherwise
*/
bool IsGUI();
#endif /* __INCLUDE__CONFIRM_H__ */ #endif /* __INCLUDE__CONFIRM_H__ */

View File

@ -303,6 +303,13 @@ public:
const wxString& GetSentryId(); const wxString& GetSentryId();
#endif #endif
/**
* Determine if the application is running with a GUI
*
* @return true if there is a GUI and false otherwise
*/
bool IsGUI();
/** /**
* wxWidgets on MSW tends to crash if you spool up more than one print job at a time. * wxWidgets on MSW tends to crash if you spool up more than one print job at a time.
*/ */

View File

@ -499,7 +499,7 @@ struct APP_KICAD_CLI : public wxAppConsole
} }
catch( const IO_ERROR& ioe ) catch( const IO_ERROR& ioe )
{ {
wxLogError( ioe.What() ); wxFprintf( stderr, ioe.What() );
} }
catch( ... ) catch( ... )
{ {

View File

@ -64,6 +64,7 @@
#include <wx/log.h> #include <wx/log.h>
#include <progress_reporter.h> #include <progress_reporter.h>
#include <board_stackup_manager/stackup_predefined_prms.h> #include <board_stackup_manager/stackup_predefined_prms.h>
#include <pgm_base.h>
// For some reason wxWidgets is built with wxUSE_BASE64 unset so expose the wxWidgets // For some reason wxWidgets is built with wxUSE_BASE64 unset so expose the wxWidgets
// base64 code. Needed for PCB_BITMAP // base64 code. Needed for PCB_BITMAP
@ -907,6 +908,8 @@ BOARD* PCB_PARSER::parseBOARD_unchecked()
m_board->SetProperties( properties ); m_board->SetProperties( properties );
if( m_undefinedLayers.size() > 0 ) if( m_undefinedLayers.size() > 0 )
{
if( Pgm().IsGUI() )
{ {
bool deleteItems; bool deleteItems;
std::vector<BOARD_ITEM*> deleteList; std::vector<BOARD_ITEM*> deleteList;
@ -918,7 +921,8 @@ BOARD* PCB_PARSER::parseBOARD_unchecked()
details += wxT( "\n " ) + undefinedLayer; details += wxT( "\n " ) + undefinedLayer;
wxRichMessageDialog dlg( nullptr, msg, _( "Warning" ), wxRichMessageDialog dlg( nullptr, msg, _( "Warning" ),
wxYES_NO | wxCANCEL | wxCENTRE | wxICON_WARNING | wxSTAY_ON_TOP ); wxYES_NO | wxCANCEL | wxCENTRE | wxICON_WARNING
| wxSTAY_ON_TOP );
dlg.ShowDetailedText( details ); dlg.ShowDetailedText( details );
dlg.SetYesNoCancelLabels( _( "Rescue" ), _( "Delete" ), _( "Cancel" ) ); dlg.SetYesNoCancelLabels( _( "Rescue" ), _( "Delete" ), _( "Cancel" ) );
@ -995,6 +999,11 @@ BOARD* PCB_PARSER::parseBOARD_unchecked()
m_undefinedLayers.clear(); m_undefinedLayers.clear();
} }
else
{
THROW_IO_ERROR( wxT( "One or more undefined layers exists was found, open the project in the PCB Editor to resolve" ) );
}
}
return m_board; return m_board;
} }
@ -2165,10 +2174,13 @@ void PCB_PARSER::parseSetup()
if( parseBool() ) if( parseBool() )
{ {
if( m_showLegacy5ZoneWarning ) if( m_showLegacy5ZoneWarning )
{
if( Pgm().IsGUI() )
{ {
// Thick outline fill mode no longer supported. Make sure user is OK with // Thick outline fill mode no longer supported. Make sure user is OK with
// converting fills. // converting fills.
KIDIALOG dlg( nullptr, _( "The legacy zone fill strategy is no longer " KIDIALOG dlg( nullptr,
_( "The legacy zone fill strategy is no longer "
"supported.\nConvert zones to smoothed polygon " "supported.\nConvert zones to smoothed polygon "
"fills?" ), "fills?" ),
_( "Legacy Zone Warning" ), wxYES_NO | wxICON_WARNING ); _( "Legacy Zone Warning" ), wxYES_NO | wxICON_WARNING );
@ -2180,6 +2192,11 @@ void PCB_PARSER::parseSetup()
m_showLegacy5ZoneWarning = false; m_showLegacy5ZoneWarning = false;
} }
else
{
THROW_IO_ERROR( wxT( "Legacy zone fill strategy found, open the project in the PCB Editor to resolve" ) );
}
}
} }
NeedRIGHT(); NeedRIGHT();

View File

@ -45,6 +45,7 @@
#include <pcb_text.h> #include <pcb_text.h>
#include <pcb_textbox.h> #include <pcb_textbox.h>
#include <pcbnew_settings.h> #include <pcbnew_settings.h>
#include <pgm_base.h>
#include <plugins/kicad/pcb_plugin.h> #include <plugins/kicad/pcb_plugin.h>
#include <plugins/kicad/pcb_parser.h> #include <plugins/kicad/pcb_parser.h>
#include <trace_helpers.h> #include <trace_helpers.h>
@ -2576,7 +2577,9 @@ void PCB_PLUGIN::FootprintSave( const wxString& aLibraryPath, const FOOTPRINT* a
"Would you like to create it?"), "Would you like to create it?"),
aLibraryPath ); aLibraryPath );
if( !IsGUI() || wxMessageBox( msg, _( "Library Not Found"), wxYES_NO | wxICON_QUESTION ) != wxYES ) if( !Pgm().IsGUI()
|| wxMessageBox( msg, _( "Library Not Found" ), wxYES_NO | wxICON_QUESTION )
!= wxYES )
return; return;
// Save throws its own IO_ERROR on failure, so no need to recreate here // Save throws its own IO_ERROR on failure, so no need to recreate here