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, you may find one here:
20 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
21 * or you may search the http://www.gnu.org website for the version 2 license,
22 * or you may write to the Free Software Foundation, Inc.,
23 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
24 */
25
26#include <refdes_utils.h>
27#include <hash.h>
28#include <sch_screen.h>
29#include <sch_marker.h>
30#include <sch_label.h>
31#include <sch_shape.h>
32#include <symbol_library.h>
33#include <sch_sheet_path.h>
34#include <sch_symbol.h>
35#include <sch_sheet.h>
36#include <schematic.h>
37#include <template_fieldnames.h>
38#include <trace_helpers.h>
39
40#include <wx/filename.h>
41#include <wx/log.h>
42
43
50{
51public:
53 SCH_ITEM( nullptr, NOT_USED )
54 {}
55
56 wxString GetItemDescription( UNITS_PROVIDER* aUnitsProvider, bool aFull ) const override
57 {
58 return _( "(Deleted Item)" );
59 }
60
61 wxString GetClass() const override
62 {
63 return wxT( "DELETED_SHEET_ITEM" );
64 }
65
67 {
68 static DELETED_SHEET_ITEM* item = nullptr;
69
70 if( !item )
71 item = new DELETED_SHEET_ITEM();
72
73 return item;
74 }
75
76 // pure virtuals:
77 void SetPosition( const VECTOR2I& ) override {}
78 void Move( const VECTOR2I& aMoveVector ) override {}
79 void MirrorHorizontally( int aCenter ) override {}
80 void MirrorVertically( int aCenter ) override {}
81 void Rotate( const VECTOR2I& aCenter, bool aRotateCCW ) override {}
82
83 double Similarity( const SCH_ITEM& aOther ) const override
84 {
85 return 0.0;
86 }
87
88 bool operator==( const SCH_ITEM& aOther ) const override
89 {
90 return false;
91 }
92
93#if defined(DEBUG)
94 void Show( int , std::ostream& ) const override {}
95#endif
96};
97
98
99namespace std
100{
102 {
103 return path.GetCurrentHash();
104 }
105}
106
107
113
114
116{
117 initFromOther( aOther );
118}
119
120
122{
123 initFromOther( aOther );
124 return *this;
125}
126
127
128// Move assignment operator
130{
131 m_sheets = std::move( aOther.m_sheets );
132
133 m_virtualPageNumber = aOther.m_virtualPageNumber;
134 m_current_hash = aOther.m_current_hash;
135 m_cached_page_number = aOther.m_cached_page_number;
136
137 m_recursion_test_cache = std::move( aOther.m_recursion_test_cache );
138
139 return *this;
140}
141
142
144{
145 SCH_SHEET_PATH retv = *this;
146
147 size_t size = aOther.size();
148
149 for( size_t i = 0; i < size; i++ )
150 retv.push_back( aOther.at( i ) );
151
152 return retv;
153}
154
155
157{
158 m_sheets = aOther.m_sheets;
162
163 // Note: don't copy m_recursion_test_cache as it is slow and we want std::vector<SCH_SHEET_PATH>
164 // to be very fast to construct for use in the connectivity algorithm.
166}
167
168
170{
171 // The root sheet path is empty. All other sheet paths must start with the root sheet path.
172 return ( m_sheets.size() == 0 ) || ( GetSheet( 0 )->IsRootSheet() );
173}
174
175
177{
178 m_current_hash = 0;
179
180 for( SCH_SHEET* sheet : m_sheets )
181 hash_combine( m_current_hash, sheet->m_Uuid.Hash() );
182}
183
184
185int SCH_SHEET_PATH::Cmp( const SCH_SHEET_PATH& aSheetPathToTest ) const
186{
187 if( size() > aSheetPathToTest.size() )
188 return 1;
189
190 if( size() < aSheetPathToTest.size() )
191 return -1;
192
193 // otherwise, same number of sheets.
194 for( unsigned i = 0; i < size(); i++ )
195 {
196 if( at( i )->m_Uuid < aSheetPathToTest.at( i )->m_Uuid )
197 return -1;
198
199 if( at( i )->m_Uuid != aSheetPathToTest.at( i )->m_Uuid )
200 return 1;
201 }
202
203 return 0;
204}
205
206
207int SCH_SHEET_PATH::ComparePageNum( const SCH_SHEET_PATH& aSheetPathToTest ) const
208{
209 wxString pageA = this->GetPageNumber();
210 wxString pageB = aSheetPathToTest.GetPageNumber();
211
212 int pageNumComp = SCH_SHEET::ComparePageNum( pageA, pageB );
213
214 if( pageNumComp == 0 )
215 {
216 int virtualPageA = GetVirtualPageNumber();
217 int virtualPageB = aSheetPathToTest.GetVirtualPageNumber();
218
219 if( virtualPageA > virtualPageB )
220 pageNumComp = 1;
221 else if( virtualPageA < virtualPageB )
222 pageNumComp = -1;
223 }
224
225 return pageNumComp;
226}
227
228
229bool SCH_SHEET_PATH::IsContainedWithin( const SCH_SHEET_PATH& aSheetPathToTest ) const
230{
231 if( aSheetPathToTest.size() > size() )
232 return false;
233
234 for( size_t i = 0; i < aSheetPathToTest.size(); ++i )
235 {
236 if( at( i )->m_Uuid != aSheetPathToTest.at( i )->m_Uuid )
237 {
238 wxLogTrace( traceSchSheetPaths, "Sheet path '%s' is not within path '%s'.",
239 aSheetPathToTest.Path().AsString(), Path().AsString() );
240
241 return false;
242 }
243 }
244
245 wxLogTrace( traceSchSheetPaths, "Sheet path '%s' is within path '%s'.",
246 aSheetPathToTest.Path().AsString(), Path().AsString() );
247
248 return true;
249}
250
251
253{
254 if( !empty() )
255 return m_sheets.back();
256
257 return nullptr;
258}
259
260
262{
263 SCH_SHEET* lastSheet = Last();
264
265 if( lastSheet )
266 return lastSheet->GetScreen();
267
268 return nullptr;
269}
270
271
273{
274 SCH_SHEET* lastSheet = Last();
275
276 if( lastSheet )
277 return lastSheet->GetScreen();
278
279 return nullptr;
280}
281
282
284{
285 for( SCH_SHEET* sheet : m_sheets )
286 {
287 if( sheet->GetExcludedFromSim() )
288 return true;
289 }
290
291 return false;
292}
293
294
296{
297 for( SCH_SHEET* sheet : m_sheets )
298 {
299 if( sheet->GetExcludedFromBOM() )
300 return true;
301 }
302
303 return false;
304}
305
306
308{
309 for( SCH_SHEET* sheet : m_sheets )
310 {
311 if( sheet->GetExcludedFromBoard() )
312 return true;
313 }
314
315 return false;
316}
317
318
320{
321 for( SCH_SHEET* sheet : m_sheets )
322 {
323 if( sheet->GetDNP() )
324 return true;
325 }
326
327 return false;
328}
329
330
332{
333 wxString s;
334
335 s = wxT( "/" ); // This is the root path
336
337 // Start at 1 to avoid the root sheet, which does not need to be added to the path.
338 // Its timestamp changes anyway.
339 for( unsigned i = 1; i < size(); i++ )
340 s += at( i )->m_Uuid.AsString() + "/";
341
342 return s;
343}
344
345
347{
349 path.reserve( m_sheets.size() );
350
351 for( const SCH_SHEET* sheet : m_sheets )
352 path.push_back( sheet->m_Uuid );
353
354 return path;
355}
356
357
358wxString SCH_SHEET_PATH::PathHumanReadable( bool aUseShortRootName,
359 bool aStripTrailingSeparator ) const
360{
361 wxString s;
362
363 if( aUseShortRootName )
364 {
365 s = wxS( "/" ); // Use only the short name in netlists
366 }
367 else
368 {
369 wxString fileName;
370
371 if( !empty() && at( 0 )->GetScreen() )
372 fileName = at( 0 )->GetScreen()->GetFileName();
373
374 wxFileName fn = fileName;
375
376 s = fn.GetName() + wxS( "/" );
377 }
378
379 // Start at 1 since we've already processed the root sheet.
380 for( unsigned i = 1; i < size(); i++ )
381 s << at( i )->GetField( FIELD_T::SHEET_NAME )->GetShownText( false ) << wxS( "/" );
382
383 if( aStripTrailingSeparator && s.EndsWith( "/" ) )
384 s = s.Left( s.length() - 1 );
385
386 return s;
387}
388
389
391{
392 std::vector<SCH_ITEM*> items;
393
394 std::copy_if( LastScreen()->Items().begin(), LastScreen()->Items().end(),
395 std::back_inserter( items ),
396 []( SCH_ITEM* aItem )
397 {
398 return ( aItem->Type() == SCH_SYMBOL_T
399 || aItem->Type() == SCH_GLOBAL_LABEL_T
400 || aItem->Type() == SCH_SHAPE_T );
401 } );
402
403 for( SCH_ITEM* item : items )
404 {
405 if( item->Type() == SCH_SYMBOL_T )
406 {
407 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
408
409 symbol->GetField( FIELD_T::REFERENCE )->SetText( symbol->GetRef( this ) );
410 symbol->SetUnit( symbol->GetUnitSelection( this ) );
411 LastScreen()->Update( item, false );
412 }
413 else if( item->Type() == SCH_GLOBAL_LABEL_T )
414 {
415 SCH_GLOBALLABEL* label = static_cast<SCH_GLOBALLABEL*>( item );
416
417 if( label->GetFields().size() > 0 ) // Possible when reading a legacy .sch schematic
418 {
419 SCH_FIELD* intersheetRefs = label->GetField( FIELD_T::INTERSHEET_REFS );
420
421 // Fixup for legacy files which didn't store a position for the intersheet refs
422 // unless they were shown.
423 if( intersheetRefs->GetPosition() == VECTOR2I() && !intersheetRefs->IsVisible() )
425
426 intersheetRefs->SetVisible( label->Schematic()->Settings().m_IntersheetRefsShow );
427 LastScreen()->Update( intersheetRefs );
428 }
429 }
430 else if( item->Type() == SCH_SHAPE_T )
431 {
432 SCH_SHAPE* shape = static_cast<SCH_SHAPE*>( item );
433 shape->UpdateHatching();
434 }
435 }
436}
437
438
439void SCH_SHEET_PATH::GetSymbols( SCH_REFERENCE_LIST& aReferences, bool aIncludePowerSymbols,
440 bool aForceIncludeOrphanSymbols ) const
441{
442 for( SCH_ITEM* item : LastScreen()->Items().OfType( SCH_SYMBOL_T ) )
443 {
444 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
445 AppendSymbol( aReferences, symbol, aIncludePowerSymbols, aForceIncludeOrphanSymbols );
446 }
447}
448
449
451 bool aIncludePowerSymbols,
452 bool aForceIncludeOrphanSymbols ) const
453{
454 // Skip pseudo-symbols, which have a reference starting with #. This mainly
455 // affects power symbols.
456 if( aIncludePowerSymbols || aSymbol->GetRef( this )[0] != wxT( '#' ) )
457 {
458 if( aSymbol->GetLibSymbolRef() || aForceIncludeOrphanSymbols )
459 {
460 SCH_REFERENCE schReference( aSymbol, *this );
461
462 schReference.SetSheetNumber( GetPageNumberAsInt() );
463 aReferences.AddItem( schReference );
464 }
465 }
466}
467
468
470 bool aIncludePowerSymbols ) const
471{
472 for( SCH_ITEM* item : LastScreen()->Items().OfType( SCH_SYMBOL_T ) )
473 {
474 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
475 AppendMultiUnitSymbol( aRefList, symbol, aIncludePowerSymbols );
476 }
477}
478
479
481 SCH_SYMBOL* aSymbol,
482 bool aIncludePowerSymbols ) const
483{
484 // Skip pseudo-symbols, which have a reference starting with #. This mainly
485 // affects power symbols.
486 if( !aIncludePowerSymbols && aSymbol->GetRef( this )[0] == wxT( '#' ) )
487 return;
488
489 LIB_SYMBOL* symbol = aSymbol->GetLibSymbolRef().get();
490
491 if( symbol && symbol->GetUnitCount() > 1 )
492 {
493 SCH_REFERENCE schReference = SCH_REFERENCE( aSymbol, *this );
494 schReference.SetSheetNumber( GetPageNumberAsInt() );
495 wxString reference_str = schReference.GetRef();
496
497 // Never lock unassigned references
498 if( reference_str[reference_str.Len() - 1] == '?' )
499 return;
500
501 aRefList[reference_str].AddItem( schReference );
502 }
503}
504
505
507{
508 return m_current_hash == d1.GetCurrentHash();
509}
510
511
512bool SCH_SHEET_PATH::TestForRecursion( const wxString& aSrcFileName, const wxString& aDestFileName )
513{
514 auto pair = std::make_pair( aSrcFileName, aDestFileName );
515
516 if( m_recursion_test_cache.count( pair ) )
517 return m_recursion_test_cache.at( pair );
518
519 SCHEMATIC* sch = LastScreen()->Schematic();
520
521 wxCHECK_MSG( sch, false, "No SCHEMATIC found in SCH_SHEET_PATH::TestForRecursion!" );
522
523 wxFileName rootFn = sch->GetFileName();
524 wxFileName srcFn = aSrcFileName;
525 wxFileName destFn = aDestFileName;
526
527 if( srcFn.IsRelative() )
528 srcFn.MakeAbsolute( rootFn.GetPath() );
529
530 if( destFn.IsRelative() )
531 destFn.MakeAbsolute( rootFn.GetPath() );
532
533 // The source and destination sheet file names cannot be the same.
534 if( srcFn == destFn )
535 {
536 m_recursion_test_cache[pair] = true;
537 return true;
538 }
539
543 unsigned i = 0;
544
545 while( i < size() )
546 {
547 wxFileName cmpFn = at( i )->GetFileName();
548
549 if( cmpFn.IsRelative() )
550 cmpFn.MakeAbsolute( rootFn.GetPath() );
551
552 // Test if the file name of the destination sheet is in anywhere in this sheet path.
553 if( cmpFn == destFn )
554 break;
555
556 i++;
557 }
558
559 // The destination sheet file name was not found in the sheet path or the destination
560 // sheet file name is the root sheet so no recursion is possible.
561 if( i >= size() || i == 0 )
562 {
563 m_recursion_test_cache[pair] = false;
564 return false;
565 }
566
567 // Walk back up to the root sheet to see if the source file name is already a parent in
568 // the sheet path. If so, recursion will occur.
569 do
570 {
571 i -= 1;
572
573 wxFileName cmpFn = at( i )->GetFileName();
574
575 if( cmpFn.IsRelative() )
576 cmpFn.MakeAbsolute( rootFn.GetPath() );
577
578 if( cmpFn == srcFn )
579 {
580 m_recursion_test_cache[pair] = true;
581 return true;
582 }
583
584 } while( i != 0 );
585
586 // The source sheet file name is not a parent of the destination sheet file name.
587 m_recursion_test_cache[pair] = false;
588 return false;
589}
590
591
593{
594 SCH_SHEET* sheet = Last();
595
596 wxCHECK( sheet, wxEmptyString );
597
598 KIID_PATH tmpPath = Path();
599 tmpPath.pop_back();
600
601 return sheet->getPageNumber( tmpPath );
602}
603
605{
606 long page;
607 wxString pageStr = GetPageNumber();
608
609 if( pageStr.ToLong( &page ) )
610 return (int) page;
611
612 return GetVirtualPageNumber();
613}
614
615
616void SCH_SHEET_PATH::SetPageNumber( const wxString& aPageNumber )
617{
618 SCH_SHEET* sheet = Last();
619
620 wxCHECK( sheet, /* void */ );
621
622 KIID_PATH tmpPath = Path();
623
624 tmpPath.pop_back();
625
626 sheet->addInstance( tmpPath );
627 sheet->setPageNumber( tmpPath, aPageNumber );
628}
629
630
632 const wxString& aProjectName )
633{
634 wxCHECK( !aProjectName.IsEmpty(), /* void */ );
635
636 SCH_SHEET_PATH newSheetPath( aPrefixSheetPath );
637 SCH_SHEET_PATH currentSheetPath( *this );
638
639 // Prefix the new hierarchical path.
640 newSheetPath = newSheetPath + currentSheetPath;
641
642 for( SCH_ITEM* item : LastScreen()->Items().OfType( SCH_SYMBOL_T ) )
643 {
644 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
645
646 wxCHECK2( symbol, continue );
647
648 SCH_SYMBOL_INSTANCE newSymbolInstance;
649
650 if( symbol->GetInstance( newSymbolInstance, Path(), true ) )
651 {
652 newSymbolInstance.m_ProjectName = aProjectName;
653
654 // Use an existing symbol instance for this path if it exists.
655 newSymbolInstance.m_Path = newSheetPath.Path();
656 symbol->AddHierarchicalReference( newSymbolInstance );
657 }
658 else if( !symbol->GetInstances().empty() )
659 {
660 newSymbolInstance.m_ProjectName = aProjectName;
661
662 // Use the first symbol instance if any symbol instance data exists.
663 newSymbolInstance = symbol->GetInstances()[0];
664 newSymbolInstance.m_Path = newSheetPath.Path();
665 symbol->AddHierarchicalReference( newSymbolInstance );
666 }
667 else
668 {
669 newSymbolInstance.m_ProjectName = aProjectName;
670
671 // Fall back to the last saved symbol field and unit settings if there is no
672 // instance data.
673 newSymbolInstance.m_Path = newSheetPath.Path();
674 newSymbolInstance.m_Reference = symbol->GetField( FIELD_T::REFERENCE )->GetText();
675 newSymbolInstance.m_Unit = symbol->GetUnit();
676 symbol->AddHierarchicalReference( newSymbolInstance );
677 }
678 }
679}
680
681
683{
684 for( SCH_ITEM* item : LastScreen()->Items().OfType( SCH_SYMBOL_T ) )
685 {
686 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
687
688 wxCHECK2( symbol, continue );
689
690 SCH_SHEET_PATH fullSheetPath( aPrefixSheetPath );
691 SCH_SHEET_PATH currentSheetPath( *this );
692
693 // Prefix the hierarchical path of the symbol instance to be removed.
694 fullSheetPath = fullSheetPath + currentSheetPath;
695 symbol->RemoveInstance( fullSheetPath );
696 }
697}
698
699
700void SCH_SHEET_PATH::CheckForMissingSymbolInstances( const wxString& aProjectName )
701{
702 wxCHECK( !aProjectName.IsEmpty() && LastScreen(), /* void */ );
703
704 for( SCH_ITEM* item : LastScreen()->Items().OfType( SCH_SYMBOL_T ) )
705 {
706 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
707
708 wxCHECK2( symbol, continue );
709
710 SCH_SYMBOL_INSTANCE symbolInstance;
711
712 if( !symbol->GetInstance( symbolInstance, Path() ) )
713 {
714 wxLogTrace( traceSchSheetPaths, "Adding missing symbol \"%s\" instance data for "
715 "sheet path '%s'.",
716 symbol->m_Uuid.AsString(), PathHumanReadable( false ) );
717
718 // Legacy schematics that are not shared do not contain separate instance data.
719 // The symbol reference and unit are saved in the reference field and unit entries.
720 if( ( LastScreen()->GetRefCount() <= 1 ) &&
721 ( LastScreen()->GetFileFormatVersionAtLoad() <= 20200310 ) )
722 {
723 SCH_FIELD* refField = symbol->GetField( FIELD_T::REFERENCE );
724 symbolInstance.m_Reference = refField->GetShownText( this, true );
725 symbolInstance.m_Unit = symbol->GetUnit();
726 }
727 else
728 {
729 // When schematics are shared, we cannot know which instance the current symbol
730 // reference field and unit belong to. In this case, we clear the reference
731 // annotation and set the unit to 1.
732 symbolInstance.m_Reference = UTIL::GetRefDesUnannotated( symbol->GetPrefix() );
733 }
734
735 symbolInstance.m_ProjectName = aProjectName;
736 symbolInstance.m_Path = Path();
737 symbol->AddHierarchicalReference( symbolInstance );
738 }
739 }
740}
741
742
744{
745 wxCHECK( m_sheets.size() > 1, /* void */ );
746
747 wxFileName sheetFileName = Last()->GetFileName();
748
749 // If the sheet file name is absolute, then the user requested is so don't make it relative.
750 if( sheetFileName.IsAbsolute() )
751 return;
752
753 SCH_SCREEN* screen = LastScreen();
754 SCH_SCREEN* parentScreen = m_sheets[ m_sheets.size() - 2 ]->GetScreen();
755
756 wxCHECK( screen && parentScreen, /* void */ );
757
758 wxFileName fileName = screen->GetFileName();
759 wxFileName parentFileName = parentScreen->GetFileName();
760
761 // SCH_SCREEN file names must be absolute. If they are not, someone set them incorrectly
762 // on load or on creation.
763 wxCHECK( fileName.IsAbsolute() && parentFileName.IsAbsolute(), /* void */ );
764
765 if( fileName.GetPath() == parentFileName.GetPath() )
766 {
767 Last()->SetFileName( fileName.GetFullName() );
768 }
769 else if( fileName.MakeRelativeTo( parentFileName.GetPath() ) )
770 {
771 Last()->SetFileName( fileName.GetFullPath() );
772 }
773 else
774 {
775 Last()->SetFileName( screen->GetFileName() );
776 }
777
778 wxLogTrace( tracePathsAndFiles,
779 wxT( "\n File name: '%s'"
780 "\n parent file name '%s',"
781 "\n sheet '%s' file name '%s'." ),
782 screen->GetFileName(), parentScreen->GetFileName(), PathHumanReadable(),
783 Last()->GetFileName() );
784}
785
786
788{
789 if( aSheet != nullptr )
790 BuildSheetList( aSheet, false );
791}
792
793
794void SCH_SHEET_LIST::BuildSheetList( SCH_SHEET* aSheet, bool aCheckIntegrity )
795{
796 if( !aSheet )
797 return;
798
799 std::vector<SCH_SHEET*> badSheets;
800
801 m_currentSheetPath.push_back( aSheet );
802 m_currentSheetPath.SetVirtualPageNumber( static_cast<int>( size() ) + 1 );
803 push_back( m_currentSheetPath );
804
805 if( m_currentSheetPath.LastScreen() )
806 {
807 wxString parentFileName = aSheet->GetFileName();
808 std::vector<SCH_ITEM*> childSheets;
809 m_currentSheetPath.LastScreen()->GetSheets( &childSheets );
810
811 for( SCH_ITEM* item : childSheets )
812 {
813 SCH_SHEET* sheet = static_cast<SCH_SHEET*>( item );
814
815 if( aCheckIntegrity )
816 {
817 if( !m_currentSheetPath.TestForRecursion( sheet->GetFileName(), parentFileName ) )
818 BuildSheetList( sheet, true );
819 else
820 badSheets.push_back( sheet );
821 }
822 else
823 {
824 // If we are not performing a full recursion test, at least check if we are in
825 // a simple recursion scenario to prevent stack overflow crashes
826 wxCHECK2_MSG( sheet->GetFileName() != aSheet->GetFileName(), continue,
827 wxT( "Recursion prevented in SCH_SHEET_LIST::BuildSheetList" ) );
828
829 BuildSheetList( sheet, false );
830 }
831 }
832 }
833
834 if( aCheckIntegrity )
835 {
836 for( SCH_SHEET* sheet : badSheets )
837 {
838 m_currentSheetPath.LastScreen()->Remove( sheet );
839 m_currentSheetPath.LastScreen()->SetContentModified();
840 }
841 }
842
843 m_currentSheetPath.pop_back();
844}
845
846
847void SCH_SHEET_LIST::SortByHierarchicalPageNumbers( bool aUpdateVirtualPageNums )
848{
849 for( const SCH_SHEET_PATH& path : *this )
850 path.CachePageNumber();
851
852 std::sort( begin(), end(),
853 []( const SCH_SHEET_PATH& a, const SCH_SHEET_PATH& b ) -> bool
854 {
855 // Find the divergence point in the paths
856 size_t common_len = 0;
857 size_t min_len = std::min( a.size(), b.size() );
858
859 while( common_len < min_len && a.at( common_len )->m_Uuid == b.at( common_len )->m_Uuid )
860 common_len++;
861
862 // If one path is a prefix of the other, the shorter one comes first
863 // This ensures parents come before children
864 if( common_len == a.size() )
865 return true; // a is a prefix of b - a is the parent
866 if( common_len == b.size() )
867 return false; // b is a prefix of a - b is the parent
868
869 // Paths diverge at common_len
870 // If they share the same parent, sort by page number
871 // This ensures siblings are sorted by page number
872 SCH_SHEET* sheet_a = a.at( common_len );
873 SCH_SHEET* sheet_b = b.at( common_len );
874
875 // Create partial paths to get to these sheets for page number comparison
876 KIID_PATH ancestor;
877 for( size_t i = 0; i < common_len; i++ )
878 ancestor.push_back( a.at( i )->m_Uuid );
879
880 // Compare page numbers - use the last sheet's page number
881 wxString page_a = sheet_a->getPageNumber( ancestor );
882 wxString page_b = sheet_b->getPageNumber( ancestor );
883
884 int retval = SCH_SHEET::ComparePageNum( page_a, page_b );
885
886 if( retval != 0 )
887 return retval < 0;
888
889 // If page numbers are the same, use virtual page numbers as a tie-breaker
891 return true;
892 else if( a.GetVirtualPageNumber() > b.GetVirtualPageNumber() )
893 return false;
894
895 // Finally, use UUIDs for stable ordering when everything else is equal
896 return a.GetCurrentHash() < b.GetCurrentHash();
897 } );
898
899 if( aUpdateVirtualPageNums )
900 {
901 int virtualPageNum = 1;
902
903 for( SCH_SHEET_PATH& sheet : *this )
904 sheet.SetVirtualPageNumber( virtualPageNum++ );
905 }
906}
907
908
909void SCH_SHEET_LIST::SortByPageNumbers( bool aUpdateVirtualPageNums )
910{
911 for( const SCH_SHEET_PATH& path : *this )
912 path.CachePageNumber();
913
914 std::sort( begin(), end(),
915 []( const SCH_SHEET_PATH& a, const SCH_SHEET_PATH& b ) -> bool
916 {
919
920 if( retval < 0 )
921 return true;
922 else if( retval > 0 )
923 return false;
924
926 return true;
927 else if( a.GetVirtualPageNumber() > b.GetVirtualPageNumber() )
928 return false;
929
930 // Enforce strict ordering. If the page numbers are the same, use UUIDs
931 return a.GetCurrentHash() < b.GetCurrentHash();
932 } );
933
934 if( aUpdateVirtualPageNums )
935 {
936 int virtualPageNum = 1;
937
938 for( SCH_SHEET_PATH& sheet : *this )
939 sheet.SetVirtualPageNumber( virtualPageNum++ );
940 }
941}
942
943
944bool SCH_SHEET_LIST::NameExists( const wxString& aSheetName ) const
945{
946 for( const SCH_SHEET_PATH& sheet : *this )
947 {
948 if( sheet.Last()->GetName() == aSheetName )
949 return true;
950 }
951
952 return false;
953}
954
955
956bool SCH_SHEET_LIST::PageNumberExists( const wxString& aPageNumber ) const
957{
958 for( const SCH_SHEET_PATH& sheet : *this )
959 {
960 if( sheet.GetPageNumber() == aPageNumber )
961 return true;
962 }
963
964 return false;
965}
966
967
968void SCH_SHEET_LIST::TrimToPageNumbers( const std::vector<wxString>& aPageInclusions )
969{
970 auto it = std::remove_if( begin(), end(),
971 [&]( const SCH_SHEET_PATH& sheet )
972 {
973 return std::find( aPageInclusions.begin(),
974 aPageInclusions.end(),
975 sheet.GetPageNumber() ) == aPageInclusions.end();
976 } );
977
978 erase( it, end() );
979}
980
981
983{
984 for( const SCH_SHEET_PATH& sheet : *this )
985 {
986 if( sheet.LastScreen() && sheet.LastScreen()->IsContentModified() )
987 return true;
988 }
989
990 return false;
991}
992
993
995{
996 for( const SCH_SHEET_PATH& sheet : *this )
997 {
998 if( sheet.LastScreen() )
999 sheet.LastScreen()->SetContentModified( false );
1000 }
1001}
1002
1003
1004SCH_ITEM* SCH_SHEET_LIST::ResolveItem( const KIID& aID, SCH_SHEET_PATH* aPathOut, bool aAllowNullptrReturn ) const
1005{
1006 for( const SCH_SHEET_PATH& sheet : *this )
1007 {
1008 SCH_ITEM* item = sheet.ResolveItem( aID );
1009
1010 if( item )
1011 {
1012 if( aPathOut )
1013 *aPathOut = sheet;
1014
1015 return item;
1016 }
1017 }
1018
1019 // Not found; weak reference has been deleted.
1020 if( aAllowNullptrReturn )
1021 return nullptr;
1022 else
1024}
1025
1026
1028{
1029 for( SCH_ITEM* aItem : LastScreen()->Items() )
1030 {
1031 if( aItem->m_Uuid == aID )
1032 return aItem;
1033
1034 SCH_ITEM* childMatch = nullptr;
1035
1036 aItem->RunOnChildren(
1037 [&]( SCH_ITEM* aChild )
1038 {
1039 if( aChild->m_Uuid == aID )
1040 childMatch = aChild;
1041 },
1043
1044 if( childMatch )
1045 return childMatch;
1046 }
1047
1048 return nullptr;
1049}
1050
1051
1052void SCH_SHEET_LIST::FillItemMap( std::map<KIID, EDA_ITEM*>& aMap )
1053{
1054 for( const SCH_SHEET_PATH& sheet : *this )
1055 {
1056 SCH_SCREEN* screen = sheet.LastScreen();
1057
1058 for( SCH_ITEM* aItem : screen->Items() )
1059 {
1060 aMap[ aItem->m_Uuid ] = aItem;
1061
1062 aItem->RunOnChildren(
1063 [&]( SCH_ITEM* aChild )
1064 {
1065 aMap[ aChild->m_Uuid ] = aChild;
1066 },
1068 }
1069 }
1070}
1071
1072
1074{
1075 // List of reference for power symbols
1076 SCH_REFERENCE_LIST references;
1077 SCH_REFERENCE_LIST additionalreferences; // Todo: add as a parameter to this function
1078
1079 // Map of locked symbols (not used, but needed by Annotate()
1080 SCH_MULTI_UNIT_REFERENCE_MAP lockedSymbols;
1081
1082 // Build the list of power symbols:
1083 for( SCH_SHEET_PATH& sheet : *this )
1084 {
1085 for( SCH_ITEM* item : sheet.LastScreen()->Items().OfType( SCH_SYMBOL_T ) )
1086 {
1087 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
1088 LIB_SYMBOL* libSymbol = symbol->GetLibSymbolRef().get();
1089
1090 if( libSymbol && libSymbol->IsPower() )
1091 {
1092 SCH_REFERENCE schReference( symbol, sheet );
1093 references.AddItem( schReference );
1094 }
1095 }
1096 }
1097
1098 // Find duplicate, and silently clear annotation of duplicate
1099 std::map<wxString, int> ref_list; // stores the existing references
1100
1101 for( unsigned ii = 0; ii< references.GetCount(); ++ii )
1102 {
1103 wxString curr_ref = references[ii].GetRef();
1104
1105 if( curr_ref.IsEmpty() )
1106 continue;
1107
1108 if( ref_list.find( curr_ref ) == ref_list.end() )
1109 {
1110 ref_list[curr_ref] = ii;
1111 continue;
1112 }
1113
1114 // Possible duplicate, if the ref ends by a number:
1115 if( curr_ref.Last() < '0' && curr_ref.Last() > '9' )
1116 continue; // not annotated
1117
1118 // Duplicate: clear annotation by removing the number ending the ref
1119 while( !curr_ref.IsEmpty() && curr_ref.Last() >= '0' && curr_ref.Last() <= '9' )
1120 curr_ref.RemoveLast();
1121
1122 references[ii].SetRef( curr_ref );
1123 }
1124
1125 // Break full symbol reference into name (prefix) and number:
1126 // example: IC1 become IC, and 1
1127 references.SplitReferences();
1128
1129 // Ensure all power symbols have the reference starting by '#'
1130 // (Not sure this is really useful)
1131 for( unsigned ii = 0; ii< references.GetCount(); ++ii )
1132 {
1133 SCH_REFERENCE& ref_unit = references[ii];
1134
1135 if( ref_unit.GetRef()[0] != '#' )
1136 {
1137 wxString new_ref = "#" + ref_unit.GetRef();
1138 ref_unit.SetRef( new_ref );
1139 ref_unit.SetRefNum( ii );
1140 }
1141 }
1142}
1143
1144
1145void SCH_SHEET_LIST::GetSymbols( SCH_REFERENCE_LIST& aReferences, bool aIncludePowerSymbols,
1146 bool aForceIncludeOrphanSymbols ) const
1147{
1148 for( const SCH_SHEET_PATH& sheet : *this )
1149 sheet.GetSymbols( aReferences, aIncludePowerSymbols, aForceIncludeOrphanSymbols );
1150}
1151
1152
1154 const SCH_SHEET_PATH& aSheetPath,
1155 bool aIncludePowerSymbols,
1156 bool aForceIncludeOrphanSymbols ) const
1157{
1158 for( const SCH_SHEET_PATH& sheet : *this )
1159 {
1160 if( sheet.IsContainedWithin( aSheetPath ) )
1161 sheet.GetSymbols( aReferences, aIncludePowerSymbols, aForceIncludeOrphanSymbols );
1162 }
1163}
1164
1165
1166void SCH_SHEET_LIST::GetSheetsWithinPath( std::vector<SCH_SHEET_PATH>& aSheets,
1167 const SCH_SHEET_PATH& aSheetPath ) const
1168{
1169 for( const SCH_SHEET_PATH& sheet : *this )
1170 {
1171 if( sheet.IsContainedWithin( aSheetPath ) )
1172 aSheets.push_back( sheet );
1173 }
1174}
1175
1176
1177std::optional<SCH_SHEET_PATH> SCH_SHEET_LIST::GetSheetPathByKIIDPath( const KIID_PATH& aPath,
1178 bool aIncludeLastSheet ) const
1179{
1180 for( const SCH_SHEET_PATH& sheet : *this )
1181 {
1182 KIID_PATH testPath = sheet.Path();
1183
1184 if( !aIncludeLastSheet )
1185 testPath.pop_back();
1186
1187 if( testPath == aPath )
1188 return SCH_SHEET_PATH( sheet );
1189 }
1190
1191 return std::nullopt;
1192}
1193
1194
1196 bool aIncludePowerSymbols ) const
1197{
1198 for( auto it = begin(); it != end(); ++it )
1199 {
1201 ( *it ).GetMultiUnitSymbols( tempMap, aIncludePowerSymbols );
1202
1203 for( SCH_MULTI_UNIT_REFERENCE_MAP::value_type& pair : tempMap )
1204 {
1205 // Merge this list into the main one
1206 unsigned n_refs = pair.second.GetCount();
1207
1208 for( unsigned thisRef = 0; thisRef < n_refs; ++thisRef )
1209 aRefList[pair.first].AddItem( pair.second[thisRef] );
1210 }
1211 }
1212}
1213
1214
1215bool SCH_SHEET_LIST::TestForRecursion( const SCH_SHEET_LIST& aSrcSheetHierarchy,
1216 const wxString& aDestFileName )
1217{
1218 if( empty() )
1219 return false;
1220
1221 SCHEMATIC* sch = at( 0 ).LastScreen()->Schematic();
1222
1223 wxCHECK_MSG( sch, false, "No SCHEMATIC found in SCH_SHEET_LIST::TestForRecursion!" );
1224
1225 wxFileName rootFn = sch->GetFileName();
1226 wxFileName destFn = aDestFileName;
1227
1228 if( destFn.IsRelative() )
1229 destFn.MakeAbsolute( rootFn.GetPath() );
1230
1231 // Test each SCH_SHEET_PATH in this SCH_SHEET_LIST for potential recursion.
1232 for( unsigned i = 0; i < size(); i++ )
1233 {
1234 // Test each SCH_SHEET_PATH in the source sheet.
1235 for( unsigned j = 0; j < aSrcSheetHierarchy.size(); j++ )
1236 {
1237 const SCH_SHEET_PATH* sheetPath = &aSrcSheetHierarchy[j];
1238
1239 for( unsigned k = 0; k < sheetPath->size(); k++ )
1240 {
1241 if( at( i ).TestForRecursion( sheetPath->GetSheet( k )->GetFileName(),
1242 aDestFileName ) )
1243 {
1244 return true;
1245 }
1246 }
1247 }
1248 }
1249
1250 // The source sheet file can safely be added to the destination sheet file.
1251 return false;
1252}
1253
1254
1256{
1257 for( SCH_SHEET_PATH& path : *this )
1258 {
1259 if( path.Path() == aPath->Path() )
1260 return &path;
1261 }
1262
1263 return nullptr;
1264}
1265
1266
1268{
1269 for( SCH_SHEET_PATH& sheetpath : *this )
1270 {
1271 if( sheetpath.LastScreen() == aScreen )
1272 return sheetpath;
1273 }
1274
1275 return SCH_SHEET_PATH();
1276}
1277
1278
1280{
1281 SCH_SHEET_LIST retval;
1282
1283 for( const SCH_SHEET_PATH& sheetpath : *this )
1284 {
1285 if( sheetpath.LastScreen() == aScreen )
1286 retval.push_back( sheetpath );
1287 }
1288
1289 return retval;
1290}
1291
1292
1294 const std::vector<SCH_SYMBOL_INSTANCE>& aSymbolInstances )
1295{
1296 for( SCH_SHEET_PATH& sheetPath : *this )
1297 {
1298 for( SCH_ITEM* item : sheetPath.LastScreen()->Items().OfType( SCH_SYMBOL_T ) )
1299 {
1300 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
1301
1302 wxCHECK2( symbol, continue );
1303
1304 KIID_PATH sheetPathWithSymbolUuid = sheetPath.Path();
1305 sheetPathWithSymbolUuid.push_back( symbol->m_Uuid );
1306
1307 auto it = std::find_if( aSymbolInstances.begin(), aSymbolInstances.end(),
1308 [ sheetPathWithSymbolUuid ]( const SCH_SYMBOL_INSTANCE& r ) -> bool
1309 {
1310 return sheetPathWithSymbolUuid == r.m_Path;
1311 } );
1312
1313 if( it == aSymbolInstances.end() )
1314 {
1315 wxLogTrace( traceSchSheetPaths, "No symbol instance found for symbol '%s'",
1316 sheetPathWithSymbolUuid.AsString() );
1317 continue;
1318 }
1319
1320 // Symbol instance paths are stored and looked up in memory with the root path so use
1321 // the full path here.
1322 symbol->AddHierarchicalReference( sheetPath.Path(), it->m_Reference, it->m_Unit );
1323 symbol->GetField( FIELD_T::REFERENCE )->SetText( it->m_Reference );
1324
1325 if( !it->m_Value.IsEmpty() )
1326 symbol->SetValueFieldText( it->m_Value );
1327
1328 if( !it->m_Footprint.IsEmpty() )
1329 symbol->SetFootprintFieldText( it->m_Footprint );
1330
1331 symbol->UpdatePrefix();
1332 }
1333 }
1334}
1335
1336
1337void SCH_SHEET_LIST::UpdateSheetInstanceData( const std::vector<SCH_SHEET_INSTANCE>& aSheetInstances )
1338{
1339
1340 for( SCH_SHEET_PATH& path : *this )
1341 {
1342 SCH_SHEET* sheet = path.Last();
1343
1344 wxCHECK2( sheet && path.Last(), continue );
1345
1346 auto it = std::find_if( aSheetInstances.begin(), aSheetInstances.end(),
1347 [&path]( const SCH_SHEET_INSTANCE& r ) -> bool
1348 {
1349 return path.Path() == r.m_Path;
1350 } );
1351
1352 if( it == aSheetInstances.end() )
1353 {
1354 wxLogTrace( traceSchSheetPaths, "No sheet instance found for path '%s'",
1355 path.Path().AsString() );
1356 continue;
1357 }
1358
1359 wxLogTrace( traceSchSheetPaths, "Setting sheet '%s' instance '%s' page number '%s'",
1360 ( sheet->GetName().IsEmpty() ) ? wxString( wxT( "root" ) ) : sheet->GetName(),
1361 path.Path().AsString(), it->m_PageNumber );
1362 path.SetPageNumber( it->m_PageNumber );
1363 }
1364}
1365
1366
1367std::vector<KIID_PATH> SCH_SHEET_LIST::GetPaths() const
1368{
1369 std::vector<KIID_PATH> paths;
1370
1371 for( const SCH_SHEET_PATH& sheetPath : *this )
1372 paths.emplace_back( sheetPath.Path() );
1373
1374 return paths;
1375}
1376
1377
1378std::vector<SCH_SHEET_INSTANCE> SCH_SHEET_LIST::GetSheetInstances() const
1379{
1380 std::vector<SCH_SHEET_INSTANCE> retval;
1381
1382 for( const SCH_SHEET_PATH& path : *this )
1383 {
1384 const SCH_SHEET* sheet = path.Last();
1385
1386 wxCHECK2( sheet, continue );
1387
1388 SCH_SHEET_INSTANCE instance;
1389 SCH_SHEET_PATH tmpPath = path;
1390
1391 tmpPath.pop_back();
1392 instance.m_Path = tmpPath.Path();
1393 instance.m_PageNumber = path.GetPageNumber();
1394
1395 retval.push_back( std::move( instance ) );
1396 }
1397
1398 return retval;
1399}
1400
1401
1403{
1404 for( const SCH_SHEET_PATH& instance : *this )
1405 {
1406 if( !instance.GetPageNumber().IsEmpty() )
1407 return false;
1408 }
1409
1410 return true;
1411}
1412
1413
1415{
1416 // Don't accidentally renumber existing sheets.
1417 wxCHECK( AllSheetPageNumbersEmpty(), /* void */ );
1418
1419 wxString tmp;
1420 int pageNumber = 1;
1421
1422 for( SCH_SHEET_PATH& instance : *this )
1423 {
1424 tmp.Printf( "%d", pageNumber );
1425 instance.SetPageNumber( tmp );
1426 pageNumber += 1;
1427 }
1428}
1429
1430
1432 const wxString& aProjectName )
1433{
1434 for( SCH_SHEET_PATH& sheetPath : *this )
1435 sheetPath.AddNewSymbolInstances( aPrefixSheetPath, aProjectName );
1436}
1437
1438
1440{
1441 for( SCH_SHEET_PATH& sheetPath : *this )
1442 sheetPath.RemoveSymbolInstances( aPrefixSheetPath );
1443}
1444
1445
1447 int aLastVirtualPageNumber )
1448{
1449 wxString pageNumber;
1450 int lastUsedPageNumber = 1;
1451 int nextVirtualPageNumber = aLastVirtualPageNumber;
1452
1453 // Fetch the list of page numbers already in use.
1454 std::vector< wxString > usedPageNumbers;
1455
1456 if( aPrefixSheetPath.size() )
1457 {
1458 SCH_SHEET_LIST prefixHierarchy( aPrefixSheetPath.at( 0 ) );
1459
1460 for( const SCH_SHEET_PATH& path : prefixHierarchy )
1461 {
1462 pageNumber = path.GetPageNumber();
1463
1464 if( !pageNumber.IsEmpty() )
1465 usedPageNumbers.emplace_back( pageNumber );
1466 }
1467 }
1468
1469 for( SCH_SHEET_PATH& sheetPath : *this )
1470 {
1471 KIID_PATH tmp = sheetPath.Path();
1472 SCH_SHEET_PATH newSheetPath( aPrefixSheetPath );
1473
1474 // Prefix the new hierarchical path.
1475 newSheetPath = newSheetPath + sheetPath;
1476
1477 // Sheets cannot have themselves in the path.
1478 tmp.pop_back();
1479
1480 SCH_SHEET* sheet = sheetPath.Last();
1481
1482 wxCHECK2( sheet, continue );
1483
1484 nextVirtualPageNumber += 1;
1485
1486 SCH_SHEET_INSTANCE instance;
1487
1488 // Add the instance if it doesn't already exist
1489 if( !sheet->getInstance( instance, tmp, true ) )
1490 {
1491 sheet->addInstance( tmp );
1492 sheet->getInstance( instance, tmp, true );
1493 }
1494
1495 // Get a new page number if we don't have one
1496 if( instance.m_PageNumber.IsEmpty() )
1497 {
1498 // Generate the next available page number.
1499 do
1500 {
1501 pageNumber.Printf( wxT( "%d" ), lastUsedPageNumber );
1502 lastUsedPageNumber += 1;
1503 } while( std::find( usedPageNumbers.begin(), usedPageNumbers.end(), pageNumber ) !=
1504 usedPageNumbers.end() );
1505
1506 instance.m_PageNumber = pageNumber;
1507 newSheetPath.SetVirtualPageNumber( nextVirtualPageNumber );
1508 }
1509
1510 newSheetPath.SetPageNumber( instance.m_PageNumber );
1511 usedPageNumbers.push_back( instance.m_PageNumber );
1512 }
1513}
1514
1515
1516void SCH_SHEET_LIST::CheckForMissingSymbolInstances( const wxString& aProjectName )
1517{
1518 for( SCH_SHEET_PATH& sheetPath : *this )
1519 sheetPath.CheckForMissingSymbolInstances( aProjectName );
1520}
1521
1522
1524{
1525 int lastVirtualPageNumber = 1;
1526
1527 for( const SCH_SHEET_PATH& sheetPath : *this )
1528 {
1529 if( sheetPath.GetVirtualPageNumber() > lastVirtualPageNumber )
1530 lastVirtualPageNumber = sheetPath.GetVirtualPageNumber();
1531 }
1532
1533 return lastVirtualPageNumber;
1534}
1535
1536
1537bool SCH_SHEET_LIST::HasPath( const KIID_PATH& aPath ) const
1538{
1539 for( const SCH_SHEET_PATH& path : *this )
1540 {
1541 if( path.Path() == aPath )
1542 return true;
1543 }
1544
1545 return false;
1546}
1547
1548
1549bool SCH_SHEET_LIST::ContainsSheet( const SCH_SHEET* aSheet ) const
1550{
1551 for( const SCH_SHEET_PATH& path : *this )
1552 {
1553 for( size_t i = 0; i < path.size(); i++ )
1554 {
1555 if( path.at( i ) == aSheet )
1556 return true;
1557 }
1558 }
1559
1560 return false;
1561}
1562
1563
1564std::optional<SCH_SHEET_PATH> SCH_SHEET_LIST::GetOrdinalPath( const SCH_SCREEN* aScreen ) const
1565{
1566 // Sheet paths with sheets that do not have a screen object are not valid.
1567 if( !aScreen )
1568 return std::nullopt;
1569
1570 for( const SCH_SHEET_PATH& path: *this )
1571 {
1572 if( path.LastScreen() == aScreen )
1573 return std::optional<SCH_SHEET_PATH>( path );
1574 }
1575
1576 return std::nullopt;
1577}
bool IsContentModified() const
Definition base_screen.h:60
void SetContentModified(bool aModified=true)
Definition base_screen.h:59
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:516
KICAD_T Type() const
Returns the type of object.
Definition eda_item.h:110
virtual void UpdateHatching() const
virtual const wxString & GetText() const
Return the string associated with the text object.
Definition eda_text.h:97
virtual bool IsVisible() const
Definition eda_text.h:186
virtual void SetVisible(bool aVisible)
Definition eda_text.cpp:387
EE_TYPE OfType(KICAD_T aType) const
Definition sch_rtree.h:241
wxString AsString() const
Definition kiid.cpp:356
Definition kiid.h:49
wxString AsString() const
Definition kiid.cpp:246
Define a library symbol object.
Definition lib_symbol.h:85
bool IsPower() const override
int GetUnitCount() const override
Holds all the data relating to one schematic.
Definition schematic.h:88
wxString GetFileName() const
Helper to retrieve the filename from the root sheet screen.
SCHEMATIC_SETTINGS & Settings() const
VECTOR2I GetPosition() const override
wxString GetShownText(const SCH_SHEET_PATH *aPath, bool aAllowExtraText, 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:167
virtual void RunOnChildren(const std::function< void(SCH_ITEM *)> &aFunction, RECURSE_MODE aMode)
Definition sch_item.h:597
SCHEMATIC * Schematic() const
Search the item hierarchy to find a SCHEMATIC.
Definition sch_item.cpp:217
int GetUnit() const
Definition sch_item.h:238
virtual void SetUnit(int aUnit)
Definition sch_item.h:237
SCH_ITEM(EDA_ITEM *aParent, KICAD_T aType, int aUnit=0, int aBodyStyle=0)
Definition sch_item.cpp:51
void AutoplaceFields(SCH_SCREEN *aScreen, AUTOPLACE_ALGO aAlgo) override
std::vector< SCH_FIELD > & GetFields()
Definition sch_label.h:212
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:117
const wxString & GetFileName() const
Definition sch_screen.h:152
SCHEMATIC * Schematic() const
void Update(SCH_ITEM *aItem, bool aUpdateLibSymbol=true)
Update aItem's bounding box in the tree.
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.
void GetMultiUnitSymbols(SCH_MULTI_UNIT_REFERENCE_MAP &aRefList, bool aIncludePowerSymbols=true) const
Add a SCH_REFERENCE_LIST object to aRefList for each same-reference set of multi-unit parts in the li...
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
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.
bool AllSheetPageNumbersEmpty() const
Check all of the sheet instance for empty page numbers.
void GetSymbols(SCH_REFERENCE_LIST &aReferences, bool aIncludePowerSymbols=true, bool aForceIncludeOrphanSymbols=false) const
Add a SCH_REFERENCE object to aReferences for each symbol in the list of sheets.
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)
bool ContainsSheet(const SCH_SHEET *aSheet) const
std::vector< KIID_PATH > GetPaths() const
void GetSymbolsWithinPath(SCH_REFERENCE_LIST &aReferences, const SCH_SHEET_PATH &aSheetPath, bool aIncludePowerSymbols=true, bool aForceIncludeOrphanSymbols=false) const
Add a SCH_REFERENCE object to aReferences for each symbol in the list of sheets that are contained wi...
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...
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...
bool GetExcludedFromBOM() const
void AppendMultiUnitSymbol(SCH_MULTI_UNIT_REFERENCE_MAP &aRefList, SCH_SYMBOL *aSymbol, bool aIncludePowerSymbols=true) const
Append a SCH_REFERENCE_LIST object to aRefList based on aSymbol, storing same-reference set of multi-...
const SCH_SHEET * GetSheet(unsigned aIndex) const
bool empty() const
Forwarded method from std::vector.
void GetSymbols(SCH_REFERENCE_LIST &aReferences, bool aIncludePowerSymbols=true, bool aForceIncludeOrphanSymbols=false) const
Adds SCH_REFERENCE object to aReferences for each symbol in the sheet.
int ComparePageNum(const SCH_SHEET_PATH &aSheetPathToTest) const
Compare sheets by their page number.
size_t GetCurrentHash() const
wxString PathHumanReadable(bool aUseShortRootName=true, bool aStripTrailingSeparator=false) const
Return the sheet path in a human readable form made from the sheet names.
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.
bool IsFullPath() const
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 GetMultiUnitSymbols(SCH_MULTI_UNIT_REFERENCE_MAP &aRefList, bool aIncludePowerSymbols=true) const
Add a SCH_REFERENCE_LIST object to aRefList for each same-reference set of multi-unit parts in the sh...
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.
void AppendSymbol(SCH_REFERENCE_LIST &aReferences, SCH_SYMBOL *aSymbol, bool aIncludePowerSymbols=true, bool aForceIncludeOrphanSymbols=false) const
Append a SCH_REFERENCE object to aReferences based on aSymbol.
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.
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.
Sheet symbol placed in a schematic, and is the entry point for a sub schematic.
Definition sch_sheet.h:47
void SetFileName(const wxString &aFilename)
Definition sch_sheet.h:327
wxString GetFileName() const
Return the filename corresponding to this sheet.
Definition sch_sheet.h:321
bool IsRootSheet() const
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.
SCH_FIELD * GetField(FIELD_T aFieldType)
Return a mandatory field in this sheet.
wxString GetName() const
Definition sch_sheet.h:113
SCH_SCREEN * GetScreen() const
Definition sch_sheet.h:116
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.
Schematic symbol object.
Definition sch_symbol.h:75
void UpdatePrefix()
Set the prefix based on the current reference designator.
const std::vector< SCH_SYMBOL_INSTANCE > & GetInstances() const
Definition sch_symbol.h:134
void RemoveInstance(const SCH_SHEET_PATH &aInstancePath)
void SetValueFieldText(const wxString &aValue)
void SetFootprintFieldText(const wxString &aFootprint)
void AddHierarchicalReference(const KIID_PATH &aPath, const wxString &aRef, int aUnit)
Add a full hierarchical reference to this symbol.
bool GetInstance(SCH_SYMBOL_INSTANCE &aInstance, const KIID_PATH &aSheetPath, bool aTestFromEnd=false) const
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
const wxString GetRef(const SCH_SHEET_PATH *aSheet, bool aIncludeUnit=false) const override
wxString GetPrefix() const
Definition sch_symbol.h:235
SCH_FIELD * GetField(FIELD_T aFieldType)
Return a mandatory field in this symbol.
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:32
wxString GetRefDesUnannotated(const wxString &aSource)
Return an unannotated refdes from either a prefix or an existing refdes.
STL namespace.
Collection of utility functions for component reference designators (refdes)
@ AUTOPLACE_AUTO
Definition sch_item.h:70
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.
A simple container for sheet instance information.
A simple container for schematic symbol instance information.
size_t operator()(const SCH_SHEET_PATH &path) const
Definition for symbol library class.
@ INTERSHEET_REFS
Global label cross-reference page numbers.
@ REFERENCE
Field Reference of part, i.e. "IC21".
VECTOR2I end
wxLogTrace helper definitions.
@ SCH_SYMBOL_T
Definition typeinfo.h:174
@ SCH_SHAPE_T
Definition typeinfo.h:151
@ NOT_USED
the 3d code uses this value
Definition typeinfo.h:79
@ SCH_GLOBAL_LABEL_T
Definition typeinfo.h:170
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:695