void LEGACY_NETLIST_READER::loadFootprintFilters() throw( IO_ERROR, PARSE_ERROR ) { wxArrayString filters; wxString cmpRef; char* line; COMPONENT* component = NULL; // Suppress compil warning while( ( line = m_lineReader->ReadLine() ) != NULL ) { if( strnicmp( line, "$endlist", 8 ) == 0 ) // end of list for the current component { wxASSERT( component != NULL ); component->SetFootprintFilters( filters ); component = NULL; filters.Clear(); continue; } if( strnicmp( line, "$endfootprintlist", 4 ) == 0 ) // End of this section return; if( strnicmp( line, "$component", 10 ) == 0 ) // New component reference found { cmpRef = FROM_UTF8( line + 11 ); cmpRef.Trim( true ); cmpRef.Trim( false ); component = m_netlist->GetComponentByReference( cmpRef ); // Cannot happen if the netlist is valid. if( component == NULL ) { wxString msg; msg.Printf( _( "Cannot find component \'%s\' in footprint filter section " "of netlist." ), GetChars( cmpRef ) ); THROW_PARSE_ERROR( msg, m_lineReader->GetSource(), line, m_lineReader->LineNumber(), m_lineReader->Length() ); } } else { // Add new filter to list wxString fp = FROM_UTF8( line + 1 ); fp.Trim( false ); fp.Trim( true ); filters.Add( fp ); } } }
void CVPCB_MAINFRAME::SendMessageToEESCHEMA() { if( m_netlist.IsEmpty() ) return; int selection = m_compListBox->GetSelection(); if ( selection < 0 ) selection = 0; if( m_netlist.GetComponent( selection ) == NULL ) return; COMPONENT* component = m_netlist.GetComponent( selection ); std::string packet = StrPrintf( "$PART: \"%s\"", TO_UTF8( component->GetReference() ) ); if( Kiface().IsSingle() ) SendCommand( MSG_TO_SCH, packet.c_str() ); else Kiway().ExpressMail( FRAME_SCH, MAIL_CROSS_PROBE, packet, this ); }
void CVPCB_MAINFRAME::SetNewPkg( const wxString& aFootprintName, int aIndex ) { COMPONENT* component; if( m_netlist.IsEmpty() ) return; component = m_netlist.GetComponent( aIndex ); if( component == NULL ) return; LIB_ID fpid; if( !aFootprintName.IsEmpty() ) { wxCHECK_RET( fpid.Parse( aFootprintName, LIB_ID::ID_PCB ) < 0, wxString::Format( _( "\"%s\" is not a valid LIB_ID." ), aFootprintName ) ); } component->SetFPID( fpid ); // create the new component description wxString description = wxString::Format( CMP_FORMAT, aIndex + 1, GetChars( component->GetReference() ), GetChars( component->GetValue() ), GetChars( FROM_UTF8( component->GetFPID().Format().c_str() ) ) ); // Set the new description and deselect the processed component m_compListBox->SetString( aIndex, description ); // Mark this "session" as modified m_modified = true; // update the statusbar DisplayStatus(); }
void CVPCB_MAINFRAME::BuildCmpListBox() { wxString msg; COMPONENT* component; wxFont guiFont = wxSystemSettings::GetFont( wxSYS_DEFAULT_GUI_FONT ); if( m_compListBox == NULL ) { m_compListBox = new COMPONENTS_LISTBOX( this, ID_CVPCB_COMPONENT_LIST, wxDefaultPosition, wxDefaultSize ); m_compListBox->SetFont( wxFont( guiFont.GetPointSize(), wxFONTFAMILY_MODERN, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL ) ); } m_compListBox->m_ComponentList.Clear(); for( unsigned i = 0; i < m_netlist.GetCount(); i++ ) { component = m_netlist.GetComponent( i ); msg.Printf( CMP_FORMAT, m_compListBox->GetCount() + 1, GetChars( component->GetReference() ), GetChars( component->GetValue() ), GetChars( FROM_UTF8( component->GetFPID().Format().c_str() ) ) ); m_compListBox->m_ComponentList.Add( msg ); } if( m_compListBox->m_ComponentList.Count() ) { m_compListBox->SetItemCount( m_compListBox->m_ComponentList.Count() ); m_compListBox->SetSelection( 0, true ); m_compListBox->RefreshItems( 0L, m_compListBox->m_ComponentList.Count()-1 ); m_compListBox->UpdateWidth(); } }
void KICAD_NETLIST_PARSER::parseComponent() throw( IO_ERROR, PARSE_ERROR, boost::bad_pointer ) { /* Parses a section like * (comp (ref P1) * (value DB25FEMELLE) * (footprint DB25FC) * (libsource (lib conn) (part DB25)) * (sheetpath (names /) (tstamps /)) * (tstamp 3256759C)) * * other fields (unused) are skipped * A component need a reference, value, footprint name and a full time stamp * The full time stamp is the sheetpath time stamp + the component time stamp */ FPID fpid; wxString footprint; wxString tmp; wxString ref; wxString value; wxString library; wxString name; wxString pathtimestamp, timestamp; // The token comp was read, so the next data is (ref P1) while( (token = NextTok()) != T_RIGHT ) { if( token == T_LEFT ) token = NextTok(); switch( token ) { case T_ref: NeedSYMBOLorNUMBER(); ref = FROM_UTF8( CurText() ); NeedRIGHT(); break; case T_value: NeedSYMBOLorNUMBER(); value = FROM_UTF8( CurText() ); NeedRIGHT(); break; case T_footprint: NeedSYMBOLorNUMBER(); footprint = FromUTF8(); NeedRIGHT(); break; case T_libsource: // Read libsource while( (token = NextTok()) != T_RIGHT ) { if( token == T_LEFT ) token = NextTok(); if( token == T_lib ) { NeedSYMBOLorNUMBER(); library = FROM_UTF8( CurText() ); NeedRIGHT(); } else if( token == T_part ) { NeedSYMBOLorNUMBER(); name = FROM_UTF8( CurText() ); NeedRIGHT(); } else { Expecting( "part or lib" ); } } break; case T_sheetpath: while( ( token = NextTok() ) != T_tstamps ); NeedSYMBOLorNUMBER(); pathtimestamp = FROM_UTF8( CurText() ); NeedRIGHT(); NeedRIGHT(); break; case T_tstamp: NeedSYMBOLorNUMBER(); timestamp = FROM_UTF8( CurText() ); NeedRIGHT(); break; default: // Skip not used data (i.e all other tokens) skipCurrent(); break; } } if( !footprint.IsEmpty() && fpid.Parse( footprint ) >= 0 ) { wxString error; error.Printf( _( "invalid PFID in\nfile: <%s>\nline: %d\noffset: %d" ), GetChars( CurSource() ), CurLineNumber(), CurOffset() ); THROW_IO_ERROR( error ); } pathtimestamp += timestamp; COMPONENT* component = new COMPONENT( fpid, ref, value, pathtimestamp ); component->SetName( name ); component->SetLibrary( library ); m_netlist->AddComponent( component ); }
void KICAD_NETLIST_PARSER::parseNet() throw( IO_ERROR, PARSE_ERROR ) { /* Parses a section like * (net (code 20) (name /PC-A0) * (node (ref BUS1) (pin 62)) * (node (ref U3) (pin 3)) * (node (ref U9) (pin M6))) */ COMPONENT* component = NULL; wxString code; wxString name; wxString reference; wxString pin; int nodecount = 0; // The token net was read, so the next data is (code <number>) while( (token = NextTok()) != T_RIGHT ) { if( token == T_LEFT ) token = NextTok(); switch( token ) { case T_code: NeedSYMBOLorNUMBER(); code = FROM_UTF8( CurText() ); NeedRIGHT(); break; case T_name: NeedSYMBOLorNUMBER(); name = FROM_UTF8( CurText() ); NeedRIGHT(); if( name.IsEmpty() ) // Give a dummy net name like N-000109 name = wxT("N-00000") + code; break; case T_node: while( (token = NextTok()) != T_RIGHT ) { if( token == T_LEFT ) token = NextTok(); switch( token ) { case T_ref: NeedSYMBOLorNUMBER(); reference = FROM_UTF8( CurText() ); NeedRIGHT(); break; case T_pin: NeedSYMBOLorNUMBER(); pin = FROM_UTF8( CurText() ); NeedRIGHT(); break; default: skipCurrent(); break; } } component = m_netlist->GetComponentByReference( reference ); // Cannot happen if the netlist is valid. if( component == NULL ) { wxString msg; msg.Printf( _( "Cannot find component with reference \"%s\" in netlist." ), GetChars( reference ) ); THROW_PARSE_ERROR( msg, m_lineReader->GetSource(), m_lineReader->Line(), m_lineReader->LineNumber(), m_lineReader->Length() ); } component->AddNet( pin, name ); nodecount++; break; default: skipCurrent(); break; } } }
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 ); } }
bool CVPCB_MAINFRAME::ReadNetListAndLinkFiles() { wxString msg; bool hasMissingNicks = false; FP_LIB_TABLE* tbl = FootprintLibs(); ReadSchematicNetlist(); if( m_ListCmp == NULL ) return false; LoadProjectFile( m_NetlistFileName.GetFullPath() ); LoadFootprintFiles(); BuildFOOTPRINTS_LISTBOX(); BuildLIBRARY_LISTBOX(); m_ListCmp->Clear(); m_undefinedComponentCnt = 0; if( m_netlist.AnyFootprintsLinked() ) { for( unsigned i = 0; i < m_netlist.GetCount(); i++ ) { COMPONENT* component = m_netlist.GetComponent( i ); if( component->GetFPID().empty() ) continue; if( component->GetFPID().IsLegacy() ) hasMissingNicks = true; } } // Check if footprint links were generated before the footprint library table was implemented. if( hasMissingNicks ) { msg = wxT( "Some of the assigned footprints are legacy entries (are missing lib nicknames). " "Would you like CvPcb to attempt to convert them to the new required FPID format? " "(If you answer no, then these assignments will be cleared out and you will " "have to re-assign these footprints yourself.)" ); if( IsOK( this, msg ) ) { msg.Clear(); try { for( unsigned i = 0; i < m_netlist.GetCount(); i++ ) { COMPONENT* component = m_netlist.GetComponent( i ); if( component->GetFPID().IsLegacy() ) { int guess = guessNickname( tbl, (FPID*) &component->GetFPID() ); switch( guess ) { case 0: DBG(printf("%s: guessed OK ref:%s fpid:%s\n", __func__, TO_UTF8( component->GetReference() ), component->GetFPID().Format().c_str() );) m_modified = true; break; case 1: msg += wxString::Format( _( "Component '%s' footprint '%s' was <b>not found</b> in any library.\n" ), GetChars( component->GetReference() ), GetChars( component->GetFPID().GetFootprintName() ) ); break; case 2: msg += wxString::Format( _( "Component '%s' footprint '%s' was found in <b>multiple</b> libraries.\n" ), GetChars( component->GetReference() ), GetChars( component->GetFPID().GetFootprintName() ) ); break; } } } }
void CVPCB_MAINFRAME::OnSelectComponent( wxListEvent& event ) { if( m_skipComponentSelect ) return; wxString libraryName; COMPONENT* component = NULL; int filter = FOOTPRINTS_LISTBOX::UNFILTERED; if( m_mainToolBar->GetToolToggled( ID_CVPCB_FOOTPRINT_DISPLAY_FILTERED_LIST ) ) filter |= FOOTPRINTS_LISTBOX::BY_COMPONENT; if( m_mainToolBar->GetToolToggled( ID_CVPCB_FOOTPRINT_DISPLAY_PIN_FILTERED_LIST ) ) filter |= FOOTPRINTS_LISTBOX::BY_PIN_COUNT; if( m_mainToolBar->GetToolToggled( ID_CVPCB_FOOTPRINT_DISPLAY_BY_LIBRARY_LIST ) ) filter |= FOOTPRINTS_LISTBOX::BY_LIBRARY; component = GetSelectedComponent(); libraryName = m_libListBox->GetSelectedLibrary(); m_footprintListBox->SetFootprints( m_footprints, libraryName, component, filter ); // Tell AuiMgr that objects are changed ! if( m_auimgr.GetManagedWindow() ) // Be sure Aui Manager is initialized // (could be not the case when starting CvPcb m_auimgr.Update(); if( component == NULL ) return; // Preview of the already assigned footprint. // Find the footprint that was already chosen for this component and select it, // but only if the selection is made from the component list or the library list. // If the selection is made from the footprint list, do not change the current // selected footprint. if( FindFocus() == m_compListBox || FindFocus() == m_libListBox ) { wxString module = FROM_UTF8( component->GetFPID().Format().c_str() ); bool found = false; for( int ii = 0; ii < m_footprintListBox->GetCount(); ii++ ) { wxString footprintName; wxString msg = m_footprintListBox->OnGetItemText( ii, 0 ); msg.Trim( true ); msg.Trim( false ); footprintName = msg.AfterFirst( wxChar( ' ' ) ); if( module.Cmp( footprintName ) == 0 ) { m_footprintListBox->SetSelection( ii, true ); found = true; break; } } if( !found ) { int ii = m_footprintListBox->GetSelection(); if ( ii >= 0 ) m_footprintListBox->SetSelection( ii, false ); if( GetFpViewerFrame() ) { CreateScreenCmp(); } } } SendMessageToEESCHEMA(); DisplayStatus(); }
/** * Operator < * compares two #COMPONENT objects by reference designator. */ bool operator < ( const COMPONENT& item1, const COMPONENT& item2 ) { return StrNumCmp( item1.GetReference(), item2.GetReference(), INT_MAX, true ) < 0; }
/** * Function ByFPID * is a helper function used to sort the component list used by loadNewModules. */ static bool ByFPID( const COMPONENT& ref, const COMPONENT& cmp ) { return ref.GetFPID() > cmp.GetFPID(); }
void CVPCB_MAINFRAME::AutomaticFootprintMatching( wxCommandEvent& event ) { FOOTPRINT_EQUIVALENCE_LIST equiv_List; COMPONENT* component; wxString msg, error_msg; size_t ii; if( m_netlist.IsEmpty() ) return; if( buildEquivalenceList( equiv_List, &error_msg ) ) wxMessageBox( error_msg, _( "Equivalence File Load Error" ), wxOK | wxICON_WARNING, this ); // Sort the association list by component value. // When sorted, find duplicate definitions (i.e. 2 or more items // having the same component value) is more easy. std::sort( equiv_List.begin(), equiv_List.end(), sortListbyCmpValue ); // Display the number of footprint/component equivalences. msg.Printf( _( "%lu footprint/cmp equivalences found." ), (unsigned long)equiv_List.size() ); SetStatusText( msg, 0 ); // Now, associate each free component with a footprint, when the association // is found in list m_skipComponentSelect = true; ii = 0; error_msg.Empty(); for( unsigned kk = 0; kk < m_netlist.GetCount(); kk++ ) { component = m_netlist.GetComponent( kk ); bool found = false; m_compListBox->SetSelection( ii++, true ); if( !component->GetFPID().empty() ) // the component has already a footprint continue; // Here a first attempt is made. We can have multiple equivItem of the same value. // When happens, using the footprint filter of components can remove the ambiguity by // filtering equivItem so one can use multiple equiv_List (for polar and // non-polar caps for example) for( unsigned idx = 0; idx < equiv_List.size(); idx++ ) { FOOTPRINT_EQUIVALENCE& equivItem = equiv_List[idx]; if( equivItem.m_ComponentValue.CmpNoCase( component->GetValue() ) != 0 ) continue; const FOOTPRINT_INFO *module = m_FootprintsList.GetModuleInfo( equivItem.m_FootprintFPID ); bool equ_is_unique = true; unsigned next = idx+1; int previous = idx-1; if( next < equiv_List.size() && equivItem.m_ComponentValue == equiv_List[next].m_ComponentValue ) equ_is_unique = false; if( previous >= 0 && equivItem.m_ComponentValue == equiv_List[previous].m_ComponentValue ) equ_is_unique = false; // If the equivalence is unique, no ambiguity: use the association if( module && equ_is_unique ) { SetNewPkg( equivItem.m_FootprintFPID ); found = true; break; } // The equivalence is not unique: use the footprint filter to try to remove // ambiguity if( module ) { size_t filtercount = component->GetFootprintFilters().GetCount(); found = ( 0 == filtercount ); // if no entries, do not filter for( size_t jj = 0; jj < filtercount && !found; jj++ ) { found = module->GetFootprintName().Matches( component->GetFootprintFilters()[jj] ); } } else { msg.Printf( _( "Component %s: footprint %s not found in any of the project " "footprint libraries." ), GetChars( component->GetReference() ), GetChars( equivItem.m_FootprintFPID ) ); if( ! error_msg.IsEmpty() ) error_msg << wxT("\n\n"); error_msg += msg; } if( found ) { SetNewPkg( equivItem.m_FootprintFPID ); break; } } if( found ) continue; // obviously the last chance: there's only one filter matching one footprint if( 1 == component->GetFootprintFilters().GetCount() ) { // we do not need to analyze wildcards: single footprint do not // contain them and if there are wildcards it just will not match any const FOOTPRINT_INFO* module = m_FootprintsList.GetModuleInfo( component->GetFootprintFilters()[0] ); if( module ) SetNewPkg( component->GetFootprintFilters()[0] ); } } if( !error_msg.IsEmpty() ) wxMessageBox( error_msg, _( "CvPcb Warning" ), wxOK | wxICON_WARNING, this ); m_skipComponentSelect = false; }
bool DIALOG_NETLIST::verifyFootprints( const wxString& aNetlistFilename, const wxString & aCmpFilename, std::vector< MODULE* >& aDuplicates, wxArrayString& aMissing, std::vector< MODULE* >& aNotInNetlist ) { wxString msg; MODULE* module; MODULE* nextModule; NETLIST netlist; wxBusyCursor dummy; // Shows an hourglass while calculating. NETLIST_READER* netlistReader; COMPONENT* component; try { netlistReader = NETLIST_READER::GetNetlistReader( &netlist, aNetlistFilename, aCmpFilename ); if( netlistReader == NULL ) { msg.Printf( _( "Cannot open netlist file \"%s\"." ), GetChars( aNetlistFilename ) ); wxMessageBox( msg, _( "Netlist Load Error." ), wxOK | wxICON_ERROR ); return false; } std::auto_ptr< NETLIST_READER > nlr( netlistReader ); netlistReader->LoadNetlist(); } catch( const IO_ERROR& ioe ) { msg.Printf( _( "Error loading netlist file:\n%s" ), ioe.errorText.GetData() ); wxMessageBox( msg, _( "Netlist Load Error" ), wxOK | wxICON_ERROR ); return false; } BOARD* pcb = m_parent->GetBoard(); // Search for duplicate footprints. module = pcb->m_Modules; for( ; module != NULL; module = module->Next() ) { nextModule = module->Next(); for( ; nextModule != NULL; nextModule = nextModule->Next() ) { if( module->GetReference().CmpNoCase( nextModule->GetReference() ) == 0 ) { aDuplicates.push_back( module ); break; } } } // Search for component footprints in the netlist but not on the board. for( unsigned ii = 0; ii < netlist.GetCount(); ii++ ) { component = netlist.GetComponent( ii ); module = pcb->FindModuleByReference( component->GetReference() ); if( module == NULL ) { aMissing.Add( component->GetReference() ); aMissing.Add( component->GetValue() ); } } // Search for component footprints found on board but not in netlist. module = pcb->m_Modules; for( ; module != NULL; module = module->Next() ) { component = netlist.GetComponentByReference( module->GetReference() ); if( component == NULL ) aNotInNetlist.push_back( module ); } return true; }
void CVPCB_MAINFRAME::SetNewPkg( const wxString& aFootprintName ) { COMPONENT* component; bool hasFootprint = false; int componentIndex; if( m_netlist.IsEmpty() ) return; // If no component is selected, select the first one if( m_compListBox->GetFirstSelected() < 0 ) { componentIndex = 0; m_compListBox->SetSelection( componentIndex, true ); } // iterate over the selection while( m_compListBox->GetFirstSelected() != -1 ) { // Get the component for the current iteration componentIndex = m_compListBox->GetFirstSelected(); component = m_netlist.GetComponent( componentIndex ); if( component == NULL ) return; // Check to see if the component has already a footprint set. hasFootprint = !component->GetFPID().empty(); FPID fpid; if( !aFootprintName.IsEmpty() ) { wxCHECK_RET( fpid.Parse( aFootprintName ) < 0, wxString::Format( wxT( "<%s> is not a valid FPID." ), GetChars( aFootprintName ) ) ); } component->SetFPID( fpid ); // create the new component description wxString description = wxString::Format( CMP_FORMAT, componentIndex + 1, GetChars( component->GetReference() ), GetChars( component->GetValue() ), GetChars( FROM_UTF8( component->GetFPID().Format().c_str() ) ) ); // If the component hasn't had a footprint associated with it // it now has, so we decrement the count of components without // a footprint assigned. if( !hasFootprint ) { hasFootprint = true; m_undefinedComponentCnt -= 1; } // Set the new description and deselect the processed component m_compListBox->SetString( componentIndex, description ); m_compListBox->SetSelection( componentIndex, false ); } // Mark this "session" as modified m_modified = true; // select the next component, if there is one if( componentIndex < (m_compListBox->GetCount() - 1) ) componentIndex++; m_compListBox->SetSelection( componentIndex, true ); // update the statusbar DisplayStatus(); }
bool CVPCB_MAINFRAME::ReadNetListAndLinkFiles() { COMPONENT* component; wxString msg; bool isLegacy = true; ReadSchematicNetlist(); if( m_ListCmp == NULL ) return false; LoadProjectFile( m_NetlistFileName.GetFullPath() ); LoadFootprintFiles(); BuildFOOTPRINTS_LISTBOX(); BuildLIBRARY_LISTBOX(); m_ListCmp->Clear(); m_undefinedComponentCnt = 0; if( m_netlist.AnyFootprintsLinked() ) { for( unsigned i = 0; i < m_netlist.GetCount(); i++ ) { component = m_netlist.GetComponent( i ); if( component->GetFPID().empty() ) continue; if( isLegacy ) { if( !component->GetFPID().IsLegacy() ) isLegacy = false; } } } else { isLegacy = false; // None of the components have footprints assigned. } wxString missingLibs; // Check if footprint links were generated before the footprint library table was implemented. if( isLegacy ) { if( m_footprintLibTable->MissingLegacyLibs( m_ModuleLibNames, &missingLibs ) ) { msg = wxT( "The following legacy libraries are defined in the project file " "were not found in the footprint library table:\n\n" ) + missingLibs; msg += wxT( "\nDo you want to update the footprint library table before " "attempting to update the assigned footprints?" ); if( IsOK( this, msg ) ) { wxCommandEvent cmd; OnEditFootprintLibraryTable( cmd ); } } msg = wxT( "Some or all of the assigned footprints contain legacy entries. Would you " "like CvPcb to attempt to convert them to the new footprint library table " "format?" ); if( IsOK( this, msg ) ) { msg.Clear(); WX_STRING_REPORTER reporter( &msg ); if( !m_footprintLibTable->ConvertFromLegacy( m_netlist, m_ModuleLibNames, &reporter ) ) { HTML_MESSAGE_BOX dlg( this, wxEmptyString ); dlg.MessageSet( wxT( "The following errors occurred attempt to convert the " "footprint assignments:\n\n" ) ); dlg.ListSet( msg ); dlg.MessageSet( wxT( "\nYou will need to reassign them manually if you want them " "to be updated correctly the next time you import the " "netlist in Pcbnew." ) ); dlg.ShowModal(); } m_modified = true; } else { // Clear the legacy footprint assignments. for( unsigned i = 0; i < m_netlist.GetCount(); i++ ) { FPID emptyFPID; component = m_netlist.GetComponent( i ); component->SetFPID( emptyFPID ); m_modified = true; } } } for( unsigned i = 0; i < m_netlist.GetCount(); i++ ) { component = m_netlist.GetComponent( i ); msg.Printf( CMP_FORMAT, m_ListCmp->GetCount() + 1, GetChars( component->GetReference() ), GetChars( component->GetValue() ), GetChars( FROM_UTF8( component->GetFPID().Format().c_str() ) ) ); m_ListCmp->AppendLine( msg ); if( component->GetFPID().empty() ) { m_undefinedComponentCnt += 1; continue; } } if( !m_netlist.IsEmpty() ) m_ListCmp->SetSelection( 0, true ); DisplayStatus(); UpdateTitle(); UpdateFileHistory( m_NetlistFileName.GetFullPath() ); return true; }
void KICAD_NETLIST_PARSER::parseLibPartList() throw( IO_ERROR, PARSE_ERROR ) { /* Parses a section like * (libpart (lib device) (part C) * (aliases * (alias Cxx) * (alias Cyy)) * (description "Condensateur non polarise") * (footprints * (fp SM*) * (fp C?) * (fp C1-1)) * (fields * (field (name Reference) C) * (field (name Value) C)) * (pins * (pin (num 1) (name ~) (type passive)) * (pin (num 2) (name ~) (type passive)))) * * Currently footprints section/fp are read and data stored * other fields (unused) are skipped */ COMPONENT* component = NULL; wxString libName; wxString libPartName; wxArrayString footprintFilters; wxArrayString aliases; // The last token read was libpart, so read the next token while( (token = NextTok()) != T_RIGHT ) { if( token == T_LEFT ) token = NextTok(); switch( token ) { case T_lib: NeedSYMBOLorNUMBER(); libName = FROM_UTF8( CurText() ); NeedRIGHT(); break; case T_part: NeedSYMBOLorNUMBER(); libPartName = FROM_UTF8( CurText() ); NeedRIGHT(); break; case T_footprints: // Read all fp elements (footprint filter item) while( (token = NextTok()) != T_RIGHT ) { if( token == T_LEFT ) token = NextTok(); if( token != T_fp ) Expecting( T_fp ); NeedSYMBOLorNUMBER(); footprintFilters.Add( FROM_UTF8( CurText() ) ); NeedRIGHT(); } break; case T_aliases: while( (token = NextTok()) != T_RIGHT ) { if( token == T_LEFT ) token = NextTok(); if( token != T_alias ) Expecting( T_alias ); NeedSYMBOLorNUMBER(); aliases.Add( FROM_UTF8( CurText() ) ); NeedRIGHT(); } break; default: // Skip not used data (i.e all other tokens) skipCurrent(); break; } } // Find all of the components that reference this component library part definition. for( unsigned i = 0; i < m_netlist->GetCount(); i++ ) { component = m_netlist->GetComponent( i ); if( component->IsLibSource( libName, libPartName ) ) component->SetFootprintFilters( footprintFilters ); for( unsigned jj = 0; jj < aliases.GetCount(); jj++ ) { if( component->IsLibSource( libName, aliases[jj] ) ) component->SetFootprintFilters( footprintFilters ); } } }
bool CVPCB_MAINFRAME::ReadNetListAndFpFiles( const std::string& aNetlist ) { wxString msg; bool hasMissingNicks = false; ReadSchematicNetlist( aNetlist ); if( m_compListBox == NULL ) return false; LoadProjectFile(); wxSafeYield(); LoadFootprintFiles(); BuildFOOTPRINTS_LISTBOX(); BuildLIBRARY_LISTBOX(); m_compListBox->Clear(); if( m_netlist.AnyFootprintsLinked() ) { for( unsigned i = 0; i < m_netlist.GetCount(); i++ ) { COMPONENT* component = m_netlist.GetComponent( i ); if( component->GetFPID().empty() ) continue; if( component->GetFPID().IsLegacy() ) hasMissingNicks = true; } } // Check if footprint links were generated before the footprint library table was implemented. if( hasMissingNicks ) { msg = _( "Some of the assigned footprints are legacy entries (are missing lib nicknames). " "Would you like CvPcb to attempt to convert them to the new required LIB_ID format? " "(If you answer no, then these assignments will be cleared out and you will " "have to re-assign these footprints yourself.)" ); if( IsOK( this, msg ) ) { msg.Clear(); try { for( unsigned i = 0; i < m_netlist.GetCount(); i++ ) { COMPONENT* component = m_netlist.GetComponent( i ); if( component->GetFPID().IsLegacy() ) { // get this first here, it's possibly obsoleted if we get it too soon. FP_LIB_TABLE* tbl = Prj().PcbFootprintLibs( Kiway() ); int guess = guessNickname( tbl, (LIB_ID*) &component->GetFPID() ); switch( guess ) { case 0: DBG(printf("%s: guessed OK ref:%s fpid:%s\n", __func__, TO_UTF8( component->GetReference() ), component->GetFPID().Format().c_str() );) m_modified = true; break; case 1: msg += wxString::Format( _( "Component \"%s\" footprint \"%s\" was <b>not found</b> in any library.\n" ), GetChars( component->GetReference() ), GetChars( component->GetFPID().GetLibItemName() ) ); break; case 2: msg += wxString::Format( _( "Component \"%s\" footprint \"%s\" was found in <b>multiple</b> libraries.\n" ), GetChars( component->GetReference() ), GetChars( component->GetFPID().GetLibItemName() ) ); break; } } } }
COMPONENT* LEGACY_NETLIST_READER::loadComponent( char* aText ) throw( PARSE_ERROR, boost::bad_pointer ) { char* text; wxString msg; wxString timeStamp; // the full time stamp read from netlist wxString footprintName; // the footprint name read from netlist wxString value; // the component value read from netlist wxString reference; // the component schematic reference designator read from netlist wxString name; // the name of component that was placed in the schematic char line[1024]; strcpy( line, aText ); value = wxT( "~" ); // Sample component line: /40C08647 $noname R20 4.7K {Lib=R} // Read time stamp (first word) if( ( text = strtok( line, " ()\t\n" ) ) == NULL ) { msg = _( "Cannot parse time stamp in component section of netlist." ); THROW_PARSE_ERROR( msg, m_lineReader->GetSource(), line, m_lineReader->LineNumber(), m_lineReader->Length() ); } timeStamp = FROM_UTF8( text ); // Read footprint name (second word) if( ( text = strtok( NULL, " ()\t\n" ) ) == NULL ) { msg = _( "Cannot parse footprint name in component section of netlist." ); THROW_PARSE_ERROR( msg, m_lineReader->GetSource(), aText, m_lineReader->LineNumber(), m_lineReader->Length() ); } footprintName = FROM_UTF8( text ); // The footprint name will have to be looked up in the *.cmp file. if( footprintName == wxT( "$noname" ) ) footprintName = wxEmptyString; // Read schematic reference designator (third word) if( ( text = strtok( NULL, " ()\t\n" ) ) == NULL ) { msg = _( "Cannot parse reference designator in component section of netlist." ); THROW_PARSE_ERROR( msg, m_lineReader->GetSource(), aText, m_lineReader->LineNumber(), m_lineReader->Length() ); } reference = FROM_UTF8( text ); // Read schematic value (forth word) if( ( text = strtok( NULL, " ()\t\n" ) ) == NULL ) { msg = _( "Cannot parse value in component section of netlist." ); THROW_PARSE_ERROR( msg, m_lineReader->GetSource(), aText, m_lineReader->LineNumber(), m_lineReader->Length() ); } value = FROM_UTF8( text ); // Read component name (fifth word) {Lib=C} // This is an optional field (a comment), which does not always exists if( ( text = strtok( NULL, " ()\t\n" ) ) != NULL ) { name = FROM_UTF8( text ).AfterFirst( wxChar( '=' ) ).BeforeLast( wxChar( '}' ) ); } FPID fpid; if( !footprintName.IsEmpty() ) fpid.SetFootprintName( footprintName ); COMPONENT* component = new COMPONENT( fpid, reference, value, timeStamp ); component->SetName( name ); m_netlist->AddComponent( component ); return component; }
bool CMP_READER::Load( NETLIST* aNetlist ) throw( IO_ERROR, PARSE_ERROR ) { wxCHECK_MSG( aNetlist != NULL,true, wxT( "No netlist passed to CMP_READER::Load()" ) ); wxString reference; // Stores value read from line like Reference = BUS1; wxString timestamp; // Stores value read from line like TimeStamp = /32307DE2/AA450F67; wxString footprint; // Stores value read from line like IdModule = CP6; wxString buffer; wxString value; bool ok = true; while( m_lineReader->ReadLine() ) { buffer = FROM_UTF8( m_lineReader->Line() ); if( !buffer.StartsWith( wxT( "BeginCmp" ) ) ) continue; // Begin component description. reference.Empty(); footprint.Empty(); timestamp.Empty(); while( m_lineReader->ReadLine() ) { buffer = FROM_UTF8( m_lineReader->Line() ); if( buffer.StartsWith( wxT( "EndCmp" ) ) ) break; // store string value, stored between '=' and ';' delimiters. value = buffer.AfterFirst( '=' ); value = value.BeforeLast( ';' ); value.Trim( true ); value.Trim( false ); if( buffer.StartsWith( wxT( "Reference" ) ) ) { reference = value; continue; } if( buffer.StartsWith( wxT( "IdModule =" ) ) ) { footprint = value; continue; } if( buffer.StartsWith( wxT( "TimeStamp =" ) ) ) { timestamp = value; continue; } } // Find the corresponding item in component list: COMPONENT* component = aNetlist->GetComponentByReference( reference ); // The corresponding component could no longer existing in the netlist. This // can happen when it is removed from schematic and still exists in footprint // assignment list. This is an usual case during the life of a design. if( component ) { FPID fpid; if( !footprint.IsEmpty() && fpid.Parse( footprint ) >= 0 ) { wxString error; error.Printf( _( "invalid footprint ID in\nfile: <%s>\nline: %d" ), GetChars( m_lineReader->GetSource() ), m_lineReader->LineNumber() ); THROW_IO_ERROR( error ); } // For checking purpose, store the existing FPID (if any) in the alternate fpid copy // if this existing FPID differs from the FPID read from the .cmp file. // CvPcb can ask for user to chose the right FPID. // It happens if the FPID was modified outside CvPcb. if( fpid != component->GetFPID() && !component->GetFPID().empty() ) component->SetAltFPID( component->GetFPID() ); component->SetFPID( fpid ); } else { ok = false; // can be used to display a warning in Pcbnew. } } return ok; }
void CVPCB_MAINFRAME::AssocieModule( wxCommandEvent& event ) { FOOTPRINT_ALIAS_LIST aliases; FOOTPRINT_ALIAS* alias; COMPONENT* component; wxFileName fn; wxString msg, tmp; char Line[1024]; FILE* file; size_t ii; SEARCH_STACK& search = Kiface().KifaceSearch(); if( m_netlist.IsEmpty() ) return; // Find equivalents in all available files. for( ii = 0; ii < m_AliasLibNames.GetCount(); ii++ ) { fn = m_AliasLibNames[ii]; if( !fn.HasExt() ) { fn.SetExt( FootprintAliasFileExtension ); // above fails if filename has more than one point } else { fn.SetExt( fn.GetExt() + wxT( "." ) + FootprintAliasFileExtension ); } tmp = search.FindValidPath( fn.GetFullPath() ); if( !tmp ) { msg.Printf( _( "Footprint alias library file '%s' could not be found in the " "default search paths." ), GetChars( fn.GetFullName() ) ); wxMessageBox( msg, FMT_TITLE_LIB_LOAD_ERROR, wxOK | wxICON_ERROR ); continue; } file = wxFopen( tmp, wxT( "rt" ) ); if( file == NULL ) { msg.Printf( _( "Error opening alias library '%s'." ), GetChars( tmp ) ); wxMessageBox( msg, FMT_TITLE_LIB_LOAD_ERROR, wxOK | wxICON_ERROR ); continue; } while( GetLine( file, Line, NULL, sizeof(Line) ) != NULL ) { char* text = Line; wxString value, footprint, wtext = FROM_UTF8( Line ); value = GetQuotedText( wtext ); if( text == NULL || ( *text == 0 ) || value.IsEmpty() ) continue; footprint = GetQuotedText( wtext ); if( footprint.IsEmpty() ) continue; value.Replace( wxT( " " ), wxT( "_" ) ); alias = new FOOTPRINT_ALIAS(); alias->m_Name = value; alias->m_FootprintName = footprint; aliases.push_back( alias ); } fclose( file ); } // Display the number of footprint aliases. msg.Printf( _( "%d footprint aliases found." ), aliases.size() ); SetStatusText( msg, 0 ); m_skipComponentSelect = true; ii = 0; for( unsigned kk = 0; kk < m_netlist.GetCount(); kk++ ) { component = m_netlist.GetComponent( kk ); bool found = false; m_compListBox->SetSelection( ii++, true ); if( !component->GetFPID().empty() ) continue; BOOST_FOREACH( FOOTPRINT_ALIAS& alias, aliases ) { if( alias.m_Name.CmpNoCase( component->GetValue() ) != 0 ) continue; // filter alias so one can use multiple aliases (for polar and // nonpolar caps for example) const FOOTPRINT_INFO *module = m_footprints.GetModuleInfo( alias.m_FootprintName ); if( module ) { size_t filtercount = component->GetFootprintFilters().GetCount(); found = ( 0 == filtercount ); // if no entries, do not filter for( size_t jj = 0; jj < filtercount && !found; jj++ ) { found = module->GetFootprintName().Matches( component->GetFootprintFilters()[jj] ); } } else { msg.Printf( _( "Component %s: footprint %s not found in any of the project " "footprint libraries." ), GetChars( component->GetReference() ), GetChars( alias.m_FootprintName ) ); wxMessageBox( msg, _( "CvPcb Error" ), wxOK | wxICON_ERROR, this ); } if( found ) { SetNewPkg( alias.m_FootprintName ); break; } } // obviously the last chance: there's only one filter matching one footprint if( !found && 1 == component->GetFootprintFilters().GetCount() ) { // we do not need to analyse wildcards: single footprint do not // contain them and if there are wildcards it just will not match any const FOOTPRINT_INFO* module = m_footprints.GetModuleInfo( component->GetFootprintFilters()[0] ); if( module ) { SetNewPkg( component->GetFootprintFilters()[0] ); } } } m_skipComponentSelect = false; }
void CVPCB_MAINFRAME::DisplayStatus() { wxString msg; COMPONENT* component; if( wxWindow::FindFocus() == m_compListBox || wxWindow::FindFocus() == m_libListBox ) { msg.Printf( _( "Components: %d, unassigned: %d" ), (int) m_netlist.GetCount(), m_undefinedComponentCnt ); SetStatusText( msg, 0 ); msg.Empty(); component = GetSelectedComponent(); if( component ) { for( unsigned ii = 0; ii < component->GetFootprintFilters().GetCount(); ii++ ) { if( msg.IsEmpty() ) msg += component->GetFootprintFilters()[ii]; else msg += wxT( ", " ) + component->GetFootprintFilters()[ii]; } msg = _( "Filter list: " ) + msg; } SetStatusText( msg, 1 ); } else { wxString footprintName = m_footprintListBox->GetSelectedFootprint(); FOOTPRINT_INFO* module = m_footprints.GetModuleInfo( footprintName ); if( module ) // can be NULL if no netlist loaded { msg = _( "Description: " ) + module->GetDoc(); SetStatusText( msg, 0 ); msg = _( "Key words: " ) + module->GetKeywords(); SetStatusText( msg, 1 ); } } msg.Empty(); wxString filters; if( m_footprintListBox ) { if( m_mainToolBar->GetToolToggled( ID_CVPCB_FOOTPRINT_DISPLAY_FILTERED_LIST ) ) filters = _( "key words" ); if( m_mainToolBar->GetToolToggled( ID_CVPCB_FOOTPRINT_DISPLAY_PIN_FILTERED_LIST ) ) { if( !filters.IsEmpty() ) filters += wxT( "+" ); filters += _( "pin count" ); } if( m_mainToolBar->GetToolToggled( ID_CVPCB_FOOTPRINT_DISPLAY_BY_LIBRARY_LIST ) ) { if( !filters.IsEmpty() ) filters += wxT( "+" ); filters += _( "library" ); } if( filters.IsEmpty() ) msg = _( "No filtering" ); else msg.Printf( _( "Filtered by %s" ), GetChars( filters ) ); msg << wxT( ": " ) << m_footprintListBox->GetCount(); SetStatusText( msg, 2 ); } }
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 ); } }
bool BOARD_NETLIST_UPDATER::UpdateNetlist( NETLIST& aNetlist ) { wxString msg; m_errorCount = 0; m_warningCount = 0; if( !m_isDryRun ) { m_board->SetStatus( 0 ); } for( int i = 0; i < (int) aNetlist.GetCount(); i++ ) { COMPONENT* component = aNetlist.GetComponent( i ); MODULE* footprint = NULL; msg.Printf( _( "Processing component \"%s:%s:%s\".\n" ), GetChars( component->GetReference() ), GetChars( component->GetTimeStamp() ), GetChars( component->GetFPID().Format() ) ); m_reporter->Report( msg, REPORTER::RPT_INFO ); if( aNetlist.IsFindByTimeStamp() ) footprint = m_board->FindModule( component->GetTimeStamp(), true ); else footprint = m_board->FindModule( component->GetReference() ); if( footprint ) // An existing footprint. { MODULE* newFootprint = replaceComponent( aNetlist, footprint, component ); if( newFootprint ) footprint = newFootprint; } else { footprint = addNewComponent( component ); } if( footprint ) { updateComponentParameters( footprint, component ); updateComponentPadConnections( footprint, component ); } } //aNetlist.GetDeleteExtraFootprints() if( m_deleteUnusedComponents ) deleteUnusedComponents( aNetlist ); if( m_deleteSinglePadNets ) deleteSinglePadNets(); if( !m_isDryRun ) { m_commit.Push( _( "Update netlist" ) ); m_frame->Compile_Ratsnest( NULL, false ); m_board->GetRatsnest()->ProcessBoard(); testConnectivity( aNetlist ); } // Update the ratsnest m_reporter->Report( wxT( "" ), REPORTER::RPT_ACTION ); m_reporter->Report( wxT( "" ), REPORTER::RPT_ACTION ); msg.Printf( _( "Total warnings: %d, errors: %d." ), m_warningCount, m_errorCount ); m_reporter->Report( msg, REPORTER::RPT_ACTION ); if( m_errorCount ) { m_reporter->Report( _( "Errors occured during the netlist update. Unless you " "fix them, your board will not be consistent with the schematics." ), REPORTER::RPT_ERROR ); return false; } else { m_reporter->Report( _( "Netlist update successful!" ), REPORTER::RPT_ACTION ); } return true; }
/** * 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; }