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