From 1a33efa1333553869558c731a05318e576ed729d Mon Sep 17 00:00:00 2001 From: jean-pierre charras Date: Tue, 23 May 2017 20:07:36 +0200 Subject: [PATCH] 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). --- pcbnew/gpcb_plugin.cpp | 42 ++++++++++++++++++++++++++++++++++-------- pcbnew/librairi.cpp | 22 +++++++++++++--------- 2 files changed, 47 insertions(+), 17 deletions(-) diff --git a/pcbnew/gpcb_plugin.cpp b/pcbnew/gpcb_plugin.cpp index e4c092b9f8..472336a0d9 100644 --- a/pcbnew/gpcb_plugin.cpp +++ b/pcbnew/gpcb_plugin.cpp @@ -287,6 +287,9 @@ wxDateTime GPCB_FPL_CACHE::GetLibModificationTime() const 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() ); if( !dir.IsOpened() ) @@ -301,18 +304,32 @@ void GPCB_FPL_CACHE::Load() if( !dir.GetFirst( &fpFileName, wildcard, wxDIR_FILES ) ) return; + wxString cacheErrorMsg; + do { wxFileName fn( m_lib_path.GetPath(), fpFileName ); - // reader now owns fp, will close on exception or return - FILE_LINE_READER reader( fn.GetFullPath() ); - std::string name = TO_UTF8( fn.GetName() ); - MODULE* footprint = parseMODULE( &reader ); + // Queue I/O errors so only files that fail to parse don't get loaded. + try + { + // 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. - footprint->SetFPID( LIB_ID( fn.GetName() ) ); - m_modules.insert( name, new GPCB_FPL_CACHE_ITEM( footprint, fn.GetName() ) ); + std::string name = TO_UTF8( fn.GetName() ); + MODULE* footprint = parseMODULE( &reader ); + + // 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 ) ); @@ -320,6 +337,11 @@ void GPCB_FPL_CACHE::Load() // cache snapshot was made, so that in a networked environment we will // reload the cache as needed. 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 ) - THROW_IO_ERROR( "unexpected end of file" ); + { + msg = aLineReader->GetSource() + ": empty file"; + THROW_IO_ERROR( msg ); + } parameters.Clear(); parseParameters( parameters, aLineReader ); @@ -965,6 +990,7 @@ wxArrayString GPCB_PLUGIN::FootprintEnumerate( const wxString& aLibraryPath, init( aProperties ); #if 1 // Set to 0 to only read directory contents, not load cache. + cacheLib( aLibraryPath ); const MODULE_MAP& mods = m_cache->GetModules(); diff --git a/pcbnew/librairi.cpp b/pcbnew/librairi.cpp index 42df647ab6..c07ceb63cf 100644 --- a/pcbnew/librairi.cpp +++ b/pcbnew/librairi.cpp @@ -92,7 +92,6 @@ static const wxString INFO_LEGACY_LIB_WARN_DELETE( "before deleting a footprint" ) ); 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" ) @@ -103,15 +102,14 @@ static const wxString ModImportFileWildcard( _( "GPcb foot print files (*)|*" ) * @param aParent - parent window for the dialog * @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; wildCard << wxGetTranslation( KiCadFootprintLibFileWildcard ) << wxChar( '|' ) << wxGetTranslation( ModLegacyExportFileWildcard ) << wxChar( '|' ) - << wxGetTranslation( ModImportFileWildcard ) << wxChar( '|' ) - << wxGetTranslation( GedaPcbFootprintLibFileWildcard ); + << wxGetTranslation( GedaPcbFootprintLibFileWildcard ) << wxChar( '|' ); wxFileDialog dlg( aParent, FMT_IMPORT_MODULE, aLastPath, wxEmptyString, wildCard, wxFD_OPEN | wxFD_FILE_MUST_EXIST ); @@ -263,7 +261,7 @@ MODULE* FOOTPRINT_EDIT_FRAME::Import_Module() if( config ) config->Read( EXPORT_IMPORT_LASTPATH_KEY, &lastOpenedPathForLoading ); - wxFileName fn = prompt_for_module( this, lastOpenedPathForLoading ); + wxFileName fn = getFootprintFilenameFromUser( this, lastOpenedPathForLoading ); if( !fn.IsOk() ) return NULL; @@ -292,8 +290,7 @@ MODULE* FOOTPRINT_EDIT_FRAME::Import_Module() return NULL; } - MODULE* module; - wxString errMessage; + MODULE* module = NULL; try { @@ -310,7 +307,14 @@ MODULE* FOOTPRINT_EDIT_FRAME::Import_Module() catch( const IO_ERROR& ioe ) { 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