KiCad PCB EDA Suite
Loading...
Searching...
No Matches
sch_sheet_path.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) 2017 Jean-Pierre Charras, jp.charras at wanadoo.fr
5 * Copyright (C) 2011 Wayne Stambaugh <[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, see <https://www.gnu.org/licenses/>.
20 */
21
22#include <refdes_utils.h>
23#include <hash.h>
24#include <sch_screen.h>
25#include <sch_marker.h>
26#include <sch_label.h>
27#include <sch_shape.h>
28#include <sch_sheet_path.h>
29#include <sch_symbol.h>
30#include <sch_sheet.h>
31#include <schematic.h>
32#include <string_utils.h>
33#include <template_fieldnames.h>
34#include <trace_helpers.h>
35
36#include <wx/filename.h>
37#include <wx/log.h>
38
39
46{
47public:
49 SCH_ITEM( nullptr, NOT_USED )
50 {}
51
52 wxString GetItemDescription( UNITS_PROVIDER* aUnitsProvider, bool aFull ) const override
53 {
54 return _( "(Deleted Item)" );
55 }
56
57 wxString GetClass() const override
58 {
59 return wxT( "DELETED_SHEET_ITEM" );
60 }
61
63 {
64 static DELETED_SHEET_ITEM* item = nullptr;
65
66 if( !item )
67 item = new DELETED_SHEET_ITEM();
68
69 return item;
70 }
71
72 // pure virtuals:
73 void SetPosition( const VECTOR2I& ) override {}
74 void Move( const VECTOR2I& aMoveVector ) override {}
75 void MirrorHorizontally( int aCenter ) override {}
76 void MirrorVertically( int aCenter ) override {}
77 void Rotate( const VECTOR2I& aCenter, bool aRotateCCW ) override {}
78
79 double Similarity( const SCH_ITEM& aOther ) const override
80 {
81 return 0.0;
82 }
83
84 bool operator==( const SCH_ITEM& aOther ) const override
85 {
86 return false;
87 }
88
89#if defined(DEBUG)
90 void Show( int , std::ostream& ) const override {}
91#endif
92};
93
94
103
104
106{
107 m_DNP = aSheet.GetDNP();
111 m_ExcludedFromPosFiles = false; // Sheets don't have position files exclusion
112}
113
114
115namespace std
116{
118 {
119 return path.GetCurrentHash();
120 }
121}
122
123
129
130
132{
133 initFromOther( aOther );
134}
135
136
138{
139 initFromOther( aOther );
140 return *this;
141}
142
143
144// Move assignment operator
146{
147 m_sheets = std::move( aOther.m_sheets );
148
149 m_virtualPageNumber = aOther.m_virtualPageNumber;
150 m_current_hash = aOther.m_current_hash;
151 m_cached_page_number = aOther.m_cached_page_number;
152
153 m_recursion_test_cache = std::move( aOther.m_recursion_test_cache );
154
155 return *this;
156}
157
158
160{
161 SCH_SHEET_PATH retv = *this;
162
163 size_t size = aOther.size();
164
165 for( size_t i = 0; i < size; i++ )
166 retv.push_back( aOther.at( i ) );
167
168 return retv;
169}
170
171
173{
174 m_sheets = aOther.m_sheets;
178
179 // Note: don't copy m_recursion_test_cache as it is slow and we want std::vector<SCH_SHEET_PATH>
180 // to be very fast to construct for use in the connectivity algorithm.
182}
183
185{
186 m_current_hash = 0;
187
188 for( SCH_SHEET* sheet : m_sheets )
189 hash_combine( m_current_hash, sheet->m_Uuid.Hash() );
190}
191
192
193int SCH_SHEET_PATH::Cmp( const SCH_SHEET_PATH& aSheetPathToTest ) const
194{
195 if( size() > aSheetPathToTest.size() )
196 return 1;
197
198 if( size() < aSheetPathToTest.size() )
199 return -1;
200
201 // otherwise, same number of sheets.
202 for( unsigned i = 0; i < size(); i++ )
203 {
204 if( at( i )->m_Uuid < aSheetPathToTest.at( i )->m_Uuid )
205 return -1;
206
207 if( at( i )->m_Uuid != aSheetPathToTest.at( i )->m_Uuid )
208 return 1;
209 }
210
211 return 0;
212}
213
214
215int SCH_SHEET_PATH::ComparePageNum( const SCH_SHEET_PATH& aSheetPathToTest ) const
216{
217 wxString pageA = this->GetPageNumber();
218 wxString pageB = aSheetPathToTest.GetPageNumber();
219
220 int pageNumComp = SCH_SHEET::ComparePageNum( pageA, pageB );
221
222 if( pageNumComp == 0 )
223 {
224 int virtualPageA = GetVirtualPageNumber();
225 int virtualPageB = aSheetPathToTest.GetVirtualPageNumber();
226
227 if( virtualPageA > virtualPageB )
228 pageNumComp = 1;
229 else if( virtualPageA < virtualPageB )
230 pageNumComp = -1;
231 }
232
233 return pageNumComp;
234}
235
236
237bool SCH_SHEET_PATH::IsContainedWithin( const SCH_SHEET_PATH& aSheetPathToTest ) const
238{
239 if( aSheetPathToTest.size() > size() )
240 return false;
241
242 for( size_t i = 0; i < aSheetPathToTest.size(); ++i )
243 {
244 if( at( i )->m_Uuid != aSheetPathToTest.at( i )->m_Uuid )
245 {
246 wxLogTrace( traceSchSheetPaths, "Sheet path '%s' is not within path '%s'.",
247 aSheetPathToTest.Path().AsString(), Path().AsString() );
248
249 return false;
250 }
251 }
252
253 wxLogTrace( traceSchSheetPaths, "Sheet path '%s' is within path '%s'.",
254 aSheetPathToTest.Path().AsString(), Path().AsString() );
255
256 return true;
257}
258
259
261{
262 if( !empty() )
263 return m_sheets.back();
264
265 return nullptr;
266}
267
268
270{
271 SCH_SHEET* lastSheet = Last();
272
273 if( lastSheet )
274 return lastSheet->GetScreen();
275
276 return nullptr;
277}
278
279
281{
282 SCH_SHEET* lastSheet = Last();
283
284 if( lastSheet )
285 return lastSheet->GetScreen();
286
287 return nullptr;
288}
289
290
292{
293 for( SCH_SHEET* sheet : m_sheets )
294 {
295 if( sheet->GetExcludedFromSim() )
296 return true;
297 }
298
299 return false;
300}
301
302
303bool SCH_SHEET_PATH::GetExcludedFromSim( const wxString& aVariantName ) const
304{
305 if( aVariantName.IsEmpty() )
306 return GetExcludedFromSim();
307
308 SCH_SHEET_PATH copy = *this;
309
310 while( !copy.empty() )
311 {
312 SCH_SHEET* sheet = copy.Last();
313 copy.pop_back();
314
315 if( sheet->GetExcludedFromSim( &copy, aVariantName ) )
316 return true;
317 }
318
319 return false;
320}
321
322
324{
325 for( SCH_SHEET* sheet : m_sheets )
326 {
327 if( sheet->GetExcludedFromBOM() )
328 return true;
329 }
330
331 return false;
332}
333
334
335bool SCH_SHEET_PATH::GetExcludedFromBOM( const wxString& aVariantName ) const
336{
337 if( aVariantName.IsEmpty() )
338 return GetExcludedFromBOM();
339
340 SCH_SHEET_PATH copy = *this;
341
342 while( !copy.empty() )
343 {
344 SCH_SHEET* sheet = copy.Last();
345 copy.pop_back();
346
347 if( sheet->GetExcludedFromBOM( &copy, aVariantName ) )
348 return true;
349 }
350
351 return false;
352}
353
354
356{
357 for( SCH_SHEET* sheet : m_sheets )
358 {
359 if( sheet->GetExcludedFromBoard() )
360 return true;
361 }
362
363 return false;
364}
365
366
367bool SCH_SHEET_PATH::GetExcludedFromBoard( const wxString& aVariantName ) const
368{
369 if( aVariantName.IsEmpty() )
370 return GetExcludedFromBoard();
371
372 SCH_SHEET_PATH copy = *this;
373
374 while( !copy.empty() )
375 {
376 SCH_SHEET* sheet = copy.Last();
377 copy.pop_back();
378
379 if( sheet->GetExcludedFromBoard( &copy, aVariantName ) )
380 return true;
381 }
382
383 return false;
384}
385
386
388{
389 for( SCH_SHEET* sheet : m_sheets )
390 {
391 if( sheet->GetDNP() )
392 return true;
393 }
394
395 return false;
396}
397
398
399bool SCH_SHEET_PATH::GetDNP( const wxString& aVariantName ) const
400{
401 if( aVariantName.IsEmpty() )
402 return GetDNP();
403
404 SCH_SHEET_PATH copy = *this;
405
406 while( !copy.empty() )
407 {
408 SCH_SHEET* sheet = copy.Last();
409 copy.pop_back();
410
411 if( sheet->GetDNP( &copy, aVariantName ) )
412 return true;
413 }
414
415 return false;
416}
417
418
420{
421 wxString s;
422
423 s = wxT( "/" ); // This is the root path
424
425 // Start at 1 to avoid the root sheet, which does not need to be added to the path.
426 // Its timestamp changes anyway.
427 for( unsigned i = 1; i < size(); i++ )
428 s += at( i )->m_Uuid.AsString() + "/";
429
430 return s;
431}
432
433
435{
437 size_t size = m_sheets.size();
438
439 if( m_sheets.empty() )
440 return path;
441
442 if( m_sheets[0]->m_Uuid != niluuid )
443 {
444 path.reserve( size );
445 path.push_back( m_sheets[0]->m_Uuid );
446 }
447 else
448 {
449 // Skip the virtual root
450 path.reserve( size - 1 );
451 }
452
453 for( size_t i = 1; i < size; i++ )
454 path.push_back( m_sheets[i]->m_Uuid );
455
456 return path;
457}
458
459
460wxString SCH_SHEET_PATH::PathHumanReadable( bool aUseShortRootName,
461 bool aStripTrailingSeparator,
462 bool aEscapeSheetNames ) const
463{
464 wxString s;
465
466 // Determine the starting index - skip virtual root if present
467 size_t startIdx = 0;
468
469 if( !empty() && at( 0 )->IsVirtualRootSheet() )
470 startIdx = 1;
471
472 if( aUseShortRootName )
473 {
474 s = wxS( "/" ); // Use only the short name in netlists
475 }
476 else
477 {
478 wxString fileName;
479
480 if( size() > startIdx && at( startIdx )->GetScreen() )
481 fileName = at( startIdx )->GetScreen()->GetFileName();
482
483 wxFileName fn = fileName;
484
485 s = fn.GetName() + wxS( "/" );
486 }
487
488 // When the schematic has multiple top-level sheets, the top-level sheet
489 // belongs in the path: otherwise sibling top-level sheets collapse to the
490 // same prefix (just "/") and local labels with identical text on different
491 // top-level sheets end up sharing a net.
492 size_t loopStart = startIdx + 1;
493
494 if( aUseShortRootName && size() > startIdx )
495 {
496 SCH_SHEET* first = at( startIdx );
497 SCHEMATIC* schem = first ? first->Schematic() : nullptr;
498
499 if( schem && schem->GetTopLevelSheets().size() > 1 && first->IsTopLevelSheet() )
500 loopStart = startIdx;
501 }
502
503 for( unsigned i = loopStart; i < size(); i++ )
504 {
505 wxString sheetName = at( i )->GetField( FIELD_T::SHEET_NAME )->GetShownText( false );
506
507 if( aEscapeSheetNames )
508 sheetName = EscapeString( sheetName, CTX_NETNAME );
509
510 s << sheetName << wxS( "/" );
511 }
512
513 if( aStripTrailingSeparator && s.EndsWith( "/" ) )
514 s = s.Left( s.length() - 1 );
515
516 return s;
517}
518
519
521{
522 std::vector<SCH_ITEM*> items;
523
524 std::copy_if( LastScreen()->Items().begin(), LastScreen()->Items().end(),
525 std::back_inserter( items ),
526 []( SCH_ITEM* aItem )
527 {
528 return ( aItem->Type() == SCH_SYMBOL_T
529 || aItem->Type() == SCH_GLOBAL_LABEL_T
530 || aItem->Type() == SCH_SHAPE_T );
531 } );
532
533 std::optional<wxString> variantName;
534 const SCHEMATIC* schematic = LastScreen()->Schematic();
535
536 if( schematic )
537 variantName = schematic->GetCurrentVariant();
538
539 for( SCH_ITEM* item : items )
540 {
541 if( item->Type() == SCH_SYMBOL_T )
542 {
543 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
544
545 symbol->GetField( FIELD_T::REFERENCE )->SetText( symbol->GetRef( this ) );
546 symbol->SetUnit( symbol->GetUnitSelection( this ) );
547 LastScreen()->Update( item, false );
548 }
549 else if( item->Type() == SCH_GLOBAL_LABEL_T )
550 {
551 SCH_GLOBALLABEL* label = static_cast<SCH_GLOBALLABEL*>( item );
552
553 if( label->GetFields().size() > 0 ) // Possible when reading a legacy .sch schematic
554 {
555 SCH_FIELD* intersheetRefs = label->GetField( FIELD_T::INTERSHEET_REFS );
556
557 // Fixup for legacy files which didn't store a position for the intersheet refs
558 // unless they were shown.
559 if( intersheetRefs->GetPosition() == VECTOR2I() && !intersheetRefs->IsVisible() )
561
562 intersheetRefs->SetVisible( label->Schematic()->Settings().m_IntersheetRefsShow );
563 LastScreen()->Update( intersheetRefs );
564 }
565 }
566 else if( item->Type() == SCH_SHAPE_T )
567 {
568 SCH_SHAPE* shape = static_cast<SCH_SHAPE*>( item );
569 shape->UpdateHatching();
570 }
571 }
572}
573
574
575static bool matchesSymbolFilter( const wxString& aReference, SYMBOL_FILTER aSymbolFilter )
576{
577 bool isPowerSymbol = !aReference.IsEmpty() && aReference[0] == wxT( '#' );
578
579 switch( aSymbolFilter )
580 {
581 case SYMBOL_FILTER_POWER: return isPowerSymbol;
582
583 case SYMBOL_FILTER_ALL: return true;
584
586 default: return !isPowerSymbol;
587 }
588}
589
590
592 bool aForceIncludeOrphanSymbols ) const
593{
594 for( SCH_ITEM* item : LastScreen()->Items().OfType( SCH_SYMBOL_T ) )
595 {
596 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
597 AppendSymbol( aReferences, symbol, aSymbolFilter, aForceIncludeOrphanSymbols );
598 }
599}
600
601
603 bool aForceIncludeOrphanSymbols ) const
604{
605 // Skip pseudo-symbols, which have a reference starting with #. This mainly
606 // affects power symbols.
607 if( matchesSymbolFilter( aSymbol->GetRef( this ), aSymbolFilter ) )
608 {
609 if( aSymbol->GetLibSymbolRef() || aForceIncludeOrphanSymbols )
610 {
611 SCH_REFERENCE schReference( aSymbol, *this );
612
613 schReference.SetSheetNumber( GetPageNumberAsInt() );
614 aReferences.AddItem( schReference );
615 }
616 }
617}
618
619
621{
622 for( SCH_ITEM* item : LastScreen()->Items().OfType( SCH_SYMBOL_T ) )
623 {
624 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
625 AppendMultiUnitSymbol( aRefList, symbol, aSymbolFilter );
626 }
627}
628
629
631 SYMBOL_FILTER aSymbolFilter ) const
632{
633 // Skip pseudo-symbols, which have a reference starting with #. This mainly
634 // affects power symbols.
635 if( !matchesSymbolFilter( aSymbol->GetRef( this ), aSymbolFilter ) )
636 return;
637
638 LIB_SYMBOL* symbol = aSymbol->GetLibSymbolRef().get();
639
640 if( symbol && symbol->GetUnitCount() > 1 )
641 {
642 SCH_REFERENCE schReference = SCH_REFERENCE( aSymbol, *this );
643 schReference.SetSheetNumber( GetPageNumberAsInt() );
644 wxString reference_str = schReference.GetRef();
645
646 // Never lock unassigned references
647 if( reference_str[reference_str.Len() - 1] == '?' )
648 return;
649
650 aRefList[reference_str].AddItem( schReference );
651 }
652}
653
654
656{
657 return m_current_hash == d1.GetCurrentHash();
658}
659
660
661bool SCH_SHEET_PATH::TestForRecursion( const wxString& aSrcFileName, const wxString& aDestFileName )
662{
663 auto pair = std::make_pair( aSrcFileName, aDestFileName );
664
665 if( m_recursion_test_cache.count( pair ) )
666 return m_recursion_test_cache.at( pair );
667
668 SCHEMATIC* sch = LastScreen()->Schematic();
669
670 wxCHECK_MSG( sch, false, "No SCHEMATIC found in SCH_SHEET_PATH::TestForRecursion!" );
671
672 wxFileName rootFn = sch->GetFileName();
673 wxFileName srcFn = aSrcFileName;
674 wxFileName destFn = aDestFileName;
675
676 if( srcFn.IsRelative() )
677 srcFn.MakeAbsolute( rootFn.GetPath() );
678
679 if( destFn.IsRelative() )
680 destFn.MakeAbsolute( rootFn.GetPath() );
681
682 // The source and destination sheet file names cannot be the same.
683 if( srcFn == destFn )
684 {
685 m_recursion_test_cache[pair] = true;
686 return true;
687 }
688
692 unsigned i = 0;
693
694 while( i < size() )
695 {
696 wxFileName cmpFn = at( i )->GetFileName();
697
698 if( cmpFn.IsRelative() )
699 cmpFn.MakeAbsolute( rootFn.GetPath() );
700
701 // Test if the file name of the destination sheet is in anywhere in this sheet path.
702 if( cmpFn == destFn )
703 break;
704
705 i++;
706 }
707
708 // The destination sheet file name was not found in the sheet path or the destination
709 // sheet file name is the root sheet so no recursion is possible.
710 if( i >= size() || i == 0 )
711 {
712 m_recursion_test_cache[pair] = false;
713 return false;
714 }
715
716 // Walk back up to the root sheet to see if the source file name is already a parent in
717 // the sheet path. If so, recursion will occur.
718 do
719 {
720 i -= 1;
721
722 wxFileName cmpFn = at( i )->GetFileName();
723
724 if( cmpFn.IsRelative() )
725 cmpFn.MakeAbsolute( rootFn.GetPath() );
726
727 if( cmpFn == srcFn )
728 {
729 m_recursion_test_cache[pair] = true;
730 return true;
731 }
732
733 } while( i != 0 );
734
735 // The source sheet file name is not a parent of the destination sheet file name.
736 m_recursion_test_cache[pair] = false;
737 return false;
738}
739
740
742{
743 SCH_SHEET* sheet = Last();
744
745 wxCHECK( sheet, wxEmptyString );
746
747 KIID_PATH tmpPath = Path();
748
749 if( !tmpPath.empty() )
750 tmpPath.pop_back();
751 else
752 return wxEmptyString;
753
754 return sheet->getPageNumber( tmpPath );
755}
756
758{
759 long page;
760 wxString pageStr = GetPageNumber();
761
762 if( pageStr.ToLong( &page ) )
763 return (int) page;
764
765 return GetVirtualPageNumber();
766}
767
768
769void SCH_SHEET_PATH::SetPageNumber( const wxString& aPageNumber )
770{
771 SCH_SHEET* sheet = Last();
772
773 wxCHECK( sheet, /* void */ );
774
775 KIID_PATH tmpPath = Path();
776
777 if( !tmpPath.empty() )
778 {
779 tmpPath.pop_back();
780 }
781 else
782 {
783 wxCHECK_MSG( false, /* void */, wxS( "Sheet paths must have a least one valid sheet." ) );
784 }
785
786 sheet->addInstance( tmpPath );
787 sheet->setPageNumber( tmpPath, aPageNumber );
788}
789
790
792 const wxString& aProjectName )
793{
794 wxCHECK( !aProjectName.IsEmpty(), /* void */ );
795
796 SCH_SHEET_PATH newSheetPath( aPrefixSheetPath );
797 SCH_SHEET_PATH currentSheetPath( *this );
798
799 // Prefix the new hierarchical path.
800 newSheetPath = newSheetPath + currentSheetPath;
801
802 for( SCH_ITEM* item : LastScreen()->Items().OfType( SCH_SYMBOL_T ) )
803 {
804 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
805
806 wxCHECK2( symbol, continue );
807
808 SCH_SYMBOL_INSTANCE newSymbolInstance;
809
810 if( symbol->GetInstance( newSymbolInstance, Path(), true ) )
811 {
812 newSymbolInstance.m_ProjectName = aProjectName;
813
814 // Use an existing symbol instance for this path if it exists.
815 newSymbolInstance.m_Path = newSheetPath.Path();
816 symbol->AddHierarchicalReference( newSymbolInstance );
817 }
818 else if( !symbol->GetInstances().empty() )
819 {
820 newSymbolInstance.m_ProjectName = aProjectName;
821
822 // Use the first symbol instance if any symbol instance data exists.
823 newSymbolInstance = symbol->GetInstances()[0];
824 newSymbolInstance.m_Path = newSheetPath.Path();
825 symbol->AddHierarchicalReference( newSymbolInstance );
826 }
827 else
828 {
829 newSymbolInstance.m_ProjectName = aProjectName;
830
831 // Fall back to the last saved symbol field and unit settings if there is no
832 // instance data.
833 newSymbolInstance.m_Path = newSheetPath.Path();
834 newSymbolInstance.m_Reference = symbol->GetField( FIELD_T::REFERENCE )->GetText();
835 newSymbolInstance.m_Unit = symbol->GetUnit();
836 symbol->AddHierarchicalReference( newSymbolInstance );
837 }
838 }
839}
840
841
843{
844 for( SCH_ITEM* item : LastScreen()->Items().OfType( SCH_SYMBOL_T ) )
845 {
846 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
847
848 wxCHECK2( symbol, continue );
849
850 SCH_SHEET_PATH fullSheetPath( aPrefixSheetPath );
851 SCH_SHEET_PATH currentSheetPath( *this );
852
853 // Prefix the hierarchical path of the symbol instance to be removed.
854 fullSheetPath = fullSheetPath + currentSheetPath;
855 symbol->RemoveInstance( fullSheetPath );
856 }
857}
858
859
860void SCH_SHEET_PATH::CheckForMissingSymbolInstances( const wxString& aProjectName )
861{
862 // Skip sheet paths without screens (e.g., sheets that haven't been loaded yet or virtual root)
863 if( aProjectName.IsEmpty() || !LastScreen() )
864 return;
865
866 wxLogTrace( traceSchSheetPaths, "CheckForMissingSymbolInstances for path: %s (project: %s)",
867 PathHumanReadable( false ), aProjectName );
868 wxLogTrace( traceSchSheetPaths, " Sheet path size=%zu, Path().AsString()='%s'",
869 size(), Path().AsString() );
870
871 for( SCH_ITEM* item : LastScreen()->Items().OfType( SCH_SYMBOL_T ) )
872 {
873 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
874
875 wxCHECK2( symbol, continue );
876
877 SCH_SYMBOL_INSTANCE symbolInstance;
878
879 if( !symbol->GetInstance( symbolInstance, Path() ) )
880 {
881 wxLogTrace( traceSchSheetPaths, "Adding missing symbol \"%s\" instance data for "
882 "sheet path '%s'.",
883 symbol->m_Uuid.AsString(), PathHumanReadable( false ) );
884
885 // Legacy schematics that are not shared do not contain separate instance data.
886 // The symbol reference and unit are saved in the reference field and unit entries.
887 if( ( LastScreen()->GetRefCount() <= 1 ) &&
888 ( LastScreen()->GetFileFormatVersionAtLoad() <= 20200310 ) )
889 {
890 SCH_FIELD* refField = symbol->GetField( FIELD_T::REFERENCE );
891 symbolInstance.m_Reference = refField->GetShownText( this, true );
892 symbolInstance.m_Unit = symbol->GetUnit();
893
894 wxLogTrace( traceSchSheetPaths,
895 " Legacy format: Using reference '%s' from field, unit %d",
896 symbolInstance.m_Reference, symbolInstance.m_Unit );
897 }
898 else if( !symbol->GetInstances().empty() )
899 {
900 // Prefer an instance from the current project; shared schematics may carry
901 // instance data for several projects. Copying the full instance carries
902 // variant DNP / value / field overrides across when v9-imported files have
903 // been re-rooted and their stored paths no longer match.
904 const std::vector<SCH_SYMBOL_INSTANCE>& instances = symbol->GetInstances();
905
906 auto sourceIt = std::find_if( instances.begin(), instances.end(),
907 [&aProjectName]( const SCH_SYMBOL_INSTANCE& aInstance )
908 {
909 return aInstance.m_ProjectName == aProjectName;
910 } );
911
912 if( sourceIt == instances.end() )
913 sourceIt = instances.begin();
914
915 symbolInstance = *sourceIt;
916
917 wxLogTrace( traceSchSheetPaths,
918 " Using available instance (project '%s'): ref=%s, unit=%d, variants=%zu",
919 sourceIt->m_ProjectName, symbolInstance.m_Reference,
920 symbolInstance.m_Unit, symbolInstance.m_Variants.size() );
921 }
922 else
923 {
924 // Fall back to the symbol's reference field and unit if no instance data exists.
925 SCH_FIELD* refField = symbol->GetField( FIELD_T::REFERENCE );
926 symbolInstance.m_Reference = refField->GetText();
927 symbolInstance.m_Unit = symbol->GetUnit();
928
929 wxLogTrace( traceSchSheetPaths,
930 " No instance data: Using reference '%s' from field, unit %d",
931 symbolInstance.m_Reference, symbolInstance.m_Unit );
932 }
933
934 symbolInstance.m_ProjectName = aProjectName;
935 symbolInstance.m_Path = Path();
936 symbol->AddHierarchicalReference( symbolInstance );
937
938 wxLogTrace( traceSchSheetPaths,
939 " Created instance: ref=%s, path=%s",
940 symbolInstance.m_Reference, symbolInstance.m_Path.AsString() );
941 }
942 else
943 {
944 wxLogTrace( traceSchSheetPaths,
945 " Symbol %s already has instance: ref=%s, path=%s",
946 symbol->m_Uuid.AsString(),
947 symbolInstance.m_Reference,
948 symbolInstance.m_Path.AsString() );
949 }
950 }
951}
952
953
955{
956 wxCHECK( m_sheets.size() > 1, /* void */ );
957
958 wxFileName sheetFileName = Last()->GetFileName();
959
960 // If the sheet file name is absolute, then the user requested is so don't make it relative.
961 if( sheetFileName.IsAbsolute() )
962 return;
963
964 SCH_SCREEN* screen = LastScreen();
965 SCH_SCREEN* parentScreen = m_sheets[ m_sheets.size() - 2 ]->GetScreen();
966
967 wxCHECK( screen && parentScreen, /* void */ );
968
969 wxFileName fileName = screen->GetFileName();
970 wxFileName parentFileName = parentScreen->GetFileName();
971
972 // SCH_SCREEN file names must be absolute. If they are not, someone set them incorrectly
973 // on load or on creation.
974 wxCHECK( fileName.IsAbsolute() && parentFileName.IsAbsolute(), /* void */ );
975
976 if( fileName.GetPath() == parentFileName.GetPath() )
977 {
978 Last()->SetFileName( fileName.GetFullName() );
979 }
980 else if( fileName.MakeRelativeTo( parentFileName.GetPath() ) )
981 {
982 Last()->SetFileName( fileName.GetFullPath() );
983 }
984 else
985 {
986 Last()->SetFileName( screen->GetFileName() );
987 }
988
989 wxLogTrace( tracePathsAndFiles,
990 wxT( "\n File name: '%s'"
991 "\n parent file name '%s',"
992 "\n sheet '%s' file name '%s'." ),
993 screen->GetFileName(), parentScreen->GetFileName(), PathHumanReadable(),
994 Last()->GetFileName() );
995}
996
997
999{
1000 if( aSheet != nullptr )
1001 BuildSheetList( aSheet, false );
1002}
1003
1004
1005void SCH_SHEET_LIST::BuildSheetList( SCH_SHEET* aSheet, bool aCheckIntegrity )
1006{
1007 if( !aSheet )
1008 return;
1009
1010 wxLogTrace( traceSchSheetPaths,
1011 "BuildSheetList called with sheet '%s' (UUID=%s, isVirtualRoot=%d)",
1012 aSheet->GetName(),
1013 aSheet->m_Uuid.AsString(),
1014 aSheet->m_Uuid == niluuid ? 1 : 0 );
1015
1016 // Special handling for virtual root: process its children without adding the root itself
1017 if( aSheet->IsVirtualRootSheet() )
1018 {
1019 wxLogTrace( traceSchSheetPaths, " Skipping virtual root, processing children only" );
1020
1021 if( aSheet->GetScreen() )
1022 {
1023 std::vector<SCH_ITEM*> childSheets;
1024 aSheet->GetScreen()->GetSheets( &childSheets );
1025
1026 for( SCH_ITEM* item : childSheets )
1027 {
1028 SCH_SHEET* sheet = static_cast<SCH_SHEET*>( item );
1029 BuildSheetList( sheet, aCheckIntegrity );
1030 }
1031 }
1032
1033 return;
1034 }
1035
1036 std::vector<SCH_SHEET*> badSheets;
1037
1038 m_currentSheetPath.push_back( aSheet );
1039 m_currentSheetPath.SetVirtualPageNumber( static_cast<int>( size() ) + 1 );
1041
1042 if( m_currentSheetPath.LastScreen() )
1043 {
1044 wxString parentFileName = aSheet->GetFileName();
1045 std::vector<SCH_ITEM*> childSheets;
1046 m_currentSheetPath.LastScreen()->GetSheets( &childSheets );
1047
1048 for( SCH_ITEM* item : childSheets )
1049 {
1050 SCH_SHEET* sheet = static_cast<SCH_SHEET*>( item );
1051
1052 if( aCheckIntegrity )
1053 {
1054 if( !m_currentSheetPath.TestForRecursion( sheet->GetFileName(), parentFileName ) )
1055 BuildSheetList( sheet, true );
1056 else
1057 badSheets.push_back( sheet );
1058 }
1059 else
1060 {
1061 // If we are not performing a full recursion test, at least check if we are in
1062 // a simple recursion scenario to prevent stack overflow crashes
1063 wxCHECK2_MSG( sheet->GetFileName() != aSheet->GetFileName(), continue,
1064 wxT( "Recursion prevented in SCH_SHEET_LIST::BuildSheetList" ) );
1065
1066 BuildSheetList( sheet, false );
1067 }
1068 }
1069 }
1070
1071 if( aCheckIntegrity )
1072 {
1073 for( SCH_SHEET* sheet : badSheets )
1074 {
1075 m_currentSheetPath.LastScreen()->Remove( sheet );
1076 m_currentSheetPath.LastScreen()->SetContentModified();
1077 }
1078 }
1079
1080 m_currentSheetPath.pop_back();
1081}
1082
1083
1084void SCH_SHEET_LIST::SortByHierarchicalPageNumbers( bool aUpdateVirtualPageNums )
1085{
1086 for( const SCH_SHEET_PATH& path : *this )
1087 path.CachePageNumber();
1088
1089 std::sort( begin(), end(),
1090 []( const SCH_SHEET_PATH& a, const SCH_SHEET_PATH& b ) -> bool
1091 {
1092 // Find the divergence point in the paths
1093 size_t common_len = 0;
1094 size_t min_len = std::min( a.size(), b.size() );
1095
1096 while( common_len < min_len && a.at( common_len )->m_Uuid == b.at( common_len )->m_Uuid )
1097 common_len++;
1098
1099 // If one path is a prefix of the other, the shorter one comes first
1100 // This ensures parents come before children
1101 if( common_len == a.size() )
1102 return true; // a is a prefix of b - a is the parent
1103 if( common_len == b.size() )
1104 return false; // b is a prefix of a - b is the parent
1105
1106 // Paths diverge at common_len
1107 // If they share the same parent, sort by page number
1108 // This ensures siblings are sorted by page number
1109 SCH_SHEET* sheet_a = a.at( common_len );
1110 SCH_SHEET* sheet_b = b.at( common_len );
1111
1112 // Create partial paths to get to these sheets for page number comparison
1113 KIID_PATH ancestor;
1114 for( size_t i = 0; i < common_len; i++ )
1115 ancestor.push_back( a.at( i )->m_Uuid );
1116
1117 // Compare page numbers - use the last sheet's page number
1118 wxString page_a = sheet_a->getPageNumber( ancestor );
1119 wxString page_b = sheet_b->getPageNumber( ancestor );
1120
1121 int retval = SCH_SHEET::ComparePageNum( page_a, page_b );
1122
1123 if( retval != 0 )
1124 return retval < 0;
1125
1126 // If page numbers are the same, use virtual page numbers as a tie-breaker
1128 return true;
1129 else if( a.GetVirtualPageNumber() > b.GetVirtualPageNumber() )
1130 return false;
1131
1132 // Finally, use UUIDs for stable ordering when everything else is equal
1133 return a.GetCurrentHash() < b.GetCurrentHash();
1134 } );
1135
1136 if( aUpdateVirtualPageNums )
1137 {
1138 int virtualPageNum = 1;
1139
1140 for( SCH_SHEET_PATH& sheet : *this )
1141 sheet.SetVirtualPageNumber( virtualPageNum++ );
1142 }
1143}
1144
1145
1146void SCH_SHEET_LIST::SortByPageNumbers( bool aUpdateVirtualPageNums )
1147{
1148 for( const SCH_SHEET_PATH& path : *this )
1149 path.CachePageNumber();
1150
1151 std::sort( begin(), end(),
1152 []( const SCH_SHEET_PATH& a, const SCH_SHEET_PATH& b ) -> bool
1153 {
1155 b.GetCachedPageNumber() );
1156
1157 if( retval < 0 )
1158 return true;
1159 else if( retval > 0 )
1160 return false;
1161
1163 return true;
1164 else if( a.GetVirtualPageNumber() > b.GetVirtualPageNumber() )
1165 return false;
1166
1167 // Enforce strict ordering. If the page numbers are the same, use UUIDs
1168 return a.GetCurrentHash() < b.GetCurrentHash();
1169 } );
1170
1171 if( aUpdateVirtualPageNums )
1172 {
1173 int virtualPageNum = 1;
1174
1175 for( SCH_SHEET_PATH& sheet : *this )
1176 sheet.SetVirtualPageNumber( virtualPageNum++ );
1177 }
1178}
1179
1180
1181bool SCH_SHEET_LIST::NameExists( const wxString& aSheetName ) const
1182{
1183 for( const SCH_SHEET_PATH& sheet : *this )
1184 {
1185 if( sheet.Last()->GetName() == aSheetName )
1186 return true;
1187 }
1188
1189 return false;
1190}
1191
1192
1193bool SCH_SHEET_LIST::PageNumberExists( const wxString& aPageNumber ) const
1194{
1195 for( const SCH_SHEET_PATH& sheet : *this )
1196 {
1197 if( sheet.GetPageNumber() == aPageNumber )
1198 return true;
1199 }
1200
1201 return false;
1202}
1203
1204
1205void SCH_SHEET_LIST::TrimToPageNumbers( const std::vector<wxString>& aPageInclusions )
1206{
1207 auto it = std::remove_if( begin(), end(),
1208 [&]( const SCH_SHEET_PATH& sheet )
1209 {
1210 return std::find( aPageInclusions.begin(),
1211 aPageInclusions.end(),
1212 sheet.GetPageNumber() ) == aPageInclusions.end();
1213 } );
1214
1215 erase( it, end() );
1216}
1217
1218
1220{
1221 wxString pageNumber;
1222
1223 // Find the next available page number by checking all existing page numbers
1224 std::set<int> usedPageNumbers;
1225
1226 for( const SCH_SHEET_PATH& path : *this )
1227 {
1228 wxString existingPageNum = path.GetPageNumber();
1229 long pageNum = 0;
1230
1231 if( existingPageNum.ToLong( &pageNum ) && pageNum > 0 )
1232 usedPageNumbers.insert( static_cast<int>( pageNum ) );
1233 }
1234
1235 // Find the first available number starting from 1
1236 int nextAvailable = 1;
1237
1238 while( usedPageNumbers.count( nextAvailable ) > 0 )
1239 nextAvailable++;
1240
1241 pageNumber.Printf( wxT( "%d" ), nextAvailable );
1242 return pageNumber;
1243}
1244
1245
1247{
1248 for( const SCH_SHEET_PATH& sheet : *this )
1249 {
1250 if( sheet.LastScreen() && sheet.LastScreen()->IsContentModified() )
1251 return true;
1252 }
1253
1254 return false;
1255}
1256
1257
1259{
1260 for( const SCH_SHEET_PATH& sheet : *this )
1261 {
1262 if( sheet.LastScreen() )
1263 sheet.LastScreen()->SetContentModified( false );
1264 }
1265}
1266
1267
1268SCH_ITEM* SCH_SHEET_LIST::ResolveItem( const KIID& aID, SCH_SHEET_PATH* aPathOut, bool aAllowNullptrReturn ) const
1269{
1270 for( const SCH_SHEET_PATH& sheet : *this )
1271 {
1272 SCH_ITEM* item = sheet.ResolveItem( aID );
1273
1274 if( item )
1275 {
1276 if( aPathOut )
1277 *aPathOut = sheet;
1278
1279 return item;
1280 }
1281 }
1282
1283 // Not found; weak reference has been deleted.
1284 if( aAllowNullptrReturn )
1285 return nullptr;
1286 else
1288}
1289
1290
1292{
1293 for( SCH_ITEM* aItem : LastScreen()->Items() )
1294 {
1295 if( aItem->m_Uuid == aID )
1296 return aItem;
1297
1298 SCH_ITEM* childMatch = nullptr;
1299
1300 aItem->RunOnChildren(
1301 [&]( SCH_ITEM* aChild )
1302 {
1303 if( aChild->m_Uuid == aID )
1304 childMatch = aChild;
1305 },
1307
1308 if( childMatch )
1309 return childMatch;
1310 }
1311
1312 return nullptr;
1313}
1314
1315
1316void SCH_SHEET_LIST::FillItemMap( std::map<KIID, EDA_ITEM*>& aMap )
1317{
1318 for( const SCH_SHEET_PATH& sheet : *this )
1319 {
1320 SCH_SCREEN* screen = sheet.LastScreen();
1321
1322 for( SCH_ITEM* aItem : screen->Items() )
1323 {
1324 aMap[ aItem->m_Uuid ] = aItem;
1325
1326 aItem->RunOnChildren(
1327 [&]( SCH_ITEM* aChild )
1328 {
1329 aMap[ aChild->m_Uuid ] = aChild;
1330 },
1332 }
1333 }
1334}
1335
1336
1338{
1339 // List of reference for power symbols
1340 SCH_REFERENCE_LIST references;
1341
1342 // Map of locked symbols (not used, but needed by Annotate()
1343 SCH_MULTI_UNIT_REFERENCE_MAP lockedSymbols;
1344
1345 // Build the list of power symbols:
1346 for( SCH_SHEET_PATH& sheet : *this )
1347 {
1348 for( SCH_ITEM* item : sheet.LastScreen()->Items().OfType( SCH_SYMBOL_T ) )
1349 {
1350 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
1351 LIB_SYMBOL* libSymbol = symbol->GetLibSymbolRef().get();
1352
1353 if( libSymbol && libSymbol->IsPower() )
1354 {
1355 SCH_REFERENCE schReference( symbol, sheet );
1356 references.AddItem( schReference );
1357 }
1358 }
1359 }
1360
1361 // Find duplicate, and silently clear annotation of duplicate
1362 std::map<wxString, int> ref_list; // stores the existing references
1363
1364 for( unsigned ii = 0; ii< references.GetCount(); ++ii )
1365 {
1366 wxString curr_ref = references[ii].GetRef();
1367
1368 if( curr_ref.IsEmpty() )
1369 continue;
1370
1371 if( ref_list.find( curr_ref ) == ref_list.end() )
1372 {
1373 ref_list[curr_ref] = ii;
1374 continue;
1375 }
1376
1377 // Possible duplicate, if the ref ends by a number:
1378 if( curr_ref.Last() < '0' && curr_ref.Last() > '9' )
1379 continue; // not annotated
1380
1381 // Duplicate: clear annotation by removing the number ending the ref
1382 while( !curr_ref.IsEmpty() && curr_ref.Last() >= '0' && curr_ref.Last() <= '9' )
1383 curr_ref.RemoveLast();
1384
1385 references[ii].SetRef( curr_ref );
1386 }
1387
1388 // Break full symbol reference into name (prefix) and number:
1389 // example: IC1 become IC, and 1
1390 references.SplitReferences();
1391
1392 // Ensure all power symbols have the reference starting by '#'
1393 // (Not sure this is really useful)
1394 for( unsigned ii = 0; ii< references.GetCount(); ++ii )
1395 {
1396 SCH_REFERENCE& ref_unit = references[ii];
1397
1398 if( ref_unit.GetRef()[0] != '#' )
1399 {
1400 wxString new_ref = "#" + ref_unit.GetRef();
1401 ref_unit.SetRef( new_ref );
1402 ref_unit.SetRefNum( ii );
1403 }
1404 }
1405}
1406
1407
1409 bool aForceIncludeOrphanSymbols ) const
1410{
1411 for( const SCH_SHEET_PATH& sheet : *this )
1412 sheet.GetSymbols( aReferences, aSymbolFilter, aForceIncludeOrphanSymbols );
1413}
1414
1415
1417 SYMBOL_FILTER aSymbolFilter, bool aForceIncludeOrphanSymbols ) const
1418{
1419 for( const SCH_SHEET_PATH& sheet : *this )
1420 {
1421 if( sheet.IsContainedWithin( aSheetPath ) )
1422 sheet.GetSymbols( aReferences, aSymbolFilter, aForceIncludeOrphanSymbols );
1423 }
1424}
1425
1426
1427void SCH_SHEET_LIST::GetSheetsWithinPath( std::vector<SCH_SHEET_PATH>& aSheets,
1428 const SCH_SHEET_PATH& aSheetPath ) const
1429{
1430 for( const SCH_SHEET_PATH& sheet : *this )
1431 {
1432 if( sheet.IsContainedWithin( aSheetPath ) )
1433 aSheets.push_back( sheet );
1434 }
1435}
1436
1437
1438std::optional<SCH_SHEET_PATH> SCH_SHEET_LIST::GetSheetPathByKIIDPath( const KIID_PATH& aPath,
1439 bool aIncludeLastSheet ) const
1440{
1441 for( const SCH_SHEET_PATH& sheet : *this )
1442 {
1443 KIID_PATH testPath = sheet.Path();
1444
1445 if( !aIncludeLastSheet )
1446 testPath.pop_back();
1447
1448 if( testPath == aPath )
1449 return SCH_SHEET_PATH( sheet );
1450 }
1451
1452 return std::nullopt;
1453}
1454
1455
1457{
1458 for( auto it = begin(); it != end(); ++it )
1459 {
1461 ( *it ).GetMultiUnitSymbols( tempMap, aSymbolFilter );
1462
1463 for( SCH_MULTI_UNIT_REFERENCE_MAP::value_type& pair : tempMap )
1464 {
1465 // Merge this list into the main one
1466 unsigned n_refs = pair.second.GetCount();
1467
1468 for( unsigned thisRef = 0; thisRef < n_refs; ++thisRef )
1469 aRefList[pair.first].AddItem( pair.second[thisRef] );
1470 }
1471 }
1472}
1473
1474
1475bool SCH_SHEET_LIST::TestForRecursion( const SCH_SHEET_LIST& aSrcSheetHierarchy,
1476 const wxString& aDestFileName )
1477{
1478 if( empty() )
1479 return false;
1480
1481 SCHEMATIC* sch = at( 0 ).LastScreen()->Schematic();
1482
1483 wxCHECK_MSG( sch, false, "No SCHEMATIC found in SCH_SHEET_LIST::TestForRecursion!" );
1484
1485 wxFileName rootFn = sch->GetFileName();
1486 wxFileName destFn = aDestFileName;
1487
1488 if( destFn.IsRelative() )
1489 destFn.MakeAbsolute( rootFn.GetPath() );
1490
1491 // Test each SCH_SHEET_PATH in this SCH_SHEET_LIST for potential recursion.
1492 for( unsigned i = 0; i < size(); i++ )
1493 {
1494 // Test each SCH_SHEET_PATH in the source sheet.
1495 for( unsigned j = 0; j < aSrcSheetHierarchy.size(); j++ )
1496 {
1497 const SCH_SHEET_PATH* sheetPath = &aSrcSheetHierarchy[j];
1498
1499 for( unsigned k = 0; k < sheetPath->size(); k++ )
1500 {
1501 if( at( i ).TestForRecursion( sheetPath->GetSheet( k )->GetFileName(),
1502 aDestFileName ) )
1503 {
1504 return true;
1505 }
1506 }
1507 }
1508 }
1509
1510 // The source sheet file can safely be added to the destination sheet file.
1511 return false;
1512}
1513
1514
1516{
1517 for( SCH_SHEET_PATH& path : *this )
1518 {
1519 if( path.Path() == aPath->Path() )
1520 return &path;
1521 }
1522
1523 return nullptr;
1524}
1525
1526
1528{
1529 for( SCH_SHEET_PATH& sheetpath : *this )
1530 {
1531 if( sheetpath.LastScreen() == aScreen )
1532 return sheetpath;
1533 }
1534
1535 return SCH_SHEET_PATH();
1536}
1537
1538
1540{
1541 SCH_SHEET_LIST retval;
1542
1543 for( const SCH_SHEET_PATH& sheetpath : *this )
1544 {
1545 if( sheetpath.LastScreen() == aScreen )
1546 retval.push_back( sheetpath );
1547 }
1548
1549 return retval;
1550}
1551
1552
1554 const std::vector<SCH_SYMBOL_INSTANCE>& aSymbolInstances )
1555{
1556 for( SCH_SHEET_PATH& sheetPath : *this )
1557 {
1558 for( SCH_ITEM* item : sheetPath.LastScreen()->Items().OfType( SCH_SYMBOL_T ) )
1559 {
1560 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
1561
1562 wxCHECK2( symbol, continue );
1563
1564 KIID_PATH sheetPathWithSymbolUuid = sheetPath.Path();
1565 sheetPathWithSymbolUuid.push_back( symbol->m_Uuid );
1566
1567 auto it = std::find_if( aSymbolInstances.begin(), aSymbolInstances.end(),
1568 [ sheetPathWithSymbolUuid ]( const SCH_SYMBOL_INSTANCE& r ) -> bool
1569 {
1570 return sheetPathWithSymbolUuid == r.m_Path;
1571 } );
1572
1573 if( it == aSymbolInstances.end() )
1574 {
1575 wxLogTrace( traceSchSheetPaths, "No symbol instance found for symbol '%s'",
1576 sheetPathWithSymbolUuid.AsString() );
1577 continue;
1578 }
1579
1580 // Symbol instance paths are stored and looked up in memory with the root path so use
1581 // the full path here.
1582 symbol->AddHierarchicalReference( sheetPath.Path(), it->m_Reference, it->m_Unit );
1583 symbol->GetField( FIELD_T::REFERENCE )->SetText( it->m_Reference );
1584
1585 if( !it->m_Value.IsEmpty() )
1586 symbol->SetValueFieldText( it->m_Value );
1587
1588 if( !it->m_Footprint.IsEmpty() )
1589 symbol->SetFootprintFieldText( it->m_Footprint );
1590
1591 symbol->UpdatePrefix();
1592 }
1593 }
1594}
1595
1596
1597void SCH_SHEET_LIST::UpdateSheetInstanceData( const std::vector<SCH_SHEET_INSTANCE>& aSheetInstances )
1598{
1599
1600 for( SCH_SHEET_PATH& path : *this )
1601 {
1602 SCH_SHEET* sheet = path.Last();
1603
1604 wxCHECK2( sheet && path.Last(), continue );
1605
1606 auto it = std::find_if( aSheetInstances.begin(), aSheetInstances.end(),
1607 [&path]( const SCH_SHEET_INSTANCE& r ) -> bool
1608 {
1609 return path.Path() == r.m_Path;
1610 } );
1611
1612 if( it == aSheetInstances.end() )
1613 {
1614 wxLogTrace( traceSchSheetPaths, "No sheet instance found for path '%s'",
1615 path.Path().AsString() );
1616 continue;
1617 }
1618
1619 wxLogTrace( traceSchSheetPaths, "Setting sheet '%s' instance '%s' page number '%s'",
1620 ( sheet->GetName().IsEmpty() ) ? wxString( wxT( "root" ) ) : sheet->GetName(),
1621 path.Path().AsString(), it->m_PageNumber );
1622 path.SetPageNumber( it->m_PageNumber );
1623 }
1624}
1625
1626
1627std::vector<KIID_PATH> SCH_SHEET_LIST::GetPaths() const
1628{
1629 std::vector<KIID_PATH> paths;
1630
1631 for( const SCH_SHEET_PATH& sheetPath : *this )
1632 paths.emplace_back( sheetPath.Path() );
1633
1634 return paths;
1635}
1636
1637
1638std::vector<SCH_SHEET_INSTANCE> SCH_SHEET_LIST::GetSheetInstances() const
1639{
1640 std::vector<SCH_SHEET_INSTANCE> retval;
1641
1642 for( const SCH_SHEET_PATH& path : *this )
1643 {
1644 const SCH_SHEET* sheet = path.Last();
1645
1646 wxCHECK2( sheet, continue );
1647
1648 SCH_SHEET_INSTANCE instance;
1649 SCH_SHEET_PATH tmpPath = path;
1650
1651 tmpPath.pop_back();
1652 instance.m_Path = tmpPath.Path();
1653 instance.m_PageNumber = path.GetPageNumber();
1654
1655 retval.push_back( std::move( instance ) );
1656 }
1657
1658 return retval;
1659}
1660
1661
1663{
1664 for( const SCH_SHEET_PATH& instance : *this )
1665 {
1666 if( !instance.GetPageNumber().IsEmpty() )
1667 return false;
1668 }
1669
1670 return true;
1671}
1672
1673
1675{
1676 // Don't accidentally renumber existing sheets.
1677 wxCHECK( AllSheetPageNumbersEmpty(), /* void */ );
1678
1679 wxString tmp;
1680 int pageNumber = 1;
1681
1682 for( SCH_SHEET_PATH& instance : *this )
1683 {
1684 if( instance.Last()->IsVirtualRootSheet() )
1685 continue;
1686
1687 tmp.Printf( "%d", pageNumber );
1688 instance.SetPageNumber( tmp );
1689 pageNumber += 1;
1690 }
1691}
1692
1693
1695 const wxString& aProjectName )
1696{
1697 for( SCH_SHEET_PATH& sheetPath : *this )
1698 sheetPath.AddNewSymbolInstances( aPrefixSheetPath, aProjectName );
1699}
1700
1701
1703{
1704 for( SCH_SHEET_PATH& sheetPath : *this )
1705 sheetPath.RemoveSymbolInstances( aPrefixSheetPath );
1706}
1707
1708
1710 int aLastVirtualPageNumber )
1711{
1712 wxString pageNumber;
1713 int lastUsedPageNumber = 1;
1714 int nextVirtualPageNumber = aLastVirtualPageNumber;
1715
1716 // Fetch the list of page numbers already in use.
1717 std::vector< wxString > usedPageNumbers;
1718
1719 if( aPrefixSheetPath.size() )
1720 {
1721 SCH_SHEET_LIST prefixHierarchy( aPrefixSheetPath.at( 0 ) );
1722
1723 for( const SCH_SHEET_PATH& path : prefixHierarchy )
1724 {
1725 pageNumber = path.GetPageNumber();
1726
1727 if( !pageNumber.IsEmpty() )
1728 usedPageNumbers.emplace_back( pageNumber );
1729 }
1730 }
1731
1732 for( SCH_SHEET_PATH& sheetPath : *this )
1733 {
1734 KIID_PATH tmp = sheetPath.Path();
1735 SCH_SHEET_PATH newSheetPath( aPrefixSheetPath );
1736
1737 // Prefix the new hierarchical path.
1738 newSheetPath = newSheetPath + sheetPath;
1739
1740 // Sheets cannot have themselves in the path.
1741 tmp.pop_back();
1742
1743 SCH_SHEET* sheet = sheetPath.Last();
1744
1745 wxCHECK2( sheet, continue );
1746
1747 nextVirtualPageNumber += 1;
1748
1749 SCH_SHEET_INSTANCE instance;
1750
1751 // Add the instance if it doesn't already exist
1752 if( !sheet->getInstance( instance, tmp, true ) )
1753 {
1754 sheet->addInstance( tmp );
1755 sheet->getInstance( instance, tmp, true );
1756 }
1757
1758 // Get a new page number if we don't have one
1759 if( instance.m_PageNumber.IsEmpty() )
1760 {
1761 // Generate the next available page number.
1762 do
1763 {
1764 pageNumber.Printf( wxT( "%d" ), lastUsedPageNumber );
1765 lastUsedPageNumber += 1;
1766 } while( std::find( usedPageNumbers.begin(), usedPageNumbers.end(), pageNumber ) !=
1767 usedPageNumbers.end() );
1768
1769 instance.m_PageNumber = pageNumber;
1770 newSheetPath.SetVirtualPageNumber( nextVirtualPageNumber );
1771 }
1772
1773 newSheetPath.SetPageNumber( instance.m_PageNumber );
1774 usedPageNumbers.push_back( instance.m_PageNumber );
1775 }
1776}
1777
1778
1779void SCH_SHEET_LIST::CheckForMissingSymbolInstances( const wxString& aProjectName )
1780{
1781 wxLogTrace( traceSchSheetPaths,
1782 "SCH_SHEET_LIST::CheckForMissingSymbolInstances: Processing %zu sheet paths",
1783 size() );
1784
1785 for( SCH_SHEET_PATH& sheetPath : *this )
1786 {
1787 wxLogTrace( traceSchSheetPaths,
1788 " Processing sheet path: '%s' (size=%zu, KIID_PATH='%s')",
1789 sheetPath.PathHumanReadable( false ),
1790 sheetPath.size(),
1791 sheetPath.Path().AsString() );
1792 sheetPath.CheckForMissingSymbolInstances( aProjectName );
1793 }
1794}
1795
1796
1798{
1799 int lastVirtualPageNumber = 1;
1800
1801 for( const SCH_SHEET_PATH& sheetPath : *this )
1802 {
1803 if( sheetPath.GetVirtualPageNumber() > lastVirtualPageNumber )
1804 lastVirtualPageNumber = sheetPath.GetVirtualPageNumber();
1805 }
1806
1807 return lastVirtualPageNumber;
1808}
1809
1810
1811bool SCH_SHEET_LIST::HasPath( const KIID_PATH& aPath ) const
1812{
1813 for( const SCH_SHEET_PATH& path : *this )
1814 {
1815 if( path.Path() == aPath )
1816 return true;
1817 }
1818
1819 return false;
1820}
1821
1822
1823bool SCH_SHEET_LIST::ContainsSheet( const SCH_SHEET* aSheet ) const
1824{
1825 for( const SCH_SHEET_PATH& path : *this )
1826 {
1827 for( size_t i = 0; i < path.size(); i++ )
1828 {
1829 if( path.at( i ) == aSheet )
1830 return true;
1831 }
1832 }
1833
1834 return false;
1835}
1836
1837
1838std::optional<SCH_SHEET_PATH> SCH_SHEET_LIST::GetOrdinalPath( const SCH_SCREEN* aScreen ) const
1839{
1840 // Sheet paths with sheets that do not have a screen object are not valid.
1841 if( !aScreen )
1842 return std::nullopt;
1843
1844 for( const SCH_SHEET_PATH& path: *this )
1845 {
1846 if( path.LastScreen() == aScreen )
1847 return std::optional<SCH_SHEET_PATH>( path );
1848 }
1849
1850 return std::nullopt;
1851}
bool IsContentModified() const
Definition base_screen.h:56
void SetContentModified(bool aModified=true)
Definition base_screen.h:55
wxString GetClass() const override
Return the class name.
void SetPosition(const VECTOR2I &) override
static DELETED_SHEET_ITEM * GetInstance()
double Similarity(const SCH_ITEM &aOther) const override
Return a measure of how likely the other object is to represent the same object.
void Rotate(const VECTOR2I &aCenter, bool aRotateCCW) override
Rotate the item around aCenter 90 degrees in the clockwise direction.
void Move(const VECTOR2I &aMoveVector) override
Move the item by aMoveVector to a new position.
wxString GetItemDescription(UNITS_PROVIDER *aUnitsProvider, bool aFull) const override
Return a user-visible description string of this item.
bool operator==(const SCH_ITEM &aOther) const override
void MirrorVertically(int aCenter) override
Mirror item vertically about aCenter.
void MirrorHorizontally(int aCenter) override
Mirror item horizontally about aCenter.
const KIID m_Uuid
Definition eda_item.h:531
KICAD_T Type() const
Returns the type of object.
Definition eda_item.h:108
virtual void UpdateHatching() const
virtual bool IsVisible() const
Definition eda_text.h:208
virtual void SetVisible(bool aVisible)
Definition eda_text.cpp:381
EE_TYPE OfType(KICAD_T aType) const
Definition sch_rtree.h:221
wxString AsString() const
Definition kiid.cpp:393
Definition kiid.h:44
wxString AsString() const
Definition kiid.cpp:242
Define a library symbol object.
Definition lib_symbol.h:79
bool IsPower() const override
int GetUnitCount() const override
Holds all the data relating to one schematic.
Definition schematic.h:90
wxString GetFileName() const
Helper to retrieve the filename from the root sheet screen.
SCHEMATIC_SETTINGS & Settings() const
wxString GetCurrentVariant() const
Return the current variant being edited.
std::vector< SCH_SHEET * > GetTopLevelSheets() const
Get the list of top-level sheets.
VECTOR2I GetPosition() const override
virtual const wxString & GetText() const override
Return the string associated with the text object.
Definition sch_field.h:128
wxString GetShownText(const SCH_SHEET_PATH *aPath, bool aAllowExtraText, int aDepth=0, const wxString &aVariantName=wxEmptyString) const
void SetText(const wxString &aText) override
SCH_FIELD * GetField(FIELD_T aFieldType)
Return a mandatory field in this label.
Base class for any item which can be embedded within the SCHEMATIC container class,...
Definition sch_item.h:162
virtual void RunOnChildren(const std::function< void(SCH_ITEM *)> &aFunction, RECURSE_MODE aMode)
Definition sch_item.h:628
SCHEMATIC * Schematic() const
Search the item hierarchy to find a SCHEMATIC.
Definition sch_item.cpp:268
int GetUnit() const
Definition sch_item.h:233
virtual void SetUnit(int aUnit)
Definition sch_item.h:232
SCH_ITEM(EDA_ITEM *aParent, KICAD_T aType, int aUnit=0, int aBodyStyle=0)
Definition sch_item.cpp:52
void AutoplaceFields(SCH_SCREEN *aScreen, AUTOPLACE_ALGO aAlgo) override
std::vector< SCH_FIELD > & GetFields()
Definition sch_label.h:210
Container to create a flattened list of symbols because in a complex hierarchy, a symbol can be used ...
void SplitReferences()
Attempt to split all reference designators into a name (U) and number (1).
void AddItem(const SCH_REFERENCE &aItem)
A helper to define a symbol's reference designator in a schematic.
void SetRef(const wxString &aReference)
void SetRefNum(int aNum)
wxString GetRef() const
void SetSheetNumber(int aSheetNumber)
EE_RTREE & Items()
Get the full RTree, usually for iterating.
Definition sch_screen.h:115
const wxString & GetFileName() const
Definition sch_screen.h:150
SCHEMATIC * Schematic() const
void Update(SCH_ITEM *aItem, bool aUpdateLibSymbol=true)
Update aItem's bounding box in the tree.
void GetSheets(std::vector< SCH_ITEM * > *aItems) const
Similar to Items().OfType( SCH_SHEET_T ), but return the sheets in a deterministic order (L-R,...
std::optional< SCH_SHEET_PATH > GetSheetPathByKIIDPath(const KIID_PATH &aPath, bool aIncludeLastSheet=true) const
Finds a SCH_SHEET_PATH that matches the provided KIID_PATH.
SCH_ITEM * ResolveItem(const KIID &aID, SCH_SHEET_PATH *aPathOut=nullptr, bool aAllowNullptrReturn=false) const
Fetch a SCH_ITEM by ID.
std::optional< SCH_SHEET_PATH > GetOrdinalPath(const SCH_SCREEN *aScreen) const
Return the ordinal sheet path of aScreen.
void FillItemMap(std::map< KIID, EDA_ITEM * > &aMap)
Fill an item cache for temporary use when many items need to be fetched.
SCH_SHEET_PATH m_currentSheetPath
void TrimToPageNumbers(const std::vector< wxString > &aPageInclusions)
Truncates the list by removing sheet's with page numbers not in the given list.
void SortByPageNumbers(bool aUpdateVirtualPageNums=true)
Sort the list of sheets by page number.
void AddNewSymbolInstances(const SCH_SHEET_PATH &aPrefixSheetPath, const wxString &aProjectName)
Attempt to add new symbol instances for all symbols in this list of sheet paths prefixed with aPrefix...
bool NameExists(const wxString &aSheetName) const
void GetSymbolsWithinPath(SCH_REFERENCE_LIST &aReferences, const SCH_SHEET_PATH &aSheetPath, SYMBOL_FILTER aSymbolFilter, bool aForceIncludeOrphanSymbols=false) const
Add a SCH_REFERENCE object to aReferences for each symbol in the list of sheets that are contained wi...
std::vector< SCH_SHEET_INSTANCE > GetSheetInstances() const
Fetch the instance information for all of the sheets in the hierarchy.
void UpdateSheetInstanceData(const std::vector< SCH_SHEET_INSTANCE > &aSheetInstances)
Update all of the sheet instance information using aSheetInstances.
void SetInitialPageNumbers()
Set initial sheet page numbers.
void RemoveSymbolInstances(const SCH_SHEET_PATH &aPrefixSheetPath)
SCH_SHEET_LIST FindAllSheetsForScreen(const SCH_SCREEN *aScreen) const
Return a SCH_SHEET_LIST with a copy of all the SCH_SHEET_PATH using a particular screen.
wxString GetNextPageNumber() const
bool AllSheetPageNumbersEmpty() const
Check all of the sheet instance for empty page numbers.
bool IsModified() const
Check the entire hierarchy for any modifications.
SCH_SHEET_LIST(SCH_SHEET *aSheet=nullptr)
Construct a flattened list of SCH_SHEET_PATH objects from aSheet.
void AnnotatePowerSymbols()
Silently annotate the not yet annotated power symbols of the entire hierarchy of the sheet path list.
int GetLastVirtualPageNumber() const
void UpdateSymbolInstanceData(const std::vector< SCH_SYMBOL_INSTANCE > &aSymbolInstances)
Update all of the symbol instance information using aSymbolInstances.
void GetSheetsWithinPath(std::vector< SCH_SHEET_PATH > &aSheets, const SCH_SHEET_PATH &aSheetPath) const
Add a SCH_SHEET_PATH object to aSheets for each sheet in the list that are contained within aSheetPat...
bool PageNumberExists(const wxString &aPageNumber) const
void SortByHierarchicalPageNumbers(bool aUpdateVirtualPageNums=true)
This works like SortByPageNumbers, but it sorts the sheets first by their hierarchical depth and then...
void AddNewSheetInstances(const SCH_SHEET_PATH &aPrefixSheetPath, int aLastVirtualPageNumber)
void GetMultiUnitSymbols(SCH_MULTI_UNIT_REFERENCE_MAP &aRefList, SYMBOL_FILTER aSymbolFilter) const
Add a SCH_REFERENCE_LIST object to aRefList for each same-reference set of multi-unit parts in the li...
bool ContainsSheet(const SCH_SHEET *aSheet) const
std::vector< KIID_PATH > GetPaths() const
void BuildSheetList(SCH_SHEET *aSheet, bool aCheckIntegrity)
Build the list of sheets and their sheet path from aSheet.
SCH_SHEET_PATH FindSheetForScreen(const SCH_SCREEN *aScreen)
Return the first SCH_SHEET_PATH object (not necessarily the only one) using a particular screen.
void CheckForMissingSymbolInstances(const wxString &aProjectName)
bool HasPath(const KIID_PATH &aPath) const
SCH_SHEET_PATH * FindSheetForPath(const SCH_SHEET_PATH *aPath)
Return a pointer to the first SCH_SHEET_PATH object (not necessarily the only one) matching the provi...
void GetSymbols(SCH_REFERENCE_LIST &aReferences, SYMBOL_FILTER aSymbolFilter, bool aForceIncludeOrphanSymbols=false) const
Add a SCH_REFERENCE object to aReferences for each symbol in the list of sheets.
bool TestForRecursion(const SCH_SHEET_LIST &aSrcSheetHierarchy, const wxString &aDestFileName)
Test every SCH_SHEET_PATH in this SCH_SHEET_LIST to verify if adding the sheets stored in aSrcSheetHi...
Handle access to a stack of flattened SCH_SHEET objects by way of a path for creating a flattened sch...
void AppendSymbol(SCH_REFERENCE_LIST &aReferences, SCH_SYMBOL *aSymbol, SYMBOL_FILTER aSymbolFilter, bool aForceIncludeOrphanSymbols=false) const
Append a SCH_REFERENCE object to aReferences based on aSymbol.
bool GetExcludedFromBOM() const
const SCH_SHEET * GetSheet(unsigned aIndex) const
bool empty() const
Forwarded method from std::vector.
int ComparePageNum(const SCH_SHEET_PATH &aSheetPathToTest) const
Compare sheets by their page number.
size_t GetCurrentHash() const
void GetMultiUnitSymbols(SCH_MULTI_UNIT_REFERENCE_MAP &aRefList, SYMBOL_FILTER aSymbolFilter) const
Add a SCH_REFERENCE_LIST object to aRefList for each same-reference set of multi-unit parts in the sh...
void GetSymbols(SCH_REFERENCE_LIST &aReferences, SYMBOL_FILTER aSymbolFilter, bool aForceIncludeOrphanSymbols=false) const
Adds SCH_REFERENCE object to aReferences for each symbol in the sheet.
bool operator==(const SCH_SHEET_PATH &d1) const
void AddNewSymbolInstances(const SCH_SHEET_PATH &aPrefixSheetPath, const wxString &aProjectName)
Attempt to add new symbol instances for all symbols in this sheet path prefixed with aPrefixSheetPath...
KIID_PATH Path() const
Get the sheet path as an KIID_PATH.
bool TestForRecursion(const wxString &aSrcFileName, const wxString &aDestFileName)
Test the SCH_SHEET_PATH file names to check adding the sheet stored in the file aSrcFileName to the s...
void UpdateAllScreenReferences() const
Update all the symbol references for this sheet path.
void MakeFilePathRelativeToParentSheet()
Make the sheet file name relative to its parent sheet.
SCH_ITEM * ResolveItem(const KIID &aID) const
Fetch a SCH_ITEM by ID.
wxString GetCachedPageNumber() const
std::vector< SCH_SHEET * > m_sheets
SCH_SCREEN * LastScreen()
int Cmp(const SCH_SHEET_PATH &aSheetPathToTest) const
Compare if this is the same sheet path as aSheetPathToTest.
void initFromOther(const SCH_SHEET_PATH &aOther)
wxString m_cached_page_number
wxString GetPageNumber() const
void RemoveSymbolInstances(const SCH_SHEET_PATH &aPrefixSheetPath)
void CheckForMissingSymbolInstances(const wxString &aProjectName)
bool IsContainedWithin(const SCH_SHEET_PATH &aSheetPathToTest) const
Check if this path is contained inside aSheetPathToTest.
SCH_SHEET * at(size_t aIndex) const
Forwarded method from std::vector.
void SetVirtualPageNumber(int aPageNumber)
Set the sheet instance virtual page number.
wxString PathHumanReadable(bool aUseShortRootName=true, bool aStripTrailingSeparator=false, bool aEscapeSheetNames=false) const
Return the sheet path in a human readable form made from the sheet names.
std::map< std::pair< wxString, wxString >, bool > m_recursion_test_cache
bool GetExcludedFromSim() const
wxString PathAsString() const
Return the path of time stamps which do not changes even when editing sheet parameters.
void AppendMultiUnitSymbol(SCH_MULTI_UNIT_REFERENCE_MAP &aRefList, SCH_SYMBOL *aSymbol, SYMBOL_FILTER aSymbolFilter) const
Append a SCH_REFERENCE_LIST object to aRefList based on aSymbol, storing same-reference set of multi-...
bool GetExcludedFromBoard() const
void SetPageNumber(const wxString &aPageNumber)
Set the sheet instance user definable page number.
SCH_SHEET_PATH & operator=(const SCH_SHEET_PATH &aOther)
int GetPageNumberAsInt() const
bool GetDNP() const
SCH_SHEET * Last() const
Return a pointer to the last SCH_SHEET of the list.
SCH_SHEET_PATH operator+(const SCH_SHEET_PATH &aOther)
int m_virtualPageNumber
Page numbers are maintained by the sheet load order.
void push_back(SCH_SHEET *aSheet)
Forwarded method from std::vector.
size_t size() const
Forwarded method from std::vector.
int GetVirtualPageNumber() const
void pop_back()
Forwarded method from std::vector.
void InitializeAttributes(const SCH_SHEET &aSheet)
Sheet symbol placed in a schematic, and is the entry point for a sub schematic.
Definition sch_sheet.h:44
void SetFileName(const wxString &aFilename)
Definition sch_sheet.h:376
wxString GetFileName() const
Return the filename corresponding to this sheet.
Definition sch_sheet.h:370
bool getInstance(SCH_SHEET_INSTANCE &aInstance, const KIID_PATH &aSheetPath, bool aTestFromEnd=false) const
bool addInstance(const KIID_PATH &aInstance)
Add a new instance aSheetPath to the instance list.
wxString getPageNumber(const KIID_PATH &aParentPath) const
Return the sheet page number for aParentPath.
bool IsTopLevelSheet() const
Check if this sheet is a top-level sheet.
SCH_FIELD * GetField(FIELD_T aFieldType)
Return a mandatory field in this sheet.
wxString GetName() const
Definition sch_sheet.h:136
bool GetExcludedFromBOM(const SCH_SHEET_PATH *aInstance=nullptr, const wxString &aVariantName=wxEmptyString) const override
bool GetExcludedFromSim(const SCH_SHEET_PATH *aInstance=nullptr, const wxString &aVariantName=wxEmptyString) const override
SCH_SCREEN * GetScreen() const
Definition sch_sheet.h:139
static int ComparePageNum(const wxString &aPageNumberA, const wxString &aPageNumberB)
Compare page numbers of schematic sheets.
void setPageNumber(const KIID_PATH &aInstance, const wxString &aPageNumber)
Set the page number for the sheet instance aInstance.
bool IsVirtualRootSheet() const
bool GetDNP(const SCH_SHEET_PATH *aInstance=nullptr, const wxString &aVariantName=wxEmptyString) const override
Set or clear the 'Do Not Populate' flags.
bool GetExcludedFromBoard(const SCH_SHEET_PATH *aInstance=nullptr, const wxString &aVariantName=wxEmptyString) const override
Definition sch_sheet.h:461
void InitializeAttributes(const SCH_SYMBOL &aSymbol)
Schematic symbol object.
Definition sch_symbol.h:69
void UpdatePrefix()
Set the prefix based on the current reference designator.
bool GetExcludedFromSim(const SCH_SHEET_PATH *aInstance=nullptr, const wxString &aVariantName=wxEmptyString) const override
const std::vector< SCH_SYMBOL_INSTANCE > & GetInstances() const
Definition sch_symbol.h:128
void RemoveInstance(const SCH_SHEET_PATH &aInstancePath)
bool GetExcludedFromBOM(const SCH_SHEET_PATH *aInstance=nullptr, const wxString &aVariantName=wxEmptyString) const override
void SetFootprintFieldText(const wxString &aFootprint)
void AddHierarchicalReference(const KIID_PATH &aPath, const wxString &aRef, int aUnit)
Add a full hierarchical reference to this symbol.
void SetValueFieldText(const wxString &aValue, const SCH_SHEET_PATH *aInstance=nullptr, const wxString &aVariantName=wxEmptyString)
bool GetExcludedFromPosFiles(const SCH_SHEET_PATH *aInstance=nullptr, const wxString &aVariantName=wxEmptyString) const override
bool GetInstance(SCH_SYMBOL_INSTANCE &aInstance, const KIID_PATH &aSheetPath, bool aTestFromEnd=false) const
bool GetExcludedFromBoard(const SCH_SHEET_PATH *aInstance=nullptr, const wxString &aVariantName=wxEmptyString) const override
int GetUnitSelection(const SCH_SHEET_PATH *aSheet) const
Return the instance-specific unit selection for the given sheet path.
std::unique_ptr< LIB_SYMBOL > & GetLibSymbolRef()
Definition sch_symbol.h:177
virtual bool GetDNP(const SCH_SHEET_PATH *aInstance=nullptr, const wxString &aVariantName=wxEmptyString) const override
Set or clear the 'Do Not Populate' flag.
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.
bool m_ExcludedFromBOM
bool m_ExcludedFromPosFiles
bool m_ExcludedFromSim
bool m_ExcludedFromBoard
static bool empty(const wxTextEntryBase *aCtrl)
#define _(s)
@ NO_RECURSE
Definition eda_item.h:50
const wxChar *const tracePathsAndFiles
Flag to enable path and file name debug output.
const wxChar *const traceSchSheetPaths
Flag to enable debug output of schematic symbol sheet path manipulation code.
static constexpr void hash_combine(std::size_t &seed)
This is a dummy function to take the final case of hash_combine below.
Definition hash.h:28
KIID niluuid(0)
STL namespace.
Collection of utility functions for component reference designators (refdes)
@ AUTOPLACE_AUTO
Definition sch_item.h:67
static bool matchesSymbolFilter(const wxString &aReference, SYMBOL_FILTER aSymbolFilter)
Definition of the SCH_SHEET_PATH and SCH_SHEET_LIST classes for Eeschema.
std::map< wxString, SCH_REFERENCE_LIST > SCH_MULTI_UNIT_REFERENCE_MAP
Container to map reference designators for multi-unit parts.
SYMBOL_FILTER
@ SYMBOL_FILTER_NON_POWER
@ SYMBOL_FILTER_ALL
@ SYMBOL_FILTER_POWER
wxString EscapeString(const wxString &aSource, ESCAPE_CONTEXT aContext)
The Escape/Unescape routines use HTML-entity-reference-style encoding to handle characters which are:...
@ CTX_NETNAME
A simple container for sheet instance information.
A simple container for schematic symbol instance information.
std::map< wxString, SCH_SYMBOL_VARIANT > m_Variants
A list of symbol variants.
size_t operator()(const SCH_SHEET_PATH &path) const
@ INTERSHEET_REFS
Global label cross-reference page numbers.
@ REFERENCE
Field Reference of part, i.e. "IC21".
std::string path
table push_back({ "Source", "Layer", "Vertices", "Strategy", "Build(us)", "ns/query", "Mquery/s", "Inside" })
VECTOR2I end
wxLogTrace helper definitions.
@ SCH_SYMBOL_T
Definition typeinfo.h:169
@ SCH_SHAPE_T
Definition typeinfo.h:146
@ NOT_USED
the 3d code uses this value
Definition typeinfo.h:72
@ SCH_GLOBAL_LABEL_T
Definition typeinfo.h:165
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:683