35#include <wx/wfstream.h>
37#include <nlohmann/json.hpp>
52 wxFFileOutputStream stream( aOutFileName );
60 return xdoc.Save( stream, 2 );
68 xroot->AddAttribute( wxT(
"version" ), wxT(
"E" ) );
100 wxString description;
102 nlohmann::ordered_map<wxString, wxString> userFields;
113 wxString ref = aSymbol->
GetRef( aSheet );
118 for(
unsigned i = 0; i < sheetList.size(); i++ )
124 wxString ref2 = symbol2->
GetRef( &sheetList[i] );
126 if( ref2.CmpNoCase( ref ) != 0 )
136 if( !candidate.IsEmpty() && ( unit < minUnit || value.IsEmpty() ) )
142 if( !candidate.IsEmpty() && ( unit < minUnit || footprint.IsEmpty() ) )
143 footprint = candidate;
150 if( !candidate.IsEmpty() && ( unit < minUnit ||
datasheet.IsEmpty() ) )
158 if( !candidate.IsEmpty() && ( unit < minUnit || description.IsEmpty() ) )
159 description = candidate;
166 if( unit < minUnit || userFields.count( f.
GetName() ) == 0 )
175 minUnit = std::min( unit, minUnit );
211 aNode->AddChild(
node( wxT(
"value" ), wxT(
"~" ) ) );
213 if( footprint.size() )
222 if( userFields.size() )
225 aNode->AddChild( xfields =
node( wxT(
"fields" ) ) );
228 datasheetField->AddAttribute(
231 xfields->AddChild( datasheetField );
234 descriptionField->AddAttribute(
237 xfields->AddChild( descriptionField );
239 for(
const std::pair<const wxString, wxString>& f : userFields )
243 xfields->AddChild( xfield );
251 XNODE* xcomps =
node( wxT(
"components" ) );
262 for(
unsigned ii = 0; ii < sheetList.size(); ii++ )
273 b->GetRef( &sheet,
false ),
true ) < 0 );
276 std::set<
SCH_SYMBOL*,
decltype( cmp )> ordered_symbols( cmp );
277 std::multiset<
SCH_SYMBOL*,
decltype( cmp )> extra_units( cmp );
282 auto test = ordered_symbols.insert( symbol );
286 if( ( *(
test.first ) )->m_Uuid > symbol->
m_Uuid )
288 extra_units.insert( *(
test.first ) );
289 ordered_symbols.erase(
test.first );
290 ordered_symbols.insert( symbol );
294 extra_units.insert( symbol );
299 for(
EDA_ITEM* item : ordered_symbols )
315 xcomps->AddChild( xcomp =
node( wxT(
"comp" ) ) );
317 xcomp->AddAttribute( wxT(
"ref" ), symbol->
GetRef( &sheet ) );
321 xcomp->AddChild( xlibsource =
node( wxT(
"libsource" ) ) );
339 xlibsource->AddAttribute( wxT(
"lib" ), libName );
342 xlibsource->AddAttribute( wxT(
"part" ), partName );
344 xlibsource->AddAttribute( wxT(
"description" ), symbol->
GetDescription() );
349 std::vector<SCH_FIELD>& fields = symbol->
GetFields();
353 xcomp->AddChild( xproperty =
node( wxT(
"property" ) ) );
354 xproperty->AddAttribute( wxT(
"name" ), fields[jj].GetCanonicalName() );
357 xproperty->AddAttribute( wxT(
"value" ), fields[jj].GetShownText( &sheet,
false ) );
359 xproperty->AddAttribute( wxT(
"value" ), fields[jj].GetText() );
364 xcomp->AddChild( xproperty =
node( wxT(
"property" ) ) );
365 xproperty->AddAttribute( wxT(
"name" ), sheetField.GetCanonicalName() );
370 xproperty->AddAttribute( wxT(
"value" ), sheetField.GetShownText( &sheet,
false ) );
372 xproperty->AddAttribute( wxT(
"value" ), sheetField.GetText() );
377 xcomp->AddChild( xproperty =
node( wxT(
"property" ) ) );
378 xproperty->AddAttribute( wxT(
"name" ), wxT(
"exclude_from_bom" ) );
383 xcomp->AddChild( xproperty =
node( wxT(
"property" ) ) );
384 xproperty->AddAttribute( wxT(
"name" ), wxT(
"exclude_from_board" ) );
389 xcomp->AddChild( xproperty =
node( wxT(
"property" ) ) );
390 xproperty->AddAttribute( wxT(
"name" ), wxT(
"dnp" ) );
393 if(
const std::unique_ptr<LIB_SYMBOL>& part = symbol->
GetLibSymbolRef() )
395 if( part->GetKeyWords().size() )
397 xcomp->AddChild( xproperty =
node( wxT(
"property" ) ) );
398 xproperty->AddAttribute( wxT(
"name" ), wxT(
"ki_keywords" ) );
399 xproperty->AddAttribute( wxT(
"value" ), part->GetKeyWords() );
404 xcomp->AddChild( xsheetpath =
node( wxT(
"sheetpath" ) ) );
407 xsheetpath->AddAttribute( wxT(
"tstamps" ), sheet.
PathAsString() );
410 xcomp->AddChild( xunits =
node( wxT(
"tstamps" ) ) );
412 auto range = extra_units.equal_range( symbol );
416 for(
auto it = range.first; it != range.second; ++it )
418 uuid = ( *it )->m_Uuid.AsString();
425 xunits->AddChild(
new XNODE( wxXML_TEXT_NODE, wxEmptyString, uuid ) );
430 xunits->AddChild(
new XNODE( wxXML_TEXT_NODE, wxEmptyString, uuid ) );
443 XNODE* xdesign =
node( wxT(
"design" ) );
449 wxFileName sourceFileName;
461 for(
const std::pair<const wxString, wxString>& prop : properties )
463 xdesign->AddChild( xtextvar =
node( wxT(
"textvar" ), prop.second ) );
464 xtextvar->AddAttribute( wxT(
"name" ), prop.first );
472 for(
unsigned i = 0; i < sheetList.size(); i++ )
474 screen = sheetList[i].LastScreen();
476 xdesign->AddChild( xsheet =
node( wxT(
"sheet" ) ) );
481 sheetTxt.Printf( wxT(
"%u" ), i + 1 );
482 xsheet->AddAttribute( wxT(
"number" ), sheetTxt );
483 xsheet->AddAttribute( wxT(
"name" ), sheetList[i].PathHumanReadable() );
484 xsheet->AddAttribute( wxT(
"tstamps" ), sheetList[i].PathAsString() );
489 xsheet->AddChild( xtitleBlock =
node( wxT(
"title_block" ) ) );
497 sourceFileName = wxFileName( screen->
GetFileName() );
498 xtitleBlock->AddChild(
node( wxT(
"source" ), sourceFileName.GetFullName() ) );
500 xtitleBlock->AddChild( xcomment =
node( wxT(
"comment" ) ) );
501 xcomment->AddAttribute( wxT(
"number" ), wxT(
"1" ) );
504 xtitleBlock->AddChild( xcomment =
node( wxT(
"comment" ) ) );
505 xcomment->AddAttribute( wxT(
"number" ), wxT(
"2" ) );
508 xtitleBlock->AddChild( xcomment =
node( wxT(
"comment" ) ) );
509 xcomment->AddAttribute( wxT(
"number" ), wxT(
"3" ) );
512 xtitleBlock->AddChild( xcomment =
node( wxT(
"comment" ) ) );
513 xcomment->AddAttribute( wxT(
"number" ), wxT(
"4" ) );
516 xtitleBlock->AddChild( xcomment =
node( wxT(
"comment" ) ) );
517 xcomment->AddAttribute( wxT(
"number" ), wxT(
"5" ) );
520 xtitleBlock->AddChild( xcomment =
node( wxT(
"comment" ) ) );
521 xcomment->AddAttribute( wxT(
"number" ), wxT(
"6" ) );
524 xtitleBlock->AddChild( xcomment =
node( wxT(
"comment" ) ) );
525 xcomment->AddAttribute( wxT(
"number" ), wxT(
"7" ) );
528 xtitleBlock->AddChild( xcomment =
node( wxT(
"comment" ) ) );
529 xcomment->AddAttribute( wxT(
"number" ), wxT(
"8" ) );
532 xtitleBlock->AddChild( xcomment =
node( wxT(
"comment" ) ) );
533 xcomment->AddAttribute( wxT(
"number" ), wxT(
"9" ) );
543 XNODE* xlibs =
node( wxT(
"libraries" ) );
548 wxString libNickname = *it;
551 if( symbolLibTable->
HasLibrary( libNickname ) )
553 xlibs->AddChild( xlibrary =
node( wxT(
"library" ) ) );
554 xlibrary->AddAttribute( wxT(
"logical" ), libNickname );
555 xlibrary->AddChild(
node( wxT(
"uri" ), symbolLibTable->
GetFullURI( libNickname ) ) );
567 XNODE* xlibparts =
node( wxT(
"libparts" ) );
570 std::vector<LIB_FIELD*> fieldList;
576 wxString libNickname = lcomp->GetLibId().GetLibNickname();;
579 if( !libNickname.IsEmpty() )
583 xlibparts->AddChild( xlibpart =
node( wxT(
"libpart" ) ) );
584 xlibpart->AddAttribute( wxT(
"lib" ), libNickname );
585 xlibpart->AddAttribute( wxT(
"part" ), lcomp->GetName() );
588 if( !lcomp->GetDescription().IsEmpty() )
589 xlibpart->AddChild(
node( wxT(
"description" ), lcomp->GetDescription() ) );
591 if( !lcomp->GetDatasheetField().GetText().IsEmpty() )
592 xlibpart->AddChild(
node( wxT(
"docs" ), lcomp->GetDatasheetField().GetText() ) );
595 if( lcomp->GetFPFilters().GetCount() )
598 xlibpart->AddChild( xfootprints =
node( wxT(
"footprints" ) ) );
600 for(
unsigned i = 0; i < lcomp->GetFPFilters().GetCount(); ++i )
601 xfootprints->AddChild(
node( wxT(
"fp" ), lcomp->GetFPFilters()[i] ) );
606 lcomp->GetFields( fieldList );
609 xlibpart->AddChild( xfields =
node(
"fields" ) );
611 for(
const LIB_FIELD* field : fieldList )
614 xfields->AddChild( xfield =
node( wxT(
"field" ), field->GetText() ) );
615 xfield->AddAttribute( wxT(
"name" ), field->GetCanonicalName() );
620 lcomp->GetPins( pinList, 0, 0 );
631 for(
int ii = 0; ii < (int)pinList.size()-1; ii++ )
633 if( pinList[ii]->GetNumber() == pinList[ii+1]->GetNumber() )
635 pinList.erase(pinList.begin() + ii + 1);
644 xlibpart->AddChild( pins =
node( wxT(
"pins" ) ) );
645 for(
unsigned i=0; i<pinList.size(); ++i )
649 pins->AddChild(
pin =
node( wxT(
"pin" ) ) );
650 pin->AddAttribute( wxT(
"num" ), pinList[i]->GetShownNumber() );
651 pin->AddAttribute( wxT(
"name" ), pinList[i]->GetShownName() );
652 pin->AddAttribute( wxT(
"type" ), pinList[i]->GetCanonicalElectricalTypeName() );
670 XNODE* xnet =
nullptr;
690 NET_RECORD(
const wxString& aName ) : m_Name( aName ), m_HasNoConnect(
false ){};
694 std::vector<NET_NODE> m_Nodes;
697 std::vector<NET_RECORD*> nets;
701 wxString net_name = key.Name;
702 NET_RECORD* net_record =
nullptr;
704 if( subgraphs.empty() )
707 nets.emplace_back(
new NET_RECORD( net_name ) );
708 net_record = nets.back();
712 bool nc = subgraph->GetNoConnect() && subgraph->GetNoConnect()->Type() ==
SCH_NO_CONNECT_T;
716 net_record->m_HasNoConnect =
true;
718 for(
SCH_ITEM* item : subgraph->GetItems() )
732 net_record->m_Nodes.emplace_back(
pin, sheet );
739 std::sort( nets.begin(), nets.end(),
740 [](
const NET_RECORD* a,
const NET_RECORD*b )
742 return StrNumCmp( a->m_Name, b->m_Name ) < 0;
745 for(
int i = 0; i < (int) nets.size(); ++i )
747 NET_RECORD* net_record = nets[i];
752 std::sort( net_record->m_Nodes.begin(), net_record->m_Nodes.end(),
753 [](
const NET_NODE& a,
const NET_NODE& b )
755 wxString refA = a.m_Pin->GetParentSymbol()->GetRef( &a.m_Sheet );
756 wxString refB = b.m_Pin->GetParentSymbol()->GetRef( &b.m_Sheet );
759 return a.m_Pin->GetShownNumber() < b.m_Pin->GetShownNumber();
768 [](
const NET_NODE& a,
const NET_NODE& b )
770 wxString refA = a.m_Pin->GetParentSymbol()->GetRef( &a.m_Sheet );
771 wxString refB = b.m_Pin->GetParentSymbol()->GetRef( &b.m_Sheet );
773 return refA == refB && a.m_Pin->GetShownNumber() == b.m_Pin->GetShownNumber();
778 bool allNetPinsStacked =
true;
780 if( net_record->m_Nodes.size() > 1 )
782 SCH_PIN* firstPin = net_record->m_Nodes.begin()->m_Pin;
784 std::all_of( net_record->m_Nodes.begin() + 1, net_record->m_Nodes.end(),
787 return firstPin->GetParent() == node.m_Pin->GetParent()
788 && firstPin->GetPosition() == node.m_Pin->GetPosition()
789 && firstPin->GetName() == node.m_Pin->GetName();
793 for(
const NET_NODE& netNode : net_record->m_Nodes )
795 wxString refText = netNode.m_Pin->GetParentSymbol()->GetRef( &netNode.m_Sheet );
796 wxString pinText = netNode.m_Pin->GetShownNumber();
799 if( refText[0] == wxChar(
'#' ) )
804 netCodeTxt.Printf( wxT(
"%d" ), i + 1 );
806 xnets->AddChild( xnet =
node( wxT(
"net" ) ) );
807 xnet->AddAttribute( wxT(
"code" ), netCodeTxt );
808 xnet->AddAttribute( wxT(
"name" ), net_record->m_Name );
813 xnet->AddChild( xnode =
node( wxT(
"node" ) ) );
814 xnode->AddAttribute( wxT(
"ref" ), refText );
815 xnode->AddAttribute( wxT(
"pin" ), pinText );
817 wxString pinName = netNode.m_Pin->GetShownName();
818 wxString pinType = netNode.m_Pin->GetCanonicalElectricalTypeName();
820 if( !pinName.IsEmpty() )
821 xnode->AddAttribute( wxT(
"pinfunction" ), pinName );
823 if( net_record->m_HasNoConnect
824 && ( net_record->m_Nodes.size() == 1 || allNetPinsStacked ) )
825 pinType += wxT(
"+no_connect" );
827 xnode->AddAttribute( wxT(
"pintype" ), pinType );
831 for( NET_RECORD* record : nets )
839 const wxString& aTextualContent )
841 XNODE* n =
new XNODE( wxXML_ELEMENT_NODE, aName );
843 if( aTextualContent.Len() > 0 )
844 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 wxString GetUniStringLibItemName() const
Get strings for display messages in dialogs.
const wxString GetUniStringLibNickname() const
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.
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
bool GetExcludedFromBOM() 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
bool GetExcludedFromBoard() 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)
wxString GetISO8601CurrentDateTime()
static const wxString GetDefaultFieldName(int aFieldNdx, bool aTranslateForHI=false)
Return a default symbol field name for field aFieldNdx for all components.
Definition for symbol library class.
@ DATASHEET_FIELD
name of datasheet
@ MANDATORY_FIELDS
The first 5 are mandatory, and must be instantiated in SCH_COMPONENT and LIB_PART constructors.
@ DESCRIPTION_FIELD
Field Description of part, i.e. "1/4W 1% Metal Film Resistor".