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 )->GetField( FIELD_T::SHEET_NAME )->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( FIELD_T::REFERENCE )->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->GetField( FIELD_T::INTERSHEET_REFS );
404
405 // Fixup for legacy files which didn't store a position for the intersheet refs
406 // unless they were shown.
407 if( intersheetRefs->GetPosition() == VECTOR2I() && !intersheetRefs->IsVisible() )
409
410 intersheetRefs->SetVisible( label->Schematic()->Settings().m_IntersheetRefsShow );
411 LastScreen()->Update( intersheetRefs );
412 }
413 }
414 }
415}
416
417
418void SCH_SHEET_PATH::GetSymbols( SCH_REFERENCE_LIST& aReferences, bool aIncludePowerSymbols,
419 bool aForceIncludeOrphanSymbols ) const
420{
421 for( SCH_ITEM* item : LastScreen()->Items().OfType( SCH_SYMBOL_T ) )
422 {
423 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
424 AppendSymbol( aReferences, symbol, aIncludePowerSymbols, aForceIncludeOrphanSymbols );
425 }
426}
427
428
430 bool aIncludePowerSymbols,
431 bool aForceIncludeOrphanSymbols ) const
432{
433 // Skip pseudo-symbols, which have a reference starting with #. This mainly
434 // affects power symbols.
435 if( aIncludePowerSymbols || aSymbol->GetRef( this )[0] != wxT( '#' ) )
436 {
437 if( aSymbol->GetLibSymbolRef() || aForceIncludeOrphanSymbols )
438 {
439 SCH_REFERENCE schReference( aSymbol, *this );
440
441 schReference.SetSheetNumber( m_virtualPageNumber );
442 aReferences.AddItem( schReference );
443 }
444 }
445}
446
447
449 bool aIncludePowerSymbols ) const
450{
451 for( SCH_ITEM* item : LastScreen()->Items().OfType( SCH_SYMBOL_T ) )
452 {
453 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
454 AppendMultiUnitSymbol( aRefList, symbol, aIncludePowerSymbols );
455 }
456}
457
458
460 SCH_SYMBOL* aSymbol,
461 bool aIncludePowerSymbols ) const
462{
463 // Skip pseudo-symbols, which have a reference starting with #. This mainly
464 // affects power symbols.
465 if( !aIncludePowerSymbols && aSymbol->GetRef( this )[0] == wxT( '#' ) )
466 return;
467
468 LIB_SYMBOL* symbol = aSymbol->GetLibSymbolRef().get();
469
470 if( symbol && symbol->GetUnitCount() > 1 )
471 {
472 SCH_REFERENCE schReference = SCH_REFERENCE( aSymbol, *this );
473 schReference.SetSheetNumber( m_virtualPageNumber );
474 wxString reference_str = schReference.GetRef();
475
476 // Never lock unassigned references
477 if( reference_str[reference_str.Len() - 1] == '?' )
478 return;
479
480 aRefList[reference_str].AddItem( schReference );
481 }
482}
483
484
486{
487 return m_current_hash == d1.GetCurrentHash();
488}
489
490
491bool SCH_SHEET_PATH::TestForRecursion( const wxString& aSrcFileName, const wxString& aDestFileName )
492{
493 auto pair = std::make_pair( aSrcFileName, aDestFileName );
494
495 if( m_recursion_test_cache.count( pair ) )
496 return m_recursion_test_cache.at( pair );
497
498 SCHEMATIC* sch = LastScreen()->Schematic();
499
500 wxCHECK_MSG( sch, false, "No SCHEMATIC found in SCH_SHEET_PATH::TestForRecursion!" );
501
502 wxFileName rootFn = sch->GetFileName();
503 wxFileName srcFn = aSrcFileName;
504 wxFileName destFn = aDestFileName;
505
506 if( srcFn.IsRelative() )
507 srcFn.MakeAbsolute( rootFn.GetPath() );
508
509 if( destFn.IsRelative() )
510 destFn.MakeAbsolute( rootFn.GetPath() );
511
512 // The source and destination sheet file names cannot be the same.
513 if( srcFn == destFn )
514 {
515 m_recursion_test_cache[pair] = true;
516 return true;
517 }
518
522 unsigned i = 0;
523
524 while( i < size() )
525 {
526 wxFileName cmpFn = at( i )->GetFileName();
527
528 if( cmpFn.IsRelative() )
529 cmpFn.MakeAbsolute( rootFn.GetPath() );
530
531 // Test if the file name of the destination sheet is in anywhere in this sheet path.
532 if( cmpFn == destFn )
533 break;
534
535 i++;
536 }
537
538 // The destination sheet file name was not found in the sheet path or the destination
539 // sheet file name is the root sheet so no recursion is possible.
540 if( i >= size() || i == 0 )
541 {
542 m_recursion_test_cache[pair] = false;
543 return false;
544 }
545
546 // Walk back up to the root sheet to see if the source file name is already a parent in
547 // the sheet path. If so, recursion will occur.
548 do
549 {
550 i -= 1;
551
552 wxFileName cmpFn = at( i )->GetFileName();
553
554 if( cmpFn.IsRelative() )
555 cmpFn.MakeAbsolute( rootFn.GetPath() );
556
557 if( cmpFn == srcFn )
558 {
559 m_recursion_test_cache[pair] = true;
560 return true;
561 }
562
563 } while( i != 0 );
564
565 // The source sheet file name is not a parent of the destination sheet file name.
566 m_recursion_test_cache[pair] = false;
567 return false;
568}
569
570
572{
573 SCH_SHEET* sheet = Last();
574
575 wxCHECK( sheet, wxEmptyString );
576
577 KIID_PATH tmpPath = Path();
578 tmpPath.pop_back();
579
580 return sheet->getPageNumber( tmpPath );
581}
582
583
584void SCH_SHEET_PATH::SetPageNumber( const wxString& aPageNumber )
585{
586 SCH_SHEET* sheet = Last();
587
588 wxCHECK( sheet, /* void */ );
589
590 KIID_PATH tmpPath = Path();
591
592 tmpPath.pop_back();
593
594 sheet->addInstance( tmpPath );
595 sheet->setPageNumber( tmpPath, aPageNumber );
596}
597
598
600 const wxString& aProjectName )
601{
602 wxCHECK( !aProjectName.IsEmpty(), /* void */ );
603
604 SCH_SHEET_PATH newSheetPath( aPrefixSheetPath );
605 SCH_SHEET_PATH currentSheetPath( *this );
606
607 // Prefix the new hierarchical path.
608 newSheetPath = newSheetPath + currentSheetPath;
609
610 for( SCH_ITEM* item : LastScreen()->Items().OfType( SCH_SYMBOL_T ) )
611 {
612 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
613
614 wxCHECK2( symbol, continue );
615
616 SCH_SYMBOL_INSTANCE newSymbolInstance;
617
618 if( symbol->GetInstance( newSymbolInstance, Path(), true ) )
619 {
620 newSymbolInstance.m_ProjectName = aProjectName;
621
622 // Use an existing symbol instance for this path if it exists.
623 newSymbolInstance.m_Path = newSheetPath.Path();
624 symbol->AddHierarchicalReference( newSymbolInstance );
625 }
626 else if( !symbol->GetInstances().empty() )
627 {
628 newSymbolInstance.m_ProjectName = aProjectName;
629
630 // Use the first symbol instance if any symbol instance data exists.
631 newSymbolInstance = symbol->GetInstances()[0];
632 newSymbolInstance.m_Path = newSheetPath.Path();
633 symbol->AddHierarchicalReference( newSymbolInstance );
634 }
635 else
636 {
637 newSymbolInstance.m_ProjectName = aProjectName;
638
639 // Fall back to the last saved symbol field and unit settings if there is no
640 // instance data.
641 newSymbolInstance.m_Path = newSheetPath.Path();
642 newSymbolInstance.m_Reference = symbol->GetField( FIELD_T::REFERENCE )->GetText();
643 newSymbolInstance.m_Unit = symbol->GetUnit();
644 symbol->AddHierarchicalReference( newSymbolInstance );
645 }
646 }
647}
648
649
651{
652 for( SCH_ITEM* item : LastScreen()->Items().OfType( SCH_SYMBOL_T ) )
653 {
654 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
655
656 wxCHECK2( symbol, continue );
657
658 SCH_SHEET_PATH fullSheetPath( aPrefixSheetPath );
659 SCH_SHEET_PATH currentSheetPath( *this );
660
661 // Prefix the hierarchical path of the symbol instance to be removed.
662 fullSheetPath = fullSheetPath + currentSheetPath;
663 symbol->RemoveInstance( fullSheetPath );
664 }
665}
666
667
668void SCH_SHEET_PATH::CheckForMissingSymbolInstances( const wxString& aProjectName )
669{
670 wxCHECK( !aProjectName.IsEmpty() && LastScreen(), /* void */ );
671
672 for( SCH_ITEM* item : LastScreen()->Items().OfType( SCH_SYMBOL_T ) )
673 {
674 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
675
676 wxCHECK2( symbol, continue );
677
678 SCH_SYMBOL_INSTANCE symbolInstance;
679
680 if( !symbol->GetInstance( symbolInstance, Path() ) )
681 {
682 wxLogTrace( traceSchSheetPaths, "Adding missing symbol \"%s\" instance data for "
683 "sheet path '%s'.",
684 symbol->m_Uuid.AsString(), PathHumanReadable( false ) );
685
686 // Legacy schematics that are not shared do not contain separate instance data.
687 // The symbol reference and unit are saved in the reference field and unit entries.
688 if( ( LastScreen()->GetRefCount() <= 1 ) &&
689 ( LastScreen()->GetFileFormatVersionAtLoad() <= 20200310 ) )
690 {
691 SCH_FIELD* refField = symbol->GetField( FIELD_T::REFERENCE );
692 symbolInstance.m_Reference = refField->GetShownText( this, true );
693 symbolInstance.m_Unit = symbol->GetUnit();
694 }
695 else
696 {
697 // When schematics are shared, we cannot know which instance the current symbol
698 // reference field and unit belong to. In this case, we clear the reference
699 // annotation and set the unit to 1.
700 symbolInstance.m_Reference = UTIL::GetRefDesUnannotated( symbol->GetPrefix() );
701 }
702
703 symbolInstance.m_ProjectName = aProjectName;
704 symbolInstance.m_Path = Path();
705 symbol->AddHierarchicalReference( symbolInstance );
706 }
707 }
708}
709
710
712{
713 wxCHECK( m_sheets.size() > 1, /* void */ );
714
715 wxFileName sheetFileName = Last()->GetFileName();
716
717 // If the sheet file name is absolute, then the user requested is so don't make it relative.
718 if( sheetFileName.IsAbsolute() )
719 return;
720
721 SCH_SCREEN* screen = LastScreen();
722 SCH_SCREEN* parentScreen = m_sheets[ m_sheets.size() - 2 ]->GetScreen();
723
724 wxCHECK( screen && parentScreen, /* void */ );
725
726 wxFileName fileName = screen->GetFileName();
727 wxFileName parentFileName = parentScreen->GetFileName();
728
729 // SCH_SCREEN file names must be absolute. If they are not, someone set them incorrectly
730 // on load or on creation.
731 wxCHECK( fileName.IsAbsolute() && parentFileName.IsAbsolute(), /* void */ );
732
733 if( fileName.GetPath() == parentFileName.GetPath() )
734 {
735 Last()->SetFileName( fileName.GetFullName() );
736 }
737 else if( fileName.MakeRelativeTo( parentFileName.GetPath() ) )
738 {
739 Last()->SetFileName( fileName.GetFullPath() );
740 }
741 else
742 {
743 Last()->SetFileName( screen->GetFileName() );
744 }
745
746 wxLogTrace( tracePathsAndFiles,
747 wxT( "\n File name: '%s'"
748 "\n parent file name '%s',"
749 "\n sheet '%s' file name '%s'." ),
750 screen->GetFileName(), parentScreen->GetFileName(), PathHumanReadable(),
751 Last()->GetFileName() );
752}
753
754
756{
757 if( aSheet != nullptr )
758 BuildSheetList( aSheet, false );
759}
760
761
762void SCH_SHEET_LIST::BuildSheetList( SCH_SHEET* aSheet, bool aCheckIntegrity )
763{
764 wxCHECK_RET( aSheet != nullptr, wxT( "Cannot build sheet list from undefined sheet." ) );
765
766 std::vector<SCH_SHEET*> badSheets;
767
769 m_currentSheetPath.SetVirtualPageNumber( static_cast<int>( size() ) + 1 );
770 push_back( m_currentSheetPath );
771
773 {
774 wxString parentFileName = aSheet->GetFileName();
775 std::vector<SCH_ITEM*> childSheets;
776 m_currentSheetPath.LastScreen()->GetSheets( &childSheets );
777
778 for( SCH_ITEM* item : childSheets )
779 {
780 SCH_SHEET* sheet = static_cast<SCH_SHEET*>( item );
781
782 if( aCheckIntegrity )
783 {
784 if( !m_currentSheetPath.TestForRecursion( sheet->GetFileName(), parentFileName ) )
785 BuildSheetList( sheet, true );
786 else
787 badSheets.push_back( sheet );
788 }
789 else
790 {
791 // If we are not performing a full recursion test, at least check if we are in
792 // a simple recursion scenario to prevent stack overflow crashes
793 wxCHECK2_MSG( sheet->GetFileName() != aSheet->GetFileName(), continue,
794 wxT( "Recursion prevented in SCH_SHEET_LIST::BuildSheetList" ) );
795
796 BuildSheetList( sheet, false );
797 }
798 }
799 }
800
801 if( aCheckIntegrity )
802 {
803 for( SCH_SHEET* sheet : badSheets )
804 {
807 }
808 }
809
811}
812
813
814void SCH_SHEET_LIST::SortByHierarchicalPageNumbers( bool aUpdateVirtualPageNums )
815{
816 for( const SCH_SHEET_PATH& path : *this )
817 path.CachePageNumber();
818
819 std::sort( begin(), end(),
820 []( const SCH_SHEET_PATH& a, const SCH_SHEET_PATH& b ) -> bool
821 {
822 if( a.size() != b.size() )
823 return a.size() < b.size();
824
827
828 if( retval < 0 )
829 return true;
830 else if( retval > 0 )
831 return false;
832
834 return true;
835 else if( a.GetVirtualPageNumber() > b.GetVirtualPageNumber() )
836 return false;
837
838 // Enforce strict ordering. If the page numbers are the same, use UUIDs
839 return a.GetCurrentHash() < b.GetCurrentHash();
840 } );
841
842 if( aUpdateVirtualPageNums )
843 {
844 int virtualPageNum = 1;
845
846 for( SCH_SHEET_PATH& sheet : *this )
847 sheet.SetVirtualPageNumber( virtualPageNum++ );
848 }
849}
850
851
852void SCH_SHEET_LIST::SortByPageNumbers( bool aUpdateVirtualPageNums )
853{
854 for( const SCH_SHEET_PATH& path : *this )
855 path.CachePageNumber();
856
857 std::sort( begin(), end(),
858 []( const SCH_SHEET_PATH& a, const SCH_SHEET_PATH& b ) -> bool
859 {
862
863 if( retval < 0 )
864 return true;
865 else if( retval > 0 )
866 return false;
867
869 return true;
870 else if( a.GetVirtualPageNumber() > b.GetVirtualPageNumber() )
871 return false;
872
873 // Enforce strict ordering. If the page numbers are the same, use UUIDs
874 return a.GetCurrentHash() < b.GetCurrentHash();
875 } );
876
877 if( aUpdateVirtualPageNums )
878 {
879 int virtualPageNum = 1;
880
881 for( SCH_SHEET_PATH& sheet : *this )
882 sheet.SetVirtualPageNumber( virtualPageNum++ );
883 }
884}
885
886
887bool SCH_SHEET_LIST::NameExists( const wxString& aSheetName ) const
888{
889 for( const SCH_SHEET_PATH& sheet : *this )
890 {
891 if( sheet.Last()->GetName() == aSheetName )
892 return true;
893 }
894
895 return false;
896}
897
898
899bool SCH_SHEET_LIST::PageNumberExists( const wxString& aPageNumber ) const
900{
901 for( const SCH_SHEET_PATH& sheet : *this )
902 {
903 if( sheet.GetPageNumber() == aPageNumber )
904 return true;
905 }
906
907 return false;
908}
909
910
911void SCH_SHEET_LIST::TrimToPageNumbers( const std::vector<wxString>& aPageInclusions )
912{
913 auto it = std::remove_if( begin(), end(),
914 [&]( SCH_SHEET_PATH sheet )
915 {
916 return std::find( aPageInclusions.begin(), aPageInclusions.end(),
917 sheet.GetPageNumber() )
918 == aPageInclusions.end();
919 } );
920
921 erase( it, end() );
922}
923
924
926{
927 for( const SCH_SHEET_PATH& sheet : *this )
928 {
929 if( sheet.LastScreen() && sheet.LastScreen()->IsContentModified() )
930 return true;
931 }
932
933 return false;
934}
935
936
938{
939 for( const SCH_SHEET_PATH& sheet : *this )
940 {
941 if( sheet.LastScreen() )
942 sheet.LastScreen()->SetContentModified( false );
943 }
944}
945
946
948{
949 for( const SCH_SHEET_PATH& sheet : *this )
950 {
951 SCH_ITEM* item = sheet.GetItem( aID );
952
953 if( item )
954 {
955 if( aPathOut )
956 *aPathOut = sheet;
957
958 return item;
959 }
960 }
961
962 // Not found; weak reference has been deleted.
964}
965
966
968{
969 for( SCH_ITEM* aItem : LastScreen()->Items() )
970 {
971 if( aItem->m_Uuid == aID )
972 return aItem;
973
974 SCH_ITEM* childMatch = nullptr;
975
976 aItem->RunOnChildren(
977 [&]( SCH_ITEM* aChild )
978 {
979 if( aChild->m_Uuid == aID )
980 childMatch = aChild;
981 } );
982
983 if( childMatch )
984 return childMatch;
985 }
986
987 return nullptr;
988}
989
990
991void SCH_SHEET_LIST::FillItemMap( std::map<KIID, EDA_ITEM*>& aMap )
992{
993 for( const SCH_SHEET_PATH& sheet : *this )
994 {
995 SCH_SCREEN* screen = sheet.LastScreen();
996
997 for( SCH_ITEM* aItem : screen->Items() )
998 {
999 aMap[ aItem->m_Uuid ] = aItem;
1000
1001 aItem->RunOnChildren(
1002 [&]( SCH_ITEM* aChild )
1003 {
1004 aMap[ aChild->m_Uuid ] = aChild;
1005 } );
1006 }
1007 }
1008}
1009
1010
1012{
1013 // List of reference for power symbols
1014 SCH_REFERENCE_LIST references;
1015 SCH_REFERENCE_LIST additionalreferences; // Todo: add as a parameter to this function
1016
1017 // Map of locked symbols (not used, but needed by Annotate()
1018 SCH_MULTI_UNIT_REFERENCE_MAP lockedSymbols;
1019
1020 // Build the list of power symbols:
1021 for( SCH_SHEET_PATH& sheet : *this )
1022 {
1023 for( SCH_ITEM* item : sheet.LastScreen()->Items().OfType( SCH_SYMBOL_T ) )
1024 {
1025 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
1026 LIB_SYMBOL* libSymbol = symbol->GetLibSymbolRef().get();
1027
1028 if( libSymbol && libSymbol->IsPower() )
1029 {
1030 SCH_REFERENCE schReference( symbol, sheet );
1031 references.AddItem( schReference );
1032 }
1033 }
1034 }
1035
1036 // Find duplicate, and silently clear annotation of duplicate
1037 std::map<wxString, int> ref_list; // stores the existing references
1038
1039 for( unsigned ii = 0; ii< references.GetCount(); ++ii )
1040 {
1041 wxString curr_ref = references[ii].GetRef();
1042
1043 if( ref_list.find( curr_ref ) == ref_list.end() )
1044 {
1045 ref_list[curr_ref] = ii;
1046 continue;
1047 }
1048
1049 // Possible duplicate, if the ref ends by a number:
1050 if( curr_ref.Last() < '0' && curr_ref.Last() > '9' )
1051 continue; // not annotated
1052
1053 // Duplicate: clear annotation by removing the number ending the ref
1054 while( curr_ref.Last() >= '0' && curr_ref.Last() <= '9' )
1055 curr_ref.RemoveLast();
1056
1057 references[ii].SetRef( curr_ref );
1058 }
1059
1060 // Break full symbol reference into name (prefix) and number:
1061 // example: IC1 become IC, and 1
1062 references.SplitReferences();
1063
1064 // Ensure all power symbols have the reference starting by '#'
1065 // (Not sure this is really useful)
1066 for( unsigned ii = 0; ii< references.GetCount(); ++ii )
1067 {
1068 if( references[ii].GetRef()[0] != '#' )
1069 {
1070 wxString new_ref = "#" + references[ii].GetRef();
1071 references[ii].SetRef( new_ref );
1072 }
1073 }
1074
1075 // Recalculate and update reference numbers in schematic
1076 references.Annotate( false, 0, 100, lockedSymbols, additionalreferences );
1077 references.UpdateAnnotation();
1078}
1079
1080
1081void SCH_SHEET_LIST::GetSymbols( SCH_REFERENCE_LIST& aReferences, bool aIncludePowerSymbols,
1082 bool aForceIncludeOrphanSymbols ) const
1083{
1084 for( const SCH_SHEET_PATH& sheet : *this )
1085 sheet.GetSymbols( aReferences, aIncludePowerSymbols, aForceIncludeOrphanSymbols );
1086}
1087
1088
1090 const SCH_SHEET_PATH& aSheetPath,
1091 bool aIncludePowerSymbols,
1092 bool aForceIncludeOrphanSymbols ) const
1093{
1094 for( const SCH_SHEET_PATH& sheet : *this )
1095 {
1096 if( sheet.IsContainedWithin( aSheetPath ) )
1097 sheet.GetSymbols( aReferences, aIncludePowerSymbols, aForceIncludeOrphanSymbols );
1098 }
1099}
1100
1101
1102void SCH_SHEET_LIST::GetSheetsWithinPath( std::vector<SCH_SHEET_PATH>& aSheets,
1103 const SCH_SHEET_PATH& aSheetPath ) const
1104{
1105 for( const SCH_SHEET_PATH& sheet : *this )
1106 {
1107 if( sheet.IsContainedWithin( aSheetPath ) )
1108 aSheets.push_back( sheet );
1109 }
1110}
1111
1112
1113std::optional<SCH_SHEET_PATH> SCH_SHEET_LIST::GetSheetPathByKIIDPath( const KIID_PATH& aPath,
1114 bool aIncludeLastSheet ) const
1115{
1116 for( const SCH_SHEET_PATH& sheet : *this )
1117 {
1118 KIID_PATH testPath = sheet.Path();
1119
1120 if( !aIncludeLastSheet )
1121 testPath.pop_back();
1122
1123 if( testPath == aPath )
1124 return SCH_SHEET_PATH( sheet );
1125 }
1126
1127 return std::nullopt;
1128}
1129
1130
1132 bool aIncludePowerSymbols ) const
1133{
1134 for( auto it = begin(); it != end(); ++it )
1135 {
1137 ( *it ).GetMultiUnitSymbols( tempMap, aIncludePowerSymbols );
1138
1139 for( SCH_MULTI_UNIT_REFERENCE_MAP::value_type& pair : tempMap )
1140 {
1141 // Merge this list into the main one
1142 unsigned n_refs = pair.second.GetCount();
1143
1144 for( unsigned thisRef = 0; thisRef < n_refs; ++thisRef )
1145 aRefList[pair.first].AddItem( pair.second[thisRef] );
1146 }
1147 }
1148}
1149
1150
1151bool SCH_SHEET_LIST::TestForRecursion( const SCH_SHEET_LIST& aSrcSheetHierarchy,
1152 const wxString& aDestFileName )
1153{
1154 if( empty() )
1155 return false;
1156
1157 SCHEMATIC* sch = at( 0 ).LastScreen()->Schematic();
1158
1159 wxCHECK_MSG( sch, false, "No SCHEMATIC found in SCH_SHEET_LIST::TestForRecursion!" );
1160
1161 wxFileName rootFn = sch->GetFileName();
1162 wxFileName destFn = aDestFileName;
1163
1164 if( destFn.IsRelative() )
1165 destFn.MakeAbsolute( rootFn.GetPath() );
1166
1167 // Test each SCH_SHEET_PATH in this SCH_SHEET_LIST for potential recursion.
1168 for( unsigned i = 0; i < size(); i++ )
1169 {
1170 // Test each SCH_SHEET_PATH in the source sheet.
1171 for( unsigned j = 0; j < aSrcSheetHierarchy.size(); j++ )
1172 {
1173 const SCH_SHEET_PATH* sheetPath = &aSrcSheetHierarchy[j];
1174
1175 for( unsigned k = 0; k < sheetPath->size(); k++ )
1176 {
1177 if( at( i ).TestForRecursion( sheetPath->GetSheet( k )->GetFileName(),
1178 aDestFileName ) )
1179 {
1180 return true;
1181 }
1182 }
1183 }
1184 }
1185
1186 // The source sheet file can safely be added to the destination sheet file.
1187 return false;
1188}
1189
1190
1192{
1193 for( SCH_SHEET_PATH& path : *this )
1194 {
1195 if( path.Path() == aPath->Path() )
1196 return &path;
1197 }
1198
1199 return nullptr;
1200}
1201
1202
1204{
1205 for( SCH_SHEET_PATH& sheetpath : *this )
1206 {
1207 if( sheetpath.LastScreen() == aScreen )
1208 return sheetpath;
1209 }
1210
1211 return SCH_SHEET_PATH();
1212}
1213
1214
1216{
1217 SCH_SHEET_LIST retval;
1218
1219 for( const SCH_SHEET_PATH& sheetpath : *this )
1220 {
1221 if( sheetpath.LastScreen() == aScreen )
1222 retval.push_back( sheetpath );
1223 }
1224
1225 return retval;
1226}
1227
1228
1230 const std::vector<SCH_SYMBOL_INSTANCE>& aSymbolInstances )
1231{
1232 for( SCH_SHEET_PATH& sheetPath : *this )
1233 {
1234 for( SCH_ITEM* item : sheetPath.LastScreen()->Items().OfType( SCH_SYMBOL_T ) )
1235 {
1236 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
1237
1238 wxCHECK2( symbol, continue );
1239
1240 KIID_PATH sheetPathWithSymbolUuid = sheetPath.Path();
1241 sheetPathWithSymbolUuid.push_back( symbol->m_Uuid );
1242
1243 auto it = std::find_if( aSymbolInstances.begin(), aSymbolInstances.end(),
1244 [ sheetPathWithSymbolUuid ]( const SCH_SYMBOL_INSTANCE& r ) -> bool
1245 {
1246 return sheetPathWithSymbolUuid == r.m_Path;
1247 } );
1248
1249 if( it == aSymbolInstances.end() )
1250 {
1251 wxLogTrace( traceSchSheetPaths, "No symbol instance found for symbol '%s'",
1252 sheetPathWithSymbolUuid.AsString() );
1253 continue;
1254 }
1255
1256 // Symbol instance paths are stored and looked up in memory with the root path so use
1257 // the full path here.
1258 symbol->AddHierarchicalReference( sheetPath.Path(), it->m_Reference, it->m_Unit );
1259 symbol->GetField( FIELD_T::REFERENCE )->SetText( it->m_Reference );
1260
1261 if( !it->m_Value.IsEmpty() )
1262 symbol->SetValueFieldText( it->m_Value );
1263
1264 if( !it->m_Footprint.IsEmpty() )
1265 symbol->SetFootprintFieldText( it->m_Footprint );
1266
1267 symbol->UpdatePrefix();
1268 }
1269 }
1270}
1271
1272
1273void SCH_SHEET_LIST::UpdateSheetInstanceData( const std::vector<SCH_SHEET_INSTANCE>& aSheetInstances )
1274{
1275
1276 for( SCH_SHEET_PATH& path : *this )
1277 {
1278 SCH_SHEET* sheet = path.Last();
1279
1280 wxCHECK2( sheet && path.Last(), continue );
1281
1282 auto it = std::find_if( aSheetInstances.begin(), aSheetInstances.end(),
1283 [ path ]( const SCH_SHEET_INSTANCE& r ) -> bool
1284 {
1285 return path.Path() == r.m_Path;
1286 } );
1287
1288 if( it == aSheetInstances.end() )
1289 {
1290 wxLogTrace( traceSchSheetPaths, "No sheet instance found for path '%s'",
1291 path.Path().AsString() );
1292 continue;
1293 }
1294
1295 wxLogTrace( traceSchSheetPaths, "Setting sheet '%s' instance '%s' page number '%s'",
1296 ( sheet->GetName().IsEmpty() ) ? wxString( wxT( "root" ) ) : sheet->GetName(),
1297 path.Path().AsString(), it->m_PageNumber );
1298 path.SetPageNumber( it->m_PageNumber );
1299 }
1300}
1301
1302
1303std::vector<KIID_PATH> SCH_SHEET_LIST::GetPaths() const
1304{
1305 std::vector<KIID_PATH> paths;
1306
1307 for( const SCH_SHEET_PATH& sheetPath : *this )
1308 paths.emplace_back( sheetPath.Path() );
1309
1310 return paths;
1311}
1312
1313
1314std::vector<SCH_SHEET_INSTANCE> SCH_SHEET_LIST::GetSheetInstances() const
1315{
1316 std::vector<SCH_SHEET_INSTANCE> retval;
1317
1318 for( const SCH_SHEET_PATH& path : *this )
1319 {
1320 const SCH_SHEET* sheet = path.Last();
1321
1322 wxCHECK2( sheet, continue );
1323
1324 SCH_SHEET_INSTANCE instance;
1325 SCH_SHEET_PATH tmpPath = path;
1326
1327 tmpPath.pop_back();
1328 instance.m_Path = tmpPath.Path();
1329 instance.m_PageNumber = path.GetPageNumber();
1330
1331 retval.push_back( instance );
1332 }
1333
1334 return retval;
1335}
1336
1337
1339{
1340 for( const SCH_SHEET_PATH& instance : *this )
1341 {
1342 if( !instance.GetPageNumber().IsEmpty() )
1343 return false;
1344 }
1345
1346 return true;
1347}
1348
1349
1351{
1352 // Don't accidentally renumber existing sheets.
1353 wxCHECK( AllSheetPageNumbersEmpty(), /* void */ );
1354
1355 wxString tmp;
1356 int pageNumber = 1;
1357
1358 for( SCH_SHEET_PATH& instance : *this )
1359 {
1360 tmp.Printf( "%d", pageNumber );
1361 instance.SetPageNumber( tmp );
1362 pageNumber += 1;
1363 }
1364}
1365
1366
1368 const wxString& aProjectName )
1369{
1370 for( SCH_SHEET_PATH& sheetPath : *this )
1371 sheetPath.AddNewSymbolInstances( aPrefixSheetPath, aProjectName );
1372}
1373
1374
1376{
1377 for( SCH_SHEET_PATH& sheetPath : *this )
1378 sheetPath.RemoveSymbolInstances( aPrefixSheetPath );
1379}
1380
1381
1383 int aLastVirtualPageNumber )
1384{
1385 wxString pageNumber;
1386 int lastUsedPageNumber = 1;
1387 int nextVirtualPageNumber = aLastVirtualPageNumber;
1388
1389 // Fetch the list of page numbers already in use.
1390 std::vector< wxString > usedPageNumbers;
1391
1392 if( aPrefixSheetPath.size() )
1393 {
1394 SCH_SHEET_LIST prefixHierarchy( aPrefixSheetPath.at( 0 ) );
1395
1396 for( const SCH_SHEET_PATH& path : prefixHierarchy )
1397 {
1398 pageNumber = path.GetPageNumber();
1399
1400 if( !pageNumber.IsEmpty() )
1401 usedPageNumbers.emplace_back( pageNumber );
1402 }
1403 }
1404
1405 for( SCH_SHEET_PATH& sheetPath : *this )
1406 {
1407 KIID_PATH tmp = sheetPath.Path();
1408 SCH_SHEET_PATH newSheetPath( aPrefixSheetPath );
1409
1410 // Prefix the new hierarchical path.
1411 newSheetPath = newSheetPath + sheetPath;
1412
1413 // Sheets cannot have themselves in the path.
1414 tmp.pop_back();
1415
1416 SCH_SHEET* sheet = sheetPath.Last();
1417
1418 wxCHECK2( sheet, continue );
1419
1420 nextVirtualPageNumber += 1;
1421
1422 SCH_SHEET_INSTANCE instance;
1423
1424 // Add the instance if it doesn't already exist
1425 if( !sheet->getInstance( instance, tmp, true ) )
1426 {
1427 sheet->addInstance( tmp );
1428 sheet->getInstance( instance, tmp, true );
1429 }
1430
1431 // Get a new page number if we don't have one
1432 if( instance.m_PageNumber.IsEmpty() )
1433 {
1434 // Generate the next available page number.
1435 do
1436 {
1437 pageNumber.Printf( wxT( "%d" ), lastUsedPageNumber );
1438 lastUsedPageNumber += 1;
1439 } while( std::find( usedPageNumbers.begin(), usedPageNumbers.end(), pageNumber ) !=
1440 usedPageNumbers.end() );
1441
1442 instance.m_PageNumber = pageNumber;
1443 newSheetPath.SetVirtualPageNumber( nextVirtualPageNumber );
1444 }
1445
1446 newSheetPath.SetPageNumber( instance.m_PageNumber );
1447 usedPageNumbers.push_back( instance.m_PageNumber );
1448 }
1449}
1450
1451
1452void SCH_SHEET_LIST::CheckForMissingSymbolInstances( const wxString& aProjectName )
1453{
1454 for( SCH_SHEET_PATH& sheetPath : *this )
1455 sheetPath.CheckForMissingSymbolInstances( aProjectName );
1456}
1457
1458
1460{
1461 int lastVirtualPageNumber = 1;
1462
1463 for( const SCH_SHEET_PATH& sheetPath : *this )
1464 {
1465 if( sheetPath.GetVirtualPageNumber() > lastVirtualPageNumber )
1466 lastVirtualPageNumber = sheetPath.GetVirtualPageNumber();
1467 }
1468
1469 return lastVirtualPageNumber;
1470}
1471
1472
1473bool SCH_SHEET_LIST::HasPath( const KIID_PATH& aPath ) const
1474{
1475 for( const SCH_SHEET_PATH& path : *this )
1476 {
1477 if( path.Path() == aPath )
1478 return true;
1479 }
1480
1481 return false;
1482}
1483
1484
1485bool SCH_SHEET_LIST::ContainsSheet( const SCH_SHEET* aSheet ) const
1486{
1487 for( const SCH_SHEET_PATH& path : *this )
1488 {
1489 for( size_t i = 0; i < path.size(); i++ )
1490 {
1491 if( path.at( i ) == aSheet )
1492 return true;
1493 }
1494 }
1495
1496 return false;
1497}
1498
1499
1500std::optional<SCH_SHEET_PATH> SCH_SHEET_LIST::GetOrdinalPath( const SCH_SCREEN* aScreen ) const
1501{
1502 // Sheet paths with sheets that do not have a screen object are not valid.
1503 if( !aScreen )
1504 return std::nullopt;
1505
1506 for( const SCH_SHEET_PATH& path: *this )
1507 {
1508 if( path.LastScreen() == aScreen )
1509 return std::optional<SCH_SHEET_PATH>( path );
1510 }
1511
1512 return std::nullopt;
1513}
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:85
bool IsPower() const override
Definition: lib_symbol.cpp:467
int GetUnitCount() const override
Holds all the data relating to one schematic.
Definition: schematic.h:69
wxString GetFileName() const
Helper to retrieve the filename from the root sheet screen.
Definition: schematic.cpp:300
SCHEMATIC_SETTINGS & Settings() const
Definition: schematic.cpp:306
VECTOR2I GetPosition() const override
Definition: sch_field.cpp:1306
wxString GetShownText(const SCH_SHEET_PATH *aPath, bool aAllowExtraText, int aDepth=0) const
Definition: sch_field.cpp:192
void SetText(const wxString &aText) override
Definition: sch_field.cpp:1061
SCH_FIELD * GetField(FIELD_T aFieldType)
Return a mandatory field in this label.
Definition: sch_label.cpp:1838
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:566
std::vector< SCH_FIELD > & GetFields()
Definition: sch_label.h:207
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:112
const wxString & GetFileName() const
Definition: sch_screen.h:147
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 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
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: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
Definition: sch_sheet.cpp:169
bool getInstance(SCH_SHEET_INSTANCE &aInstance, const KIID_PATH &aSheetPath, bool aTestFromEnd=false) const
Definition: sch_sheet.cpp:1395
bool addInstance(const KIID_PATH &aInstance)
Add a new instance aSheetPath to the instance list.
Definition: sch_sheet.cpp:1372
SCH_FIELD * GetField(FIELD_T aFieldType)
Return a mandatory field in this sheet.
Definition: sch_sheet.cpp:369
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.
Definition: sch_sheet.cpp:1530
void setPageNumber(const KIID_PATH &aInstance, const wxString &aPageNumber)
Set the page number for the sheet instance aInstance.
Definition: sch_sheet.cpp:1464
wxString getPageNumber(const KIID_PATH &aInstance) const
Return the sheet page number for aInstance.
Definition: sch_sheet.cpp:1447
Schematic symbol object.
Definition: sch_symbol.h:75
void UpdatePrefix()
Set the prefix based on the current reference designator.
Definition: sch_symbol.cpp:703
const std::vector< SCH_SYMBOL_INSTANCE > & GetInstances() const
Definition: sch_symbol.h:134
void RemoveInstance(const SCH_SHEET_PATH &aInstancePath)
Definition: sch_symbol.cpp:483
void SetValueFieldText(const wxString &aValue)
Definition: sch_symbol.cpp:791
void SetFootprintFieldText(const wxString &aFootprint)
Definition: sch_symbol.cpp:807
void AddHierarchicalReference(const KIID_PATH &aPath, const wxString &aRef, int aUnit)
Add a full hierarchical reference to this symbol.
Definition: sch_symbol.cpp:511
bool GetInstance(SCH_SYMBOL_INSTANCE &aInstance, const KIID_PATH &aSheetPath, bool aTestFromEnd=false) const
Definition: sch_symbol.cpp:459
int GetUnitSelection(const SCH_SHEET_PATH *aSheet) const
Return the instance-specific unit selection for the given sheet path.
Definition: sch_symbol.cpp:739
std::unique_ptr< LIB_SYMBOL > & GetLibSymbolRef()
Definition: sch_symbol.h:183
const wxString GetRef(const SCH_SHEET_PATH *aSheet, bool aIncludeUnit=false) const override
Definition: sch_symbol.cpp:611
wxString GetPrefix() const
Definition: sch_symbol.h:249
SCH_FIELD * GetField(FIELD_T aFieldType)
Return a mandatory field in this symbol.
Definition: sch_symbol.cpp:813
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
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.
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