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