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