Pcbnew footprint library plug in fixes and minor code cleaning.

* When loading footprint do not retest every footprint in cache.  Only test
  the footprint being loaded.  Fixes long load times on libraries with a lot
  of parts.
* Fix footprint name bug where file extension was added to the end of the
  footprint name.
* Fix bug in path equivalence test due to Posix path separators in footprint
  library table.  Convert paths to native separator before comparison.
* Fix a bug in FOOTPRINT_VIEWER_FRAME::OnActivate() which cause the footprint
  list to always get reloaded when using footprint library tables.
* Remove some unnecessary debugging messages.
* Add a few Doxygen comments to FP_CACHE in kicad_plugin.cpp.
This commit is contained in:
Wayne Stambaugh 2013-09-24 14:45:57 -04:00
parent 7125da8a45
commit 85777d6569
5 changed files with 131 additions and 44 deletions

View File

@ -158,9 +158,6 @@ bool FOOTPRINT_LIST::ReadFootprintFiles( FP_LIB_TABLE& aTable )
wxString path = FP_LIB_TABLE::ExpandSubstitutions( row->GetFullURI() ); wxString path = FP_LIB_TABLE::ExpandSubstitutions( row->GetFullURI() );
wxArrayString fpnames = pi->FootprintEnumerate( path ); wxArrayString fpnames = pi->FootprintEnumerate( path );
wxLogDebug( wxT( "Load footprint library type %s from path <%s>" ),
GetChars( row->GetType() ), GetChars( path ) );
for( unsigned i=0; i<fpnames.GetCount(); ++i ) for( unsigned i=0; i<fpnames.GetCount(); ++i )
{ {
std::auto_ptr<MODULE> m( pi->FootprintLoad( path, fpnames[i] ) ); std::auto_ptr<MODULE> m( pi->FootprintLoad( path, fpnames[i] ) );

View File

@ -59,7 +59,7 @@ using namespace std;
/** /**
* Definition for enabling and disabling footprint library trace output. See the * Definition for enabling and disabling footprint library trace output. See the
* wxWidgets documentation on useing the WXTRACE environment variable. * wxWidgets documentation on using the WXTRACE environment variable.
*/ */
static const wxString traceFootprintLibrary( wxT( "KicadFootprintLib" ) ); static const wxString traceFootprintLibrary( wxT( "KicadFootprintLib" ) );
@ -95,12 +95,25 @@ FP_CACHE_ITEM::FP_CACHE_ITEM( MODULE* aModule, const wxFileName& aFileName ) :
m_module( aModule ) m_module( aModule )
{ {
m_file_name = aFileName; m_file_name = aFileName;
m_mod_time.Now();
if( m_file_name.FileExists() )
m_mod_time = m_file_name.GetModificationTime();
else
m_mod_time.Now();
} }
bool FP_CACHE_ITEM::IsModified() const bool FP_CACHE_ITEM::IsModified() const
{ {
if( !m_file_name.FileExists() )
return false;
wxLogTrace( traceFootprintLibrary, wxT( "File <%s>, m_mod_time %s-%s, file mod time: %s-%s." ),
GetChars( m_file_name.GetFullPath() ),
GetChars( m_mod_time.FormatDate() ), GetChars( m_mod_time.FormatTime() ),
GetChars( m_file_name.GetModificationTime().FormatDate() ),
GetChars( m_file_name.GetModificationTime().FormatTime() ) );
return m_file_name.GetModificationTime() != m_mod_time; return m_file_name.GetModificationTime() != m_mod_time;
} }
@ -136,9 +149,35 @@ public:
void Remove( const wxString& aFootprintName ); void Remove( const wxString& aFootprintName );
wxDateTime GetLibModificationTime(); wxDateTime GetLibModificationTime() const;
bool IsModified(); /**
* Function IsModified
* check if the footprint cache has been modified relative to \a aLibPath
* and \a aFootprintName.
*
* @param aLibPath is a path to test the current cache library path against.
* @param aFootprintName is the footprint name in the cache to test. If the footprint
* name is empty, the all the footprint files in the library are
* checked to see if they have been modified.
* @return true if the cache has been modified.
*/
bool IsModified( const wxString& aLibPath,
const wxString& aFootprintName = wxEmptyString ) const;
/**
* Function IsPath
* checks if \a aPath is the same as the current cache path.
*
* This tests paths by converting \a aPath using the native separators. Internally
* #FP_CACHE stores the current path using native separators. This prevents path
* miscompares on Windows due to the fact that paths can be stored with / instead of \\
* in the footprint library table.
*
* @param aPath is the library path to test against.
* @return true if \a aPath is the same as the cache path.
*/
bool IsPath( const wxString& aPath ) const;
}; };
@ -149,7 +188,7 @@ FP_CACHE::FP_CACHE( PCB_IO* aOwner, const wxString& aLibraryPath )
} }
wxDateTime FP_CACHE::GetLibModificationTime() wxDateTime FP_CACHE::GetLibModificationTime() const
{ {
return m_lib_path.GetModificationTime(); return m_lib_path.GetModificationTime();
} }
@ -181,7 +220,8 @@ void FP_CACHE::Save()
// Allow file output stream to go out of scope to close the file stream before // Allow file output stream to go out of scope to close the file stream before
// renaming the file. // renaming the file.
{ {
// wxLogTrace( traceFootprintLibrary, wxT( "Creating temporary library file %s" ), GetChars( tempFileName ) ); wxLogTrace( traceFootprintLibrary, wxT( "Creating temporary library file %s" ),
GetChars( tempFileName ) );
FILE_OUTPUTFORMATTER formatter( tempFileName ); FILE_OUTPUTFORMATTER formatter( tempFileName );
@ -228,9 +268,12 @@ void FP_CACHE::Load()
m_owner->m_parser->SetLineReader( &reader ); m_owner->m_parser->SetLineReader( &reader );
std::string name = TO_UTF8( fpFileName ); std::string name = TO_UTF8( fullPath.GetName() );
MODULE* footprint = (MODULE*) m_owner->m_parser->Parse();
m_modules.insert( name, new FP_CACHE_ITEM( (MODULE*) m_owner->m_parser->Parse(), fpFileName ) ); // The footprint name is the file name without the extension.
footprint->SetFPID( fullPath.GetName() );
m_modules.insert( name, new FP_CACHE_ITEM( footprint, fullPath ) );
} while( dir.GetNext( &fpFileName ) ); } while( dir.GetNext( &fpFileName ) );
@ -263,30 +306,56 @@ void FP_CACHE::Remove( const wxString& aFootprintName )
} }
bool FP_CACHE::IsModified() bool FP_CACHE::IsPath( const wxString& aPath ) const
{ {
if( !m_lib_path.DirExists() ) // Converts path separators to native path separators
wxFileName newPath;
newPath.AssignDir( aPath );
return m_lib_path == newPath;
}
bool FP_CACHE::IsModified( const wxString& aLibPath, const wxString& aFootprintName ) const
{
// The library is modified if the library path got deleted or changed.
if( !m_lib_path.DirExists() || !IsPath( aLibPath ) )
return true; return true;
for( MODULE_ITER it = m_modules.begin(); it != m_modules.end(); ++it ) // If no footprint was specified, check every file modification time against the time
// it was loaded.
if( aFootprintName.IsEmpty() )
{ {
wxFileName fn = it->second->GetFileName(); for( MODULE_CITER it = m_modules.begin(); it != m_modules.end(); ++it )
if( !fn.FileExists() )
{ {
wxLogTrace( traceFootprintLibrary, wxT( "Footprint cache file '%s' does not exist." ), wxFileName fn = m_lib_path;
fn.GetFullPath().GetData() ); fn.SetName( it->second->GetFileName().GetName() );
return true; fn.SetExt( KiCadFootprintFileExtension );
}
if( it->second->IsModified() ) if( !fn.FileExists() )
{ {
wxLogTrace( traceFootprintLibrary, wxLogTrace( traceFootprintLibrary,
wxT( "Footprint cache file '%s' has been modified." ), wxT( "Footprint cache file '%s' does not exist." ),
fn.GetFullPath().GetData() ); fn.GetFullPath().GetData() );
return true; return true;
}
if( it->second->IsModified() )
{
wxLogTrace( traceFootprintLibrary,
wxT( "Footprint cache file '%s' has been modified." ),
fn.GetFullPath().GetData() );
return true;
}
} }
} }
else
{
MODULE_CITER it = m_modules.find( TO_UTF8( aFootprintName ) );
if( it == m_modules.end() || it->second->IsModified() )
return true;
}
return false; return false;
} }
@ -1590,9 +1659,9 @@ void PCB_IO::init( PROPERTIES* aProperties )
} }
void PCB_IO::cacheLib( const wxString& aLibraryPath ) void PCB_IO::cacheLib( const wxString& aLibraryPath, const wxString& aFootprintName )
{ {
if( !m_cache || m_cache->GetPath() != aLibraryPath || m_cache->IsModified() ) if( !m_cache || m_cache->IsModified( aLibraryPath, aFootprintName ) )
{ {
// a spectacular episode in memory management: // a spectacular episode in memory management:
delete m_cache; delete m_cache;
@ -1630,7 +1699,7 @@ MODULE* PCB_IO::FootprintLoad( const wxString& aLibraryPath, const wxString& aFo
init( aProperties ); init( aProperties );
cacheLib( aLibraryPath ); cacheLib( aLibraryPath, aFootprintName );
const MODULE_MAP& mods = m_cache->GetModules(); const MODULE_MAP& mods = m_cache->GetModules();
@ -1817,7 +1886,7 @@ bool PCB_IO::FootprintLibDelete( const wxString& aLibraryPath, PROPERTIES* aProp
wxMilliSleep( 250L ); wxMilliSleep( 250L );
#endif #endif
if( m_cache && m_cache->GetPath() == aLibraryPath ) if( m_cache && !m_cache->IsPath( aLibraryPath ) )
{ {
delete m_cache; delete m_cache;
m_cache = NULL; m_cache = NULL;

View File

@ -210,7 +210,7 @@ private:
throw( IO_ERROR ); throw( IO_ERROR );
/// we only cache one footprint library for now, this determines which one. /// we only cache one footprint library for now, this determines which one.
void cacheLib( const wxString& aLibraryPath ); void cacheLib( const wxString& aLibraryPath, const wxString& aFootprintName = wxEmptyString );
void init( PROPERTIES* aProperties ); void init( PROPERTIES* aProperties );
}; };

View File

@ -149,7 +149,7 @@ FOOTPRINT_VIEWER_FRAME::FOOTPRINT_VIEWER_FRAME( PCB_BASE_FRAME* aParent,
SetBoard( new BOARD() ); SetBoard( new BOARD() );
// Ensure all layers and items are visible: // Ensure all layers and items are visible:
GetBoard()->SetVisibleAlls(); GetBoard()->SetVisibleAlls();
SetScreen( new PCB_SCREEN(GetPageSizeIU()) ); SetScreen( new PCB_SCREEN( GetPageSizeIU() ) );
GetScreen()->m_Center = true; // Center coordinate origins on screen. GetScreen()->m_Center = true; // Center coordinate origins on screen.
LoadSettings(); LoadSettings();
@ -198,7 +198,7 @@ FOOTPRINT_VIEWER_FRAME::FOOTPRINT_VIEWER_FRAME( PCB_BASE_FRAME* aParent,
DisplayLibInfos(); DisplayLibInfos();
// If a footprint was previsiously loaded, reload it // If a footprint was previously loaded, reload it
if( !m_libraryName.IsEmpty() && !m_footprintName.IsEmpty() ) if( !m_libraryName.IsEmpty() && !m_footprintName.IsEmpty() )
{ {
#if !defined( USE_FP_LIB_TABLE ) #if !defined( USE_FP_LIB_TABLE )
@ -235,9 +235,9 @@ FOOTPRINT_VIEWER_FRAME::FOOTPRINT_VIEWER_FRAME( PCB_BASE_FRAME* aParent,
mesg.MessageToolbarPane(); mesg.MessageToolbarPane();
// Manage main toolbal // Manage main toolbar
m_auimgr.AddPane( m_mainToolBar, m_auimgr.AddPane( m_mainToolBar,
wxAuiPaneInfo( horiz ).Name( wxT ("m_mainToolBar" ) ).Top().Row( 0 ) ); wxAuiPaneInfo( horiz ).Name( wxT( "m_mainToolBar" ) ).Top().Row( 0 ) );
wxSize minsize( 60, -1 ); wxSize minsize( 60, -1 );
@ -290,6 +290,7 @@ FOOTPRINT_VIEWER_FRAME::~FOOTPRINT_VIEWER_FRAME()
m_Draw3DFrame->Destroy(); m_Draw3DFrame->Destroy();
} }
/* return the frame name used when creating the frame /* return the frame name used when creating the frame
* used to get a reference to this frame, if exists * used to get a reference to this frame, if exists
*/ */
@ -298,13 +299,14 @@ const wxChar* FOOTPRINT_VIEWER_FRAME::GetFootprintViewerFrameName()
return FOOTPRINT_VIEWER_FRAME_NAME; return FOOTPRINT_VIEWER_FRAME_NAME;
} }
/* return a reference to the current opened Footprint viewer /* return a reference to the current opened Footprint viewer
* or NULL if no Footprint viewer currently opened * or NULL if no Footprint viewer currently opened
*/ */
FOOTPRINT_VIEWER_FRAME* FOOTPRINT_VIEWER_FRAME::GetActiveFootprintViewer() FOOTPRINT_VIEWER_FRAME* FOOTPRINT_VIEWER_FRAME::GetActiveFootprintViewer()
{ {
return (FOOTPRINT_VIEWER_FRAME*) return (FOOTPRINT_VIEWER_FRAME*)
wxWindow::FindWindowByName(GetFootprintViewerFrameName()); wxWindow::FindWindowByName( GetFootprintViewerFrameName() );
} }
@ -400,8 +402,8 @@ void FOOTPRINT_VIEWER_FRAME::ReCreateLibraryList()
} }
else else
{ {
/* If not found, clear current library selection because it can be // If not found, clear current library selection because it can be deleted after
* deleted after a config change. */ // a configuration change.
m_libraryName = wxEmptyString; m_libraryName = wxEmptyString;
m_footprintName = wxEmptyString; m_footprintName = wxEmptyString;
} }
@ -452,6 +454,7 @@ void FOOTPRINT_VIEWER_FRAME::ReCreateFootprintList()
if( !libLoaded ) if( !libLoaded )
{ {
m_footprintName = wxEmptyString;
m_libraryName = wxEmptyString; m_libraryName = wxEmptyString;
wxString msg; wxString msg;
@ -462,7 +465,7 @@ void FOOTPRINT_VIEWER_FRAME::ReCreateFootprintList()
msg += _( "Files not found:\n\n" ) + fp_info_list.m_filesNotFound; msg += _( "Files not found:\n\n" ) + fp_info_list.m_filesNotFound;
if( !fp_info_list.m_filesInvalid.IsEmpty() ) if( !fp_info_list.m_filesInvalid.IsEmpty() )
msg += _("\n\nFile load errors:\n\n" ) + fp_info_list.m_filesInvalid; msg += _( "\n\nFile load errors:\n\n" ) + fp_info_list.m_filesInvalid;
DisplayError( this, msg ); DisplayError( this, msg );
return; return;
@ -566,7 +569,7 @@ void FOOTPRINT_VIEWER_FRAME::DClickOnFootprintList( wxCommandEvent& event )
// event in the parent window which would cause the part to be parked // event in the parent window which would cause the part to be parked
// rather than staying in mode mode. // rather than staying in mode mode.
// Remember the mouse button will be released in the parent window // Remember the mouse button will be released in the parent window
// thus creating a mouse button release event which should be ingnored. // thus creating a mouse button release event which should be ignored
((PCB_BASE_FRAME*)GetParent())->SkipNextLeftButtonReleaseEvent(); ((PCB_BASE_FRAME*)GetParent())->SkipNextLeftButtonReleaseEvent();
} }
} }
@ -640,19 +643,37 @@ void FOOTPRINT_VIEWER_FRAME::OnActivate( wxActivateEvent& event )
m_selectedFootprintName.Empty(); m_selectedFootprintName.Empty();
// Ensure we have the right library list: // Ensure we have the right library list:
#if !defined( USE_FP_LIB_TABLE )
if( g_LibraryNames.GetCount() == m_LibList->GetCount() ) if( g_LibraryNames.GetCount() == m_LibList->GetCount() )
{ {
unsigned ii; unsigned ii;
for( ii = 0; ii < g_LibraryNames.GetCount(); ii++ ) for( ii = 0; ii < g_LibraryNames.GetCount(); ii++ )
{ {
if( m_LibList->GetString(ii) != g_LibraryNames[ii] ) if( m_LibList->GetString( ii ) != g_LibraryNames[ii] )
break; break;
} }
if( ii == g_LibraryNames.GetCount() ) if( ii == g_LibraryNames.GetCount() )
return; return;
} }
#else
std::vector< wxString > libNicknames = m_footprintLibTable->GetLogicalLibs();
if( libNicknames.size() == m_LibList->GetCount() )
{
unsigned ii;
for( ii = 0; ii < libNicknames.size(); ii++ )
{
if( libNicknames[ii] != m_LibList->GetString( ii ) )
break;
}
if( ii == libNicknames.size() )
return;
}
#endif
// If we are here, the library list has changed, rebuild it // If we are here, the library list has changed, rebuild it
ReCreateLibraryList(); ReCreateLibraryList();

View File

@ -754,8 +754,8 @@ T PCB_PARSER::lookUpLayer( const M& aMap ) throw( PARSE_ERROR, IO_ERROR )
// dump the whole darn table, there's something wrong with it. // dump the whole darn table, there's something wrong with it.
for( it = aMap.begin(); it != aMap.end(); ++it ) for( it = aMap.begin(); it != aMap.end(); ++it )
{ {
printf( &aMap == (void*)&m_layerIndices ? "lm[%s] = %d\n" : "lm[%s] = %08X\n", wxLogDebug( &aMap == (void*)&m_layerIndices ? wxT( "lm[%s] = %d" ) :
it->first.c_str(), it->second ); wxT( "lm[%s] = %08X" ), it->first.c_str(), it->second );
} }
#endif #endif