Fix an issue when reading a gpcb footprint library when a .fp file has a problem.

Now the full library loading is not aborted (and the other libraries in list are also loaded).
Only the bad .fp file(s) is not loaded.
Mainly, a .fp file load error does not throw a library load error, and this is a temporary fix.
But throwing a library error when a .fp file cannot be loaded is worst (you even cannot import a good .fp file).
This commit is contained in:
jean-pierre charras 2017-05-23 20:07:36 +02:00
parent ea855c1abf
commit 1a33efa133
2 changed files with 47 additions and 17 deletions

View File

@ -287,6 +287,9 @@ wxDateTime GPCB_FPL_CACHE::GetLibModificationTime() const
void GPCB_FPL_CACHE::Load() void GPCB_FPL_CACHE::Load()
{ {
// Note: like our .pretty footprint libraries, the gpcb footprint libraries are folders,
// and the footprints are the .fp files inside this folder.
wxDir dir( m_lib_path.GetPath() ); wxDir dir( m_lib_path.GetPath() );
if( !dir.IsOpened() ) if( !dir.IsOpened() )
@ -301,18 +304,32 @@ void GPCB_FPL_CACHE::Load()
if( !dir.GetFirst( &fpFileName, wildcard, wxDIR_FILES ) ) if( !dir.GetFirst( &fpFileName, wildcard, wxDIR_FILES ) )
return; return;
wxString cacheErrorMsg;
do do
{ {
wxFileName fn( m_lib_path.GetPath(), fpFileName ); wxFileName fn( m_lib_path.GetPath(), fpFileName );
// reader now owns fp, will close on exception or return // Queue I/O errors so only files that fail to parse don't get loaded.
FILE_LINE_READER reader( fn.GetFullPath() ); try
std::string name = TO_UTF8( fn.GetName() ); {
MODULE* footprint = parseMODULE( &reader ); // reader now owns fp, will close on exception or return
FILE_LINE_READER reader( fn.GetFullPath() );
// The footprint name is the file name without the extension. std::string name = TO_UTF8( fn.GetName() );
footprint->SetFPID( LIB_ID( fn.GetName() ) ); MODULE* footprint = parseMODULE( &reader );
m_modules.insert( name, new GPCB_FPL_CACHE_ITEM( footprint, fn.GetName() ) );
// The footprint name is the file name without the extension.
footprint->SetFPID( LIB_ID( fn.GetName() ) );
m_modules.insert( name, new GPCB_FPL_CACHE_ITEM( footprint, fn.GetName() ) );
}
catch( const IO_ERROR& ioe )
{
if( !cacheErrorMsg.IsEmpty() )
cacheErrorMsg += "\n";
cacheErrorMsg += ioe.What();
}
} while( dir.GetNext( &fpFileName ) ); } while( dir.GetNext( &fpFileName ) );
@ -320,6 +337,11 @@ void GPCB_FPL_CACHE::Load()
// cache snapshot was made, so that in a networked environment we will // cache snapshot was made, so that in a networked environment we will
// reload the cache as needed. // reload the cache as needed.
m_mod_time = GetLibModificationTime(); m_mod_time = GetLibModificationTime();
#if 0
if( !cacheErrorMsg.IsEmpty() )
THROW_IO_ERROR( cacheErrorMsg );
#endif
} }
@ -416,7 +438,10 @@ MODULE* GPCB_FPL_CACHE::parseMODULE( LINE_READER* aLineReader ) throw( IO_ERROR,
if( aLineReader->ReadLine() == NULL ) if( aLineReader->ReadLine() == NULL )
THROW_IO_ERROR( "unexpected end of file" ); {
msg = aLineReader->GetSource() + ": empty file";
THROW_IO_ERROR( msg );
}
parameters.Clear(); parameters.Clear();
parseParameters( parameters, aLineReader ); parseParameters( parameters, aLineReader );
@ -965,6 +990,7 @@ wxArrayString GPCB_PLUGIN::FootprintEnumerate( const wxString& aLibraryPath,
init( aProperties ); init( aProperties );
#if 1 // Set to 0 to only read directory contents, not load cache. #if 1 // Set to 0 to only read directory contents, not load cache.
cacheLib( aLibraryPath ); cacheLib( aLibraryPath );
const MODULE_MAP& mods = m_cache->GetModules(); const MODULE_MAP& mods = m_cache->GetModules();

View File

@ -92,7 +92,6 @@ static const wxString INFO_LEGACY_LIB_WARN_DELETE(
"before deleting a footprint" ) ); "before deleting a footprint" ) );
static const wxString ModLegacyExportFileWildcard( _( "Legacy foot print export files (*.emp)|*.emp" ) ); static const wxString ModLegacyExportFileWildcard( _( "Legacy foot print export files (*.emp)|*.emp" ) );
static const wxString ModImportFileWildcard( _( "GPcb foot print files (*)|*" ) );
#define EXPORT_IMPORT_LASTPATH_KEY wxT( "import_last_path" ) #define EXPORT_IMPORT_LASTPATH_KEY wxT( "import_last_path" )
@ -103,15 +102,14 @@ static const wxString ModImportFileWildcard( _( "GPcb foot print files (*)|*" )
* @param aParent - parent window for the dialog * @param aParent - parent window for the dialog
* @param aLastPath - last opened path * @param aLastPath - last opened path
*/ */
static wxFileName prompt_for_module( wxWindow* aParent, const wxString& aLastPath ) static wxFileName getFootprintFilenameFromUser( wxWindow* aParent, const wxString& aLastPath )
{ {
static int lastFilterIndex = 0; static int lastFilterIndex = 0; // To store the last choice during a session.
wxString wildCard; wxString wildCard;
wildCard << wxGetTranslation( KiCadFootprintLibFileWildcard ) << wxChar( '|' ) wildCard << wxGetTranslation( KiCadFootprintLibFileWildcard ) << wxChar( '|' )
<< wxGetTranslation( ModLegacyExportFileWildcard ) << wxChar( '|' ) << wxGetTranslation( ModLegacyExportFileWildcard ) << wxChar( '|' )
<< wxGetTranslation( ModImportFileWildcard ) << wxChar( '|' ) << wxGetTranslation( GedaPcbFootprintLibFileWildcard ) << wxChar( '|' );
<< wxGetTranslation( GedaPcbFootprintLibFileWildcard );
wxFileDialog dlg( aParent, FMT_IMPORT_MODULE, aLastPath, wxEmptyString, wildCard, wxFileDialog dlg( aParent, FMT_IMPORT_MODULE, aLastPath, wxEmptyString, wildCard,
wxFD_OPEN | wxFD_FILE_MUST_EXIST ); wxFD_OPEN | wxFD_FILE_MUST_EXIST );
@ -263,7 +261,7 @@ MODULE* FOOTPRINT_EDIT_FRAME::Import_Module()
if( config ) if( config )
config->Read( EXPORT_IMPORT_LASTPATH_KEY, &lastOpenedPathForLoading ); config->Read( EXPORT_IMPORT_LASTPATH_KEY, &lastOpenedPathForLoading );
wxFileName fn = prompt_for_module( this, lastOpenedPathForLoading ); wxFileName fn = getFootprintFilenameFromUser( this, lastOpenedPathForLoading );
if( !fn.IsOk() ) if( !fn.IsOk() )
return NULL; return NULL;
@ -292,8 +290,7 @@ MODULE* FOOTPRINT_EDIT_FRAME::Import_Module()
return NULL; return NULL;
} }
MODULE* module; MODULE* module = NULL;
wxString errMessage;
try try
{ {
@ -310,7 +307,14 @@ MODULE* FOOTPRINT_EDIT_FRAME::Import_Module()
catch( const IO_ERROR& ioe ) catch( const IO_ERROR& ioe )
{ {
DisplayError( this, ioe.What() ); DisplayError( this, ioe.What() );
return NULL;
// if the footprint is not loaded, exit.
// However, even if an error happens, it can be loaded, because in KICAD and GPCB format,
// a fp library is a set of separate files, and the error(s) are not necessary when
// reading the selected file
if( !module )
return NULL;
} }
// Insert footprint in list // Insert footprint in list