void PCB_EDIT_FRAME::loadFootprints( NETLIST& aNetlist, REPORTER* aReporter )
    throw( IO_ERROR, PARSE_ERROR )
{
    wxString   msg;
    FPID       lastFPID;
    COMPONENT* component;
    MODULE*    module = 0;
    MODULE*    fpOnBoard;

    if( aNetlist.IsEmpty() || FootprintLibs()->IsEmpty() )
        return;

    aNetlist.SortByFPID();

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

#if ALLOW_PARTIAL_FPID
        // The FPID is ok as long as there is a footprint portion coming
        // from eeschema.
        if( !component->GetFPID().GetFootprintName().size() )
#else
        if( component->GetFPID().empty() )
#endif
        {
            if( aReporter )
            {
                msg.Printf( _( "No footprint defined for component '%s'.\n" ),
                            GetChars( component->GetReference() ) );
                aReporter->Report( msg );
            }

            continue;
        }

        // Check if component footprint is already on BOARD and only load the footprint from
        // the library if it's needed.  Nickname can be blank.
        if( aNetlist.IsFindByTimeStamp() )
            fpOnBoard = m_Pcb->FindModule( aNetlist.GetComponent( ii )->GetTimeStamp(), true );
        else
            fpOnBoard = m_Pcb->FindModule( aNetlist.GetComponent( ii )->GetReference() );

        bool footprintMisMatch = fpOnBoard &&
                                 fpOnBoard->GetFPID() != component->GetFPID();

        if( footprintMisMatch && !aNetlist.GetReplaceFootprints() )
        {
            if( aReporter )
            {
                msg.Printf( _( "* Warning: component '%s' has footprint '%s' and should be '%s'\n" ),
                            GetChars( component->GetReference() ),
                            fpOnBoard->GetFPID().GetFootprintName().c_str(),
                            component->GetFPID().GetFootprintName().c_str() );
                aReporter->Report( msg );
            }

            continue;
        }

        if( !aNetlist.GetReplaceFootprints() )
            footprintMisMatch = false;

        bool loadFootprint = (fpOnBoard == NULL) || footprintMisMatch;

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

#if ALLOW_PARTIAL_FPID
            // The FPID is ok as long as there is a footprint portion coming
            // the library if it's needed.  Nickname can be blank.
            if( !component->GetFPID().GetFootprintName().size() )
#else
            if( !component->GetFPID().IsValid() )
#endif
            {
                if( aReporter )
                {
                    msg.Printf( _( "*** Warning: Component '%s' footprint ID '%s' is not "
                                   "valid. ***\n" ),
                                GetChars( component->GetReference() ),
                                component->GetFPID().GetFootprintName().c_str() );
                    aReporter->Report( msg );
                }

                continue;
            }

            // loadFootprint() can find a footprint with an empty nickname in fpid.
            module = PCB_BASE_FRAME::loadFootprint( component->GetFPID() );

            if( module )
            {
                lastFPID = component->GetFPID();
            }
            else
            {
                if( aReporter )
                {
                    wxString msg;
                    msg.Printf( _( "*** Warning: component '%s' footprint '%s' was not found in "
                                   "any libraries in the footprint library table. ***\n" ),
                                GetChars( component->GetReference() ),
                                component->GetFPID().GetFootprintName().c_str() );
                    aReporter->Report( msg );
                }

                continue;
            }
        }
        else
        {
            // Footprint already loaded from a library, duplicate it (faster)
            if( module == NULL )
                continue;            // Module does not exist in any library.

            module = new MODULE( *module );
        }

        if( loadFootprint && module != NULL )
            component->SetModule( module );
    }
}
Beispiel #2
0
void PCB_EDIT_FRAME::LoadFootprints( NETLIST& aNetlist, REPORTER* aReporter )
{
    wxString   msg;
    LIB_ID     lastFPID;
    COMPONENT* component;
    MODULE*    module = 0;
    MODULE*    fpOnBoard;

    if( aNetlist.IsEmpty() || Prj().PcbFootprintLibs()->IsEmpty() )
        return;

    aNetlist.SortByFPID();

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

#if ALLOW_PARTIAL_FPID
        // The FPID is ok as long as there is a footprint portion coming
        // from eeschema.
        if( !component->GetFPID().GetLibItemName().size() )
#else
        if( component->GetFPID().empty() )
#endif
        {
            if( aReporter )
            {
                msg.Printf( _( "No footprint defined for symbol \"%s\".\n" ),
                            GetChars( component->GetReference() ) );
                aReporter->Report( msg, REPORTER::RPT_ERROR );
            }

            continue;
        }

        // Check if component footprint is already on BOARD and only load the footprint from
        // the library if it's needed.  Nickname can be blank.
        if( aNetlist.IsFindByTimeStamp() )
            fpOnBoard = m_Pcb->FindModule( aNetlist.GetComponent( ii )->GetTimeStamp(), true );
        else
            fpOnBoard = m_Pcb->FindModule( aNetlist.GetComponent( ii )->GetReference() );

        bool footprintMisMatch = fpOnBoard &&
                                 fpOnBoard->GetFPID() != component->GetFPID();

        if( footprintMisMatch && !aNetlist.GetReplaceFootprints() )
        {
            if( aReporter )
            {
                msg.Printf( _( "Footprint of symbol \"%s\" changed: board footprint \"%s\", netlist footprint \"%s\"\n" ),
                            GetChars( component->GetReference() ),
                            GetChars( fpOnBoard->GetFPID().Format() ),
                            GetChars( component->GetFPID().Format() ) );
                aReporter->Report( msg, REPORTER::RPT_WARNING );
            }

            continue;
        }

        if( !aNetlist.GetReplaceFootprints() )
            footprintMisMatch = false;

        if( fpOnBoard && !footprintMisMatch )   // nothing else to do here
            continue;

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

#if ALLOW_PARTIAL_FPID
            // The LIB_ID is ok as long as there is a footprint portion coming
            // the library if it's needed.  Nickname can be blank.
            if( !component->GetFPID().GetLibItemName().size() )
#else
            if( !component->GetFPID().IsValid() )
#endif
            {
                if( aReporter )
                {
                    msg.Printf( _( "Component \"%s\" footprint ID \"%s\" is not "
                                   "valid.\n" ),
                                GetChars( component->GetReference() ),
                                GetChars( component->GetFPID().Format() ) );
                    aReporter->Report( msg, REPORTER::RPT_ERROR );
                }

                continue;
            }

            // loadFootprint() can find a footprint with an empty nickname in fpid.
            module = PCB_BASE_FRAME::loadFootprint( component->GetFPID() );

            if( module )
            {
                lastFPID = component->GetFPID();
            }
            else
            {
                if( aReporter )
                {
                    msg.Printf( _( "Component \"%s\" footprint \"%s\" was not found in "
                                   "any libraries in the footprint library table.\n" ),
                                GetChars( component->GetReference() ),
                                GetChars( component->GetFPID().GetLibItemName() ) );
                    aReporter->Report( msg, REPORTER::RPT_ERROR );
                }

                continue;
            }
        }
        else
        {
            // Footprint already loaded from a library, duplicate it (faster)
            if( module == NULL )
                continue;            // Module does not exist in any library.

            module = new MODULE( *module );
        }

        if( module )
            component->SetModule( module );
    }
}
/**
 * Function convertFromLegacy
 * converts the footprint names in \a aNetList from the legacy format to the #FPID format.
 *
 * @param aNetList is the #NETLIST object to convert.
 * @param aLibNames is the list of legacy footprint library names from the currently loaded
 *                  project.
 * @param aReporter is the #REPORTER object to dump messages into.
 * @return true if all footprint names were successfully converted to a valid FPID.
 */
static bool convertFromLegacy( FP_LIB_TABLE* aTbl, SEARCH_STACK& aSStack, NETLIST& aNetList,
        const wxArrayString& aLibNames, REPORTER* aReporter = NULL ) throw( IO_ERROR )
{
    wxString   msg;
    FPID       lastFPID;
    COMPONENT* component;
    MODULE*    module = 0;
    bool       retv = true;

    if( aNetList.IsEmpty() )
        return true;

    aNetList.SortByFPID();

    wxString   libPath;

    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++ )
            {
                wxFileName fn( wxEmptyString, aLibNames[ii], LegacyFootprintLibPathExtension );

                libPath = aSStack.FindValidPath( fn.GetFullPath() );

                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, component->GetFPID().GetFootprintName() );

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

        if( !module )
        {
            if( aReporter )
            {
                msg.Printf( _( "Component '%s' footprint '%s' was not found in any legacy "
                               "library.\n" ),
                            GetChars( component->GetReference() ),
                            GetChars( component->GetFPID().Format() ) );
                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
        {
            wxString    libNickname;

            const FP_LIB_TABLE::ROW* row;

            if( ( row = aTbl->FindRowByURI( libPath ) ) != NULL )
                libNickname = row->GetNickName();

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

                retv = false;
            }
            else
            {
                FPID newFPID = lastFPID;
                newFPID.SetLibNickname( libNickname );

                if( !newFPID.IsValid() )
                {
                    if( aReporter )
                    {
                        msg.Printf( _( "Component '%s' FPID '%s' is not valid.\n" ),
                                    GetChars( component->GetReference() ),
                                    GetChars( newFPID.Format() ) );
                        aReporter->Report( msg );
                    }

                    retv = false;
                }
                else
                {
                    // The footprint name should already be set.
                    component->SetFPID( newFPID );
                }
            }
        }
    }

    return retv;
}