Refuse to load schematics from the future.

Also fixes a bug where an empty window would get left when loading
a file from the KiCad manager window errored out.

Also fixes a bug where we were getting the wrong exception because
we were rethrowing the type-casted one (rather than just calling
throw).

Fixes https://gitlab.com/kicad/code/kicad/issues/8604
This commit is contained in:
Jeff Young 2021-06-30 16:06:07 +01:00
parent e695c580fd
commit 6810912f09
9 changed files with 75 additions and 48 deletions

View File

@ -87,33 +87,43 @@ void PARSE_ERROR::init( const wxString& aProblem, const char* aThrowersFile,
// a short filename will be printed (it is better for user, the full filename has no meaning).
wxString srcname = aThrowersFile;
where.Printf( _( "from %s : %s() line:%d" ),
srcname.AfterLast( '/' ),
wxString( aThrowersFunction ),
aThrowersLineNumber );
where.Printf( _( "from %s : %s() line:%d" ),
srcname.AfterLast( '/' ),
wxString( aThrowersFunction ),
aThrowersLineNumber );
}
void FUTURE_FORMAT_ERROR::init( const wxString& aRequiredVersion )
{
requiredVersion = aRequiredVersion;
problem.Printf( _( "KiCad was unable to open this file because it was created with a more "
"recent version than the one you are running.\n\n"
"To open it you will need to upgrade KiCad to a version dated %s or "
"later." ),
aRequiredVersion );
}
FUTURE_FORMAT_ERROR::FUTURE_FORMAT_ERROR( const wxString& aRequiredVersion ) :
PARSE_ERROR()
{
init( aRequiredVersion );
lineNumber = 0;
byteIndex = 0;
}
FUTURE_FORMAT_ERROR::FUTURE_FORMAT_ERROR( const PARSE_ERROR& aParseError,
const wxString& aRequiredVersion ) :
PARSE_ERROR(), requiredVersion( aRequiredVersion )
PARSE_ERROR()
{
// Avoid double-printing the error message
bool wrapped_same_type = !!( dynamic_cast<const FUTURE_FORMAT_ERROR *>( &aParseError ) );
init( aRequiredVersion );
if( wrapped_same_type )
{
problem = aParseError.Problem();
}
else
{
problem.Printf( _( "KiCad was unable to open this file, as it was created with a more\n"
"recent version than the one you are running.\n"
"To open it you will need to upgrade KiCad to a more recent version.\n\n"
"Date of KiCad version required (or newer): %s\n\n"
"Full error text:\n%s" ),
requiredVersion, aParseError.Problem() );
}
if( !aParseError.Problem().IsEmpty() )
problem += wxS( "\n\n" ) + _( "Full error text:" ) + wxS( "\n" ) + aParseError.Problem();
lineNumber = aParseError.lineNumber;
byteIndex = aParseError.byteIndex;

View File

@ -393,22 +393,30 @@ bool SCH_EDIT_FRAME::OpenProjectFiles( const std::vector<wxString>& aFileSet, in
pi->SetProgressReporter( &progressReporter );
bool failedLoad = false;
try
{
Schematic().SetRoot( pi->Load( fullFileName, &Schematic() ) );
if( !pi->GetError().IsEmpty() )
{
DisplayErrorMessage( this,
_( "The entire schematic could not be loaded. Errors "
"occurred attempting to load \nhierarchical sheet "
"schematics." ),
DisplayErrorMessage( this, _( "The entire schematic could not be loaded. Errors "
"occurred attempting to load hierarchical sheets." ),
pi->GetError() );
}
}
catch( const FUTURE_FORMAT_ERROR& ffe )
{
msg.Printf( _( "Error loading schematic '%s'." ), fullFileName);
progressReporter.Hide();
DisplayErrorMessage( this, msg, ffe.Problem() );
failedLoad = true;
}
catch( const IO_ERROR& ioe )
{
msg.Printf( _( "Error loading schematic '%s'." ), fullFileName);
progressReporter.Hide();
DisplayErrorMessage( this, msg, ioe.What() );
failedLoad = true;
@ -416,7 +424,8 @@ bool SCH_EDIT_FRAME::OpenProjectFiles( const std::vector<wxString>& aFileSet, in
catch( const std::bad_alloc& )
{
msg.Printf( _( "Memory exhausted loading schematic '%s'." ), fullFileName );
DisplayErrorMessage( this, msg );
progressReporter.Hide();
DisplayErrorMessage( this, msg, wxEmptyString );
failedLoad = true;
}

View File

@ -113,12 +113,6 @@ bool SCH_SEXPR_PARSER::parseBool()
}
bool SCH_SEXPR_PARSER::IsTooRecent() const
{
return m_requiredVersion && m_requiredVersion > SEXPR_SYMBOL_LIB_FILE_VERSION;
}
void SCH_SEXPR_PARSER::ParseLib( LIB_SYMBOL_MAP& aSymbolLibMap )
{
T token;
@ -695,6 +689,10 @@ void SCH_SEXPR_PARSER::parseHeader( TSCHEMATIC_T::T aHeaderType, int aFileVersio
if( tok == T_version )
{
m_requiredVersion = parseInt( FromUTF8().mb_str( wxConvUTF8 ) );
if( m_requiredVersion > aFileVersion )
throw FUTURE_FORMAT_ERROR( FromUTF8() );
NeedRIGHT();
// Skip the host name and host build version information.

View File

@ -220,11 +220,6 @@ public:
*/
void ParseSchematic( SCH_SHEET* aSheet, bool aIsCopyablyOnly = false,
int aFileVersion = SEXPR_SCHEMATIC_FILE_VERSION );
/**
* Return whether a version number, if any was parsed, was too recent
*/
bool IsTooRecent() const;
};
#endif // __SCH_SEXPR_PARSER_H__

View File

@ -510,7 +510,7 @@ void SCH_SEXPR_PLUGIN::loadHierarchy( SCH_SHEET* aSheet )
{
// If there is a problem loading the root sheet, there is no recovery.
if( aSheet == m_rootSheet )
throw( ioe );
throw;
// For all subsheets, queue up the error message for the caller.
if( !m_error.IsEmpty() )

View File

@ -175,8 +175,11 @@ struct FUTURE_FORMAT_ERROR : public PARSE_ERROR
{
wxString requiredVersion; ///< version or date of KiCad required to open file
FUTURE_FORMAT_ERROR( const wxString& aRequiredVersion );
FUTURE_FORMAT_ERROR( const PARSE_ERROR& aParseError, const wxString& aRequiredVersion );
~FUTURE_FORMAT_ERROR() throw () {}
void init( const wxString& aRequiredVersion );
};
/** @} exception_types */

View File

@ -666,7 +666,10 @@ int KICAD_MANAGER_CONTROL::ShowPlayer( const TOOL_EVENT& aEvent )
if( !filepath.IsEmpty() )
{
if( !player->OpenProjectFiles( std::vector<wxString>( 1, filepath ) ) )
{
player->Destroy();
return -1;
}
}
player->Show( true );

View File

@ -658,9 +658,9 @@ bool PCB_EDIT_FRAME::OpenProjectFiles( const std::vector<wxString>& aFileSet, in
}
else
{
BOARD* loadedBoard = nullptr; // it will be set to non-NULL if loaded OK
BOARD* loadedBoard = nullptr; // it will be set to non-NULL if loaded OK
PLUGIN::RELEASER pi( IO_MGR::PluginFind( pluginType ) );
wxString msg;
LAYER_REMAPPABLE_PLUGIN* layerRemappablePlugin =
dynamic_cast< LAYER_REMAPPABLE_PLUGIN* >( (PLUGIN*) pi );
@ -701,21 +701,31 @@ bool PCB_EDIT_FRAME::OpenProjectFiles( const std::vector<wxString>& aFileSet, in
printf( "PLUGIN::Load(): %u usecs\n", stopTime - startTime );
#endif
}
catch( const FUTURE_FORMAT_ERROR& ffe )
{
msg.Printf( _( "Error loading PCB '%s'." ), fullFileName );
progressReporter.Hide();
DisplayErrorMessage( this, msg, ffe.Problem() );
failedLoad = true;
}
catch( const IO_ERROR& ioe )
{
if( ioe.Problem() != wxT( "CANCEL" ) )
{
DisplayErrorMessage( this, wxString::Format( _( "Error loading PCB '%s'." ),
fullFileName ),
ioe.What() );
msg.Printf( _( "Error loading PCB '%s'." ), fullFileName );
progressReporter.Hide();
DisplayErrorMessage( this, msg, ioe.What() );
}
failedLoad = true;
}
catch( const std::bad_alloc& )
{
DisplayErrorMessage( this, wxString::Format( _( "Memory exhausted loading PCB '%s'" ),
fullFileName ) );
msg.Printf( _( "Memory exhausted loading PCB '%s'" ), fullFileName );
progressReporter.Hide();
DisplayErrorMessage( this, msg, wxEmptyString );
failedLoad = true;
}

View File

@ -2199,7 +2199,7 @@ BOARD* PCB_IO::Load( const wxString& aFileName, BOARD* aAppendToMe, const PROPER
aProgressReporter->Report( wxString::Format( _( "Loading %s..." ), aFileName ) );
if( !aProgressReporter->KeepRefreshing() )
THROW_IO_ERROR( ( "Open cancelled by user." ) );
THROW_IO_ERROR( _( "Open cancelled by user." ) );
while( reader.ReadLine() )
lineCount++;
@ -2248,9 +2248,8 @@ BOARD* PCB_IO::DoLoad( LINE_READER& aReader, BOARD* aAppendToMe, const PROPERTIE
if( !board )
{
// The parser loaded something that was valid, but wasn't a board.
THROW_PARSE_ERROR( _( "this file does not contain a PCB" ),
m_parser->CurSource(), m_parser->CurLine(),
m_parser->CurLineNumber(), m_parser->CurOffset() );
THROW_PARSE_ERROR( _( "This file does not contain a PCB." ), m_parser->CurSource(),
m_parser->CurLine(), m_parser->CurLineNumber(), m_parser->CurOffset() );
}
return board;