Commit ce409e36 authored by Wayne Stambaugh's avatar Wayne Stambaugh
Browse files

CvPcb footprint library table implementation.

* Add code to CvPcb to handle assigning component footprints from the
  footprint library table instead of the search path method.
* Add code to CvPcb to allow editing of the footprint library table.
* CvPcb footprint and component panes display fully qualified FPID names.
* Make CvPcb library pane display footprint library table nicknames instead
  of library file names.
* Add code to FP_LIB_TABLE object to test the paths in the table against the
  list of libraries loaded from the project file.
* Add code to FP_LIB_TABLE to convert assigned footprints in a NETLIST from
  legacy format to footprint library table format.
* Split out COMPONENT_NET, COMPONENT, and NETLIST objects from netlist_reader
  files and create new pcb_netlist files.
* Fix minor wxListView scroll bar sizing issues.
* Add new token and code to save and load FPID nickname in board file.
* Add new token and code to save and load FPID nickname in s-expression net
  list file.
* Add WX_STRING_REPORT object to dump strings to a wxString object.
parent 87290e52
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -137,6 +137,7 @@ set(PCB_COMMON_SRCS
    ../pcbnew/legacy_plugin.cpp
    ../pcbnew/kicad_plugin.cpp
    ../pcbnew/gpcb_plugin.cpp
    ../pcbnew/pcb_netlist.cpp
    pcb_plot_params_keywords.cpp
    pcb_keywords.cpp
    ../pcbnew/pcb_parser.cpp
+26 −0
Original line number Diff line number Diff line
@@ -39,6 +39,7 @@
#include <footprint_info.h>
#include <io_mgr.h>
#include <fp_lib_table.h>
#include <fpid.h>

#include <class_module.h>

@@ -182,6 +183,31 @@ bool FOOTPRINT_LIST::ReadFootprintFiles( FP_LIB_TABLE& aTable )
}


FOOTPRINT_INFO* FOOTPRINT_LIST::GetModuleInfo( const wxString & aFootprintName )
{
    BOOST_FOREACH( FOOTPRINT_INFO& footprint, m_List )
    {
#if defined( USE_FP_LIB_TABLE )
        FPID fpid;

        wxCHECK_MSG( fpid.Parse( TO_UTF8( aFootprintName ) ) < 0, NULL,
                     wxString::Format( wxT( "<%s> is not a valid FPID." ),
                                       GetChars( aFootprintName ) ) );

        wxString libNickname = FROM_UTF8( fpid.GetLibNickname().c_str() );
        wxString footprintName = FROM_UTF8( fpid.GetFootprintName().c_str() );

        if( libNickname == footprint.m_libName && footprintName == footprint.m_Module )
            return &footprint;
#else
        if( aFootprintName.CmpNoCase( footprint.m_Module ) == 0 )
            return &footprint;
#endif
    }
    return NULL;
}


bool FOOTPRINT_INFO::InLibrary( const wxString& aLibrary ) const
{
    if( aLibrary.IsEmpty() )
+215 −3
Original line number Diff line number Diff line
@@ -31,10 +31,14 @@
#include <set>

#include <appl_wxstruct.h>
#include <pcb_netlist.h>
#include <reporter.h>
#include <footprint_info.h>
#include <wildcards_and_files_ext.h>
#include <fpid.h>
#include <fp_lib_table_lexer.h>
#include <fp_lib_table.h>


using namespace FP_LIB_TABLE_T;


@@ -251,6 +255,35 @@ const FP_LIB_TABLE::ROW* FP_LIB_TABLE::findRow( const wxString& aNickName )
}


const FP_LIB_TABLE::ROW* FP_LIB_TABLE::FindRowByURI( const wxString& aURI )
{
    FP_LIB_TABLE* cur = this;

    do
    {
        cur->ensureIndex();

        for( unsigned i = 0;  i < cur->rows.size();  i++ )
        {
            wxString uri = ExpandSubstitutions( cur->rows[i].GetFullURI() );

            if( wxFileName::GetPathSeparator() == wxChar( '\\' ) && uri.Find( wxChar( '/' ) ) >= 0 )
                uri.Replace( wxT( "/" ), wxT( "\\" ) );

            if( (wxFileName::IsCaseSensitive() && uri == aURI)
              || (!wxFileName::IsCaseSensitive() && uri.Upper() == aURI.Upper() ) )
            {
                return &cur->rows[i];  // found
            }
        }

        // not found, search fall back table(s), if any
    } while( ( cur = cur->fallBack ) != 0 );

    return 0;   // not found
}


bool FP_LIB_TABLE::InsertRow( const ROW& aRow, bool doReplace )
{
    ensureIndex();
@@ -320,6 +353,185 @@ bool FP_LIB_TABLE::IsEmpty() const
}


bool FP_LIB_TABLE::MissingLegacyLibs( const wxArrayString& aLibNames, wxString* aErrorMsg )
{
    bool retv = false;

    for( unsigned i = 0;  i < aLibNames.GetCount();  i++ )
    {
        wxFileName fn = wxFileName( wxEmptyString, aLibNames[i], LegacyFootprintLibPathExtension );
        wxString legacyLibPath = wxGetApp().FindLibraryPath( fn );

        if( legacyLibPath.IsEmpty() )
            continue;

        if( FindRowByURI( legacyLibPath ) == 0 )
        {
            retv = true;

            if( aErrorMsg )
                *aErrorMsg += wxT( "\"" ) + legacyLibPath + wxT( "\"\n" );
        }
    }

    return retv;
}


bool FP_LIB_TABLE::ConvertFromLegacy( NETLIST& aNetList, const wxArrayString& aLibNames,
                                      REPORTER* aReporter ) throw( IO_ERROR )
{
    wxString   msg;
    FPID       lastFPID;
    COMPONENT* component;
    MODULE*    module = 0;
    bool       retv = true;

    if( aNetList.IsEmpty() )
        return true;

    aNetList.SortByFPID();

    wxString   libPath;
    wxFileName fn;

    PLUGIN::RELEASER pi( IO_MGR::PluginFind( IO_MGR::LEGACY ) );

    for( unsigned ii = 0; ii < aNetList.GetCount(); ii++ )
    {
        component = aNetList.GetComponent( ii );

        // The footprint hasn't been assigned yet so ignore it.
        if( component->GetFPID().empty() )
            continue;

        if( component->GetFPID() != lastFPID )
        {
            module = NULL;

            for( unsigned ii = 0; ii < aLibNames.GetCount(); ii++ )
            {
                fn = wxFileName( wxEmptyString, aLibNames[ii], LegacyFootprintLibPathExtension );

                libPath = wxGetApp().FindLibraryPath( fn );

                if( !libPath )
                {
                    if( aReporter )
                    {
                        msg.Printf( _( "Cannot find footprint library file \"%s\" in any of the "
                                       "KiCad legacy library search paths.\n" ),
                                    GetChars( fn.GetFullPath() ) );
                        aReporter->Report( msg );
                    }

                    retv = false;
                    continue;
                }

                module = pi->FootprintLoad( libPath,
                                            FROM_UTF8( component->GetFPID().GetFootprintName().c_str() ) );

                if( module )
                {
                    lastFPID = component->GetFPID();
                    break;
                }
            }
        }

        if( module == NULL )
        {
            if( aReporter )
            {
                msg.Printf( _( "Component `%s` footprint <%s> was not found in any legacy "
                               "library.\n" ),
                            GetChars( component->GetReference() ),
                            GetChars( FROM_UTF8( component->GetFPID().Format().c_str() ) ) );
                aReporter->Report( msg );
            }

            // Clear the footprint assignment since the old library lookup method is no
            // longer valid.
            FPID emptyFPID;
            component->SetFPID( emptyFPID );
            retv = false;
            continue;
        }
        else
        {
            wxLogDebug( wxT( "Found component %s footprint %s in legacy library <%s>." ),
                        GetChars( component->GetReference() ),
                        GetChars( GetChars( FROM_UTF8( component->GetFPID().Format().c_str() ) ) ),
                        GetChars( libPath ) );

            wxString libNickname;

            FP_LIB_TABLE* cur = this;

            do
            {
                cur->ensureIndex();

                for( unsigned i = 0;  i < cur->rows.size();  i++ )
                {
                    wxString uri = ExpandSubstitutions( cur->rows[i].GetFullURI() );

                    if( wxFileName::GetPathSeparator() == wxChar( '\\' )
                      && uri.Find( wxChar( '/' ) ) >= 0 )
                        uri.Replace( wxT( "/"), wxT( "\\" ) );

                    wxLogDebug( wxT( "Comparing legacy path <%s> to lib table path <%s>." ),
                                GetChars( libPath ), GetChars( uri ) );

                    if( uri == libPath )
                    {
                        libNickname = cur->rows[i].GetNickName();
                        break;
                    }
                }
            } while( ( cur = cur->fallBack ) != 0 && libNickname.IsEmpty() );

            if( libNickname.IsEmpty() )
            {
                if( aReporter )
                {
                    msg.Printf( _( "Component `%s` footprint <%s> legacy library path <%s > "
                                   "was not found in the footprint library table.\n" ),
                                GetChars( component->GetReference() ),
                                GetChars( FROM_UTF8( component->GetFPID().Format().c_str() ) ) );
                    aReporter->Report( msg );
                }

                retv = false;
            }
            else
            {
                FPID newFPID = lastFPID;

                newFPID.SetLibNickname( libNickname );

                if( !newFPID.IsValid() )
                {
                    msg.Printf( _( "Component `%s` FPID <%s> is not valid.\n" ),
                                GetChars( component->GetReference() ),
                                GetChars( FROM_UTF8( newFPID.Format().c_str() ) ) );
                    aReporter->Report( msg );
                    retv = false;
                }
                else
                {
                    // The footprint name should already be set.
                    component->SetFPID( newFPID );
                }
            }
        }
    }

    return retv;
}


bool FP_LIB_TABLE::LoadGlobalTable( FP_LIB_TABLE& aTable ) throw (IO_ERROR, PARSE_ERROR )
{
    bool tableExists = true;
+11 −1
Original line number Diff line number Diff line
/**
 * @file reporter.h
 * @file reporter.cpp
 */
/*
 * This program source code file is part of KiCad, a free EDA CAD application.
@@ -43,3 +43,13 @@ REPORTER& WX_TEXT_CTRL_REPORTER::Report( const wxString& aText )
    m_textCtrl->AppendText( aText );
    return *this;
}


REPORTER& WX_STRING_REPORTER::Report( const wxString& aText )
{
    wxCHECK_MSG( m_string != NULL, *this,
                 wxT( "No wxString object defined in WX_STRING_REPORTER." ) );

    *m_string << aText;
    return *this;
}
+3 −0
Original line number Diff line number Diff line
@@ -9,6 +9,7 @@ include_directories(
    ./dialogs
    ../3d-viewer
    ../pcbnew
    ../pcbnew/dialogs
    ../polygon
    ../common
    ${INC_AFTER}
@@ -22,6 +23,8 @@ set( CVPCB_DIALOGS
    dialogs/dialog_cvpcb_config_fbp.cpp
    dialogs/dialog_display_options.cpp
    dialogs/dialog_display_options_base.cpp
    ../pcbnew/dialogs/dialog_fp_lib_table.cpp
    ../pcbnew/dialogs/dialog_fp_lib_table_base.cpp
    )

set( CVPCB_SRCS
Loading