Eeschema: allow for partial schematic loading.

With the implementation of the legacy schematic plugin, any I/O error
when parsing the schematics would prevent the entire schematic from
being loaded.  This change restores (somewhat) the previous behavior
where as long as the root schematic is loaded properly, then all of
the remaining sub-sheet will attempt to load.

Add GetError() method the SCH_PLUGIN object to allow for partial
schematic loading.

Check the error message contents when no exception was caught to warn
the user of any accumulated errors.

Fixes lp:1690644

https://bugs.launchpad.net/kicad/+bug/1690644
This commit is contained in:
Wayne Stambaugh 2017-12-06 19:10:45 -05:00
parent f44d4d01ea
commit 8af9aa7574
6 changed files with 85 additions and 18 deletions

View File

@ -293,6 +293,15 @@ bool SCH_EDIT_FRAME::OpenProjectFiles( const std::vector<wxString>& aFileSet, in
g_RootSheet = pi->Load( fullFileName, &Kiway() );
m_CurrentSheet->clear();
m_CurrentSheet->push_back( g_RootSheet );
if( !pi->GetError().IsEmpty() )
{
DisplayErrorMessage( this,
_( "The entire schematic could not be load. Errors "
"occurred attempting to load hierarchical sheet "
"schematics." ),
pi->GetError() );
}
}
catch( const IO_ERROR& ioe )
{
@ -434,6 +443,15 @@ bool SCH_EDIT_FRAME::AppendSchematic()
try
{
pi->Load( fullFileName, &Kiway(), newSheet.get() );
if( !pi->GetError().IsEmpty() )
{
DisplayErrorMessage( this,
_( "The entire schematic could not be load. Errors "
"occurred attempting to load hierarchical sheet "
"schematics." ),
pi->GetError() );
}
}
catch( const IO_ERROR& ioe )
{

View File

@ -486,13 +486,23 @@ public:
virtual void SymbolLibOptions( PROPERTIES* aListToAppendTo ) const;
/**
* Function CheckHeader
* returns true if the first line in @a aFileName begins with the expected header
* Return true if the first line in @a aFileName begins with the expected header.
*
* @param aFileName is the name of the file to use as input
*
*/
virtual bool CheckHeader( const wxString& aFileName );
/**
* Return an error string to the caller.
*
* This is useful for schematic loaders that can load partial schematics where throwing
* an exception would be problematic such as the KiCad legacy plugin.
*
* @return an unformatted string containing errors if any.
*/
virtual const wxString& GetError() const;
//-----</PUBLIC SCH_PLUGIN API>------------------------------------------------

View File

@ -652,28 +652,44 @@ void SCH_LEGACY_PLUGIN::loadHierarchy( SCH_SHEET* aSheet )
{
aSheet->SetScreen( new SCH_SCREEN( m_kiway ) );
aSheet->GetScreen()->SetFileName( fileName.GetFullPath() );
loadFile( fileName.GetFullPath(), aSheet->GetScreen() );
EDA_ITEM* item = aSheet->GetScreen()->GetDrawItems();
while( item )
try
{
if( item->Type() == SCH_SHEET_T )
loadFile( fileName.GetFullPath(), aSheet->GetScreen() );
EDA_ITEM* item = aSheet->GetScreen()->GetDrawItems();
while( item )
{
SCH_SHEET* sheet = (SCH_SHEET*) item;
if( item->Type() == SCH_SHEET_T )
{
SCH_SHEET* sheet = (SCH_SHEET*) item;
// Set the parent to aSheet. This effectively creates a method to find
// the root sheet from any sheet so a pointer to the root sheet does not
// need to be stored globally. Note: this is not the same as a hierarchy.
// Complex hierarchies can have multiple copies of a sheet. This only
// provides a simple tree to find the root sheet.
sheet->SetParent( aSheet );
// Set the parent to aSheet. This effectively creates a method to find
// the root sheet from any sheet so a pointer to the root sheet does not
// need to be stored globally. Note: this is not the same as a hierarchy.
// Complex hierarchies can have multiple copies of a sheet. This only
// provides a simple tree to find the root sheet.
sheet->SetParent( aSheet );
// Recursion starts here.
loadHierarchy( sheet );
// Recursion starts here.
loadHierarchy( sheet );
}
item = item->Next();
}
}
catch( const IO_ERROR& ioe )
{
// If there is a problem loading the root sheet, there is no recovery.
if( aSheet == m_rootSheet )
throw( ioe );
item = item->Next();
// For all subsheets, queue up the error message for the caller.
if( !m_error.IsEmpty() )
m_error += "\n";
m_error += ioe.What();
}
}
}

View File

@ -125,6 +125,8 @@ public:
bool CheckHeader( const wxString& aFileName ) override;
bool IsSymbolLibWritable( const wxString& aLibraryPath ) override;
const wxString& GetError() const override { return m_error; }
private:
void loadHierarchy( SCH_SHEET* aSheet );
void loadHeader( FILE_LINE_READER& aReader, SCH_SCREEN* aScreen );
@ -155,7 +157,10 @@ private:
protected:
int m_version; ///< Version of file being loaded.
wxString m_error; ///< For throwing exceptions
/** For throwing exceptions or errors on partial schematic loads. */
wxString m_error;
wxString m_path; ///< Root project path for loading child sheets.
const PROPERTIES* m_props; ///< Passed via Save() or Load(), no ownership, may be NULL.
KIWAY* m_kiway; ///< Required for path to legacy component libraries.

View File

@ -188,3 +188,12 @@ bool SCH_PLUGIN::CheckHeader( const wxString& aFileName )
not_implemented( this, __FUNCTION__ );
return false;
}
const wxString& SCH_PLUGIN::GetError() const
{
// not pure virtual so that plugins only have to implement subset of the SCH_PLUGIN interface.
not_implemented( this, __FUNCTION__ );
static wxString error;
return error;
}

View File

@ -247,6 +247,15 @@ bool SCH_EDIT_FRAME::EditSheet( SCH_SHEET* aSheet, SCH_SHEET_PATH* aHierarchy )
try
{
aSheet = pi->Load( newFilename, &Kiway(), aSheet );
if( !pi->GetError().IsEmpty() )
{
DisplayErrorMessage( this,
_( "The entire schematic could not be load. Errors "
"occurred attempting to load hierarchical sheet "
"schematics." ),
pi->GetError() );
}
}
catch( const IO_ERROR& ioe )
{