KiCad PCB EDA Suite
Loading...
Searching...
No Matches
netlist_exporter_xml.cpp
Go to the documentation of this file.
1/*
2 * This program source code file is part of KiCad, a free EDA CAD application.
3 *
4 * Copyright (C) 1992-2013 jp.charras at wanadoo.fr
5 * Copyright (C) 2013-2017 SoftPLC Corporation, Dick Hollenbeck <[email protected]>
6 * Copyright The KiCad Developers, see AUTHORS.txt for contributors.
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version 2
11 * of the License, or (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, you may find one here:
20 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
21 * or you may search the http://www.gnu.org website for the version 2 license,
22 * or you may write to the Free Software Foundation, Inc.,
23 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
24 */
25
27
28#include <build_version.h>
29#include <common.h> // for ExpandTextVars
30#include <sch_base_frame.h>
31#include <sch_group.h>
32#include <string_utils.h>
33#include <connection_graph.h>
34#include <pgm_base.h>
35#include <core/kicad_algo.h>
36#include <wx/wfstream.h>
37#include <xnode.h> // also nests: <wx/xml/xml.h>
38#include <json_common.h>
39#include <project_sch.h>
40#include <trace_helpers.h>
41
42#include <set>
44
45static bool sortPinsByNumber( SCH_PIN* aPin1, SCH_PIN* aPin2 );
46
47bool NETLIST_EXPORTER_XML::WriteNetlist( const wxString& aOutFileName, unsigned aNetlistOptions,
48 REPORTER& aReporter )
49{
50 // output the XML format netlist.
51
52 // declare the stream ourselves to use the buffered FILE api
53 // instead of letting wx use the syscall variant
54 wxFFileOutputStream stream( aOutFileName );
55
56 if( !stream.IsOk() )
57 return false;
58
59 wxXmlDocument xdoc;
60 xdoc.SetRoot( makeRoot( GNL_ALL | aNetlistOptions ) );
61
62 return xdoc.Save( stream, 2 /* indent bug, today was ignored by wxXml lib */ );
63}
64
65
67{
68 XNODE* xroot = node( wxT( "export" ) );
69
70 xroot->AddAttribute( wxT( "version" ), wxT( "E" ) );
71
72 if( aCtl & GNL_HEADER )
73 // add the "design" header
74 xroot->AddChild( makeDesignHeader() );
75
76 if( aCtl & GNL_SYMBOLS )
77 {
78 xroot->AddChild( makeSymbols( aCtl ) );
79
80 if( aCtl & GNL_OPT_KICAD )
81 xroot->AddChild( makeGroups() );
82 }
83
84 if( aCtl & GNL_PARTS )
85 xroot->AddChild( makeLibParts() );
86
87 if( aCtl & GNL_LIBRARIES )
88 // must follow makeGenericLibParts()
89 xroot->AddChild( makeLibraries() );
90
91 if( aCtl & GNL_NETS )
92 xroot->AddChild( makeListOfNets( aCtl ) );
93
94 return xroot;
95}
96
97
99
100
102 const SCH_SHEET_PATH& aSheet,
103 const SCH_SHEET_LIST& aSheetList )
104{
105 wxString value;
106 wxString footprint;
107 wxString datasheet;
108 wxString description;
109 wxString candidate;
110 nlohmann::ordered_map<wxString, wxString> fields;
111
112 if( aSymbol->GetUnitCount() > 1 )
113 {
114 // Sadly, each unit of a symbol can have its own unique fields. This
115 // block finds the unit with the lowest number having a non blank field
116 // value and records it. Therefore user is best off setting fields
117 // into only the first unit. But this scavenger algorithm will find
118 // any non blank fields in all units and use the first non-blank field
119 // for each unique field name.
120
121 wxString ref = aSymbol->GetRef( &aSheet );
122
123 int minUnit = aSymbol->GetUnitSelection( &aSheet );
124
125 for( const SCH_SHEET_PATH& sheet : aSheetList )
126 {
127 for( SCH_ITEM* item : sheet.LastScreen()->Items().OfType( SCH_SYMBOL_T ) )
128 {
129 SCH_SYMBOL* symbol2 = static_cast<SCH_SYMBOL*>( item );
130
131 wxString ref2 = symbol2->GetRef( &sheet );
132
133 if( ref2.CmpNoCase( ref ) != 0 )
134 continue;
135
136 int unit = symbol2->GetUnitSelection( &aSheet );
137
138 // The lowest unit number wins. User should only set fields in any one unit.
139
140 // Value
141 candidate = symbol2->GetValue( m_resolveTextVars, &sheet, false );
142
143 if( !candidate.IsEmpty() && ( unit < minUnit || value.IsEmpty() ) )
144 value = candidate;
145
146 // Footprint
147 candidate = symbol2->GetFootprintFieldText( m_resolveTextVars, &sheet, false );
148
149 if( !candidate.IsEmpty() && ( unit < minUnit || footprint.IsEmpty() ) )
150 footprint = candidate;
151
152 // Datasheet
153 candidate = m_resolveTextVars
154 ? symbol2->GetField( FIELD_T::DATASHEET )->GetShownText( &sheet, false )
155 : symbol2->GetField( FIELD_T::DATASHEET )->GetText();
156
157 if( !candidate.IsEmpty() && ( unit < minUnit || datasheet.IsEmpty() ) )
158 datasheet = candidate;
159
160 // Description
161 candidate = m_resolveTextVars
162 ? symbol2->GetField( FIELD_T::DESCRIPTION )->GetShownText( &sheet, false )
163 : symbol2->GetField( FIELD_T::DESCRIPTION )->GetText();
164
165 if( !candidate.IsEmpty() && ( unit < minUnit || description.IsEmpty() ) )
166 description = candidate;
167
168 // All non-mandatory fields
169 for( SCH_FIELD& field : symbol2->GetFields() )
170 {
171 if( field.IsMandatory() || field.IsPrivate() )
172 continue;
173
174 if( unit < minUnit || fields.count( field.GetName() ) == 0 )
175 {
177 fields[field.GetName()] = field.GetShownText( &aSheet, false );
178 else
179 fields[field.GetName()] = field.GetText();
180 }
181 }
182
183 minUnit = std::min( unit, minUnit );
184 }
185 }
186 }
187 else
188 {
189 value = aSymbol->GetValue( m_resolveTextVars, &aSheet, false );
190 footprint = aSymbol->GetFootprintFieldText( m_resolveTextVars, &aSheet, false );
191
192 SCH_FIELD* datasheetField = aSymbol->GetField( FIELD_T::DATASHEET );
193 SCH_FIELD* descriptionField = aSymbol->GetField( FIELD_T::DESCRIPTION );
194
195 // Datasheet
197 datasheet = datasheetField->GetShownText( &aSheet, false );
198 else
199 datasheet = datasheetField->GetText();
200
201 // Description
203 description = descriptionField->GetShownText( &aSheet, false );
204 else
205 description = descriptionField->GetText();
206
207 for( SCH_FIELD& field : aSymbol->GetFields() )
208 {
209 if( field.IsMandatory() || field.IsPrivate() )
210 continue;
211
213 fields[field.GetName()] = field.GetShownText( &aSheet, false );
214 else
215 fields[field.GetName()] = field.GetText();
216 }
217 }
218
219 fields[GetCanonicalFieldName( FIELD_T::FOOTPRINT )] = footprint;
221 fields[GetCanonicalFieldName( FIELD_T::DESCRIPTION )] = description;
222
223 // Do not output field values blank in netlist:
224 if( value.size() )
225 aNode->AddChild( node( wxT( "value" ), UnescapeString( value ) ) );
226 else // value field always written in netlist
227 aNode->AddChild( node( wxT( "value" ), wxT( "~" ) ) );
228
229 if( footprint.size() )
230 aNode->AddChild( node( wxT( "footprint" ), UnescapeString( footprint ) ) );
231
232 if( datasheet.size() )
233 aNode->AddChild( node( wxT( "datasheet" ), UnescapeString( datasheet ) ) );
234
235 if( description.size() )
236 aNode->AddChild( node( wxT( "description" ), UnescapeString( description ) ) );
237
238 XNODE* xfields;
239 aNode->AddChild( xfields = node( wxT( "fields" ) ) );
240
241 for( const auto& [ fieldName, fieldValue ] : fields )
242 {
243 XNODE* xfield = node( wxT( "field" ), UnescapeString( fieldValue ) );
244 xfield->AddAttribute( wxT( "name" ), UnescapeString( fieldName ) );
245 xfields->AddChild( xfield );
246 }
247}
248
249
251{
252 XNODE* xcomps = node( wxT( "components" ) );
253
255 m_libParts.clear();
256
257 SCH_SHEET_PATH currentSheet = m_schematic->CurrentSheet();
258 SCH_SHEET_LIST sheetList = m_schematic->Hierarchy();
259
260 // Output is xml, so there is no reason to remove spaces from the field values.
261 // And XML element names need not be translated to various languages.
262
263 for( const SCH_SHEET_PATH& sheet : sheetList )
264 {
265 // Change schematic CurrentSheet in each iteration to allow hierarchical
266 // resolution of text variables in sheet fields.
267 m_schematic->SetCurrentSheet( sheet );
268
269 auto cmp =
270 [&sheet]( SCH_SYMBOL* a, SCH_SYMBOL* b )
271 {
272 return ( StrNumCmp( a->GetRef( &sheet, false ),
273 b->GetRef( &sheet, false ), true ) < 0 );
274 };
275
276 std::set<SCH_SYMBOL*, decltype( cmp )> ordered_symbols( cmp );
277 std::multiset<SCH_SYMBOL*, decltype( cmp )> extra_units( cmp );
278
279 for( SCH_ITEM* item : sheet.LastScreen()->Items().OfType( SCH_SYMBOL_T ) )
280 {
281 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
282 auto test = ordered_symbols.insert( symbol );
283
284 if( !test.second )
285 {
286 if( ( *( test.first ) )->m_Uuid > symbol->m_Uuid )
287 {
288 extra_units.insert( *( test.first ) );
289 ordered_symbols.erase( test.first );
290 ordered_symbols.insert( symbol );
291 }
292 else
293 {
294 extra_units.insert( symbol );
295 }
296 }
297 }
298
299 for( EDA_ITEM* item : ordered_symbols )
300 {
301 SCH_SYMBOL* symbol = findNextSymbol( item, sheet );
302 bool forBOM = aCtl & GNL_OPT_BOM;
303 bool forBoard = aCtl & GNL_OPT_KICAD;
304
305 if( !symbol )
306 continue;
307
308 if( forBOM && ( sheet.GetExcludedFromBOM() || symbol->ResolveExcludedFromBOM() ) )
309 continue;
310
311 if( forBoard && ( sheet.GetExcludedFromBoard() || symbol->ResolveExcludedFromBoard() ) )
312 continue;
313
314 // Output the symbol's elements in order of expected access frequency. This may
315 // not always look best, but it will allow faster execution under XSL processing
316 // systems which do sequential searching within an element.
317
318 XNODE* xcomp; // current symbol being constructed
319 xcomps->AddChild( xcomp = node( wxT( "comp" ) ) );
320
321 xcomp->AddAttribute( wxT( "ref" ), symbol->GetRef( &sheet ) );
322 addSymbolFields( xcomp, symbol, sheet, sheetList );
323
324 XNODE* xlibsource;
325 xcomp->AddChild( xlibsource = node( wxT( "libsource" ) ) );
326
327 // "logical" library name, which is in anticipation of a better search algorithm
328 // for parts based on "logical_lib.part" and where logical_lib is merely the library
329 // name minus path and extension.
330 wxString libName;
331 wxString partName;
332
333 if( symbol->UseLibIdLookup() )
334 {
335 libName = symbol->GetLibId().GetUniStringLibNickname();
336 partName = symbol->GetLibId().GetUniStringLibItemName();
337 }
338 else
339 {
340 partName = symbol->GetSchSymbolLibraryName();
341 }
342
343 xlibsource->AddAttribute( wxT( "lib" ), libName );
344
345 // We only want the symbol name, not the full LIB_ID.
346 xlibsource->AddAttribute( wxT( "part" ), partName );
347
349 xlibsource->AddAttribute( wxT( "description" ), symbol->GetShownDescription() );
350 else
351 xlibsource->AddAttribute( wxT( "description" ), symbol->GetDescription() );
352
353 /* Add the symbol properties. */
354 XNODE* xproperty;
355
356 std::vector<SCH_FIELD>& fields = symbol->GetFields();
357
358 for( SCH_FIELD& field : fields )
359 {
360 if( field.IsMandatory() || field.IsPrivate() )
361 continue;
362
363 xcomp->AddChild( xproperty = node( wxT( "property" ) ) );
364 xproperty->AddAttribute( wxT( "name" ), field.GetCanonicalName() );
365
367 xproperty->AddAttribute( wxT( "value" ), field.GetShownText( &sheet, false ) );
368 else
369 xproperty->AddAttribute( wxT( "value" ), field.GetText() );
370 }
371
372 for( const SCH_FIELD& sheetField : sheet.Last()->GetFields() )
373 {
374 xcomp->AddChild( xproperty = node( wxT( "property" ) ) );
375 xproperty->AddAttribute( wxT( "name" ), sheetField.GetCanonicalName() );
376
378 // do not allow GetShownText() to add any prefix useful only when displaying
379 // the field on screen
380 xproperty->AddAttribute( wxT( "value" ), sheetField.GetShownText( &sheet, false ) );
381 else
382 xproperty->AddAttribute( wxT( "value" ), sheetField.GetText() );
383 }
384
385 if( symbol->ResolveExcludedFromBOM() || sheet.GetExcludedFromBOM() )
386 {
387 xcomp->AddChild( xproperty = node( wxT( "property" ) ) );
388 xproperty->AddAttribute( wxT( "name" ), wxT( "exclude_from_bom" ) );
389 }
390
391 if( symbol->ResolveExcludedFromBoard() || sheet.GetExcludedFromBoard() )
392 {
393 xcomp->AddChild( xproperty = node( wxT( "property" ) ) );
394 xproperty->AddAttribute( wxT( "name" ), wxT( "exclude_from_board" ) );
395 }
396
397 if( symbol->ResolveDNP() || sheet.GetDNP() )
398 {
399 xcomp->AddChild( xproperty = node( wxT( "property" ) ) );
400 xproperty->AddAttribute( wxT( "name" ), wxT( "dnp" ) );
401 }
402
403 if( const std::unique_ptr<LIB_SYMBOL>& part = symbol->GetLibSymbolRef() )
404 {
405 if( part->GetKeyWords().size() )
406 {
407 xcomp->AddChild( xproperty = node( wxT( "property" ) ) );
408 xproperty->AddAttribute( wxT( "name" ), wxT( "ki_keywords" ) );
409 xproperty->AddAttribute( wxT( "value" ), part->GetKeyWords() );
410 }
411
412 if( !part->GetFPFilters().IsEmpty() )
413 {
414 wxString filters;
415
416 for( const wxString& filter : part->GetFPFilters() )
417 filters += ' ' + filter;
418
419 xcomp->AddChild( xproperty = node( wxT( "property" ) ) );
420 xproperty->AddAttribute( wxT( "name" ), wxT( "ki_fp_filters" ) );
421 xproperty->AddAttribute( wxT( "value" ), filters.Trim( false ) );
422 }
423
424 if( part->GetDuplicatePinNumbersAreJumpers() )
425 xcomp->AddChild( node( wxT( "duplicate_pin_numbers_are_jumpers" ), wxT( "1" ) ) );
426
427 const std::vector<std::set<wxString>>& jumperGroups = part->JumperPinGroups();
428
429 if( !jumperGroups.empty() )
430 {
431 XNODE* groupNode;
432 xcomp->AddChild( xproperty = node( wxT( "jumper_pin_groups" ) ) );
433
434 for( const std::set<wxString>& group : jumperGroups )
435 {
436 xproperty->AddChild( groupNode = node( wxT( "group" ) ) );
437
438 for( const wxString& pinName : group )
439 groupNode->AddChild( node( wxT( "pin" ), pinName ) );
440 }
441 }
442 }
443
444 XNODE* xsheetpath;
445 xcomp->AddChild( xsheetpath = node( wxT( "sheetpath" ) ) );
446
447 xsheetpath->AddAttribute( wxT( "names" ), sheet.PathHumanReadable() );
448 xsheetpath->AddAttribute( wxT( "tstamps" ), sheet.PathAsString() );
449
450 // Node for component class
451 std::vector<wxString> compClassNames =
452 getComponentClassNamesForAllSymbolUnits( symbol, sheet, sheetList );
453
454 if( compClassNames.size() > 0 )
455 {
456 XNODE* xcompclasslist;
457 xcomp->AddChild( xcompclasslist = node( wxT( "component_classes" ) ) );
458
459 for( const wxString& compClass : compClassNames )
460 {
461 xcompclasslist->AddChild( node( wxT( "class" ), UnescapeString( compClass ) ) );
462 }
463 }
464
465 XNODE* xunits; // Node for extra units
466 xcomp->AddChild( xunits = node( wxT( "tstamps" ) ) );
467
468 auto range = extra_units.equal_range( symbol );
469 wxString uuid;
470
471 // Output a series of children with all UUIDs associated with the REFDES
472 for( auto it = range.first; it != range.second; ++it )
473 {
474 uuid = ( *it )->m_Uuid.AsString();
475
476 // Add a space between UUIDs, if not in KICAD mode (i.e.
477 // using wxXmlDocument::Save()). KICAD MODE has its own XNODE::Format function.
478 if( !( aCtl & GNL_OPT_KICAD ) ) // i.e. for .xml format
479 uuid += ' ';
480
481 xunits->AddChild( new XNODE( wxXML_TEXT_NODE, wxEmptyString, uuid ) );
482 }
483
484 // Output the primary UUID
485 uuid = symbol->m_Uuid.AsString();
486 xunits->AddChild( new XNODE( wxXML_TEXT_NODE, wxEmptyString, uuid ) );
487
488 // Emit unit information (per-unit name and pins) after tstamps
489 XNODE* xunitInfo;
490 xcomp->AddChild( xunitInfo = node( wxT( "units" ) ) );
491
492 // Emit all units defined by the library symbol, independent of placement
493 const std::unique_ptr<LIB_SYMBOL>& libSym = symbol->GetLibSymbolRef();
494
495 if( libSym )
496 {
497 for( const LIB_SYMBOL::UNIT_PIN_INFO& unitInfo : libSym->GetUnitPinInfo() )
498 {
499 XNODE* xunit;
500 xunitInfo->AddChild( xunit = node( wxT( "unit" ) ) );
501 xunit->AddAttribute( wxT( "name" ), unitInfo.m_unitName );
502
503 XNODE* xpins;
504 xunit->AddChild( xpins = node( wxT( "pins" ) ) );
505
506 for( const wxString& number : unitInfo.m_pinNumbers )
507 {
508 XNODE* xpin;
509 xpins->AddChild( xpin = node( wxT( "pin" ) ) );
510 xpin->AddAttribute( wxT( "num" ), number );
511 }
512 }
513 }
514 }
515 }
516
517 m_schematic->SetCurrentSheet( currentSheet );
518
519 return xcomps;
520}
521
522
524{
525 XNODE* xcomps = node( wxT( "groups" ) );
526
528 // Do not clear m_libParts here: it is populated in makeSymbols() and used later by
529 // makeLibParts() to emit the libparts section for CvPcb and other consumers.
530
531 SCH_SHEET_PATH currentSheet = m_schematic->CurrentSheet();
532 SCH_SHEET_LIST sheetList = m_schematic->Hierarchy();
533
534 for( const SCH_SHEET_PATH& sheet : sheetList )
535 {
536 // Change schematic CurrentSheet in each iteration to allow hierarchical
537 // resolution of text variables in sheet fields.
538 m_schematic->SetCurrentSheet( sheet );
539
540 for( SCH_ITEM* item : sheet.LastScreen()->Items().OfType( SCH_GROUP_T ) )
541 {
542 SCH_GROUP* group = static_cast<SCH_GROUP*>( item );
543
544 XNODE* xgroup; // current symbol being constructed
545 xcomps->AddChild( xgroup = node( wxT( "group" ) ) );
546
547 xgroup->AddAttribute( wxT( "name" ), group->GetName() );
548 xgroup->AddAttribute( wxT( "uuid" ), group->m_Uuid.AsString() );
549 xgroup->AddAttribute( wxT( "lib_id" ), group->GetDesignBlockLibId().Format() );
550
551 XNODE* xmembers;
552 xgroup->AddChild( xmembers = node( wxT( "members" ) ) );
553
554 for( EDA_ITEM* member : group->GetItems() )
555 {
556 if( member->Type() == SCH_SYMBOL_T )
557 {
558 XNODE* xmember;
559 xmembers->AddChild( xmember = node( wxT( "member" ) ) );
560 xmember->AddAttribute( wxT( "uuid" ), member->m_Uuid.AsString() );
561 }
562 }
563 }
564 }
565
566 m_schematic->SetCurrentSheet( currentSheet );
567
568 return xcomps;
569}
570
571
573 SCH_SYMBOL* aSymbol, const SCH_SHEET_PATH& aSymbolSheet, const SCH_SHEET_LIST& aSheetList )
574{
575 std::unordered_set<wxString> compClassNames = aSymbol->GetComponentClassNames( &aSymbolSheet );
576 int primaryUnit = aSymbol->GetUnitSelection( &aSymbolSheet );
577
578 if( aSymbol->GetUnitCount() > 1 )
579 {
580 wxString ref = aSymbol->GetRef( &aSymbolSheet );
581
582 for( const SCH_SHEET_PATH& sheet : aSheetList )
583 {
584 for( SCH_ITEM* item : sheet.LastScreen()->Items().OfType( SCH_SYMBOL_T ) )
585 {
586 SCH_SYMBOL* symbol2 = static_cast<SCH_SYMBOL*>( item );
587
588 wxString ref2 = symbol2->GetRef( &sheet );
589 int otherUnit = symbol2->GetUnitSelection( &sheet );
590
591 if( ref2.CmpNoCase( ref ) != 0 )
592 continue;
593
594 if( otherUnit == primaryUnit )
595 continue;
596
597 std::unordered_set<wxString> otherClassNames =
598 symbol2->GetComponentClassNames( &sheet );
599 compClassNames.insert( otherClassNames.begin(), otherClassNames.end() );
600 }
601 }
602 }
603
604 std::vector<wxString> sortedCompClassNames( compClassNames.begin(), compClassNames.end() );
605 std::sort( sortedCompClassNames.begin(), sortedCompClassNames.end(),
606 []( const wxString& str1, const wxString& str2 )
607 {
608 return str1.Cmp( str2 ) < 0;
609 } );
610
611 return sortedCompClassNames;
612}
613
614
616{
617 SCH_SCREEN* screen;
618 XNODE* xdesign = node( wxT( "design" ) );
619 XNODE* xtitleBlock;
620 XNODE* xsheet;
621 XNODE* xcomment;
622 XNODE* xtextvar;
623 wxString sheetTxt;
624 wxFileName sourceFileName;
625
626 // the root sheet is a special sheet, call it source
627 xdesign->AddChild( node( wxT( "source" ), m_schematic->GetFileName() ) );
628
629 xdesign->AddChild( node( wxT( "date" ), GetISO8601CurrentDateTime() ) );
630
631 // which Eeschema tool
632 xdesign->AddChild( node( wxT( "tool" ), wxT( "Eeschema " ) + GetBuildVersion() ) );
633
634 const std::map<wxString, wxString>& properties = m_schematic->Project().GetTextVars();
635
636 for( const std::pair<const wxString, wxString>& prop : properties )
637 {
638 xdesign->AddChild( xtextvar = node( wxT( "textvar" ), prop.second ) );
639 xtextvar->AddAttribute( wxT( "name" ), prop.first );
640 }
641
642 /*
643 * Export the sheets information
644 */
645 unsigned sheetIndex = 1; // Human readable index
646
647 for( const SCH_SHEET_PATH& sheet : m_schematic->Hierarchy() )
648 {
649 screen = sheet.LastScreen();
650
651 xdesign->AddChild( xsheet = node( wxT( "sheet" ) ) );
652
653 // get the string representation of the sheet index number.
654 sheetTxt.Printf( wxT( "%u" ), sheetIndex++ );
655 xsheet->AddAttribute( wxT( "number" ), sheetTxt );
656 xsheet->AddAttribute( wxT( "name" ), sheet.PathHumanReadable() );
657 xsheet->AddAttribute( wxT( "tstamps" ), sheet.PathAsString() );
658
659 TITLE_BLOCK tb = screen->GetTitleBlock();
660 PROJECT* prj = &m_schematic->Project();
661
662 xsheet->AddChild( xtitleBlock = node( wxT( "title_block" ) ) );
663
664 xtitleBlock->AddChild( node( wxT( "title" ), ExpandTextVars( tb.GetTitle(), prj ) ) );
665 xtitleBlock->AddChild( node( wxT( "company" ), ExpandTextVars( tb.GetCompany(), prj ) ) );
666 xtitleBlock->AddChild( node( wxT( "rev" ), ExpandTextVars( tb.GetRevision(), prj ) ) );
667 xtitleBlock->AddChild( node( wxT( "date" ), ExpandTextVars( tb.GetDate(), prj ) ) );
668
669 // We are going to remove the fileName directories.
670 sourceFileName = wxFileName( screen->GetFileName() );
671 xtitleBlock->AddChild( node( wxT( "source" ), sourceFileName.GetFullName() ) );
672
673 xtitleBlock->AddChild( xcomment = node( wxT( "comment" ) ) );
674 xcomment->AddAttribute( wxT( "number" ), wxT( "1" ) );
675 xcomment->AddAttribute( wxT( "value" ), ExpandTextVars( tb.GetComment( 0 ), prj ) );
676
677 xtitleBlock->AddChild( xcomment = node( wxT( "comment" ) ) );
678 xcomment->AddAttribute( wxT( "number" ), wxT( "2" ) );
679 xcomment->AddAttribute( wxT( "value" ), ExpandTextVars( tb.GetComment( 1 ), prj ) );
680
681 xtitleBlock->AddChild( xcomment = node( wxT( "comment" ) ) );
682 xcomment->AddAttribute( wxT( "number" ), wxT( "3" ) );
683 xcomment->AddAttribute( wxT( "value" ), ExpandTextVars( tb.GetComment( 2 ), prj ) );
684
685 xtitleBlock->AddChild( xcomment = node( wxT( "comment" ) ) );
686 xcomment->AddAttribute( wxT( "number" ), wxT( "4" ) );
687 xcomment->AddAttribute( wxT( "value" ), ExpandTextVars( tb.GetComment( 3 ), prj ) );
688
689 xtitleBlock->AddChild( xcomment = node( wxT( "comment" ) ) );
690 xcomment->AddAttribute( wxT( "number" ), wxT( "5" ) );
691 xcomment->AddAttribute( wxT( "value" ), ExpandTextVars( tb.GetComment( 4 ), prj ) );
692
693 xtitleBlock->AddChild( xcomment = node( wxT( "comment" ) ) );
694 xcomment->AddAttribute( wxT( "number" ), wxT( "6" ) );
695 xcomment->AddAttribute( wxT( "value" ), ExpandTextVars( tb.GetComment( 5 ), prj ) );
696
697 xtitleBlock->AddChild( xcomment = node( wxT( "comment" ) ) );
698 xcomment->AddAttribute( wxT( "number" ), wxT( "7" ) );
699 xcomment->AddAttribute( wxT( "value" ), ExpandTextVars( tb.GetComment( 6 ), prj ) );
700
701 xtitleBlock->AddChild( xcomment = node( wxT( "comment" ) ) );
702 xcomment->AddAttribute( wxT( "number" ), wxT( "8" ) );
703 xcomment->AddAttribute( wxT( "value" ), ExpandTextVars( tb.GetComment( 7 ), prj ) );
704
705 xtitleBlock->AddChild( xcomment = node( wxT( "comment" ) ) );
706 xcomment->AddAttribute( wxT( "number" ), wxT( "9" ) );
707 xcomment->AddAttribute( wxT( "value" ), ExpandTextVars( tb.GetComment( 8 ), prj ) );
708 }
709
710 return xdesign;
711}
712
713
715{
716 XNODE* xlibs = node( wxT( "libraries" ) ); // auto_ptr
718
719 for( std::set<wxString>::iterator it = m_libraries.begin(); it!=m_libraries.end(); ++it )
720 {
721 wxString libNickname = *it;
722 XNODE* xlibrary;
723
724 std::optional<wxString> uri = manager.GetFullURI( LIBRARY_TABLE_TYPE::SYMBOL, libNickname );
725
726 if( uri )
727 {
728 xlibs->AddChild( xlibrary = node( wxT( "library" ) ) );
729 xlibrary->AddAttribute( wxT( "logical" ), libNickname );
730 xlibrary->AddChild( node( wxT( "uri" ), *uri ) );
731 }
732
733 // @todo: add more fun stuff here
734 }
735
736 return xlibs;
737}
738
739
741{
742 XNODE* xlibparts = node( wxT( "libparts" ) ); // auto_ptr
743 std::vector<SCH_FIELD*> fieldList;
744
745 m_libraries.clear();
746
747 for( LIB_SYMBOL* lcomp : m_libParts )
748 {
749 wxString libNickname = lcomp->GetLibId().GetLibNickname();;
750
751 // The library nickname will be empty if the cache library is used.
752 if( !libNickname.IsEmpty() )
753 m_libraries.insert( libNickname ); // inserts symbol's library if unique
754
755 XNODE* xlibpart;
756 xlibparts->AddChild( xlibpart = node( wxT( "libpart" ) ) );
757 xlibpart->AddAttribute( wxT( "lib" ), libNickname );
758 xlibpart->AddAttribute( wxT( "part" ), lcomp->GetName() );
759
760 //----- show the important properties -------------------------
761 if( !lcomp->GetDescription().IsEmpty() )
762 xlibpart->AddChild( node( wxT( "description" ), lcomp->GetDescription() ) );
763
764 if( !lcomp->GetDatasheetField().GetText().IsEmpty() )
765 xlibpart->AddChild( node( wxT( "docs" ), lcomp->GetDatasheetField().GetText() ) );
766
767 // Write the footprint list
768 if( lcomp->GetFPFilters().GetCount() )
769 {
770 XNODE* xfootprints;
771 xlibpart->AddChild( xfootprints = node( wxT( "footprints" ) ) );
772
773 for( unsigned i = 0; i < lcomp->GetFPFilters().GetCount(); ++i )
774 {
775 if( !lcomp->GetFPFilters()[i].IsEmpty() )
776 xfootprints->AddChild( node( wxT( "fp" ), lcomp->GetFPFilters()[i] ) );
777 }
778 }
779
780 //----- show the fields here ----------------------------------
781 fieldList.clear();
782 lcomp->GetFields( fieldList );
783
784 XNODE* xfields;
785 xlibpart->AddChild( xfields = node( "fields" ) );
786
787 for( const SCH_FIELD* field : fieldList )
788 {
789 XNODE* xfield;
790 xfields->AddChild( xfield = node( wxT( "field" ), field->GetText() ) );
791 xfield->AddAttribute( wxT( "name" ), field->GetCanonicalName() );
792 }
793
794 //----- show the pins here ------------------------------------
795 // NOTE: Expand stacked-pin notation into individual pins so downstream
796 // tools (e.g. CvPcb) see the actual number of footprint pins.
797 std::vector<SCH_PIN*> pinList = lcomp->GetGraphicalPins( 0, 0 );
798
799 /*
800 * We must erase redundant Pins references in pinList
801 * These redundant pins exist because some pins are found more than one time when a
802 * symbol has multiple parts per package or has 2 representations (DeMorgan conversion).
803 * For instance, a 74ls00 has DeMorgan conversion, with different pin shapes, and
804 * therefore each pin appears 2 times in the list. Common pins (VCC, GND) can also be
805 * found more than once.
806 */
807 sort( pinList.begin(), pinList.end(), sortPinsByNumber );
808
809 for( int ii = 0; ii < (int)pinList.size()-1; ii++ )
810 {
811 if( pinList[ii]->GetNumber() == pinList[ii+1]->GetNumber() )
812 { // 2 pins have the same number, remove the redundant pin at index i+1
813 pinList.erase(pinList.begin() + ii + 1);
814 ii--;
815 }
816 }
817
818 wxLogTrace( "CVPCB_PINCOUNT",
819 wxString::Format( "makeLibParts: lib='%s' part='%s' pinList(size)=%zu",
820 libNickname, lcomp->GetName(), pinList.size() ) );
821
822 if( pinList.size() )
823 {
824 XNODE* pins;
825
826 xlibpart->AddChild( pins = node( wxT( "pins" ) ) );
827
828 for( unsigned i=0; i<pinList.size(); ++i )
829 {
830 SCH_PIN* basePin = pinList[i];
831
832 bool stackedValid = false;
833 std::vector<wxString> expandedNums = basePin->GetStackedPinNumbers( &stackedValid );
834
835 // If stacked notation detected and valid, emit one libparts pin per expanded number.
836 if( stackedValid && !expandedNums.empty() )
837 {
838 for( const wxString& num : expandedNums )
839 {
840 XNODE* pin;
841 pins->AddChild( pin = node( wxT( "pin" ) ) );
842 pin->AddAttribute( wxT( "num" ), num );
843 pin->AddAttribute( wxT( "name" ), basePin->GetShownName() );
844 pin->AddAttribute( wxT( "type" ), basePin->GetCanonicalElectricalTypeName() );
845
846 wxLogTrace( "CVPCB_PINCOUNT",
847 wxString::Format( "makeLibParts: -> pin num='%s' name='%s' (expanded)",
848 num, basePin->GetShownName() ) );
849 }
850 }
851 else
852 {
853 XNODE* pin;
854 pins->AddChild( pin = node( wxT( "pin" ) ) );
855 pin->AddAttribute( wxT( "num" ), basePin->GetShownNumber() );
856 pin->AddAttribute( wxT( "name" ), basePin->GetShownName() );
857 pin->AddAttribute( wxT( "type" ), basePin->GetCanonicalElectricalTypeName() );
858
859 wxLogTrace( "CVPCB_PINCOUNT",
860 wxString::Format( "makeLibParts: -> pin num='%s' name='%s'",
861 basePin->GetShownNumber(),
862 basePin->GetShownName() ) );
863 }
864
865 // caution: construction work site here, drive slowly
866 }
867 }
868 }
869
870 return xlibparts;
871}
872
873
875{
876 wxString netCodeTxt;
877 XNODE* xnets = node( wxT( "nets" ) ); // auto_ptr if exceptions ever get used.
878 XNODE* xnet = nullptr;
879
880 /* output:
881 <net code="123" name="/cfcard.sch/WAIT#" class="signal">
882 <node ref="R23" pin="1"/>
883 <node ref="U18" pin="12"/>
884 </net>
885 */
886
887 struct NET_NODE
888 {
889 NET_NODE( SCH_PIN* aPin, const SCH_SHEET_PATH& aSheet ) :
890 m_Pin( aPin ),
891 m_Sheet( aSheet )
892 {}
893
894 SCH_PIN* m_Pin;
895 SCH_SHEET_PATH m_Sheet;
896 };
897
898 struct NET_RECORD
899 {
900 NET_RECORD( const wxString& aName ) :
901 m_Name( aName ),
902 m_HasNoConnect( false )
903 {};
904
905 wxString m_Name;
906 wxString m_Class;
907 bool m_HasNoConnect;
908 std::vector<NET_NODE> m_Nodes;
909 };
910
911 std::vector<NET_RECORD*> nets;
912
913 for( const auto& [ key, subgraphs ] : m_schematic->ConnectionGraph()->GetNetMap() )
914 {
915 wxString net_name = key.Name;
916 NET_RECORD* net_record = nullptr;
917
918 if( !( aCtl & GNL_OPT_KICAD ) )
919 net_name = UnescapeString( net_name );
920
921 if( subgraphs.empty() )
922 continue;
923
924 nets.emplace_back( new NET_RECORD( net_name ) );
925 net_record = nets.back();
926
927 for( CONNECTION_SUBGRAPH* subgraph : subgraphs )
928 {
929 bool nc = subgraph->GetNoConnect() && subgraph->GetNoConnect()->Type() == SCH_NO_CONNECT_T;
930 const SCH_SHEET_PATH& sheet = subgraph->GetSheet();
931
932 if( net_record->m_Class.IsEmpty() && subgraph->GetDriver() )
933 {
934 if( subgraph->GetDriver()->GetEffectiveNetClass() )
935 {
936 net_record->m_Class = subgraph->GetDriver()->GetEffectiveNetClass()->GetName();
937 net_record->m_Class = UnescapeString( net_record->m_Class );
938 }
939 }
940
941 if( nc )
942 net_record->m_HasNoConnect = true;
943
944 for( SCH_ITEM* item : subgraph->GetItems() )
945 {
946 if( item->Type() == SCH_PIN_T )
947 {
948 SCH_PIN* pin = static_cast<SCH_PIN*>( item );
949 SCH_SYMBOL* symbol = dynamic_cast<SCH_SYMBOL*>( pin->GetParentSymbol() );
950 bool forBOM = aCtl & GNL_OPT_BOM;
951 bool forBoard = aCtl & GNL_OPT_KICAD;
952
953 if( !symbol )
954 continue;
955
956 if( forBOM && ( sheet.GetExcludedFromBOM() || symbol->ResolveExcludedFromBOM() ) )
957 continue;
958
959 if( forBoard && ( sheet.GetExcludedFromBoard() || symbol->ResolveExcludedFromBoard() ) )
960 continue;
961
962 net_record->m_Nodes.emplace_back( pin, sheet );
963 }
964 }
965 }
966 }
967
968 // Netlist ordering: Net name, then ref des, then pin name
969 std::sort( nets.begin(), nets.end(),
970 []( const NET_RECORD* a, const NET_RECORD*b )
971 {
972 return StrNumCmp( a->m_Name, b->m_Name ) < 0;
973 } );
974
975 for( int i = 0; i < (int) nets.size(); ++i )
976 {
977 NET_RECORD* net_record = nets[i];
978 bool added = false;
979 XNODE* xnode;
980
981 // Netlist ordering: Net name, then ref des, then pin name
982 std::sort( net_record->m_Nodes.begin(), net_record->m_Nodes.end(),
983 []( const NET_NODE& a, const NET_NODE& b )
984 {
985 wxString refA = a.m_Pin->GetParentSymbol()->GetRef( &a.m_Sheet );
986 wxString refB = b.m_Pin->GetParentSymbol()->GetRef( &b.m_Sheet );
987
988 if( refA == refB )
989 return a.m_Pin->GetShownNumber() < b.m_Pin->GetShownNumber();
990
991 return refA < refB;
992 } );
993
994 // Some duplicates can exist, for example on multi-unit parts with duplicated pins across
995 // units. If the user connects the pins on each unit, they will appear on separate
996 // subgraphs. Remove those here:
997 alg::remove_duplicates( net_record->m_Nodes,
998 []( const NET_NODE& a, const NET_NODE& b )
999 {
1000 wxString refA = a.m_Pin->GetParentSymbol()->GetRef( &a.m_Sheet );
1001 wxString refB = b.m_Pin->GetParentSymbol()->GetRef( &b.m_Sheet );
1002
1003 return refA == refB && a.m_Pin->GetShownNumber() == b.m_Pin->GetShownNumber();
1004 } );
1005
1006 // Determine if all pins in the net are stacked (nets with only one pin are implicitly
1007 // taken to be stacked)
1008 bool allNetPinsStacked = true;
1009
1010 if( net_record->m_Nodes.size() > 1 )
1011 {
1012 SCH_PIN* firstPin = net_record->m_Nodes.begin()->m_Pin;
1013 allNetPinsStacked =
1014 std::all_of( net_record->m_Nodes.begin() + 1, net_record->m_Nodes.end(),
1015 [=]( auto& node )
1016 {
1017 return firstPin->GetParent() == node.m_Pin->GetParent()
1018 && firstPin->GetPosition() == node.m_Pin->GetPosition()
1019 && firstPin->GetName() == node.m_Pin->GetName();
1020 } );
1021 }
1022
1023 for( const NET_NODE& netNode : net_record->m_Nodes )
1024 {
1025 wxString refText = netNode.m_Pin->GetParentSymbol()->GetRef( &netNode.m_Sheet );
1026
1027 // Skip power symbols and virtual symbols
1028 if( refText[0] == wxChar( '#' ) )
1029 continue;
1030
1031 if( !added )
1032 {
1033 netCodeTxt.Printf( wxT( "%d" ), i + 1 );
1034
1035 xnets->AddChild( xnet = node( wxT( "net" ) ) );
1036 xnet->AddAttribute( wxT( "code" ), netCodeTxt );
1037 xnet->AddAttribute( wxT( "name" ), net_record->m_Name );
1038 xnet->AddAttribute( wxT( "class" ), net_record->m_Class );
1039
1040 added = true;
1041 }
1042
1043 std::vector<wxString> nums = netNode.m_Pin->GetStackedPinNumbers();
1044 wxString baseName = netNode.m_Pin->GetShownName();
1045 wxString pinType = netNode.m_Pin->GetCanonicalElectricalTypeName();
1046
1047 wxLogTrace( traceStackedPins,
1048 wxString::Format( "XML: net='%s' ref='%s' base='%s' shownNum='%s' expand=%zu",
1049 net_record->m_Name, refText, baseName,
1050 netNode.m_Pin->GetShownNumber(), nums.size() ) );
1051
1052 for( const wxString& num : nums )
1053 {
1054 xnet->AddChild( xnode = node( wxT( "node" ) ) );
1055 xnode->AddAttribute( wxT( "ref" ), refText );
1056 xnode->AddAttribute( wxT( "pin" ), num );
1057
1058 wxString fullName = baseName.IsEmpty() ? num : baseName + wxT( "_" ) + num;
1059
1060 if( !baseName.IsEmpty() || nums.size() > 1 )
1061 xnode->AddAttribute( wxT( "pinfunction" ), fullName );
1062
1063 wxString typeAttr = pinType;
1064
1065 if( net_record->m_HasNoConnect
1066 && ( net_record->m_Nodes.size() == 1 || allNetPinsStacked ) )
1067 {
1068 typeAttr += wxT( "+no_connect" );
1069 wxLogTrace( traceStackedPins,
1070 wxString::Format( "XML: marking node ref='%s' pin='%s' as no_connect",
1071 refText, num ) );
1072 }
1073
1074 xnode->AddAttribute( wxT( "pintype" ), typeAttr );
1075 }
1076 }
1077 }
1078
1079 for( NET_RECORD* record : nets )
1080 delete record;
1081
1082 return xnets;
1083}
1084
1085
1086XNODE* NETLIST_EXPORTER_XML::node( const wxString& aName,
1087 const wxString& aTextualContent /* = wxEmptyString*/ )
1088{
1089 XNODE* n = new XNODE( wxXML_ELEMENT_NODE, aName );
1090
1091 if( aTextualContent.Len() > 0 ) // excludes wxEmptyString, the parameter's default value
1092 n->AddChild( new XNODE( wxXML_TEXT_NODE, wxEmptyString, aTextualContent ) );
1093
1094 return n;
1095}
1096
1097
1098static bool sortPinsByNumber( SCH_PIN* aPin1, SCH_PIN* aPin2 )
1099{
1100 // return "lhs < rhs"
1101 return StrNumCmp( aPin1->GetShownNumber(), aPin2->GetShownNumber(), true ) < 0;
1102}
wxString GetBuildVersion()
Get the full KiCad version string.
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.
Definition eda_item.h:98
const KIID m_Uuid
Definition eda_item.h:516
virtual const wxString & GetText() const
Return the string associated with the text object.
Definition eda_text.h:98
wxString AsString() const
Definition kiid.cpp:246
std::optional< wxString > GetFullURI(LIBRARY_TABLE_TYPE aType, const wxString &aNickname, bool aSubstituted=false) const
Return the full location specifying URI for the LIB, either in original UI form or in environment var...
const wxString GetUniStringLibItemName() const
Get strings for display messages in dialogs.
Definition lib_id.h:112
const wxString GetUniStringLibNickname() const
Definition lib_id.h:88
Define a library symbol object.
Definition lib_symbol.h:85
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.
virtual LIBRARY_MANAGER & GetLibraryManager() const
Definition pgm_base.h:130
Container for project specific data.
Definition project.h:66
A pure virtual class used to derive REPORTER objects from.
Definition reporter.h:73
wxString GetShownText(const SCH_SHEET_PATH *aPath, bool aAllowExtraText, int aDepth=0) const
A set of SCH_ITEMs (i.e., without duplicates).
Definition sch_group.h:52
Base class for any item which can be embedded within the SCHEMATIC container class,...
Definition sch_item.h:167
bool ResolveExcludedFromBoard() const
Definition sch_item.cpp:306
bool ResolveExcludedFromBOM(const SCH_SHEET_PATH *aInstance=nullptr, const wxString &aVariantName=wxEmptyString) const
Definition sch_item.cpp:290
bool ResolveDNP(const SCH_SHEET_PATH *aInstance=nullptr, const wxString &aVariantName=wxEmptyString) const
Definition sch_item.cpp:321
wxString GetShownNumber() const
Definition sch_pin.cpp:588
std::vector< wxString > GetStackedPinNumbers(bool *aValid=nullptr) const
Definition sch_pin.cpp:594
wxString GetCanonicalElectricalTypeName() const
Definition sch_pin.cpp:343
wxString GetShownName() const
Definition sch_pin.cpp:577
const wxString & GetFileName() const
Definition sch_screen.h:152
const TITLE_BLOCK & GetTitleBlock() const
Definition sch_screen.h:163
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
Schematic symbol object.
Definition sch_symbol.h:76
wxString GetDescription() const override
bool UseLibIdLookup() const
Definition sch_symbol.h:182
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
wxString GetShownDescription(int aDepth=0) const override
const LIB_ID & GetLibId() const override
Definition sch_symbol.h:165
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()
Definition sch_symbol.h:184
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.
Definition title_block.h:41
const wxString & GetCompany() const
Definition title_block.h:96
const wxString & GetRevision() const
Definition title_block.h:86
const wxString & GetDate() const
Definition title_block.h:76
const wxString & GetComment(int aIdx) const
const wxString & GetTitle() const
Definition title_block.h:63
An extension of wxXmlNode that can format its contents as KiCad-style s-expressions.
Definition xnode.h:71
void AddAttribute(const wxString &aName, const wxString &aValue) override
Definition xnode.cpp:92
wxString ExpandTextVars(const wxString &aSource, const PROJECT *aProject, int aFlags)
Definition common.cpp:60
The common library.
const wxChar *const traceStackedPins
Flag to enable debug output for stacked pins handling in symbol/pin code.
void remove_duplicates(_Container &__c)
Deletes all duplicate values from __c.
Definition kicad_algo.h:161
static bool sortPinsByNumber(SCH_PIN *aPin1, SCH_PIN *aPin2)
#define GNL_ALL
@ GNL_LIBRARIES
@ GNL_OPT_KICAD
@ GNL_SYMBOLS
@ GNL_OPT_BOM
PGM_BASE & Pgm()
The global program "get" accessor.
Definition pgm_base.cpp:946
see class PGM_BASE
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()
@ DESCRIPTION
Field Description of part, i.e. "1/4W 1% Metal Film Resistor".
@ FOOTPRINT
Field Name Module PCB, i.e. "16DIP300".
@ DATASHEET
name of datasheet
wxString GetCanonicalFieldName(FIELD_T aFieldType)
wxLogTrace helper definitions.
@ SCH_GROUP_T
Definition typeinfo.h:177
@ SCH_NO_CONNECT_T
Definition typeinfo.h:164
@ SCH_SYMBOL_T
Definition typeinfo.h:176
@ SCH_PIN_T
Definition typeinfo.h:157