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