36#include <wx/wfstream.h>
54 wxFFileOutputStream stream( aOutFileName );
62 return xdoc.Save( stream, 2 );
70 xroot->AddAttribute( wxT(
"version" ), wxT(
"E" ) );
108 wxString description;
110 nlohmann::ordered_map<wxString, wxString> fields;
121 wxString ref = aSymbol->
GetRef( &aSheet );
131 wxString ref2 = symbol2->
GetRef( &sheet );
133 if( ref2.CmpNoCase( ref ) != 0 )
143 if( !candidate.IsEmpty() && ( unit < minUnit || value.IsEmpty() ) )
149 if( !candidate.IsEmpty() && ( unit < minUnit || footprint.IsEmpty() ) )
150 footprint = candidate;
157 if( !candidate.IsEmpty() && ( unit < minUnit ||
datasheet.IsEmpty() ) )
165 if( !candidate.IsEmpty() && ( unit < minUnit || description.IsEmpty() ) )
166 description = candidate;
171 if( field.IsMandatory() || field.IsPrivate() )
174 if( unit < minUnit || fields.count( field.GetName() ) == 0 )
177 fields[field.GetName()] = field.GetShownText( &aSheet,
false );
179 fields[field.GetName()] = field.GetText();
183 minUnit = std::min( unit, minUnit );
203 description = descriptionField->
GetShownText( &aSheet,
false );
205 description = descriptionField->
GetText();
209 if( field.IsMandatory() || field.IsPrivate() )
213 fields[field.GetName()] = field.GetShownText( &aSheet,
false );
215 fields[field.GetName()] = field.GetText();
227 aNode->AddChild(
node( wxT(
"value" ), wxT(
"~" ) ) );
229 if( footprint.size() )
235 if( description.size() )
239 aNode->AddChild( xfields =
node( wxT(
"fields" ) ) );
241 for(
const auto& [ fieldName, fieldValue ] : fields )
244 xfield->AddAttribute( wxT(
"name" ),
UnescapeString( fieldName ) );
245 xfields->AddChild( xfield );
252 XNODE* xcomps =
node( wxT(
"components" ) );
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 )
319 xcomps->AddChild( xcomp =
node( wxT(
"comp" ) ) );
321 xcomp->AddAttribute( wxT(
"ref" ), symbol->
GetRef( &sheet ) );
325 xcomp->AddChild( xlibsource =
node( wxT(
"libsource" ) ) );
343 xlibsource->AddAttribute( wxT(
"lib" ), libName );
346 xlibsource->AddAttribute( wxT(
"part" ), partName );
348 xlibsource->AddAttribute( wxT(
"description" ), symbol->
GetDescription() );
353 std::vector<SCH_FIELD>& fields = symbol->
GetFields();
357 if( field.IsMandatory() || field.IsPrivate() )
360 xcomp->AddChild( xproperty =
node( wxT(
"property" ) ) );
361 xproperty->AddAttribute( wxT(
"name" ), field.GetCanonicalName() );
364 xproperty->AddAttribute( wxT(
"value" ), field.GetShownText( &sheet,
false ) );
366 xproperty->AddAttribute( wxT(
"value" ), field.GetText() );
369 for(
const SCH_FIELD& sheetField : sheet.Last()->GetFields() )
371 xcomp->AddChild( xproperty =
node( wxT(
"property" ) ) );
372 xproperty->AddAttribute( wxT(
"name" ), sheetField.GetCanonicalName() );
377 xproperty->AddAttribute( wxT(
"value" ), sheetField.GetShownText( &sheet,
false ) );
379 xproperty->AddAttribute( wxT(
"value" ), sheetField.GetText() );
384 xcomp->AddChild( xproperty =
node( wxT(
"property" ) ) );
385 xproperty->AddAttribute( wxT(
"name" ), wxT(
"exclude_from_bom" ) );
390 xcomp->AddChild( xproperty =
node( wxT(
"property" ) ) );
391 xproperty->AddAttribute( wxT(
"name" ), wxT(
"exclude_from_board" ) );
396 xcomp->AddChild( xproperty =
node( wxT(
"property" ) ) );
397 xproperty->AddAttribute( wxT(
"name" ), wxT(
"dnp" ) );
400 if(
const std::unique_ptr<LIB_SYMBOL>& part = symbol->
GetLibSymbolRef() )
402 if( part->GetKeyWords().size() )
404 xcomp->AddChild( xproperty =
node( wxT(
"property" ) ) );
405 xproperty->AddAttribute( wxT(
"name" ), wxT(
"ki_keywords" ) );
406 xproperty->AddAttribute( wxT(
"value" ), part->GetKeyWords() );
409 if( !part->GetFPFilters().IsEmpty() )
413 for(
const wxString&
filter : part->GetFPFilters() )
416 xcomp->AddChild( xproperty =
node( wxT(
"property" ) ) );
417 xproperty->AddAttribute( wxT(
"name" ), wxT(
"ki_fp_filters" ) );
418 xproperty->AddAttribute( wxT(
"value" ), filters.Trim(
false ) );
421 if( part->GetDuplicatePinNumbersAreJumpers() )
422 xcomp->AddChild(
node( wxT(
"duplicate_pin_numbers_are_jumpers" ), wxT(
"1" ) ) );
424 const std::vector<std::set<wxString>>& jumperGroups = part->JumperPinGroups();
426 if( !jumperGroups.empty() )
429 xcomp->AddChild( xproperty =
node( wxT(
"jumper_pin_groups" ) ) );
431 for(
const std::set<wxString>&
group : jumperGroups )
433 xproperty->AddChild( groupNode =
node( wxT(
"group" ) ) );
435 for(
const wxString& padName :
group )
436 groupNode->AddAttribute( wxT(
"pin" ), padName );
442 xcomp->AddChild( xsheetpath =
node( wxT(
"sheetpath" ) ) );
444 xsheetpath->AddAttribute( wxT(
"names" ), sheet.PathHumanReadable() );
445 xsheetpath->AddAttribute( wxT(
"tstamps" ), sheet.PathAsString() );
448 std::vector<wxString> compClassNames =
451 if( compClassNames.size() > 0 )
453 XNODE* xcompclasslist;
454 xcomp->AddChild( xcompclasslist =
node( wxT(
"component_classes" ) ) );
456 for(
const wxString& compClass : compClassNames )
463 xcomp->AddChild( xunits =
node( wxT(
"tstamps" ) ) );
465 auto range = extra_units.equal_range( symbol );
469 for(
auto it = range.first; it != range.second; ++it )
471 uuid = ( *it )->m_Uuid.AsString();
478 xunits->AddChild(
new XNODE( wxXML_TEXT_NODE, wxEmptyString, uuid ) );
483 xunits->AddChild(
new XNODE( wxXML_TEXT_NODE, wxEmptyString, uuid ) );
514 xcomps->AddChild( xgroup =
node( wxT(
"group" ) ) );
516 xgroup->AddAttribute( wxT(
"name" ),
group->GetName() );
517 xgroup->AddAttribute( wxT(
"uuid" ),
group->m_Uuid.AsString() );
518 xgroup->AddAttribute( wxT(
"lib_id" ),
group->GetDesignBlockLibId().Format() );
521 xgroup->AddChild( xmembers =
node( wxT(
"members" ) ) );
528 xmembers->AddChild( xmember =
node( wxT(
"member" ) ) );
529 xmember->AddAttribute( wxT(
"uuid" ), member->m_Uuid.AsString() );
549 wxString ref = aSymbol->
GetRef( &aSymbolSheet );
557 wxString ref2 = symbol2->
GetRef( &sheet );
560 if( ref2.CmpNoCase( ref ) != 0 )
563 if( otherUnit == primaryUnit )
566 std::unordered_set<wxString> otherClassNames =
568 compClassNames.insert( otherClassNames.begin(), otherClassNames.end() );
573 std::vector<wxString> sortedCompClassNames( compClassNames.begin(), compClassNames.end() );
574 std::sort( sortedCompClassNames.begin(), sortedCompClassNames.end(),
575 [](
const wxString& str1,
const wxString& str2 )
577 return str1.Cmp( str2 ) < 0;
580 return sortedCompClassNames;
587 XNODE* xdesign =
node( wxT(
"design" ) );
593 wxFileName sourceFileName;
605 for(
const std::pair<const wxString, wxString>& prop : properties )
607 xdesign->AddChild( xtextvar =
node( wxT(
"textvar" ), prop.second ) );
608 xtextvar->AddAttribute( wxT(
"name" ), prop.first );
614 unsigned sheetIndex = 1;
618 screen = sheet.LastScreen();
620 xdesign->AddChild( xsheet =
node( wxT(
"sheet" ) ) );
623 sheetTxt.Printf( wxT(
"%u" ), sheetIndex++ );
624 xsheet->AddAttribute( wxT(
"number" ), sheetTxt );
625 xsheet->AddAttribute( wxT(
"name" ), sheet.PathHumanReadable() );
626 xsheet->AddAttribute( wxT(
"tstamps" ), sheet.PathAsString() );
631 xsheet->AddChild( xtitleBlock =
node( wxT(
"title_block" ) ) );
639 sourceFileName = wxFileName( screen->
GetFileName() );
640 xtitleBlock->AddChild(
node( wxT(
"source" ), sourceFileName.GetFullName() ) );
642 xtitleBlock->AddChild( xcomment =
node( wxT(
"comment" ) ) );
643 xcomment->AddAttribute( wxT(
"number" ), wxT(
"1" ) );
646 xtitleBlock->AddChild( xcomment =
node( wxT(
"comment" ) ) );
647 xcomment->AddAttribute( wxT(
"number" ), wxT(
"2" ) );
650 xtitleBlock->AddChild( xcomment =
node( wxT(
"comment" ) ) );
651 xcomment->AddAttribute( wxT(
"number" ), wxT(
"3" ) );
654 xtitleBlock->AddChild( xcomment =
node( wxT(
"comment" ) ) );
655 xcomment->AddAttribute( wxT(
"number" ), wxT(
"4" ) );
658 xtitleBlock->AddChild( xcomment =
node( wxT(
"comment" ) ) );
659 xcomment->AddAttribute( wxT(
"number" ), wxT(
"5" ) );
662 xtitleBlock->AddChild( xcomment =
node( wxT(
"comment" ) ) );
663 xcomment->AddAttribute( wxT(
"number" ), wxT(
"6" ) );
666 xtitleBlock->AddChild( xcomment =
node( wxT(
"comment" ) ) );
667 xcomment->AddAttribute( wxT(
"number" ), wxT(
"7" ) );
670 xtitleBlock->AddChild( xcomment =
node( wxT(
"comment" ) ) );
671 xcomment->AddAttribute( wxT(
"number" ), wxT(
"8" ) );
674 xtitleBlock->AddChild( xcomment =
node( wxT(
"comment" ) ) );
675 xcomment->AddAttribute( wxT(
"number" ), wxT(
"9" ) );
685 XNODE* xlibs =
node( wxT(
"libraries" ) );
690 wxString libNickname = *it;
693 if( symbolLibTable->
HasLibrary( libNickname ) )
695 xlibs->AddChild( xlibrary =
node( wxT(
"library" ) ) );
696 xlibrary->AddAttribute( wxT(
"logical" ), libNickname );
697 xlibrary->AddChild(
node( wxT(
"uri" ), symbolLibTable->
GetFullURI( libNickname ) ) );
709 XNODE* xlibparts =
node( wxT(
"libparts" ) );
710 std::vector<SCH_FIELD*> fieldList;
716 wxString libNickname = lcomp->GetLibId().GetLibNickname();;
719 if( !libNickname.IsEmpty() )
723 xlibparts->AddChild( xlibpart =
node( wxT(
"libpart" ) ) );
724 xlibpart->AddAttribute( wxT(
"lib" ), libNickname );
725 xlibpart->AddAttribute( wxT(
"part" ), lcomp->GetName() );
728 if( !lcomp->GetDescription().IsEmpty() )
729 xlibpart->AddChild(
node( wxT(
"description" ), lcomp->GetDescription() ) );
731 if( !lcomp->GetDatasheetField().GetText().IsEmpty() )
732 xlibpart->AddChild(
node( wxT(
"docs" ), lcomp->GetDatasheetField().GetText() ) );
735 if( lcomp->GetFPFilters().GetCount() )
738 xlibpart->AddChild( xfootprints =
node( wxT(
"footprints" ) ) );
740 for(
unsigned i = 0; i < lcomp->GetFPFilters().GetCount(); ++i )
742 if( !lcomp->GetFPFilters()[i].IsEmpty() )
743 xfootprints->AddChild(
node( wxT(
"fp" ), lcomp->GetFPFilters()[i] ) );
749 lcomp->GetFields( fieldList );
752 xlibpart->AddChild( xfields =
node(
"fields" ) );
754 for(
const SCH_FIELD* field : fieldList )
757 xfields->AddChild( xfield =
node( wxT(
"field" ), field->GetText() ) );
758 xfield->AddAttribute( wxT(
"name" ), field->GetCanonicalName() );
762 std::vector<SCH_PIN*> pinList = lcomp->GetPins( 0, 0 );
774 for(
int ii = 0; ii < (int)pinList.size()-1; ii++ )
776 if( pinList[ii]->GetNumber() == pinList[ii+1]->GetNumber() )
778 pinList.erase(pinList.begin() + ii + 1);
787 xlibpart->AddChild( pins =
node( wxT(
"pins" ) ) );
789 for(
unsigned i=0; i<pinList.size(); ++i )
793 pins->AddChild(
pin =
node( wxT(
"pin" ) ) );
794 pin->AddAttribute( wxT(
"num" ), pinList[i]->GetShownNumber() );
795 pin->AddAttribute( wxT(
"name" ), pinList[i]->GetShownName() );
796 pin->AddAttribute( wxT(
"type" ), pinList[i]->GetCanonicalElectricalTypeName() );
811 XNODE* xnet =
nullptr;
833 NET_RECORD(
const wxString& aName ) :
835 m_HasNoConnect(
false )
841 std::vector<NET_NODE> m_Nodes;
844 std::vector<NET_RECORD*> nets;
848 wxString net_name = key.Name;
849 NET_RECORD* net_record =
nullptr;
854 if( subgraphs.empty() )
857 nets.emplace_back(
new NET_RECORD( net_name ) );
858 net_record = nets.back();
862 bool nc = subgraph->GetNoConnect() && subgraph->GetNoConnect()->Type() ==
SCH_NO_CONNECT_T;
865 if( net_record->m_Class.IsEmpty() && subgraph->GetDriver() )
867 if( subgraph->GetDriver()->GetEffectiveNetClass() )
869 net_record->m_Class = subgraph->GetDriver()->GetEffectiveNetClass()->GetName();
875 net_record->m_HasNoConnect =
true;
877 for(
SCH_ITEM* item : subgraph->GetItems() )
895 net_record->m_Nodes.emplace_back(
pin, sheet );
902 std::sort( nets.begin(), nets.end(),
903 [](
const NET_RECORD* a,
const NET_RECORD*b )
905 return StrNumCmp( a->m_Name, b->m_Name ) < 0;
908 for(
int i = 0; i < (int) nets.size(); ++i )
910 NET_RECORD* net_record = nets[i];
915 std::sort( net_record->m_Nodes.begin(), net_record->m_Nodes.end(),
916 [](
const NET_NODE& a,
const NET_NODE& b )
918 wxString refA = a.m_Pin->GetParentSymbol()->GetRef( &a.m_Sheet );
919 wxString refB = b.m_Pin->GetParentSymbol()->GetRef( &b.m_Sheet );
922 return a.m_Pin->GetShownNumber() < b.m_Pin->GetShownNumber();
931 [](
const NET_NODE& a,
const NET_NODE& b )
933 wxString refA = a.m_Pin->GetParentSymbol()->GetRef( &a.m_Sheet );
934 wxString refB = b.m_Pin->GetParentSymbol()->GetRef( &b.m_Sheet );
936 return refA == refB && a.m_Pin->GetShownNumber() == b.m_Pin->GetShownNumber();
941 bool allNetPinsStacked =
true;
943 if( net_record->m_Nodes.size() > 1 )
945 SCH_PIN* firstPin = net_record->m_Nodes.begin()->m_Pin;
947 std::all_of( net_record->m_Nodes.begin() + 1, net_record->m_Nodes.end(),
950 return firstPin->GetParent() == node.m_Pin->GetParent()
951 && firstPin->GetPosition() == node.m_Pin->GetPosition()
952 && firstPin->GetName() == node.m_Pin->GetName();
956 for(
const NET_NODE& netNode : net_record->m_Nodes )
958 wxString refText = netNode.m_Pin->GetParentSymbol()->GetRef( &netNode.m_Sheet );
959 wxString pinText = netNode.m_Pin->GetShownNumber();
962 if( refText[0] == wxChar(
'#' ) )
967 netCodeTxt.Printf( wxT(
"%d" ), i + 1 );
969 xnets->AddChild( xnet =
node( wxT(
"net" ) ) );
970 xnet->AddAttribute( wxT(
"code" ), netCodeTxt );
971 xnet->AddAttribute( wxT(
"name" ), net_record->m_Name );
972 xnet->AddAttribute( wxT(
"class" ), net_record->m_Class );
977 xnet->AddChild( xnode =
node( wxT(
"node" ) ) );
978 xnode->AddAttribute( wxT(
"ref" ), refText );
979 xnode->AddAttribute( wxT(
"pin" ), pinText );
981 wxString pinName = netNode.m_Pin->GetShownName();
982 wxString pinType = netNode.m_Pin->GetCanonicalElectricalTypeName();
984 if( !pinName.IsEmpty() )
985 xnode->AddAttribute( wxT(
"pinfunction" ), pinName );
987 if( net_record->m_HasNoConnect
988 && ( net_record->m_Nodes.size() == 1 || allNetPinsStacked ) )
989 pinType += wxT(
"+no_connect" );
991 xnode->AddAttribute( wxT(
"pintype" ), pinType );
995 for( NET_RECORD* record : nets )
1003 const wxString& aTextualContent )
1005 XNODE* n =
new XNODE( wxXML_ELEMENT_NODE, aName );
1007 if( aTextualContent.Len() > 0 )
1008 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.
wxString AsString() const
const wxString GetUniStringLibItemName() const
Get strings for display messages in dialogs.
const wxString GetUniStringLibNickname() 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.
SCHEMATIC * m_schematic
The schematic we're generating a netlist for.
SCH_SYMBOL * findNextSymbol(EDA_ITEM *aItem, const SCH_SHEET_PATH &aSheetPath)
Check if the given symbol should be processed for netlisting.
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.
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.
void addSymbolFields(XNODE *aNode, SCH_SYMBOL *aSymbol, const SCH_SHEET_PATH &aSheet, const SCH_SHEET_LIST &aSheetList)
Holder for multi-unit symbol fields.
std::vector< wxString > getComponentClassNamesForAllSymbolUnits(SCH_SYMBOL *aSymbol, const SCH_SHEET_PATH &aSymbolSheet, const SCH_SHEET_LIST &aSheetList)
Finds all component class names attached to any sub-unit of a given symbol.
XNODE * makeSymbols(unsigned aCtl)
XNODE * makeRoot(unsigned aCtl=GNL_ALL)
Build the entire document tree for the generic export.
std::set< wxString > m_libraries
XNODE * makeLibParts()
Fill out an XML node with the unique library parts and returns it.
static SYMBOL_LIB_TABLE * SchSymbolLibTable(PROJECT *aProject)
Accessor for project symbol library table.
Container for project specific data.
virtual std::map< wxString, wxString > & GetTextVars() const
A pure virtual class used to derive REPORTER objects from.
PROJECT & Prj() const
Return a reference to the project this schematic is part of.
void SetCurrentSheet(const SCH_SHEET_PATH &aPath)
wxString GetFileName() const
Helper to retrieve the filename from the root sheet screen.
SCH_SHEET_LIST Hierarchy() const
Return the full schematic flattened hierarchical sheet list.
CONNECTION_GRAPH * ConnectionGraph() const
SCH_SHEET_PATH & CurrentSheet() const
wxString GetShownText(const SCH_SHEET_PATH *aPath, bool aAllowExtraText, int aDepth=0) const
A set of SCH_ITEMs (i.e., without duplicates).
Base class for any item which can be embedded within the SCHEMATIC container class,...
bool ResolveExcludedFromBOM() const
bool ResolveExcludedFromBoard() const
wxString GetShownNumber() const
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...
bool GetExcludedFromBOM() const
const SCH_SHEET * GetSheet(unsigned aIndex) const
bool GetExcludedFromBoard() const
wxString GetDescription() const override
bool UseLibIdLookup() const
wxString GetSchSymbolLibraryName() const
const wxString GetValue(bool aResolve, const SCH_SHEET_PATH *aPath, bool aAllowExtraText) const override
void GetFields(std::vector< SCH_FIELD * > &aVector, bool aVisibleOnly) const override
Populate a std::vector with SCH_FIELDs, sorted in ordinal order.
const wxString GetFootprintFieldText(bool aResolve, const SCH_SHEET_PATH *aPath, bool aAllowExtraText) const
const LIB_ID & GetLibId() const override
int GetUnitSelection(const SCH_SHEET_PATH *aSheet) const
Return the instance-specific unit selection for the given sheet path.
int GetUnitCount() const override
Return the number of units per package of the symbol.
std::unique_ptr< LIB_SYMBOL > & GetLibSymbolRef()
std::unordered_set< wxString > GetComponentClassNames(const SCH_SHEET_PATH *aPath) const
Return the component classes this symbol belongs in.
const wxString GetRef(const SCH_SHEET_PATH *aSheet, bool aIncludeUnit=false) const override
SCH_FIELD * GetField(FIELD_T aFieldType)
Return a mandatory field in this symbol.
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, int aFlags)
void remove_duplicates(_Container &__c)
Deletes all duplicate values from __c.
static bool sortPinsByNumber(SCH_PIN *aPin1, SCH_PIN *aPin2)
Class to handle a set of SCH_ITEMs.
int StrNumCmp(const wxString &aString1, const wxString &aString2, bool aIgnoreCase)
Compare two strings with alphanumerical content.
wxString UnescapeString(const wxString &aSource)
wxString GetISO8601CurrentDateTime()
Definition for symbol library class.
wxString GetCanonicalFieldName(FIELD_T aFieldType)