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 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::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; }