Commit 85777d65 authored by Wayne Stambaugh's avatar Wayne Stambaugh
Browse files

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.
parent 7125da8a
Loading
Loading
Loading
Loading
+0 −3
Original line number Original line Diff line number Diff line
@@ -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] ) );
+97 −28
Original line number Original line Diff line number Diff line
@@ -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;

    if( m_file_name.FileExists() )
        m_mod_time = m_file_name.GetModificationTime();
    else
        m_mod_time.Now();
        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,18 +306,36 @@ 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 )
        {
            wxFileName fn = m_lib_path;
            fn.SetName( it->second->GetFileName().GetName() );
            fn.SetExt( KiCadFootprintFileExtension );


            if( !fn.FileExists() )
            if( !fn.FileExists() )
            {
            {
            wxLogTrace( traceFootprintLibrary, wxT( "Footprint cache file '%s' does not exist." ),
                wxLogTrace( traceFootprintLibrary,
                            wxT( "Footprint cache file '%s' does not exist." ),
                            fn.GetFullPath().GetData() );
                            fn.GetFullPath().GetData() );
                return true;
                return true;
            }
            }
@@ -287,6 +348,14 @@ bool FP_CACHE::IsModified()
                return true;
                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;
+1 −1
Original line number Original line Diff line number Diff line
@@ -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 );
};
};
+31 −10
Original line number Original line Diff line number Diff line
@@ -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,7 +235,7 @@ 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 ) );


@@ -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,6 +299,7 @@ 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
 */
 */
@@ -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;
@@ -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,6 +643,7 @@ 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;
@@ -653,6 +657,23 @@ void FOOTPRINT_VIEWER_FRAME::OnActivate( wxActivateEvent& event )
        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();
+2 −2
Original line number Original line Diff line number Diff line
@@ -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