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 symbol->GetField( FIELD_T::REFERENCE )->SetText( symbol->GetRef( this ) );
594 symbol->SetUnit( symbol->GetUnitSelection( this ) );
595 LastScreen()->Update( item, false );
596 }
597 else if( item->Type() == SCH_GLOBAL_LABEL_T )
598 {
599 SCH_GLOBALLABEL* label = static_cast<SCH_GLOBALLABEL*>( item );
600
601 if( label->GetFields().size() > 0 ) // Possible when reading a legacy .sch schematic
602 {
603 SCH_FIELD* intersheetRefs = label->GetField( FIELD_T::INTERSHEET_REFS );
604
605 // Fixup for legacy files which didn't store a position for the intersheet refs
606 // unless they were shown.
607 if( intersheetRefs->GetPosition() == VECTOR2I() && !intersheetRefs->IsVisible() )
609
610 intersheetRefs->SetVisible( label->Schematic()->Settings().m_IntersheetRefsShow );
611 LastScreen()->Update( intersheetRefs );
612 }
613 }
614 else if( item->Type() == SCH_SHAPE_T )
615 {
616 SCH_SHAPE* shape = static_cast<SCH_SHAPE*>( item );
617 shape->UpdateHatching();
618 }
619 }
620}
621
622
623static bool matchesSymbolFilter( const wxString& aReference, SYMBOL_FILTER aSymbolFilter )
624{
625 bool isPowerSymbol = !aReference.IsEmpty() && aReference[0] == wxT( '#' );
626
627 switch( aSymbolFilter )
628 {
629 case SYMBOL_FILTER_POWER: return isPowerSymbol;
630
631 case SYMBOL_FILTER_ALL: return true;
632
634 default: return !isPowerSymbol;
635 }
636}
637
638
640 bool aForceIncludeOrphanSymbols ) const
641{
642 for( SCH_ITEM* item : LastScreen()->Items().OfType( SCH_SYMBOL_T ) )
643 {
644 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
645 AppendSymbol( aReferences, symbol, aSymbolFilter, aForceIncludeOrphanSymbols );
646 }
647}
648
649
651 bool aForceIncludeOrphanSymbols ) const
652{
653 // Skip pseudo-symbols, which have a reference starting with #. This mainly
654 // affects power symbols.
655 if( matchesSymbolFilter( aSymbol->GetRef( this ), aSymbolFilter ) )
656 {
657 if( aSymbol->GetLibSymbolRef() || aForceIncludeOrphanSymbols )
658 {
659 SCH_REFERENCE schReference( aSymbol, *this );
660
661 schReference.SetSheetNumber( GetPageNumberAsInt() );
662 aReferences.AddItem( schReference );
663 }
664 }
665}
666
667
669{
670 for( SCH_ITEM* item : LastScreen()->Items().OfType( SCH_SYMBOL_T ) )
671 {
672 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
673 AppendMultiUnitSymbol( aRefList, symbol, aSymbolFilter );
674 }
675}
676
677
679 SYMBOL_FILTER aSymbolFilter ) const
680{
681 // Skip pseudo-symbols, which have a reference starting with #. This mainly
682 // affects power symbols.
683 if( !matchesSymbolFilter( aSymbol->GetRef( this ), aSymbolFilter ) )
684 return;
685
686 LIB_SYMBOL* symbol = aSymbol->GetLibSymbolRef().get();
687
688 if( symbol && symbol->GetUnitCount() > 1 )
689 {
690 SCH_REFERENCE schReference = SCH_REFERENCE( aSymbol, *this );
691 schReference.SetSheetNumber( GetPageNumberAsInt() );
692 wxString reference_str = schReference.GetRef();
693
694 // Never lock unassigned references
695 if( reference_str[reference_str.Len() - 1] == '?' )
696 return;
697
698 aRefList[reference_str].AddItem( schReference );
699 }
700}
701
702
704{
705 return m_current_hash == d1.GetCurrentHash();
706}
707
708
709bool SCH_SHEET_PATH::TestForRecursion( const wxString& aSrcFileName, const wxString& aDestFileName )
710{
711 auto pair = std::make_pair( aSrcFileName, aDestFileName );
712
713 if( m_recursion_test_cache.count( pair ) )
714 return m_recursion_test_cache.at( pair );
715
716 SCHEMATIC* sch = LastScreen()->Schematic();
717
718 wxCHECK_MSG( sch, false, "No SCHEMATIC found in SCH_SHEET_PATH::TestForRecursion!" );
719
720 wxFileName rootFn = sch->GetFileName();
721 wxFileName srcFn = aSrcFileName;
722 wxFileName destFn = aDestFileName;
723
724 if( srcFn.IsRelative() )
725 srcFn.MakeAbsolute( rootFn.GetPath() );
726
727 if( destFn.IsRelative() )
728 destFn.MakeAbsolute( rootFn.GetPath() );
729
730 // The source and destination sheet file names cannot be the same.
731 if( srcFn == destFn )
732 {
733 m_recursion_test_cache[pair] = true;
734 return true;
735 }
736
740 unsigned i = 0;
741
742 while( i < size() )
743 {
744 wxFileName cmpFn = at( i )->GetFileName();
745
746 if( cmpFn.IsRelative() )
747 cmpFn.MakeAbsolute( rootFn.GetPath() );
748
749 // Test if the file name of the destination sheet is in anywhere in this sheet path.
750 if( cmpFn == destFn )
751 break;
752
753 i++;
754 }
755
756 // The destination sheet file name was not found in the sheet path or the destination
757 // sheet file name is the root sheet so no recursion is possible.
758 if( i >= size() || i == 0 )
759 {
760 m_recursion_test_cache[pair] = false;
761 return false;
762 }
763
764 // Walk back up to the root sheet to see if the source file name is already a parent in
765 // the sheet path. If so, recursion will occur.
766 do
767 {
768 i -= 1;
769
770 wxFileName cmpFn = at( i )->GetFileName();
771
772 if( cmpFn.IsRelative() )
773 cmpFn.MakeAbsolute( rootFn.GetPath() );
774
775 if( cmpFn == srcFn )
776 {
777 m_recursion_test_cache[pair] = true;
778 return true;
779 }
780
781 } while( i != 0 );
782
783 // The source sheet file name is not a parent of the destination sheet file name.
784 m_recursion_test_cache[pair] = false;
785 return false;
786}
787
788
790{
791 SCH_SHEET* sheet = Last();
792
793 wxCHECK( sheet, wxEmptyString );
794
795 KIID_PATH tmpPath = Path();
796
797 if( !tmpPath.empty() )
798 tmpPath.pop_back();
799 else
800 return wxEmptyString;
801
802 return sheet->getPageNumber( tmpPath );
803}
804
806{
807 long page;
808 wxString pageStr = GetPageNumber();
809
810 if( pageStr.ToLong( &page ) )
811 return (int) page;
812
813 return GetVirtualPageNumber();
814}
815
816
817void SCH_SHEET_PATH::SetPageNumber( const wxString& aPageNumber )
818{
819 SCH_SHEET* sheet = Last();
820
821 wxCHECK( sheet, /* void */ );
822
823 KIID_PATH tmpPath = Path();
824
825 if( !tmpPath.empty() )
826 {
827 tmpPath.pop_back();
828 }
829 else
830 {
831 wxCHECK_MSG( false, /* void */, wxS( "Sheet paths must have a least one valid sheet." ) );
832 }
833
834 sheet->addInstance( tmpPath );
835 sheet->setPageNumber( tmpPath, aPageNumber );
836}
837
838
840 const wxString& aProjectName )
841{
842 wxCHECK( !aProjectName.IsEmpty(), /* void */ );
843
844 SCH_SHEET_PATH newSheetPath( aPrefixSheetPath );
845 SCH_SHEET_PATH currentSheetPath( *this );
846
847 // Prefix the new hierarchical path.
848 newSheetPath = newSheetPath + currentSheetPath;
849
850 for( SCH_ITEM* item : LastScreen()->Items().OfType( SCH_SYMBOL_T ) )
851 {
852 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
853
854 wxCHECK2( symbol, continue );
855
856 SCH_SYMBOL_INSTANCE newSymbolInstance;
857
858 if( symbol->GetInstance( newSymbolInstance, Path(), true ) )
859 {
860 newSymbolInstance.m_ProjectName = aProjectName;
861
862 // Use an existing symbol instance for this path if it exists.
863 newSymbolInstance.m_Path = newSheetPath.Path();
864 symbol->AddHierarchicalReference( newSymbolInstance );
865 }
866 else if( !symbol->GetInstances().empty() )
867 {
868 newSymbolInstance.m_ProjectName = aProjectName;
869
870 // Use the first symbol instance if any symbol instance data exists.
871 newSymbolInstance = symbol->GetInstances()[0];
872 newSymbolInstance.m_Path = newSheetPath.Path();
873 symbol->AddHierarchicalReference( newSymbolInstance );
874 }
875 else
876 {
877 newSymbolInstance.m_ProjectName = aProjectName;
878
879 // Fall back to the last saved symbol field and unit settings if there is no
880 // instance data.
881 newSymbolInstance.m_Path = newSheetPath.Path();
882 newSymbolInstance.m_Reference = symbol->GetField( FIELD_T::REFERENCE )->GetText();
883 newSymbolInstance.m_Unit = symbol->GetUnit();
884 symbol->AddHierarchicalReference( newSymbolInstance );
885 }
886 }
887}
888
889
891{
892 for( SCH_ITEM* item : LastScreen()->Items().OfType( SCH_SYMBOL_T ) )
893 {
894 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
895
896 wxCHECK2( symbol, continue );
897
898 SCH_SHEET_PATH fullSheetPath( aPrefixSheetPath );
899 SCH_SHEET_PATH currentSheetPath( *this );
900
901 // Prefix the hierarchical path of the symbol instance to be removed.
902 fullSheetPath = fullSheetPath + currentSheetPath;
903 symbol->RemoveInstance( fullSheetPath );
904 }
905}
906
907
908void SCH_SHEET_PATH::CheckForMissingSymbolInstances( const wxString& aProjectName )
909{
910 // Skip sheet paths without screens (e.g., sheets that haven't been loaded yet or virtual root)
911 if( aProjectName.IsEmpty() || !LastScreen() )
912 return;
913
914 wxLogTrace( traceSchSheetPaths, "CheckForMissingSymbolInstances for path: %s (project: %s)",
915 PathHumanReadable( false ), aProjectName );
916 wxLogTrace( traceSchSheetPaths, " Sheet path size=%zu, Path().AsString()='%s'",
917 size(), Path().AsString() );
918
919 for( SCH_ITEM* item : LastScreen()->Items().OfType( SCH_SYMBOL_T ) )
920 {
921 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
922
923 wxCHECK2( symbol, continue );
924
925 SCH_SYMBOL_INSTANCE symbolInstance;
926
927 if( !symbol->GetInstance( symbolInstance, Path() ) )
928 {
929 wxLogTrace( traceSchSheetPaths, "Adding missing symbol \"%s\" instance data for "
930 "sheet path '%s'.",
931 symbol->m_Uuid.AsString(), PathHumanReadable( false ) );
932
933 // Legacy schematics that are not shared do not contain separate instance data.
934 // The symbol reference and unit are saved in the reference field and unit entries.
935 if( !IsSharedPath() && ( LastScreen()->GetFileFormatVersionAtLoad() <= 20200310 ) )
936 {
937 SCH_FIELD* refField = symbol->GetField( FIELD_T::REFERENCE );
938 symbolInstance.m_Reference = refField->GetShownText( this, INTERNAL );
939 symbolInstance.m_Unit = symbol->GetUnit();
940
941 wxLogTrace( traceSchSheetPaths, " Legacy format: Using reference '%s' from field, unit %d",
942 symbolInstance.m_Reference, symbolInstance.m_Unit );
943 }
944 else if( !symbol->GetInstances().empty() )
945 {
946 // Prefer an instance from the current project; shared schematics may carry
947 // instance data for several projects. Copying the full instance carries
948 // variant DNP / value / field overrides across when v9-imported files have
949 // been re-rooted and their stored paths no longer match.
950 const std::vector<SCH_SYMBOL_INSTANCE>& instances = symbol->GetInstances();
951
952 auto sourceIt = std::find_if( instances.begin(), instances.end(),
953 [&aProjectName]( const SCH_SYMBOL_INSTANCE& aInstance )
954 {
955 return aInstance.m_ProjectName == aProjectName;
956 } );
957
958 if( sourceIt == instances.end() )
959 sourceIt = instances.begin();
960
961 symbolInstance = *sourceIt;
962
963 wxLogTrace( traceSchSheetPaths,
964 " Using available instance (project '%s'): ref=%s, unit=%d, variants=%zu",
965 sourceIt->m_ProjectName, symbolInstance.m_Reference,
966 symbolInstance.m_Unit, symbolInstance.m_Variants.size() );
967 }
968 else
969 {
970 // Fall back to the symbol's reference field and unit if no instance data exists.
971 SCH_FIELD* refField = symbol->GetField( FIELD_T::REFERENCE );
972 symbolInstance.m_Reference = refField->GetText();
973 symbolInstance.m_Unit = symbol->GetUnit();
974
975 wxLogTrace( traceSchSheetPaths,
976 " No instance data: Using reference '%s' from field, unit %d",
977 symbolInstance.m_Reference, symbolInstance.m_Unit );
978 }
979
980 symbolInstance.m_ProjectName = aProjectName;
981 symbolInstance.m_Path = Path();
982 symbol->AddHierarchicalReference( symbolInstance );
983
984 wxLogTrace( traceSchSheetPaths,
985 " Created instance: ref=%s, path=%s",
986 symbolInstance.m_Reference, symbolInstance.m_Path.AsString() );
987 }
988 else
989 {
990 wxLogTrace( traceSchSheetPaths,
991 " Symbol %s already has instance: ref=%s, path=%s",
992 symbol->m_Uuid.AsString(),
993 symbolInstance.m_Reference,
994 symbolInstance.m_Path.AsString() );
995 }
996 }
997}
998
999
1001{
1002 wxCHECK( m_sheets.size() > 1, /* void */ );
1003
1004 wxFileName sheetFileName = Last()->GetFileName();
1005
1006 // If the sheet file name is absolute, then the user requested is so don't make it relative.
1007 if( sheetFileName.IsAbsolute() )
1008 return;
1009
1010 SCH_SCREEN* screen = LastScreen();
1011 SCH_SCREEN* parentScreen = m_sheets[ m_sheets.size() - 2 ]->GetScreen();
1012
1013 wxCHECK( screen && parentScreen, /* void */ );
1014
1015 wxFileName fileName = screen->GetFileName();
1016 wxFileName parentFileName = parentScreen->GetFileName();
1017
1018 // SCH_SCREEN file names must be absolute. If they are not, someone set them incorrectly
1019 // on load or on creation.
1020 wxCHECK( fileName.IsAbsolute() && parentFileName.IsAbsolute(), /* void */ );
1021
1022 if( fileName.GetPath() == parentFileName.GetPath() )
1023 {
1024 Last()->SetFileName( fileName.GetFullName() );
1025 }
1026 else if( fileName.MakeRelativeTo( parentFileName.GetPath() ) )
1027 {
1028 Last()->SetFileName( fileName.GetFullPath() );
1029 }
1030 else
1031 {
1032 Last()->SetFileName( screen->GetFileName() );
1033 }
1034
1035 wxLogTrace( tracePathsAndFiles,
1036 wxT( "\n File name: '%s'"
1037 "\n parent file name '%s',"
1038 "\n sheet '%s' file name '%s'." ),
1039 screen->GetFileName(), parentScreen->GetFileName(), PathHumanReadable(),
1040 Last()->GetFileName() );
1041}
1042
1043
1045{
1046 SCH_SHEET_PATH tmp = *this;
1047
1048 while( !tmp.empty() )
1049 {
1050 wxCHECK2( tmp.LastScreen(), continue );
1051
1052 if( tmp.LastScreen()->GetRefCount() > 1 )
1053 return true;
1054
1055 tmp.pop_back();
1056 }
1057
1058 return false;
1059}
1060
1061
1063{
1064 if( aSheet != nullptr )
1065 BuildSheetList( aSheet, false );
1066}
1067
1068
1069void SCH_SHEET_LIST::BuildSheetList( SCH_SHEET* aSheet, bool aCheckIntegrity )
1070{
1071 if( !aSheet )
1072 return;
1073
1074 wxLogTrace( traceSchSheetPaths,
1075 "BuildSheetList called with sheet '%s' (UUID=%s, isVirtualRoot=%d)",
1076 aSheet->GetName(),
1077 aSheet->m_Uuid.AsString(),
1078 aSheet->m_Uuid == niluuid ? 1 : 0 );
1079
1080 // Special handling for virtual root: process its children without adding the root itself
1081 if( aSheet->IsVirtualRootSheet() )
1082 {
1083 wxLogTrace( traceSchSheetPaths, " Skipping virtual root, processing children only" );
1084
1085 if( aSheet->GetScreen() )
1086 {
1087 std::vector<SCH_ITEM*> childSheets;
1088 aSheet->GetScreen()->GetSheets( &childSheets );
1089
1090 for( SCH_ITEM* item : childSheets )
1091 {
1092 SCH_SHEET* sheet = static_cast<SCH_SHEET*>( item );
1093 BuildSheetList( sheet, aCheckIntegrity );
1094 }
1095 }
1096
1097 return;
1098 }
1099
1100 std::vector<SCH_SHEET*> badSheets;
1101
1102 m_currentSheetPath.push_back( aSheet );
1103 m_currentSheetPath.SetVirtualPageNumber( static_cast<int>( size() ) + 1 );
1104 push_back( m_currentSheetPath );
1105
1106 if( m_currentSheetPath.LastScreen() )
1107 {
1108 wxString parentFileName = aSheet->GetFileName();
1109 std::vector<SCH_ITEM*> childSheets;
1110 m_currentSheetPath.LastScreen()->GetSheets( &childSheets );
1111
1112 for( SCH_ITEM* item : childSheets )
1113 {
1114 SCH_SHEET* sheet = static_cast<SCH_SHEET*>( item );
1115
1116 if( aCheckIntegrity )
1117 {
1118 if( !m_currentSheetPath.TestForRecursion( sheet->GetFileName(), parentFileName ) )
1119 BuildSheetList( sheet, true );
1120 else
1121 badSheets.push_back( sheet );
1122 }
1123 else
1124 {
1125 // If we are not performing a full recursion test, at least check if we are in
1126 // a simple recursion scenario to prevent stack overflow crashes
1127 wxCHECK2_MSG( sheet->GetFileName() != aSheet->GetFileName(), continue,
1128 wxT( "Recursion prevented in SCH_SHEET_LIST::BuildSheetList" ) );
1129
1130 BuildSheetList( sheet, false );
1131 }
1132 }
1133 }
1134
1135 if( aCheckIntegrity )
1136 {
1137 for( SCH_SHEET* sheet : badSheets )
1138 {
1139 m_currentSheetPath.LastScreen()->Remove( sheet );
1140 m_currentSheetPath.LastScreen()->SetContentModified();
1141 }
1142 }
1143
1144 m_currentSheetPath.pop_back();
1145}
1146
1147
1148void SCH_SHEET_LIST::SortByHierarchicalPageNumbers( bool aUpdateVirtualPageNums )
1149{
1150 for( const SCH_SHEET_PATH& path : *this )
1151 path.CachePageNumber();
1152
1153 std::sort( begin(), end(),
1154 []( const SCH_SHEET_PATH& a, const SCH_SHEET_PATH& b ) -> bool
1155 {
1156 // Find the divergence point in the paths
1157 size_t common_len = 0;
1158 size_t min_len = std::min( a.size(), b.size() );
1159
1160 while( common_len < min_len && a.at( common_len )->m_Uuid == b.at( common_len )->m_Uuid )
1161 common_len++;
1162
1163 // If one path is a prefix of the other, the shorter one comes first
1164 // This ensures parents come before children
1165 if( common_len == a.size() )
1166 return true; // a is a prefix of b - a is the parent
1167 if( common_len == b.size() )
1168 return false; // b is a prefix of a - b is the parent
1169
1170 // Paths diverge at common_len
1171 // If they share the same parent, sort by page number
1172 // This ensures siblings are sorted by page number
1173 SCH_SHEET* sheet_a = a.at( common_len );
1174 SCH_SHEET* sheet_b = b.at( common_len );
1175
1176 // Create partial paths to get to these sheets for page number comparison
1177 KIID_PATH ancestor;
1178 for( size_t i = 0; i < common_len; i++ )
1179 ancestor.push_back( a.at( i )->m_Uuid );
1180
1181 // Compare page numbers - use the last sheet's page number
1182 wxString page_a = sheet_a->getPageNumber( ancestor );
1183 wxString page_b = sheet_b->getPageNumber( ancestor );
1184
1185 int retval = SCH_SHEET::ComparePageNum( page_a, page_b );
1186
1187 if( retval != 0 )
1188 return retval < 0;
1189
1190 // If page numbers are the same, use virtual page numbers as a tie-breaker
1192 return true;
1193 else if( a.GetVirtualPageNumber() > b.GetVirtualPageNumber() )
1194 return false;
1195
1196 // Finally, use UUIDs for stable ordering when everything else is equal
1197 return a.GetCurrentHash() < b.GetCurrentHash();
1198 } );
1199
1200 if( aUpdateVirtualPageNums )
1201 {
1202 int virtualPageNum = 1;
1203
1204 for( SCH_SHEET_PATH& sheet : *this )
1205 sheet.SetVirtualPageNumber( virtualPageNum++ );
1206 }
1207}
1208
1209
1210void SCH_SHEET_LIST::SortByPageNumbers( bool aUpdateVirtualPageNums )
1211{
1212 for( const SCH_SHEET_PATH& path : *this )
1213 path.CachePageNumber();
1214
1215 std::sort( begin(), end(),
1216 []( const SCH_SHEET_PATH& a, const SCH_SHEET_PATH& b ) -> bool
1217 {
1219 b.GetCachedPageNumber() );
1220
1221 if( retval < 0 )
1222 return true;
1223 else if( retval > 0 )
1224 return false;
1225
1227 return true;
1228 else if( a.GetVirtualPageNumber() > b.GetVirtualPageNumber() )
1229 return false;
1230
1231 // Enforce strict ordering. If the page numbers are the same, use UUIDs
1232 return a.GetCurrentHash() < b.GetCurrentHash();
1233 } );
1234
1235 if( aUpdateVirtualPageNums )
1236 {
1237 int virtualPageNum = 1;
1238
1239 for( SCH_SHEET_PATH& sheet : *this )
1240 sheet.SetVirtualPageNumber( virtualPageNum++ );
1241 }
1242}
1243
1244
1245bool SCH_SHEET_LIST::NameExists( const wxString& aSheetName ) const
1246{
1247 for( const SCH_SHEET_PATH& sheet : *this )
1248 {
1249 if( sheet.Last()->GetName() == aSheetName )
1250 return true;
1251 }
1252
1253 return false;
1254}
1255
1256
1257bool SCH_SHEET_LIST::PageNumberExists( const wxString& aPageNumber ) const
1258{
1259 for( const SCH_SHEET_PATH& sheet : *this )
1260 {
1261 if( sheet.GetPageNumber() == aPageNumber )
1262 return true;
1263 }
1264
1265 return false;
1266}
1267
1268
1269void SCH_SHEET_LIST::TrimToPageNumbers( const std::vector<wxString>& aPageInclusions )
1270{
1271 auto it = std::remove_if( begin(), end(),
1272 [&]( const SCH_SHEET_PATH& sheet )
1273 {
1274 return std::find( aPageInclusions.begin(),
1275 aPageInclusions.end(),
1276 sheet.GetPageNumber() ) == aPageInclusions.end();
1277 } );
1278
1279 erase( it, end() );
1280}
1281
1282
1284{
1285 wxString pageNumber;
1286
1287 // Find the next available page number by checking all existing page numbers
1288 std::set<int> usedPageNumbers;
1289
1290 for( const SCH_SHEET_PATH& path : *this )
1291 {
1292 wxString existingPageNum = path.GetPageNumber();
1293 long pageNum = 0;
1294
1295 if( existingPageNum.ToLong( &pageNum ) && pageNum > 0 )
1296 usedPageNumbers.insert( static_cast<int>( pageNum ) );
1297 }
1298
1299 // Find the first available number starting from 1
1300 int nextAvailable = 1;
1301
1302 while( usedPageNumbers.count( nextAvailable ) > 0 )
1303 nextAvailable++;
1304
1305 pageNumber.Printf( wxT( "%d" ), nextAvailable );
1306 return pageNumber;
1307}
1308
1309
1311{
1312 for( const SCH_SHEET_PATH& sheet : *this )
1313 {
1314 if( sheet.LastScreen() && sheet.LastScreen()->IsContentModified() )
1315 return true;
1316 }
1317
1318 return false;
1319}
1320
1321
1323{
1324 for( const SCH_SHEET_PATH& sheet : *this )
1325 {
1326 if( sheet.LastScreen() )
1327 sheet.LastScreen()->SetContentModified( false );
1328 }
1329}
1330
1331
1332SCH_ITEM* SCH_SHEET_LIST::ResolveItem( const KIID& aID, SCH_SHEET_PATH* aPathOut, bool aAllowNullptrReturn ) const
1333{
1334 for( const SCH_SHEET_PATH& sheet : *this )
1335 {
1336 SCH_ITEM* item = sheet.ResolveItem( aID );
1337
1338 if( item )
1339 {
1340 if( aPathOut )
1341 *aPathOut = sheet;
1342
1343 return item;
1344 }
1345 }
1346
1347 // Not found; weak reference has been deleted.
1348 if( aAllowNullptrReturn )
1349 return nullptr;
1350 else
1352}
1353
1354
1356{
1357 for( SCH_ITEM* aItem : LastScreen()->Items() )
1358 {
1359 if( aItem->m_Uuid == aID )
1360 return aItem;
1361
1362 SCH_ITEM* childMatch = nullptr;
1363
1364 aItem->RunOnChildren(
1365 [&]( SCH_ITEM* aChild )
1366 {
1367 if( aChild->m_Uuid == aID )
1368 childMatch = aChild;
1369 },
1371
1372 if( childMatch )
1373 return childMatch;
1374 }
1375
1376 return nullptr;
1377}
1378
1379
1380void SCH_SHEET_LIST::FillItemMap( std::map<KIID, EDA_ITEM*>& aMap )
1381{
1382 for( const SCH_SHEET_PATH& sheet : *this )
1383 {
1384 SCH_SCREEN* screen = sheet.LastScreen();
1385
1386 for( SCH_ITEM* aItem : screen->Items() )
1387 {
1388 aMap[ aItem->m_Uuid ] = aItem;
1389
1390 aItem->RunOnChildren(
1391 [&]( SCH_ITEM* aChild )
1392 {
1393 aMap[ aChild->m_Uuid ] = aChild;
1394 },
1396 }
1397 }
1398}
1399
1400
1402{
1403 // List of reference for power symbols
1404 SCH_REFERENCE_LIST references;
1405
1406 // Map of locked symbols (not used, but needed by Annotate()
1407 SCH_MULTI_UNIT_REFERENCE_MAP lockedSymbols;
1408
1409 // Build the list of power symbols:
1410 for( SCH_SHEET_PATH& sheet : *this )
1411 {
1412 for( SCH_ITEM* item : sheet.LastScreen()->Items().OfType( SCH_SYMBOL_T ) )
1413 {
1414 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
1415 LIB_SYMBOL* libSymbol = symbol->GetLibSymbolRef().get();
1416
1417 if( libSymbol && libSymbol->IsPower() )
1418 {
1419 SCH_REFERENCE schReference( symbol, sheet );
1420 references.AddItem( schReference );
1421 }
1422 }
1423 }
1424
1425 // Find duplicate, and silently clear annotation of duplicate
1426 std::map<wxString, int> ref_list; // stores the existing references
1427
1428 for( unsigned ii = 0; ii< references.GetCount(); ++ii )
1429 {
1430 wxString curr_ref = references[ii].GetRef();
1431
1432 if( curr_ref.IsEmpty() )
1433 continue;
1434
1435 if( ref_list.find( curr_ref ) == ref_list.end() )
1436 {
1437 ref_list[curr_ref] = ii;
1438 continue;
1439 }
1440
1441 // Possible duplicate, if the ref ends by a number:
1442 if( curr_ref.Last() < '0' && curr_ref.Last() > '9' )
1443 continue; // not annotated
1444
1445 // Duplicate: clear annotation by removing the number ending the ref
1446 while( !curr_ref.IsEmpty() && curr_ref.Last() >= '0' && curr_ref.Last() <= '9' )
1447 curr_ref.RemoveLast();
1448
1449 references[ii].SetRef( curr_ref );
1450 }
1451
1452 // Break full symbol reference into name (prefix) and number:
1453 // example: IC1 become IC, and 1
1454 references.SplitReferences();
1455
1456 // Ensure all power symbols have the reference starting by '#'
1457 // (Not sure this is really useful)
1458 for( unsigned ii = 0; ii< references.GetCount(); ++ii )
1459 {
1460 SCH_REFERENCE& ref_unit = references[ii];
1461
1462 if( ref_unit.GetRef()[0] != '#' )
1463 {
1464 wxString new_ref = "#" + ref_unit.GetRef();
1465 ref_unit.SetRef( new_ref );
1466 ref_unit.SetRefNum( ii );
1467 }
1468 }
1469}
1470
1471
1473 bool aForceIncludeOrphanSymbols ) const
1474{
1475 for( const SCH_SHEET_PATH& sheet : *this )
1476 sheet.GetSymbols( aReferences, aSymbolFilter, aForceIncludeOrphanSymbols );
1477}
1478
1479
1481 SYMBOL_FILTER aSymbolFilter, bool aForceIncludeOrphanSymbols ) const
1482{
1483 for( const SCH_SHEET_PATH& sheet : *this )
1484 {
1485 if( sheet.IsContainedWithin( aSheetPath ) )
1486 sheet.GetSymbols( aReferences, aSymbolFilter, aForceIncludeOrphanSymbols );
1487 }
1488}
1489
1490
1491void SCH_SHEET_LIST::GetSheetsWithinPath( std::vector<SCH_SHEET_PATH>& aSheets,
1492 const SCH_SHEET_PATH& aSheetPath ) const
1493{
1494 for( const SCH_SHEET_PATH& sheet : *this )
1495 {
1496 if( sheet.IsContainedWithin( aSheetPath ) )
1497 aSheets.push_back( sheet );
1498 }
1499}
1500
1501
1502std::optional<SCH_SHEET_PATH> SCH_SHEET_LIST::GetSheetPathByKIIDPath( const KIID_PATH& aPath,
1503 bool aIncludeLastSheet ) const
1504{
1505 for( const SCH_SHEET_PATH& sheet : *this )
1506 {
1507 KIID_PATH testPath = sheet.Path();
1508
1509 if( !aIncludeLastSheet )
1510 testPath.pop_back();
1511
1512 if( testPath == aPath )
1513 return SCH_SHEET_PATH( sheet );
1514 }
1515
1516 return std::nullopt;
1517}
1518
1519
1521{
1522 for( auto it = begin(); it != end(); ++it )
1523 {
1525 ( *it ).GetMultiUnitSymbols( tempMap, aSymbolFilter );
1526
1527 for( SCH_MULTI_UNIT_REFERENCE_MAP::value_type& pair : tempMap )
1528 {
1529 // Merge this list into the main one
1530 unsigned n_refs = pair.second.GetCount();
1531
1532 for( unsigned thisRef = 0; thisRef < n_refs; ++thisRef )
1533 aRefList[pair.first].AddItem( pair.second[thisRef] );
1534 }
1535 }
1536}
1537
1538
1539bool SCH_SHEET_LIST::TestForRecursion( const SCH_SHEET_LIST& aSrcSheetHierarchy,
1540 const wxString& aDestFileName )
1541{
1542 if( empty() )
1543 return false;
1544
1545 SCHEMATIC* sch = at( 0 ).LastScreen()->Schematic();
1546
1547 wxCHECK_MSG( sch, false, "No SCHEMATIC found in SCH_SHEET_LIST::TestForRecursion!" );
1548
1549 wxFileName rootFn = sch->GetFileName();
1550 wxFileName destFn = aDestFileName;
1551
1552 if( destFn.IsRelative() )
1553 destFn.MakeAbsolute( rootFn.GetPath() );
1554
1555 // Test each SCH_SHEET_PATH in this SCH_SHEET_LIST for potential recursion.
1556 for( unsigned i = 0; i < size(); i++ )
1557 {
1558 // Test each SCH_SHEET_PATH in the source sheet.
1559 for( unsigned j = 0; j < aSrcSheetHierarchy.size(); j++ )
1560 {
1561 const SCH_SHEET_PATH* sheetPath = &aSrcSheetHierarchy[j];
1562
1563 for( unsigned k = 0; k < sheetPath->size(); k++ )
1564 {
1565 if( at( i ).TestForRecursion( sheetPath->GetSheet( k )->GetFileName(),
1566 aDestFileName ) )
1567 {
1568 return true;
1569 }
1570 }
1571 }
1572 }
1573
1574 // The source sheet file can safely be added to the destination sheet file.
1575 return false;
1576}
1577
1578
1580{
1581 for( SCH_SHEET_PATH& path : *this )
1582 {
1583 if( path.Path() == aPath->Path() )
1584 return &path;
1585 }
1586
1587 return nullptr;
1588}
1589
1590
1592{
1593 for( SCH_SHEET_PATH& sheetpath : *this )
1594 {
1595 if( sheetpath.LastScreen() == aScreen )
1596 return sheetpath;
1597 }
1598
1599 return SCH_SHEET_PATH();
1600}
1601
1602
1604{
1605 SCH_SHEET_LIST retval;
1606
1607 for( const SCH_SHEET_PATH& sheetpath : *this )
1608 {
1609 if( sheetpath.LastScreen() == aScreen )
1610 retval.push_back( sheetpath );
1611 }
1612
1613 return retval;
1614}
1615
1616
1618 const std::vector<SCH_SYMBOL_INSTANCE>& aSymbolInstances )
1619{
1620 for( SCH_SHEET_PATH& sheetPath : *this )
1621 {
1622 for( SCH_ITEM* item : sheetPath.LastScreen()->Items().OfType( SCH_SYMBOL_T ) )
1623 {
1624 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
1625
1626 wxCHECK2( symbol, continue );
1627
1628 KIID_PATH sheetPathWithSymbolUuid = sheetPath.Path();
1629 sheetPathWithSymbolUuid.push_back( symbol->m_Uuid );
1630
1631 auto it = std::find_if( aSymbolInstances.begin(), aSymbolInstances.end(),
1632 [ sheetPathWithSymbolUuid ]( const SCH_SYMBOL_INSTANCE& r ) -> bool
1633 {
1634 return sheetPathWithSymbolUuid == r.m_Path;
1635 } );
1636
1637 if( it == aSymbolInstances.end() )
1638 {
1639 wxLogTrace( traceSchSheetPaths, "No symbol instance found for symbol '%s'",
1640 sheetPathWithSymbolUuid.AsString() );
1641 continue;
1642 }
1643
1644 // Symbol instance paths are stored and looked up in memory with the root path so use
1645 // the full path here.
1646 symbol->AddHierarchicalReference( sheetPath.Path(), it->m_Reference, it->m_Unit );
1647 symbol->GetField( FIELD_T::REFERENCE )->SetText( it->m_Reference );
1648
1649 if( !it->m_Value.IsEmpty() )
1650 symbol->SetValueFieldText( it->m_Value );
1651
1652 if( !it->m_Footprint.IsEmpty() )
1653 symbol->SetFootprintFieldText( it->m_Footprint );
1654
1655 symbol->UpdatePrefix();
1656 }
1657 }
1658}
1659
1660
1661void SCH_SHEET_LIST::UpdateSheetInstanceData( const std::vector<SCH_SHEET_INSTANCE>& aSheetInstances )
1662{
1663
1664 for( SCH_SHEET_PATH& path : *this )
1665 {
1666 SCH_SHEET* sheet = path.Last();
1667
1668 wxCHECK2( sheet && path.Last(), continue );
1669
1670 auto it = std::find_if( aSheetInstances.begin(), aSheetInstances.end(),
1671 [&path]( const SCH_SHEET_INSTANCE& r ) -> bool
1672 {
1673 return path.Path() == r.m_Path;
1674 } );
1675
1676 if( it == aSheetInstances.end() )
1677 {
1678 wxLogTrace( traceSchSheetPaths, "No sheet instance found for path '%s'",
1679 path.Path().AsString() );
1680 continue;
1681 }
1682
1683 wxLogTrace( traceSchSheetPaths, "Setting sheet '%s' instance '%s' page number '%s'",
1684 ( sheet->GetName().IsEmpty() ) ? wxString( wxT( "root" ) ) : sheet->GetName(),
1685 path.Path().AsString(), it->m_PageNumber );
1686 path.SetPageNumber( it->m_PageNumber );
1687 }
1688}
1689
1690
1691std::vector<KIID_PATH> SCH_SHEET_LIST::GetPaths() const
1692{
1693 std::vector<KIID_PATH> paths;
1694
1695 for( const SCH_SHEET_PATH& sheetPath : *this )
1696 paths.emplace_back( sheetPath.Path() );
1697
1698 return paths;
1699}
1700
1701
1702std::vector<SCH_SHEET_INSTANCE> SCH_SHEET_LIST::GetSheetInstances() const
1703{
1704 std::vector<SCH_SHEET_INSTANCE> retval;
1705
1706 for( const SCH_SHEET_PATH& path : *this )
1707 {
1708 const SCH_SHEET* sheet = path.Last();
1709
1710 wxCHECK2( sheet, continue );
1711
1712 SCH_SHEET_INSTANCE instance;
1713 SCH_SHEET_PATH tmpPath = path;
1714
1715 tmpPath.pop_back();
1716 instance.m_Path = tmpPath.Path();
1717 instance.m_PageNumber = path.GetPageNumber();
1718
1719 retval.push_back( std::move( instance ) );
1720 }
1721
1722 return retval;
1723}
1724
1725
1727{
1728 for( const SCH_SHEET_PATH& instance : *this )
1729 {
1730 if( !instance.GetPageNumber().IsEmpty() )
1731 return false;
1732 }
1733
1734 return true;
1735}
1736
1737
1739{
1740 // Don't accidentally renumber existing sheets.
1741 wxCHECK( AllSheetPageNumbersEmpty(), /* void */ );
1742
1743 wxString tmp;
1744 int pageNumber = 1;
1745
1746 for( SCH_SHEET_PATH& instance : *this )
1747 {
1748 if( instance.Last()->IsVirtualRootSheet() )
1749 continue;
1750
1751 tmp.Printf( "%d", pageNumber );
1752 instance.SetPageNumber( tmp );
1753 pageNumber += 1;
1754 }
1755}
1756
1757
1759{
1760 // A page number is claimed by the first sheet in the list that uses it. Any sheet with an
1761 // empty page number, or one repeating a number an earlier sheet already claimed, is reassigned
1762 // to the lowest unused positive integer. The stored string is compared as-is, so custom
1763 // schemes (e.g. "A", "1.1") are preserved when unique. Every distinct existing page number is
1764 // reserved up front so a reassignment never steals a number a later, non-conflicting sheet
1765 // already holds.
1766 std::set<wxString> reservedPageIds;
1767
1768 for( const SCH_SHEET_PATH& instance : *this )
1769 {
1770 if( instance.Last()->IsVirtualRootSheet() )
1771 continue;
1772
1773 const wxString pageNumber = instance.GetPageNumber();
1774
1775 if( !pageNumber.IsEmpty() )
1776 reservedPageIds.insert( pageNumber );
1777 }
1778
1779 std::set<wxString> assignedPageIds;
1780 bool modified = false;
1781 long nextPage = 1;
1782
1783 for( SCH_SHEET_PATH& instance : *this )
1784 {
1785 if( instance.Last()->IsVirtualRootSheet() )
1786 continue;
1787
1788 const wxString pageNumber = instance.GetPageNumber();
1789
1790 // Keep the first sheet to claim a given page number.
1791 if( !pageNumber.IsEmpty() && assignedPageIds.insert( pageNumber ).second )
1792 continue;
1793
1794 wxString pageStr = wxString::Format( wxT( "%ld" ), nextPage );
1795
1796 while( reservedPageIds.count( pageStr ) || assignedPageIds.count( pageStr ) )
1797 {
1798 nextPage++;
1799 pageStr = wxString::Format( wxT( "%ld" ), nextPage );
1800 }
1801
1802 instance.SetPageNumber( pageStr );
1803 assignedPageIds.insert( pageStr );
1804 nextPage++;
1805 modified = true;
1806 }
1807
1808 return modified;
1809}
1810
1811
1813 const wxString& aProjectName )
1814{
1815 for( SCH_SHEET_PATH& sheetPath : *this )
1816 sheetPath.AddNewSymbolInstances( aPrefixSheetPath, aProjectName );
1817}
1818
1819
1821{
1822 for( SCH_SHEET_PATH& sheetPath : *this )
1823 sheetPath.RemoveSymbolInstances( aPrefixSheetPath );
1824}
1825
1826
1828 int aLastVirtualPageNumber )
1829{
1830 wxString pageNumber;
1831 int lastUsedPageNumber = 1;
1832 int nextVirtualPageNumber = aLastVirtualPageNumber;
1833
1834 // Fetch the list of page numbers already in use.
1835 std::vector< wxString > usedPageNumbers;
1836
1837 if( aPrefixSheetPath.size() )
1838 {
1839 SCH_SHEET_LIST prefixHierarchy( aPrefixSheetPath.at( 0 ) );
1840
1841 for( const SCH_SHEET_PATH& path : prefixHierarchy )
1842 {
1843 pageNumber = path.GetPageNumber();
1844
1845 if( !pageNumber.IsEmpty() )
1846 usedPageNumbers.emplace_back( pageNumber );
1847 }
1848 }
1849
1850 for( SCH_SHEET_PATH& sheetPath : *this )
1851 {
1852 KIID_PATH tmp = sheetPath.Path();
1853 SCH_SHEET_PATH newSheetPath( aPrefixSheetPath );
1854
1855 // Prefix the new hierarchical path.
1856 newSheetPath = newSheetPath + sheetPath;
1857
1858 // Sheets cannot have themselves in the path.
1859 tmp.pop_back();
1860
1861 SCH_SHEET* sheet = sheetPath.Last();
1862
1863 wxCHECK2( sheet, continue );
1864
1865 nextVirtualPageNumber += 1;
1866
1867 SCH_SHEET_INSTANCE instance;
1868
1869 // Add the instance if it doesn't already exist
1870 if( !sheet->getInstance( instance, tmp, true ) )
1871 {
1872 sheet->addInstance( tmp );
1873 sheet->getInstance( instance, tmp, true );
1874 }
1875
1876 // Get a new page number if we don't have one
1877 if( instance.m_PageNumber.IsEmpty() )
1878 {
1879 // Generate the next available page number.
1880 do
1881 {
1882 pageNumber.Printf( wxT( "%d" ), lastUsedPageNumber );
1883 lastUsedPageNumber += 1;
1884 } while( std::find( usedPageNumbers.begin(), usedPageNumbers.end(), pageNumber ) !=
1885 usedPageNumbers.end() );
1886
1887 instance.m_PageNumber = pageNumber;
1888 newSheetPath.SetVirtualPageNumber( nextVirtualPageNumber );
1889 }
1890
1891 newSheetPath.SetPageNumber( instance.m_PageNumber );
1892 usedPageNumbers.push_back( instance.m_PageNumber );
1893 }
1894}
1895
1896
1897void SCH_SHEET_LIST::CheckForMissingSymbolInstances( const wxString& aProjectName )
1898{
1899 wxLogTrace( traceSchSheetPaths,
1900 "SCH_SHEET_LIST::CheckForMissingSymbolInstances: Processing %zu sheet paths",
1901 size() );
1902
1903 for( SCH_SHEET_PATH& sheetPath : *this )
1904 {
1905 wxLogTrace( traceSchSheetPaths,
1906 " Processing sheet path: '%s' (size=%zu, KIID_PATH='%s')",
1907 sheetPath.PathHumanReadable( false ),
1908 sheetPath.size(),
1909 sheetPath.Path().AsString() );
1910 sheetPath.CheckForMissingSymbolInstances( aProjectName );
1911 }
1912}
1913
1914
1916{
1917 int lastVirtualPageNumber = 1;
1918
1919 for( const SCH_SHEET_PATH& sheetPath : *this )
1920 {
1921 if( sheetPath.GetVirtualPageNumber() > lastVirtualPageNumber )
1922 lastVirtualPageNumber = sheetPath.GetVirtualPageNumber();
1923 }
1924
1925 return lastVirtualPageNumber;
1926}
1927
1928
1929bool SCH_SHEET_LIST::HasPath( const KIID_PATH& aPath ) const
1930{
1931 for( const SCH_SHEET_PATH& path : *this )
1932 {
1933 if( path.Path() == aPath )
1934 return true;
1935 }
1936
1937 return false;
1938}
1939
1940
1941bool SCH_SHEET_LIST::ContainsSheet( const SCH_SHEET* aSheet ) const
1942{
1943 for( const SCH_SHEET_PATH& path : *this )
1944 {
1945 for( size_t i = 0; i < path.size(); i++ )
1946 {
1947 if( path.at( i ) == aSheet )
1948 return true;
1949 }
1950 }
1951
1952 return false;
1953}
1954
1955
1956std::optional<SCH_SHEET_PATH> SCH_SHEET_LIST::GetOrdinalPath( const SCH_SCREEN* aScreen ) const
1957{
1958 // Sheet paths with sheets that do not have a screen object are not valid.
1959 if( !aScreen )
1960 return std::nullopt;
1961
1962 for( const SCH_SHEET_PATH& path: *this )
1963 {
1964 if( path.LastScreen() == aScreen )
1965 return std::optional<SCH_SHEET_PATH>( path );
1966 }
1967
1968 return std::nullopt;
1969}
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:597
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:342
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:119
bool IsPower() const override
int GetUnitCount() const override
Holds all the data relating to one schematic.
Definition schematic.h:148
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:138
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:165
virtual void RunOnChildren(const std::function< void(SCH_ITEM *)> &aFunction, RECURSE_MODE aMode)
Definition sch_item.h:641
SCHEMATIC * Schematic() const
Search the item hierarchy to find a SCHEMATIC.
Definition sch_item.cpp:281
int GetUnit() const
Definition sch_item.h:237
virtual void SetUnit(int aUnit)
Definition sch_item.h:236
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:118
const wxString & GetFileName() const
Definition sch_screen.h:153
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:171
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.
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.
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:390
wxString GetFileName() const
Return the filename corresponding to this sheet.
Definition sch_sheet.h:384
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:475
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:75
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:134
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:183
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:89
@ INTERNAL
Definition common.h:92
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:70
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:683