35#include <wx/wfstream.h>
51 wxFFileOutputStream stream( aOutFileName );
59 return xdoc.Save( stream, 2 );
67 xroot->AddAttribute( wxT(
"version" ), wxT(
"E" ) );
100 std::map<wxString, wxString> userFields;
111 wxString ref = aSymbol->
GetRef( aSheet );
116 for(
unsigned i = 0; i < sheetList.size(); i++ )
122 wxString ref2 = symbol2->
GetRef( &sheetList[i] );
124 if( ref2.CmpNoCase( ref ) != 0 )
132 if( !candidate.IsEmpty() && ( unit < minUnit || value.IsEmpty() ) )
137 if( !candidate.IsEmpty() && ( unit < minUnit || footprint.IsEmpty() ) )
138 footprint = candidate;
144 if( !candidate.IsEmpty() && ( unit < minUnit ||
datasheet.IsEmpty() ) )
152 && ( unit < minUnit || userFields.count( f.
GetName() ) == 0 ) )
161 minUnit = std::min( unit, minUnit );
193 aNode->AddChild(
node( wxT(
"value" ), wxT(
"~" ) ) );
195 if( footprint.size() )
201 if( userFields.size() )
204 aNode->AddChild( xfields =
node( wxT(
"fields" ) ) );
207 for(
const std::pair<const wxString, wxString>& f : userFields )
211 xfields->AddChild( xfield );
219 XNODE* xcomps =
node( wxT(
"components" ) );
230 for(
unsigned ii = 0; ii < sheetList.size(); ii++ )
241 b->GetRef( &sheet,
false ),
true ) < 0 );
244 std::set<
SCH_SYMBOL*,
decltype( cmp )> ordered_symbols( cmp );
245 std::multiset<
SCH_SYMBOL*,
decltype( cmp )> extra_units( cmp );
250 auto test = ordered_symbols.insert( symbol );
254 if( ( *(
test.first ) )->m_Uuid > symbol->
m_Uuid )
256 extra_units.insert( *(
test.first ) );
257 ordered_symbols.erase(
test.first );
258 ordered_symbols.insert( symbol );
262 extra_units.insert( symbol );
267 for(
EDA_ITEM* item : ordered_symbols )
283 xcomps->AddChild( xcomp =
node( wxT(
"comp" ) ) );
285 xcomp->AddAttribute( wxT(
"ref" ), symbol->
GetRef( &sheet ) );
289 xcomp->AddChild( xlibsource =
node( wxT(
"libsource" ) ) );
307 xlibsource->AddAttribute( wxT(
"lib" ), libName );
310 xlibsource->AddAttribute( wxT(
"part" ), partName );
312 xlibsource->AddAttribute( wxT(
"description" ), symbol->
GetDescription() );
316 std::vector<SCH_FIELD>& fields = symbol->
GetFields();
320 xcomp->AddChild( xproperty =
node( wxT(
"property" ) ) );
321 xproperty->AddAttribute( wxT(
"name" ), fields[jj].GetCanonicalName() );
324 xproperty->AddAttribute( wxT(
"value" ), fields[jj].GetShownText( &sheet,
false ) );
326 xproperty->AddAttribute( wxT(
"value" ), fields[jj].GetText() );
331 xcomp->AddChild( xproperty =
node( wxT(
"property" ) ) );
332 xproperty->AddAttribute( wxT(
"name" ), sheetField.GetCanonicalName() );
337 xproperty->AddAttribute( wxT(
"value" ), sheetField.GetShownText( &sheet,
false ) );
339 xproperty->AddAttribute( wxT(
"value" ), sheetField.GetText() );
344 xcomp->AddChild( xproperty =
node( wxT(
"property" ) ) );
345 xproperty->AddAttribute( wxT(
"name" ), wxT(
"exclude_from_bom" ) );
350 xcomp->AddChild( xproperty =
node( wxT(
"property" ) ) );
351 xproperty->AddAttribute( wxT(
"name" ), wxT(
"exclude_from_board" ) );
356 xcomp->AddChild( xproperty =
node( wxT(
"property" ) ) );
357 xproperty->AddAttribute( wxT(
"name" ), wxT(
"dnp" ) );
360 if(
const std::unique_ptr<LIB_SYMBOL>& part = symbol->
GetLibSymbolRef() )
362 if( part->GetDescription().size() )
364 xcomp->AddChild( xproperty =
node( wxT(
"property" ) ) );
365 xproperty->AddAttribute( wxT(
"name" ), wxT(
"ki_description" ) );
366 xproperty->AddAttribute( wxT(
"value" ), part->GetDescription() );
369 if( part->GetKeyWords().size() )
371 xcomp->AddChild( xproperty =
node( wxT(
"property" ) ) );
372 xproperty->AddAttribute( wxT(
"name" ), wxT(
"ki_keywords" ) );
373 xproperty->AddAttribute( wxT(
"value" ), part->GetKeyWords() );
378 xcomp->AddChild( xsheetpath =
node( wxT(
"sheetpath" ) ) );
381 xsheetpath->AddAttribute( wxT(
"tstamps" ), sheet.
PathAsString() );
384 xcomp->AddChild( xunits =
node( wxT(
"tstamps" ) ) );
386 auto range = extra_units.equal_range( symbol );
390 for(
auto it = range.first; it != range.second; ++it )
392 uuid = ( *it )->m_Uuid.AsString();
399 xunits->AddChild(
new XNODE( wxXML_TEXT_NODE, wxEmptyString, uuid ) );
404 xunits->AddChild(
new XNODE( wxXML_TEXT_NODE, wxEmptyString, uuid ) );
417 XNODE* xdesign =
node( wxT(
"design" ) );
423 wxFileName sourceFileName;
435 for(
const std::pair<const wxString, wxString>& prop : properties )
437 xdesign->AddChild( xtextvar =
node( wxT(
"textvar" ), prop.second ) );
438 xtextvar->AddAttribute( wxT(
"name" ), prop.first );
446 for(
unsigned i = 0; i < sheetList.size(); i++ )
448 screen = sheetList[i].LastScreen();
450 xdesign->AddChild( xsheet =
node( wxT(
"sheet" ) ) );
455 sheetTxt.Printf( wxT(
"%u" ), i + 1 );
456 xsheet->AddAttribute( wxT(
"number" ), sheetTxt );
457 xsheet->AddAttribute( wxT(
"name" ), sheetList[i].PathHumanReadable() );
458 xsheet->AddAttribute( wxT(
"tstamps" ), sheetList[i].PathAsString() );
463 xsheet->AddChild( xtitleBlock =
node( wxT(
"title_block" ) ) );
471 sourceFileName = wxFileName( screen->
GetFileName() );
472 xtitleBlock->AddChild(
node( wxT(
"source" ), sourceFileName.GetFullName() ) );
474 xtitleBlock->AddChild( xcomment =
node( wxT(
"comment" ) ) );
475 xcomment->AddAttribute( wxT(
"number" ), wxT(
"1" ) );
478 xtitleBlock->AddChild( xcomment =
node( wxT(
"comment" ) ) );
479 xcomment->AddAttribute( wxT(
"number" ), wxT(
"2" ) );
482 xtitleBlock->AddChild( xcomment =
node( wxT(
"comment" ) ) );
483 xcomment->AddAttribute( wxT(
"number" ), wxT(
"3" ) );
486 xtitleBlock->AddChild( xcomment =
node( wxT(
"comment" ) ) );
487 xcomment->AddAttribute( wxT(
"number" ), wxT(
"4" ) );
490 xtitleBlock->AddChild( xcomment =
node( wxT(
"comment" ) ) );
491 xcomment->AddAttribute( wxT(
"number" ), wxT(
"5" ) );
494 xtitleBlock->AddChild( xcomment =
node( wxT(
"comment" ) ) );
495 xcomment->AddAttribute( wxT(
"number" ), wxT(
"6" ) );
498 xtitleBlock->AddChild( xcomment =
node( wxT(
"comment" ) ) );
499 xcomment->AddAttribute( wxT(
"number" ), wxT(
"7" ) );
502 xtitleBlock->AddChild( xcomment =
node( wxT(
"comment" ) ) );
503 xcomment->AddAttribute( wxT(
"number" ), wxT(
"8" ) );
506 xtitleBlock->AddChild( xcomment =
node( wxT(
"comment" ) ) );
507 xcomment->AddAttribute( wxT(
"number" ), wxT(
"9" ) );
517 XNODE* xlibs =
node( wxT(
"libraries" ) );
522 wxString libNickname = *it;
525 if( symbolLibTable->
HasLibrary( libNickname ) )
527 xlibs->AddChild( xlibrary =
node( wxT(
"library" ) ) );
528 xlibrary->AddAttribute( wxT(
"logical" ), libNickname );
529 xlibrary->AddChild(
node( wxT(
"uri" ), symbolLibTable->
GetFullURI( libNickname ) ) );
541 XNODE* xlibparts =
node( wxT(
"libparts" ) );
544 std::vector<LIB_FIELD*> fieldList;
550 wxString libNickname = lcomp->GetLibId().GetLibNickname();;
553 if( !libNickname.IsEmpty() )
557 xlibparts->AddChild( xlibpart =
node( wxT(
"libpart" ) ) );
558 xlibpart->AddAttribute( wxT(
"lib" ), libNickname );
559 xlibpart->AddAttribute( wxT(
"part" ), lcomp->GetName() );
562 if( !lcomp->GetDescription().IsEmpty() )
563 xlibpart->AddChild(
node( wxT(
"description" ), lcomp->GetDescription() ) );
565 if( !lcomp->GetDatasheetField().GetText().IsEmpty() )
566 xlibpart->AddChild(
node( wxT(
"docs" ), lcomp->GetDatasheetField().GetText() ) );
569 if( lcomp->GetFPFilters().GetCount() )
572 xlibpart->AddChild( xfootprints =
node( wxT(
"footprints" ) ) );
574 for(
unsigned i = 0; i < lcomp->GetFPFilters().GetCount(); ++i )
575 xfootprints->AddChild(
node( wxT(
"fp" ), lcomp->GetFPFilters()[i] ) );
580 lcomp->GetFields( fieldList );
583 xlibpart->AddChild( xfields =
node(
"fields" ) );
585 for(
const LIB_FIELD* field : fieldList )
587 if( !field->GetText().IsEmpty() )
590 xfields->AddChild( xfield =
node( wxT(
"field" ), field->GetText() ) );
591 xfield->AddAttribute( wxT(
"name" ), field->GetCanonicalName() );
597 lcomp->GetPins( pinList, 0, 0 );
608 for(
int ii = 0; ii < (int)pinList.size()-1; ii++ )
610 if( pinList[ii]->GetNumber() == pinList[ii+1]->GetNumber() )
612 pinList.erase(pinList.begin() + ii + 1);
621 xlibpart->AddChild( pins =
node( wxT(
"pins" ) ) );
622 for(
unsigned i=0; i<pinList.size(); ++i )
626 pins->AddChild(
pin =
node( wxT(
"pin" ) ) );
627 pin->AddAttribute( wxT(
"num" ), pinList[i]->GetShownNumber() );
628 pin->AddAttribute( wxT(
"name" ), pinList[i]->GetShownName() );
629 pin->AddAttribute( wxT(
"type" ), pinList[i]->GetCanonicalElectricalTypeName() );
647 XNODE* xnet =
nullptr;
667 NET_RECORD(
const wxString& aName ) : m_Name( aName ), m_HasNoConnect(
false ){};
671 std::vector<NET_NODE> m_Nodes;
674 std::vector<NET_RECORD*> nets;
678 wxString net_name = key.Name;
679 NET_RECORD* net_record =
nullptr;
681 if( subgraphs.empty() )
684 nets.emplace_back(
new NET_RECORD( net_name ) );
685 net_record = nets.back();
689 bool nc = subgraph->GetNoConnect() && subgraph->GetNoConnect()->Type() ==
SCH_NO_CONNECT_T;
693 net_record->m_HasNoConnect =
true;
695 for(
SCH_ITEM* item : subgraph->GetItems() )
709 net_record->m_Nodes.emplace_back(
pin, sheet );
716 std::sort( nets.begin(), nets.end(),
717 [](
const NET_RECORD* a,
const NET_RECORD*b )
719 return StrNumCmp( a->m_Name, b->m_Name ) < 0;
722 for(
int i = 0; i < (int) nets.size(); ++i )
724 NET_RECORD* net_record = nets[i];
729 std::sort( net_record->m_Nodes.begin(), net_record->m_Nodes.end(),
730 [](
const NET_NODE& a,
const NET_NODE& b )
732 wxString refA = a.m_Pin->GetParentSymbol()->GetRef( &a.m_Sheet );
733 wxString refB = b.m_Pin->GetParentSymbol()->GetRef( &b.m_Sheet );
736 return a.m_Pin->GetShownNumber() < b.m_Pin->GetShownNumber();
745 [](
const NET_NODE& a,
const NET_NODE& b )
747 wxString refA = a.m_Pin->GetParentSymbol()->GetRef( &a.m_Sheet );
748 wxString refB = b.m_Pin->GetParentSymbol()->GetRef( &b.m_Sheet );
750 return refA == refB && a.m_Pin->GetShownNumber() == b.m_Pin->GetShownNumber();
755 bool allNetPinsStacked =
true;
757 if( net_record->m_Nodes.size() > 1 )
759 SCH_PIN* firstPin = net_record->m_Nodes.begin()->m_Pin;
761 std::all_of( net_record->m_Nodes.begin() + 1, net_record->m_Nodes.end(),
764 return firstPin->GetParent() == node.m_Pin->GetParent()
765 && firstPin->GetPosition() == node.m_Pin->GetPosition()
766 && firstPin->GetName() == node.m_Pin->GetName();
770 for(
const NET_NODE& netNode : net_record->m_Nodes )
772 wxString refText = netNode.m_Pin->GetParentSymbol()->GetRef( &netNode.m_Sheet );
773 wxString pinText = netNode.m_Pin->GetShownNumber();
776 if( refText[0] == wxChar(
'#' ) )
781 netCodeTxt.Printf( wxT(
"%d" ), i + 1 );
783 xnets->AddChild( xnet =
node( wxT(
"net" ) ) );
784 xnet->AddAttribute( wxT(
"code" ), netCodeTxt );
785 xnet->AddAttribute( wxT(
"name" ), net_record->m_Name );
790 xnet->AddChild( xnode =
node( wxT(
"node" ) ) );
791 xnode->AddAttribute( wxT(
"ref" ), refText );
792 xnode->AddAttribute( wxT(
"pin" ), pinText );
794 wxString pinName = netNode.m_Pin->GetShownName();
795 wxString pinType = netNode.m_Pin->GetCanonicalElectricalTypeName();
797 if( !pinName.IsEmpty() )
798 xnode->AddAttribute( wxT(
"pinfunction" ), pinName );
800 if( net_record->m_HasNoConnect
801 && ( net_record->m_Nodes.size() == 1 || allNetPinsStacked ) )
802 pinType += wxT(
"+no_connect" );
804 xnode->AddAttribute( wxT(
"pintype" ), pinType );
808 for( NET_RECORD* record : nets )
816 const wxString& aTextualContent )
818 XNODE* n =
new XNODE( wxXML_ELEMENT_NODE, aName );
820 if( aTextualContent.Len() > 0 )
821 n->AddChild(
new XNODE( wxXML_TEXT_NODE, wxEmptyString, aTextualContent ) );
wxString GetBuildVersion()
Get the full KiCad version string.
const NET_MAP & GetNetMap() const
A subgraph is a set of items that are electrically connected on a single sheet.
A base class for most all the KiCad significant classes used in schematics and boards.
virtual const wxString & GetText() const
Return the string associated with the text object.
EE_TYPE OfType(KICAD_T aType) const
wxString AsString() const
Field object used in symbol libraries.
const UTF8 & GetLibItemName() const
const UTF8 & GetLibNickname() const
Return the logical library name portion of a LIB_ID.
wxString GetShownNumber() const
Define a library symbol object.
bool HasLibrary(const wxString &aNickname, bool aCheckEnabled=false) const
Test for the existence of aNickname in the library table.
wxString GetFullURI(const wxString &aLibNickname, bool aExpandEnvVars=true) const
Return the full URI of the library mapped to aLibNickname.
std::set< LIB_SYMBOL *, LIB_SYMBOL_LESS_THAN > m_libParts
unique library symbols used. LIB_SYMBOL items are sorted by names
UNIQUE_STRINGS m_referencesAlreadyFound
Used for "multiple symbols per package" symbols to avoid processing a lib symbol more than once.
SCH_SYMBOL * findNextSymbol(EDA_ITEM *aItem, SCH_SHEET_PATH *aSheetPath)
Check if the given symbol should be processed for netlisting.
SCHEMATIC_IFACE * m_schematic
The schematic we're generating a netlist for.
XNODE * makeDesignHeader()
Fill out a project "design" header into an XML node.
XNODE * makeLibraries()
Fill out an XML node with a list of used libraries and returns it.
bool WriteNetlist(const wxString &aOutFileName, unsigned aNetlistOptions, REPORTER &aReporter) override
Write generic netlist to aOutFileName.
XNODE * node(const wxString &aName, const wxString &aTextualContent=wxEmptyString)
A convenience function that creates a new XNODE with an optional textual child.
XNODE * makeListOfNets(unsigned aCtl)
Fill out an XML node with a list of nets and returns it.
XNODE * makeSymbols(unsigned aCtl)
XNODE * makeRoot(unsigned aCtl=GNL_ALL)
Build the entire document tree for the generic export.
void addSymbolFields(XNODE *aNode, SCH_SYMBOL *aSymbol, SCH_SHEET_PATH *aSheet)
Holder for multi-unit symbol fields.
std::set< wxString > m_libraries
XNODE * makeLibParts()
Fill out an XML node with the unique library parts and returns it.
Container for project specific data.
virtual std::map< wxString, wxString > & GetTextVars() const
A pure virtual class used to derive REPORTER objects from.
virtual void SetCurrentSheet(const SCH_SHEET_PATH &aPath)=0
virtual wxString GetFileName() const =0
virtual CONNECTION_GRAPH * ConnectionGraph() const =0
virtual SCH_SHEET_LIST GetSheets() const =0
virtual SCH_SHEET_PATH & CurrentSheet() const =0
virtual PROJECT & Prj() const =0
Instances are attached to a symbol or sheet and provide a place for the symbol's value,...
wxString GetName(bool aUseDefaultName=true) const
Return the field name (not translated).
wxString GetShownText(const SCH_SHEET_PATH *aPath, bool aAllowExtraText, int aDepth=0) const
Base class for any item which can be embedded within the SCHEMATIC container class,...
EE_RTREE & Items()
Gets the full RTree, usually for iterating.
const wxString & GetFileName() const
const TITLE_BLOCK & GetTitleBlock() const
A container for handling SCH_SHEET_PATH objects in a flattened hierarchy.
Handle access to a stack of flattened SCH_SHEET objects by way of a path for creating a flattened sch...
const SCH_SHEET * GetSheet(unsigned aIndex) const
wxString PathHumanReadable(bool aUseShortRootName=true, bool aStripTrailingSeparator=false) const
Return the sheet path in a human readable form made from the sheet names.
SCH_SCREEN * LastScreen()
wxString PathAsString() const
Return the path of time stamps which do not changes even when editing sheet parameters.
SCH_SHEET * Last() const
Return a pointer to the last SCH_SHEET of the list.
std::vector< SCH_FIELD > & GetFields()
int GetUnitCount() const
Return the number of units per package of the symbol.
int GetFieldCount() const
Return the number of fields in this symbol.
bool UseLibIdLookup() const
wxString GetSchSymbolLibraryName() const
const wxString GetRef(const SCH_SHEET_PATH *aSheet, bool aIncludeUnit=false) const
Return the reference for the given sheet path.
bool GetIncludeOnBoard() const
bool GetIncludeInBom() const
SCH_FIELD * GetField(MANDATORY_FIELD_T aFieldType)
Return a mandatory field in this symbol.
const wxString GetFootprintFieldText(bool aResolve, const SCH_SHEET_PATH *aPath, bool aAllowExtraText) const
wxString GetDescription() const
const wxString GetValueFieldText(bool aResolve, const SCH_SHEET_PATH *aPath, bool aAllowExtraText) const
int GetUnitSelection(const SCH_SHEET_PATH *aSheet) const
Return the instance-specific unit selection for the given sheet path.
const LIB_ID & GetLibId() const
void GetFields(std::vector< SCH_FIELD * > &aVector, bool aVisibleOnly)
Populate a std::vector with SCH_FIELDs.
std::unique_ptr< LIB_SYMBOL > & GetLibSymbolRef()
Hold the information shown in the lower right corner of a plot, printout, or editing view.
const wxString & GetCompany() const
const wxString & GetRevision() const
const wxString & GetDate() const
const wxString & GetComment(int aIdx) const
const wxString & GetTitle() const
void Clear()
Erase the record.
Hold an XML or S-expression element.
wxString ExpandTextVars(const wxString &aSource, const PROJECT *aProject)
std::vector< LIB_PIN * > LIB_PINS
Helper for defining a list of pin object pointers.
void remove_duplicates(_Container &__c)
Deletes all duplicate values from __c.
static bool sortPinsByNumber(LIB_PIN *aPin1, LIB_PIN *aPin2)
int StrNumCmp(const wxString &aString1, const wxString &aString2, bool aIgnoreCase)
Compare two strings with alphanumerical content.
wxString UnescapeString(const wxString &aSource)
Definition for symbol library class.
@ DATASHEET_FIELD
name of datasheet
@ MANDATORY_FIELDS
The first 4 are mandatory, and must be instantiated in SCH_COMPONENT and LIB_PART constructors.