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