Fix BOM generation bug for components with multiple units.

Sadly, each unit of a component can have its own unique fields. This
change finds the last non blank field and records it. Last guy wins
and the order of units occuring in a schematic hierarchy is variable.
Therefore user is best off setting fields into only one unit. But this
scavenger algorithm will find any non blank fields in all units and use
the last non-blank field for each unique field name.

Fixes lp:1471417

https://bugs.launchpad.net/kicad/+bug/1471417
This commit is contained in:
Dick Hollenbeck 2017-04-24 09:15:37 -05:00 committed by Wayne Stambaugh
parent 4b5482eb5a
commit 50716c9015
4 changed files with 211 additions and 166 deletions

View File

@ -2,7 +2,7 @@
* This program source code file is part of KiCad, a free EDA CAD application. * This program source code file is part of KiCad, a free EDA CAD application.
* *
* Copyright (C) 1992-2017 jp.charras at wanadoo.fr * Copyright (C) 1992-2017 jp.charras at wanadoo.fr
* Copyright (C) 2013 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com> * Copyright (C) 2013-2017 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
* Copyright (C) 1992-2017 KiCad Developers, see AUTHORS.TXT for contributors. * Copyright (C) 1992-2017 KiCad Developers, see AUTHORS.TXT for contributors.
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
@ -157,8 +157,8 @@ static bool sortPinsByNum( NETLIST_OBJECT* aPin1, NETLIST_OBJECT* aPin2 )
} }
SCH_COMPONENT* NETLIST_EXPORTER::findNextComponentAndCreatePinList( EDA_ITEM* aItem, SCH_COMPONENT* NETLIST_EXPORTER::findNextComponentAndCreatePinList(
SCH_SHEET_PATH* aSheetPath ) EDA_ITEM* aItem, SCH_SHEET_PATH* aSheetPath )
{ {
wxString ref; wxString ref;
@ -201,7 +201,7 @@ SCH_COMPONENT* NETLIST_EXPORTER::findNextComponentAndCreatePinList( EDA_ITEM*
// Collect all pins for this reference designator by searching // Collect all pins for this reference designator by searching
// the entire design for other parts with the same reference designator. // the entire design for other parts with the same reference designator.
// This is only done once, it would be too expensive otherwise. // This is only done once, it would be too expensive otherwise.
findAllInstancesOfComponent( comp, part, aSheetPath ); findAllUnitsOfComponent( comp, part, aSheetPath );
} }
else // entry->GetUnitCount() <= 1 means one part per package else // entry->GetUnitCount() <= 1 means one part per package
@ -236,8 +236,9 @@ SCH_COMPONENT* NETLIST_EXPORTER::findNextComponentAndCreatePinList( EDA_ITEM*
return NULL; return NULL;
} }
bool NETLIST_EXPORTER::addPinToComponentPinList( SCH_COMPONENT* aComponent, bool NETLIST_EXPORTER::addPinToComponentPinList( SCH_COMPONENT* aComponent,
SCH_SHEET_PATH* aSheetPath, LIB_PIN* aPin ) SCH_SHEET_PATH* aSheetPath, LIB_PIN* aPin )
{ {
// Search the PIN description for Pin in g_NetObjectslist // Search the PIN description for Pin in g_NetObjectslist
for( unsigned ii = 0; ii < m_masterList->size(); ii++ ) for( unsigned ii = 0; ii < m_masterList->size(); ii++ )
@ -323,9 +324,8 @@ void NETLIST_EXPORTER::eraseDuplicatePins()
} }
void NETLIST_EXPORTER::findAllInstancesOfComponent( SCH_COMPONENT* aComponent, void NETLIST_EXPORTER::findAllUnitsOfComponent( SCH_COMPONENT* aComponent,
LIB_PART* aEntry, LIB_PART* aEntry, SCH_SHEET_PATH* aSheetPath )
SCH_SHEET_PATH* aSheetPath )
{ {
wxString ref = aComponent->GetRef( aSheetPath ); wxString ref = aComponent->GetRef( aSheetPath );
wxString ref2; wxString ref2;

View File

@ -91,7 +91,7 @@ protected:
PART_LIBS* m_libs; /// no ownership PART_LIBS* m_libs; /// no ownership
/// Used to temporary store and filter the list of pins of a schematic component /// Used to temporarily store and filter the list of pins of a schematic component
/// when generating schematic component data in netlist (comp section). No ownership /// when generating schematic component data in netlist (comp section). No ownership
/// of members. /// of members.
NETLIST_OBJECTS m_SortedComponentPinList; NETLIST_OBJECTS m_SortedComponentPinList;
@ -157,14 +157,14 @@ protected:
LIB_PIN* PinEntry ); LIB_PIN* PinEntry );
/** /**
* Function findAllInstancesOfComponent * Function findAllUnitsOfComponent
* is used for "multiple parts per package" components. * is used for "multiple parts per package" components.
* <p> * <p>
* Search the entire design for all instances of \a aComponent based on * Search the entire design for all units of \a aComponent based on
* matching reference designator, and for each part, add all its pins * matching reference designator, and for each unit, add all its pins
* to the temporary sorted pin list. * to the temporary sorted pin list, m_SortedComponentPinList.
*/ */
void findAllInstancesOfComponent( SCH_COMPONENT* aComponent, void findAllUnitsOfComponent( SCH_COMPONENT* aComponent,
LIB_PART* aEntry, LIB_PART* aEntry,
SCH_SHEET_PATH* aSheetPath ); SCH_SHEET_PATH* aSheetPath );

View File

@ -2,7 +2,7 @@
* This program source code file is part of KiCad, a free EDA CAD application. * This program source code file is part of KiCad, a free EDA CAD application.
* *
* Copyright (C) 1992-2013 jp.charras at wanadoo.fr * Copyright (C) 1992-2013 jp.charras at wanadoo.fr
* Copyright (C) 2013 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com> * Copyright (C) 2013-2017 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
* Copyright (C) 1992-2017 KiCad Developers, see AUTHORS.txt for contributors. * Copyright (C) 1992-2017 KiCad Developers, see AUTHORS.txt for contributors.
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
@ -49,9 +49,9 @@ bool NETLIST_EXPORTER_GENERIC::WriteNetlist( const wxString& aOutFileName, unsig
XNODE* NETLIST_EXPORTER_GENERIC::makeRoot( int aCtl ) XNODE* NETLIST_EXPORTER_GENERIC::makeRoot( int aCtl )
{ {
XNODE* xroot = node( wxT( "export" ) ); XNODE* xroot = node( "export" );
xroot->AddAttribute( wxT( "version" ), wxT( "D" ) ); xroot->AddAttribute( "version", "D" );
if( aCtl & GNL_HEADER ) if( aCtl & GNL_HEADER )
// add the "design" header // add the "design" header
@ -74,38 +74,134 @@ XNODE* NETLIST_EXPORTER_GENERIC::makeRoot( int aCtl )
} }
/// Holder for multi-unit component fields
struct COMP_FIELDS
{
wxString value;
wxString datasheet;
wxString footprint;
std::map< wxString, wxString > f;
};
void NETLIST_EXPORTER_GENERIC::addComponentFields( XNODE* xcomp, SCH_COMPONENT* comp, SCH_SHEET_PATH* aSheet )
{
if( comp->GetUnitCount() > 1 )
{
// Sadly, each unit of a component can have its own unique fields. This block
// finds the last non blank field and records it. Last guy wins and the order
// of units occuring in a schematic hierarchy is variable. Therefore user
// is best off setting fields into only one unit. But this scavenger algorithm
// will find any non blank fields in all units and use the last non-blank field
// for each unique field name.
COMP_FIELDS fields;
wxString ref = comp->GetRef( aSheet );
SCH_SHEET_LIST sheetList( g_RootSheet );
for( unsigned i = 0; i < sheetList.size(); i++ )
{
for( EDA_ITEM* item = sheetList[i].LastDrawList(); item; item = item->Next() )
{
if( item->Type() != SCH_COMPONENT_T )
continue;
SCH_COMPONENT* comp2 = (SCH_COMPONENT*) item;
wxString ref2 = comp2->GetRef( &sheetList[i] );
if( ref2.CmpNoCase( ref ) != 0 )
continue;
// The last guy wins. User should only set fields in any one unit.
if( !comp2->GetField( VALUE )->IsVoid() )
fields.value = comp2->GetField( VALUE )->GetText();
if( !comp2->GetField( FOOTPRINT )->IsVoid() )
fields.footprint = comp2->GetField( FOOTPRINT )->GetText();
if( !comp2->GetField( DATASHEET )->IsVoid() )
fields.datasheet = comp2->GetField( DATASHEET )->GetText();
for( int fldNdx = MANDATORY_FIELDS; fldNdx < comp2->GetFieldCount(); ++fldNdx )
{
SCH_FIELD* f = comp2->GetField( fldNdx );
if( f->GetText().size() )
{
fields.f[ f->GetName() ] = f->GetText();
}
}
}
}
xcomp->AddChild( node( "value", fields.value ) );
if( fields.footprint.size() )
xcomp->AddChild( node( "footprint", fields.footprint ) );
if( fields.datasheet.size() )
xcomp->AddChild( node( "datasheet", fields.datasheet ) );
if( fields.f.size() )
{
XNODE* xfields;
xcomp->AddChild( xfields = node( "fields" ) );
// non MANDATORY fields are output alphabetically
for( std::map< wxString, wxString >::const_iterator it = fields.f.begin();
it != fields.f.end(); ++it )
{
XNODE* xfield;
xfields->AddChild( xfield = node( "field", it->second ) );
xfield->AddAttribute( "name", it->first );
}
}
}
else
{
xcomp->AddChild( node( "value", comp->GetField( VALUE )->GetText() ) );
if( !comp->GetField( FOOTPRINT )->IsVoid() )
xcomp->AddChild( node( "footprint", comp->GetField( FOOTPRINT )->GetText() ) );
if( !comp->GetField( DATASHEET )->IsVoid() )
xcomp->AddChild( node( "datasheet", comp->GetField( DATASHEET )->GetText() ) );
// Export all user defined fields within the component,
// which start at field index MANDATORY_FIELDS. Only output the <fields>
// container element if there are any <field>s.
if( comp->GetFieldCount() > MANDATORY_FIELDS )
{
XNODE* xfields;
xcomp->AddChild( xfields = node( "fields" ) );
for( int fldNdx = MANDATORY_FIELDS; fldNdx < comp->GetFieldCount(); ++fldNdx )
{
SCH_FIELD* f = comp->GetField( fldNdx );
// only output a field if non empty and not just "~"
if( !f->IsVoid() )
{
XNODE* xfield;
xfields->AddChild( xfield = node( "field", f->GetText() ) );
xfield->AddAttribute( "name", f->GetName() );
}
}
}
}
}
XNODE* NETLIST_EXPORTER_GENERIC::makeComponents() XNODE* NETLIST_EXPORTER_GENERIC::makeComponents()
{ {
XNODE* xcomps = node( wxT( "components" ) ); XNODE* xcomps = node( "components" );
wxString timeStamp; wxString timeStamp;
// some strings we need many times, but don't want to construct more
// than once for performance. These are used within loops so the
// enclosing wxString constructor would fire on each loop iteration if
// they were in a nested scope.
// these are actually constructor invocations, not assignments as it appears:
wxString sFields = wxT( "fields" );
wxString sField = wxT( "field" );
wxString sComponent = wxT( "comp" ); // use "part" ?
wxString sName = wxT( "name" );
wxString sRef = wxT( "ref" );
wxString sPins = wxT( "pins" );
wxString sPin = wxT( "pin" );
wxString sValue = wxT( "value" );
wxString sSheetPath = wxT( "sheetpath" );
wxString sFootprint = wxT( "footprint" );
wxString sDatasheet = wxT( "datasheet" );
wxString sTStamp = wxT( "tstamp" );
wxString sTStamps = wxT( "tstamps" );
wxString sTSFmt = wxT( "%8.8lX" ); // comp->m_TimeStamp
wxString sLibSource = wxT( "libsource" );
wxString sLibPart = wxT( "libpart" );
wxString sLib = wxT( "lib" );
wxString sPart = wxT( "part" );
wxString sNames = wxT( "names" );
m_ReferencesAlreadyFound.Clear(); m_ReferencesAlreadyFound.Clear();
SCH_SHEET_LIST sheetList( g_RootSheet ); SCH_SHEET_LIST sheetList( g_RootSheet );
@ -117,7 +213,7 @@ XNODE* NETLIST_EXPORTER_GENERIC::makeComponents()
{ {
for( EDA_ITEM* schItem = sheetList[i].LastDrawList(); schItem; schItem = schItem->Next() ) for( EDA_ITEM* schItem = sheetList[i].LastDrawList(); schItem; schItem = schItem->Next() )
{ {
SCH_COMPONENT* comp = findNextComponentAndCreatePinList( schItem, &sheetList[i] ); SCH_COMPONENT* comp = findNextComponent( schItem, &sheetList[i] );
if( !comp ) if( !comp )
break; // No component left break; // No component left
@ -130,60 +226,32 @@ XNODE* NETLIST_EXPORTER_GENERIC::makeComponents()
// under XSL processing systems which do sequential searching within // under XSL processing systems which do sequential searching within
// an element. // an element.
xcomps->AddChild( xcomp = node( sComponent ) ); xcomps->AddChild( xcomp = node( "comp" ) );
xcomp->AddAttribute( sRef, comp->GetRef( &sheetList[i] ) ); xcomp->AddAttribute( "ref", comp->GetRef( &sheetList[i] ) );
xcomp->AddChild( node( sValue, comp->GetField( VALUE )->GetText() ) ); addComponentFields( xcomp, comp, &sheetList[i] );
if( !comp->GetField( FOOTPRINT )->IsVoid() )
xcomp->AddChild( node( sFootprint, comp->GetField( FOOTPRINT )->GetText() ) );
if( !comp->GetField( DATASHEET )->IsVoid() )
xcomp->AddChild( node( sDatasheet, comp->GetField( DATASHEET )->GetText() ) );
// Export all user defined fields within the component,
// which start at field index MANDATORY_FIELDS. Only output the <fields>
// container element if there are any <field>s.
if( comp->GetFieldCount() > MANDATORY_FIELDS )
{
XNODE* xfields;
xcomp->AddChild( xfields = node( sFields ) );
for( int fldNdx = MANDATORY_FIELDS; fldNdx < comp->GetFieldCount(); ++fldNdx )
{
SCH_FIELD* f = comp->GetField( fldNdx );
// only output a field if non empty and not just "~"
if( !f->IsVoid() )
{
XNODE* xfield;
xfields->AddChild( xfield = node( sField, f->GetText() ) );
xfield->AddAttribute( sName, f->GetName() );
}
}
}
XNODE* xlibsource; XNODE* xlibsource;
xcomp->AddChild( xlibsource = node( sLibSource ) ); xcomp->AddChild( xlibsource = node( "libsource" ) );
// "logical" library name, which is in anticipation of a better search // "logical" library name, which is in anticipation of a better search
// algorithm for parts based on "logical_lib.part" and where logical_lib // algorithm for parts based on "logical_lib.part" and where logical_lib
// is merely the library name minus path and extension. // is merely the library name minus path and extension.
LIB_PART* part = m_libs->FindLibPart( comp->GetLibId() ); LIB_PART* part = m_libs->FindLibPart( comp->GetLibId() );
if( part ) if( part )
xlibsource->AddAttribute( sLib, part->GetLib()->GetLogicalName() ); xlibsource->AddAttribute( "lib", part->GetLib()->GetLogicalName() );
// We only want the symbol name, not the full LIB_ID. // We only want the symbol name, not the full LIB_ID.
xlibsource->AddAttribute( sPart, FROM_UTF8( comp->GetLibId().GetLibItemName() ) ); xlibsource->AddAttribute( "part", FROM_UTF8( comp->GetLibId().GetLibItemName() ) );
XNODE* xsheetpath; XNODE* xsheetpath;
xcomp->AddChild( xsheetpath = node( sSheetPath ) ); xcomp->AddChild( xsheetpath = node( "sheetpath" ) );
xsheetpath->AddAttribute( sNames, sheetList[i].PathHumanReadable() ); xsheetpath->AddAttribute( "names", sheetList[i].PathHumanReadable() );
xsheetpath->AddAttribute( sTStamps, sheetList[i].Path() ); xsheetpath->AddAttribute( "tstamps", sheetList[i].Path() );
timeStamp.Printf( sTSFmt, (unsigned long)comp->GetTimeStamp() ); timeStamp.Printf( "%8.8lX", (unsigned long)comp->GetTimeStamp() );
xcomp->AddChild( node( sTStamp, timeStamp ) ); xcomp->AddChild( node( "tstamp", timeStamp ) );
} }
} }
@ -194,7 +262,7 @@ XNODE* NETLIST_EXPORTER_GENERIC::makeComponents()
XNODE* NETLIST_EXPORTER_GENERIC::makeDesignHeader() XNODE* NETLIST_EXPORTER_GENERIC::makeDesignHeader()
{ {
SCH_SCREEN* screen; SCH_SCREEN* screen;
XNODE* xdesign = node( wxT( "design" ) ); XNODE* xdesign = node( "design" );
XNODE* xtitleBlock; XNODE* xtitleBlock;
XNODE* xsheet; XNODE* xsheet;
XNODE* xcomment; XNODE* xcomment;
@ -202,12 +270,12 @@ XNODE* NETLIST_EXPORTER_GENERIC::makeDesignHeader()
wxFileName sourceFileName; wxFileName sourceFileName;
// the root sheet is a special sheet, call it source // the root sheet is a special sheet, call it source
xdesign->AddChild( node( wxT( "source" ), g_RootSheet->GetScreen()->GetFileName() ) ); xdesign->AddChild( node( "source", g_RootSheet->GetScreen()->GetFileName() ) );
xdesign->AddChild( node( wxT( "date" ), DateAndTime() ) ); xdesign->AddChild( node( "date", DateAndTime() ) );
// which Eeschema tool // which Eeschema tool
xdesign->AddChild( node( wxT( "tool" ), wxT( "Eeschema " ) + GetBuildVersion() ) ); xdesign->AddChild( node( "tool", wxString( "Eeschema " ) + GetBuildVersion() ) );
/* /*
Export the sheets information Export the sheets information
@ -218,45 +286,45 @@ XNODE* NETLIST_EXPORTER_GENERIC::makeDesignHeader()
{ {
screen = sheetList[i].LastScreen(); screen = sheetList[i].LastScreen();
xdesign->AddChild( xsheet = node( wxT( "sheet" ) ) ); xdesign->AddChild( xsheet = node( "sheet" ) );
// get the string representation of the sheet index number. // get the string representation of the sheet index number.
// Note that sheet->GetIndex() is zero index base and we need to increment the // Note that sheet->GetIndex() is zero index base and we need to increment the
// number by one to make it human readable // number by one to make it human readable
sheetTxt.Printf( wxT( "%u" ), i + 1 ); sheetTxt.Printf( "%u", i + 1 );
xsheet->AddAttribute( wxT( "number" ), sheetTxt ); xsheet->AddAttribute( "number", sheetTxt );
xsheet->AddAttribute( wxT( "name" ), sheetList[i].PathHumanReadable() ); xsheet->AddAttribute( "name", sheetList[i].PathHumanReadable() );
xsheet->AddAttribute( wxT( "tstamps" ), sheetList[i].Path() ); xsheet->AddAttribute( "tstamps", sheetList[i].Path() );
TITLE_BLOCK tb = screen->GetTitleBlock(); TITLE_BLOCK tb = screen->GetTitleBlock();
xsheet->AddChild( xtitleBlock = node( wxT( "title_block" ) ) ); xsheet->AddChild( xtitleBlock = node( "title_block" ) );
xtitleBlock->AddChild( node( wxT( "title" ), tb.GetTitle() ) ); xtitleBlock->AddChild( node( "title", tb.GetTitle() ) );
xtitleBlock->AddChild( node( wxT( "company" ), tb.GetCompany() ) ); xtitleBlock->AddChild( node( "company", tb.GetCompany() ) );
xtitleBlock->AddChild( node( wxT( "rev" ), tb.GetRevision() ) ); xtitleBlock->AddChild( node( "rev", tb.GetRevision() ) );
xtitleBlock->AddChild( node( wxT( "date" ), tb.GetDate() ) ); xtitleBlock->AddChild( node( "date", tb.GetDate() ) );
// We are going to remove the fileName directories. // We are going to remove the fileName directories.
sourceFileName = wxFileName( screen->GetFileName() ); sourceFileName = wxFileName( screen->GetFileName() );
xtitleBlock->AddChild( node( wxT( "source" ), sourceFileName.GetFullName() ) ); xtitleBlock->AddChild( node( "source", sourceFileName.GetFullName() ) );
xtitleBlock->AddChild( xcomment = node( wxT( "comment" ) ) ); xtitleBlock->AddChild( xcomment = node( "comment" ) );
xcomment->AddAttribute( wxT("number"), wxT("1") ); xcomment->AddAttribute( "number", "1" );
xcomment->AddAttribute( wxT( "value" ), tb.GetComment1() ); xcomment->AddAttribute( "value", tb.GetComment1() );
xtitleBlock->AddChild( xcomment = node( wxT( "comment" ) ) ); xtitleBlock->AddChild( xcomment = node( "comment" ) );
xcomment->AddAttribute( wxT("number"), wxT("2") ); xcomment->AddAttribute( "number", "2" );
xcomment->AddAttribute( wxT( "value" ), tb.GetComment2() ); xcomment->AddAttribute( "value", tb.GetComment2() );
xtitleBlock->AddChild( xcomment = node( wxT( "comment" ) ) ); xtitleBlock->AddChild( xcomment = node( "comment" ) );
xcomment->AddAttribute( wxT("number"), wxT("3") ); xcomment->AddAttribute( "number", "3" );
xcomment->AddAttribute( wxT( "value" ), tb.GetComment3() ); xcomment->AddAttribute( "value", tb.GetComment3() );
xtitleBlock->AddChild( xcomment = node( wxT( "comment" ) ) ); xtitleBlock->AddChild( xcomment = node( "comment" ) );
xcomment->AddAttribute( wxT("number"), wxT("4") ); xcomment->AddAttribute( "number", "4" );
xcomment->AddAttribute( wxT( "value" ), tb.GetComment4() ); xcomment->AddAttribute( "value", tb.GetComment4() );
} }
return xdesign; return xdesign;
@ -265,16 +333,16 @@ XNODE* NETLIST_EXPORTER_GENERIC::makeDesignHeader()
XNODE* NETLIST_EXPORTER_GENERIC::makeLibraries() XNODE* NETLIST_EXPORTER_GENERIC::makeLibraries()
{ {
XNODE* xlibs = node( wxT( "libraries" ) ); // auto_ptr XNODE* xlibs = node( "libraries" ); // auto_ptr
for( std::set<void*>::iterator it = m_Libraries.begin(); it!=m_Libraries.end(); ++it ) for( std::set<void*>::iterator it = m_Libraries.begin(); it!=m_Libraries.end(); ++it )
{ {
PART_LIB* lib = (PART_LIB*) *it; PART_LIB* lib = (PART_LIB*) *it;
XNODE* xlibrary; XNODE* xlibrary;
xlibs->AddChild( xlibrary = node( wxT( "library" ) ) ); xlibs->AddChild( xlibrary = node( "library" ) );
xlibrary->AddAttribute( wxT( "logical" ), lib->GetLogicalName() ); xlibrary->AddAttribute( "logical", lib->GetLogicalName() );
xlibrary->AddChild( node( wxT( "uri" ), lib->GetFullFileName() ) ); xlibrary->AddChild( node( "uri", lib->GetFullFileName() ) );
// @todo: add more fun stuff here // @todo: add more fun stuff here
} }
@ -285,24 +353,7 @@ XNODE* NETLIST_EXPORTER_GENERIC::makeLibraries()
XNODE* NETLIST_EXPORTER_GENERIC::makeLibParts() XNODE* NETLIST_EXPORTER_GENERIC::makeLibParts()
{ {
XNODE* xlibparts = node( wxT( "libparts" ) ); // auto_ptr XNODE* xlibparts = node( "libparts" ); // auto_ptr
wxString sLibpart = wxT( "libpart" );
wxString sLib = wxT( "lib" );
wxString sPart = wxT( "part" );
wxString sAliases = wxT( "aliases" );
wxString sAlias = wxT( "alias" );
wxString sPins = wxT( "pins" ); // key for library component pins list
wxString sPin = wxT( "pin" ); // key for one library component pin descr
wxString sPinNum = wxT( "num" ); // key for one library component pin num
wxString sPinName = wxT( "name" ); // key for one library component pin name
wxString sPinType = wxT( "type" ); // key for one library component pin electrical type
wxString sName = wxT( "name" );
wxString sField = wxT( "field" );
wxString sFields = wxT( "fields" );
wxString sDescr = wxT( "description" );
wxString sDocs = wxT( "docs" );
wxString sFprints = wxT( "footprints" );
wxString sFp = wxT( "fp" );
LIB_PINS pinList; LIB_PINS pinList;
LIB_FIELDS fieldList; LIB_FIELDS fieldList;
@ -317,40 +368,40 @@ XNODE* NETLIST_EXPORTER_GENERIC::makeLibParts()
m_Libraries.insert( library ); // inserts component's library if unique m_Libraries.insert( library ); // inserts component's library if unique
XNODE* xlibpart; XNODE* xlibpart;
xlibparts->AddChild( xlibpart = node( sLibpart ) ); xlibparts->AddChild( xlibpart = node( "libpart" ) );
xlibpart->AddAttribute( sLib, library->GetLogicalName() ); xlibpart->AddAttribute( "lib", library->GetLogicalName() );
xlibpart->AddAttribute( sPart, lcomp->GetName() ); xlibpart->AddAttribute( "part", lcomp->GetName() );
if( lcomp->GetAliasCount() ) if( lcomp->GetAliasCount() )
{ {
wxArrayString aliases = lcomp->GetAliasNames( false ); wxArrayString aliases = lcomp->GetAliasNames( false );
if( aliases.GetCount() ) if( aliases.GetCount() )
{ {
XNODE* xaliases = node( sAliases ); XNODE* xaliases = node( "aliases" );
xlibpart->AddChild( xaliases ); xlibpart->AddChild( xaliases );
for( unsigned i=0; i<aliases.GetCount(); ++i ) for( unsigned i=0; i<aliases.GetCount(); ++i )
{ {
xaliases->AddChild( node( sAlias, aliases[i] ) ); xaliases->AddChild( node( "alias", aliases[i] ) );
} }
} }
} }
//----- show the important properties ------------------------- //----- show the important properties -------------------------
if( !lcomp->GetAlias( 0 )->GetDescription().IsEmpty() ) if( !lcomp->GetAlias( 0 )->GetDescription().IsEmpty() )
xlibpart->AddChild( node( sDescr, lcomp->GetAlias( 0 )->GetDescription() ) ); xlibpart->AddChild( node( "description", lcomp->GetAlias( 0 )->GetDescription() ) );
if( !lcomp->GetAlias( 0 )->GetDocFileName().IsEmpty() ) if( !lcomp->GetAlias( 0 )->GetDocFileName().IsEmpty() )
xlibpart->AddChild( node( sDocs, lcomp->GetAlias( 0 )->GetDocFileName() ) ); xlibpart->AddChild( node( "docs", lcomp->GetAlias( 0 )->GetDocFileName() ) );
// Write the footprint list // Write the footprint list
if( lcomp->GetFootPrints().GetCount() ) if( lcomp->GetFootPrints().GetCount() )
{ {
XNODE* xfootprints; XNODE* xfootprints;
xlibpart->AddChild( xfootprints = node( sFprints ) ); xlibpart->AddChild( xfootprints = node( "footprints" ) );
for( unsigned i=0; i<lcomp->GetFootPrints().GetCount(); ++i ) for( unsigned i=0; i<lcomp->GetFootPrints().GetCount(); ++i )
{ {
xfootprints->AddChild( node( sFp, lcomp->GetFootPrints()[i] ) ); xfootprints->AddChild( node( "fp", lcomp->GetFootPrints()[i] ) );
} }
} }
@ -359,15 +410,15 @@ XNODE* NETLIST_EXPORTER_GENERIC::makeLibParts()
lcomp->GetFields( fieldList ); lcomp->GetFields( fieldList );
XNODE* xfields; XNODE* xfields;
xlibpart->AddChild( xfields = node( sFields ) ); xlibpart->AddChild( xfields = node( "fields" ) );
for( unsigned i=0; i<fieldList.size(); ++i ) for( unsigned i=0; i<fieldList.size(); ++i )
{ {
if( !fieldList[i].GetText().IsEmpty() ) if( !fieldList[i].GetText().IsEmpty() )
{ {
XNODE* xfield; XNODE* xfield;
xfields->AddChild( xfield = node( sField, fieldList[i].GetText() ) ); xfields->AddChild( xfield = node( "field", fieldList[i].GetText() ) );
xfield->AddAttribute( sName, fieldList[i].GetName(false) ); xfield->AddAttribute( "name", fieldList[i].GetName(false) );
} }
} }
@ -397,15 +448,15 @@ XNODE* NETLIST_EXPORTER_GENERIC::makeLibParts()
{ {
XNODE* pins; XNODE* pins;
xlibpart->AddChild( pins = node( sPins ) ); xlibpart->AddChild( pins = node( "pins" ) );
for( unsigned i=0; i<pinList.size(); ++i ) for( unsigned i=0; i<pinList.size(); ++i )
{ {
XNODE* pin; XNODE* pin;
pins->AddChild( pin = node( sPin ) ); pins->AddChild( pin = node( "pin" ) );
pin->AddAttribute( sPinNum, pinList[i]->GetNumberString() ); pin->AddAttribute( "num", pinList[i]->GetNumberString() );
pin->AddAttribute( sPinName, pinList[i]->GetName() ); pin->AddAttribute( "name", pinList[i]->GetName() );
pin->AddAttribute( sPinType, pinList[i]->GetCanonicalElectricalTypeName() ); pin->AddAttribute( "type", pinList[i]->GetCanonicalElectricalTypeName() );
// caution: construction work site here, drive slowly // caution: construction work site here, drive slowly
} }
@ -418,19 +469,11 @@ XNODE* NETLIST_EXPORTER_GENERIC::makeLibParts()
XNODE* NETLIST_EXPORTER_GENERIC::makeListOfNets() XNODE* NETLIST_EXPORTER_GENERIC::makeListOfNets()
{ {
XNODE* xnets = node( wxT( "nets" ) ); // auto_ptr if exceptions ever get used. XNODE* xnets = node( "nets" ); // auto_ptr if exceptions ever get used.
wxString netCodeTxt; wxString netCodeTxt;
wxString netName; wxString netName;
wxString ref; wxString ref;
wxString sNet = wxT( "net" );
wxString sName = wxT( "name" );
wxString sCode = wxT( "code" );
wxString sRef = wxT( "ref" );
wxString sPin = wxT( "pin" );
wxString sNode = wxT( "node" );
wxString sFmtd = wxT( "%d" );
XNODE* xnet = 0; XNODE* xnet = 0;
int netCode; int netCode;
int lastNetCode = -1; int lastNetCode = -1;
@ -474,16 +517,16 @@ XNODE* NETLIST_EXPORTER_GENERIC::makeListOfNets()
if( ++sameNetcodeCount == 1 ) if( ++sameNetcodeCount == 1 )
{ {
xnets->AddChild( xnet = node( sNet ) ); xnets->AddChild( xnet = node( "net" ) );
netCodeTxt.Printf( sFmtd, netCode ); netCodeTxt.Printf( "%d", netCode );
xnet->AddAttribute( sCode, netCodeTxt ); xnet->AddAttribute( "code", netCodeTxt );
xnet->AddAttribute( sName, netName ); xnet->AddAttribute( "name", netName );
} }
XNODE* xnode; XNODE* xnode;
xnet->AddChild( xnode = node( sNode ) ); xnet->AddChild( xnode = node( "node" ) );
xnode->AddAttribute( sRef, ref ); xnode->AddAttribute( "ref", ref );
xnode->AddAttribute( sPin, nitem->GetPinNumText() ); xnode->AddAttribute( "pin", nitem->GetPinNumText() );
} }
return xnets; return xnets;

View File

@ -123,6 +123,8 @@ protected:
* @return XNODE* - the library nodes * @return XNODE* - the library nodes
*/ */
XNODE* makeLibraries(); XNODE* makeLibraries();
void addComponentFields( XNODE* xcomp, SCH_COMPONENT* comp, SCH_SHEET_PATH* aSheet );
}; };
#endif #endif