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 <sch_sheet_path.h>
33#include <sch_symbol.h>
34#include <sch_sheet.h>
35#include <schematic.h>
36#include <string_utils.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
107
108
110{
111 m_DNP = aSheet.GetDNP();
115 m_ExcludedFromPosFiles = false; // Sheets don't have position files exclusion
116}
117
118
119namespace std
120{
122 {
123 return path.GetCurrentHash();
124 }
125}
126
127
133
134
136{
137 initFromOther( aOther );
138}
139
140
142{
143 initFromOther( aOther );
144 return *this;
145}
146
147
148// Move assignment operator
150{
151 m_sheets = std::move( aOther.m_sheets );
152
153 m_virtualPageNumber = aOther.m_virtualPageNumber;
154 m_current_hash = aOther.m_current_hash;
155 m_cached_page_number = aOther.m_cached_page_number;
156
157 m_recursion_test_cache = std::move( aOther.m_recursion_test_cache );
158
159 return *this;
160}
161
162
164{
165 SCH_SHEET_PATH retv = *this;
166
167 size_t size = aOther.size();
168
169 for( size_t i = 0; i < size; i++ )
170 retv.push_back( aOther.at( i ) );
171
172 return retv;
173}
174
175
177{
178 m_sheets = aOther.m_sheets;
182
183 // Note: don't copy m_recursion_test_cache as it is slow and we want std::vector<SCH_SHEET_PATH>
184 // to be very fast to construct for use in the connectivity algorithm.
186}
187
189{
190 m_current_hash = 0;
191
192 for( SCH_SHEET* sheet : m_sheets )
193 hash_combine( m_current_hash, sheet->m_Uuid.Hash() );
194}
195
196
197int SCH_SHEET_PATH::Cmp( const SCH_SHEET_PATH& aSheetPathToTest ) const
198{
199 if( size() > aSheetPathToTest.size() )
200 return 1;
201
202 if( size() < aSheetPathToTest.size() )
203 return -1;
204
205 // otherwise, same number of sheets.
206 for( unsigned i = 0; i < size(); i++ )
207 {
208 if( at( i )->m_Uuid < aSheetPathToTest.at( i )->m_Uuid )
209 return -1;
210
211 if( at( i )->m_Uuid != aSheetPathToTest.at( i )->m_Uuid )
212 return 1;
213 }
214
215 return 0;
216}
217
218
219int SCH_SHEET_PATH::ComparePageNum( const SCH_SHEET_PATH& aSheetPathToTest ) const
220{
221 wxString pageA = this->GetPageNumber();
222 wxString pageB = aSheetPathToTest.GetPageNumber();
223
224 int pageNumComp = SCH_SHEET::ComparePageNum( pageA, pageB );
225
226 if( pageNumComp == 0 )
227 {
228 int virtualPageA = GetVirtualPageNumber();
229 int virtualPageB = aSheetPathToTest.GetVirtualPageNumber();
230
231 if( virtualPageA > virtualPageB )
232 pageNumComp = 1;
233 else if( virtualPageA < virtualPageB )
234 pageNumComp = -1;
235 }
236
237 return pageNumComp;
238}
239
240
241bool SCH_SHEET_PATH::IsContainedWithin( const SCH_SHEET_PATH& aSheetPathToTest ) const
242{
243 if( aSheetPathToTest.size() > size() )
244 return false;
245
246 for( size_t i = 0; i < aSheetPathToTest.size(); ++i )
247 {
248 if( at( i )->m_Uuid != aSheetPathToTest.at( i )->m_Uuid )
249 {
250 wxLogTrace( traceSchSheetPaths, "Sheet path '%s' is not within path '%s'.",
251 aSheetPathToTest.Path().AsString(), Path().AsString() );
252
253 return false;
254 }
255 }
256
257 wxLogTrace( traceSchSheetPaths, "Sheet path '%s' is within path '%s'.",
258 aSheetPathToTest.Path().AsString(), Path().AsString() );
259
260 return true;
261}
262
263
265{
266 if( !empty() )
267 return m_sheets.back();
268
269 return nullptr;
270}
271
272
274{
275 SCH_SHEET* lastSheet = Last();
276
277 if( lastSheet )
278 return lastSheet->GetScreen();
279
280 return nullptr;
281}
282
283
285{
286 SCH_SHEET* lastSheet = Last();
287
288 if( lastSheet )
289 return lastSheet->GetScreen();
290
291 return nullptr;
292}
293
294
296{
297 for( SCH_SHEET* sheet : m_sheets )
298 {
299 if( sheet->GetExcludedFromSim() )
300 return true;
301 }
302
303 return false;
304}
305
306
307bool SCH_SHEET_PATH::GetExcludedFromSim( const wxString& aVariantName ) const
308{
309 if( aVariantName.IsEmpty() )
310 return GetExcludedFromSim();
311
312 SCH_SHEET_PATH copy = *this;
313
314 while( !copy.empty() )
315 {
316 SCH_SHEET* sheet = copy.Last();
317 copy.pop_back();
318
319 if( sheet->GetExcludedFromSim( &copy, aVariantName ) )
320 return true;
321 }
322
323 return false;
324}
325
326
328{
329 for( SCH_SHEET* sheet : m_sheets )
330 {
331 if( sheet->GetExcludedFromBOM() )
332 return true;
333 }
334
335 return false;
336}
337
338
339bool SCH_SHEET_PATH::GetExcludedFromBOM( const wxString& aVariantName ) const
340{
341 if( aVariantName.IsEmpty() )
342 return GetExcludedFromBOM();
343
344 SCH_SHEET_PATH copy = *this;
345
346 while( !copy.empty() )
347 {
348 SCH_SHEET* sheet = copy.Last();
349 copy.pop_back();
350
351 if( sheet->GetExcludedFromBOM( &copy, aVariantName ) )
352 return true;
353 }
354
355 return false;
356}
357
358
360{
361 for( SCH_SHEET* sheet : m_sheets )
362 {
363 if( sheet->GetExcludedFromBoard() )
364 return true;
365 }
366
367 return false;
368}
369
370
371bool SCH_SHEET_PATH::GetExcludedFromBoard( const wxString& aVariantName ) const
372{
373 if( aVariantName.IsEmpty() )
374 return GetExcludedFromBoard();
375
376 SCH_SHEET_PATH copy = *this;
377
378 while( !copy.empty() )
379 {
380 SCH_SHEET* sheet = copy.Last();
381 copy.pop_back();
382
383 if( sheet->GetExcludedFromBoard( &copy, aVariantName ) )
384 return true;
385 }
386
387 return false;
388}
389
390
392{
393 for( SCH_SHEET* sheet : m_sheets )
394 {
395 if( sheet->GetDNP() )
396 return true;
397 }
398
399 return false;
400}
401
402
403bool SCH_SHEET_PATH::GetDNP( const wxString& aVariantName ) const
404{
405 if( aVariantName.IsEmpty() )
406 return GetDNP();
407
408 SCH_SHEET_PATH copy = *this;
409
410 while( !copy.empty() )
411 {
412 SCH_SHEET* sheet = copy.Last();
413 copy.pop_back();
414
415 if( sheet->GetDNP( &copy, aVariantName ) )
416 return true;
417 }
418
419 return false;
420}
421
422
424{
425 wxString s;
426
427 s = wxT( "/" ); // This is the root path
428
429 // Start at 1 to avoid the root sheet, which does not need to be added to the path.
430 // Its timestamp changes anyway.
431 for( unsigned i = 1; i < size(); i++ )
432 s += at( i )->m_Uuid.AsString() + "/";
433
434 return s;
435}
436
437
439{
441 size_t size = m_sheets.size();
442
443 if( m_sheets.empty() )
444 return path;
445
446 if( m_sheets[0]->m_Uuid != niluuid )
447 {
448 path.reserve( size );
449 path.push_back( m_sheets[0]->m_Uuid );
450 }
451 else
452 {
453 // Skip the virtual root
454 path.reserve( size - 1 );
455 }
456
457 for( size_t i = 1; i < size; i++ )
458 path.push_back( m_sheets[i]->m_Uuid );
459
460 return path;
461}
462
463
464wxString SCH_SHEET_PATH::PathHumanReadable( bool aUseShortRootName,
465 bool aStripTrailingSeparator,
466 bool aEscapeSheetNames ) const
467{
468 wxString s;
469
470 // Determine the starting index - skip virtual root if present
471 size_t startIdx = 0;
472
473 if( !empty() && at( 0 )->IsVirtualRootSheet() )
474 startIdx = 1;
475
476 if( aUseShortRootName )
477 {
478 s = wxS( "/" ); // Use only the short name in netlists
479 }
480 else
481 {
482 wxString fileName;
483
484 if( size() > startIdx && at( startIdx )->GetScreen() )
485 fileName = at( startIdx )->GetScreen()->GetFileName();
486
487 wxFileName fn = fileName;
488
489 s = fn.GetName() + wxS( "/" );
490 }
491
492 // Start at startIdx + 1 since we've already processed the root sheet.
493 for( unsigned i = startIdx + 1; i < size(); i++ )
494 {
495 wxString sheetName = at( i )->GetField( FIELD_T::SHEET_NAME )->GetShownText( false );
496
497 if( aEscapeSheetNames )
498 sheetName = EscapeString( sheetName, CTX_NETNAME );
499
500 s << sheetName << wxS( "/" );
501 }
502
503 if( aStripTrailingSeparator && s.EndsWith( "/" ) )
504 s = s.Left( s.length() - 1 );
505
506 return s;
507}
508
509
511{
512 std::vector<SCH_ITEM*> items;
513
514 std::copy_if( LastScreen()->Items().begin(), LastScreen()->Items().end(),
515 std::back_inserter( items ),
516 []( SCH_ITEM* aItem )
517 {
518 return ( aItem->Type() == SCH_SYMBOL_T
519 || aItem->Type() == SCH_GLOBAL_LABEL_T
520 || aItem->Type() == SCH_SHAPE_T );
521 } );
522
523 std::optional<wxString> variantName;
524 const SCHEMATIC* schematic = LastScreen()->Schematic();
525
526 if( schematic )
527 variantName = schematic->GetCurrentVariant();
528
529 for( SCH_ITEM* item : items )
530 {
531 if( item->Type() == SCH_SYMBOL_T )
532 {
533 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
534
535 symbol->GetField( FIELD_T::REFERENCE )->SetText( symbol->GetRef( this ) );
536 symbol->SetUnit( symbol->GetUnitSelection( this ) );
537 LastScreen()->Update( item, false );
538 }
539 else if( item->Type() == SCH_GLOBAL_LABEL_T )
540 {
541 SCH_GLOBALLABEL* label = static_cast<SCH_GLOBALLABEL*>( item );
542
543 if( label->GetFields().size() > 0 ) // Possible when reading a legacy .sch schematic
544 {
545 SCH_FIELD* intersheetRefs = label->GetField( FIELD_T::INTERSHEET_REFS );
546
547 // Fixup for legacy files which didn't store a position for the intersheet refs
548 // unless they were shown.
549 if( intersheetRefs->GetPosition() == VECTOR2I() && !intersheetRefs->IsVisible() )
551
552 intersheetRefs->SetVisible( label->Schematic()->Settings().m_IntersheetRefsShow );
553 LastScreen()->Update( intersheetRefs );
554 }
555 }
556 else if( item->Type() == SCH_SHAPE_T )
557 {
558 SCH_SHAPE* shape = static_cast<SCH_SHAPE*>( item );
559 shape->UpdateHatching();
560 }
561 }
562}
563
564
565static bool matchesSymbolFilter( const wxString& aReference, SYMBOL_FILTER aSymbolFilter )
566{
567 bool isPowerSymbol = !aReference.IsEmpty() && aReference[0] == wxT( '#' );
568
569 switch( aSymbolFilter )
570 {
571 case SYMBOL_FILTER_POWER: return isPowerSymbol;
572
573 case SYMBOL_FILTER_ALL: return true;
574
576 default: return !isPowerSymbol;
577 }
578}
579
580
582 bool aForceIncludeOrphanSymbols ) const
583{
584 for( SCH_ITEM* item : LastScreen()->Items().OfType( SCH_SYMBOL_T ) )
585 {
586 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
587 AppendSymbol( aReferences, symbol, aSymbolFilter, aForceIncludeOrphanSymbols );
588 }
589}
590
591
593 bool aForceIncludeOrphanSymbols ) const
594{
595 // Skip pseudo-symbols, which have a reference starting with #. This mainly
596 // affects power symbols.
597 if( matchesSymbolFilter( aSymbol->GetRef( this ), aSymbolFilter ) )
598 {
599 if( aSymbol->GetLibSymbolRef() || aForceIncludeOrphanSymbols )
600 {
601 SCH_REFERENCE schReference( aSymbol, *this );
602
603 schReference.SetSheetNumber( GetPageNumberAsInt() );
604 aReferences.AddItem( schReference );
605 }
606 }
607}
608
609
611{
612 for( SCH_ITEM* item : LastScreen()->Items().OfType( SCH_SYMBOL_T ) )
613 {
614 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
615 AppendMultiUnitSymbol( aRefList, symbol, aSymbolFilter );
616 }
617}
618
619
621 SYMBOL_FILTER aSymbolFilter ) const
622{
623 // Skip pseudo-symbols, which have a reference starting with #. This mainly
624 // affects power symbols.
625 if( !matchesSymbolFilter( aSymbol->GetRef( this ), aSymbolFilter ) )
626 return;
627
628 LIB_SYMBOL* symbol = aSymbol->GetLibSymbolRef().get();
629
630 if( symbol && symbol->GetUnitCount() > 1 )
631 {
632 SCH_REFERENCE schReference = SCH_REFERENCE( aSymbol, *this );
633 schReference.SetSheetNumber( GetPageNumberAsInt() );
634 wxString reference_str = schReference.GetRef();
635
636 // Never lock unassigned references
637 if( reference_str[reference_str.Len() - 1] == '?' )
638 return;
639
640 aRefList[reference_str].AddItem( schReference );
641 }
642}
643
644
646{
647 return m_current_hash == d1.GetCurrentHash();
648}
649
650
651bool SCH_SHEET_PATH::TestForRecursion( const wxString& aSrcFileName, const wxString& aDestFileName )
652{
653 auto pair = std::make_pair( aSrcFileName, aDestFileName );
654
655 if( m_recursion_test_cache.count( pair ) )
656 return m_recursion_test_cache.at( pair );
657
658 SCHEMATIC* sch = LastScreen()->Schematic();
659
660 wxCHECK_MSG( sch, false, "No SCHEMATIC found in SCH_SHEET_PATH::TestForRecursion!" );
661
662 wxFileName rootFn = sch->GetFileName();
663 wxFileName srcFn = aSrcFileName;
664 wxFileName destFn = aDestFileName;
665
666 if( srcFn.IsRelative() )
667 srcFn.MakeAbsolute( rootFn.GetPath() );
668
669 if( destFn.IsRelative() )
670 destFn.MakeAbsolute( rootFn.GetPath() );
671
672 // The source and destination sheet file names cannot be the same.
673 if( srcFn == destFn )
674 {
675 m_recursion_test_cache[pair] = true;
676 return true;
677 }
678
682 unsigned i = 0;
683
684 while( i < size() )
685 {
686 wxFileName cmpFn = at( i )->GetFileName();
687
688 if( cmpFn.IsRelative() )
689 cmpFn.MakeAbsolute( rootFn.GetPath() );
690
691 // Test if the file name of the destination sheet is in anywhere in this sheet path.
692 if( cmpFn == destFn )
693 break;
694
695 i++;
696 }
697
698 // The destination sheet file name was not found in the sheet path or the destination
699 // sheet file name is the root sheet so no recursion is possible.
700 if( i >= size() || i == 0 )
701 {
702 m_recursion_test_cache[pair] = false;
703 return false;
704 }
705
706 // Walk back up to the root sheet to see if the source file name is already a parent in
707 // the sheet path. If so, recursion will occur.
708 do
709 {
710 i -= 1;
711
712 wxFileName cmpFn = at( i )->GetFileName();
713
714 if( cmpFn.IsRelative() )
715 cmpFn.MakeAbsolute( rootFn.GetPath() );
716
717 if( cmpFn == srcFn )
718 {
719 m_recursion_test_cache[pair] = true;
720 return true;
721 }
722
723 } while( i != 0 );
724
725 // The source sheet file name is not a parent of the destination sheet file name.
726 m_recursion_test_cache[pair] = false;
727 return false;
728}
729
730
732{
733 SCH_SHEET* sheet = Last();
734
735 wxCHECK( sheet, wxEmptyString );
736
737 KIID_PATH tmpPath = Path();
738
739 if( !tmpPath.empty() )
740 tmpPath.pop_back();
741 else
742 return wxEmptyString;
743
744 return sheet->getPageNumber( tmpPath );
745}
746
748{
749 long page;
750 wxString pageStr = GetPageNumber();
751
752 if( pageStr.ToLong( &page ) )
753 return (int) page;
754
755 return GetVirtualPageNumber();
756}
757
758
759void SCH_SHEET_PATH::SetPageNumber( const wxString& aPageNumber )
760{
761 SCH_SHEET* sheet = Last();
762
763 wxCHECK( sheet, /* void */ );
764
765 KIID_PATH tmpPath = Path();
766
767 if( !tmpPath.empty() )
768 {
769 tmpPath.pop_back();
770 }
771 else
772 {
773 wxCHECK_MSG( false, /* void */, wxS( "Sheet paths must have a least one valid sheet." ) );
774 }
775
776 sheet->addInstance( tmpPath );
777 sheet->setPageNumber( tmpPath, aPageNumber );
778}
779
780
782 const wxString& aProjectName )
783{
784 wxCHECK( !aProjectName.IsEmpty(), /* void */ );
785
786 SCH_SHEET_PATH newSheetPath( aPrefixSheetPath );
787 SCH_SHEET_PATH currentSheetPath( *this );
788
789 // Prefix the new hierarchical path.
790 newSheetPath = newSheetPath + currentSheetPath;
791
792 for( SCH_ITEM* item : LastScreen()->Items().OfType( SCH_SYMBOL_T ) )
793 {
794 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
795
796 wxCHECK2( symbol, continue );
797
798 SCH_SYMBOL_INSTANCE newSymbolInstance;
799
800 if( symbol->GetInstance( newSymbolInstance, Path(), true ) )
801 {
802 newSymbolInstance.m_ProjectName = aProjectName;
803
804 // Use an existing symbol instance for this path if it exists.
805 newSymbolInstance.m_Path = newSheetPath.Path();
806 symbol->AddHierarchicalReference( newSymbolInstance );
807 }
808 else if( !symbol->GetInstances().empty() )
809 {
810 newSymbolInstance.m_ProjectName = aProjectName;
811
812 // Use the first symbol instance if any symbol instance data exists.
813 newSymbolInstance = symbol->GetInstances()[0];
814 newSymbolInstance.m_Path = newSheetPath.Path();
815 symbol->AddHierarchicalReference( newSymbolInstance );
816 }
817 else
818 {
819 newSymbolInstance.m_ProjectName = aProjectName;
820
821 // Fall back to the last saved symbol field and unit settings if there is no
822 // instance data.
823 newSymbolInstance.m_Path = newSheetPath.Path();
824 newSymbolInstance.m_Reference = symbol->GetField( FIELD_T::REFERENCE )->GetText();
825 newSymbolInstance.m_Unit = symbol->GetUnit();
826 symbol->AddHierarchicalReference( newSymbolInstance );
827 }
828 }
829}
830
831
833{
834 for( SCH_ITEM* item : LastScreen()->Items().OfType( SCH_SYMBOL_T ) )
835 {
836 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
837
838 wxCHECK2( symbol, continue );
839
840 SCH_SHEET_PATH fullSheetPath( aPrefixSheetPath );
841 SCH_SHEET_PATH currentSheetPath( *this );
842
843 // Prefix the hierarchical path of the symbol instance to be removed.
844 fullSheetPath = fullSheetPath + currentSheetPath;
845 symbol->RemoveInstance( fullSheetPath );
846 }
847}
848
849
850void SCH_SHEET_PATH::CheckForMissingSymbolInstances( const wxString& aProjectName )
851{
852 // Skip sheet paths without screens (e.g., sheets that haven't been loaded yet or virtual root)
853 if( aProjectName.IsEmpty() || !LastScreen() )
854 return;
855
856 wxLogTrace( traceSchSheetPaths, "CheckForMissingSymbolInstances for path: %s (project: %s)",
857 PathHumanReadable( false ), aProjectName );
858 wxLogTrace( traceSchSheetPaths, " Sheet path size=%zu, Path().AsString()='%s'",
859 size(), Path().AsString() );
860
861 for( SCH_ITEM* item : LastScreen()->Items().OfType( SCH_SYMBOL_T ) )
862 {
863 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
864
865 wxCHECK2( symbol, continue );
866
867 SCH_SYMBOL_INSTANCE symbolInstance;
868
869 if( !symbol->GetInstance( symbolInstance, Path() ) )
870 {
871 wxLogTrace( traceSchSheetPaths, "Adding missing symbol \"%s\" instance data for "
872 "sheet path '%s'.",
873 symbol->m_Uuid.AsString(), PathHumanReadable( false ) );
874
875 // Legacy schematics that are not shared do not contain separate instance data.
876 // The symbol reference and unit are saved in the reference field and unit entries.
877 if( ( LastScreen()->GetRefCount() <= 1 ) &&
878 ( LastScreen()->GetFileFormatVersionAtLoad() <= 20200310 ) )
879 {
880 SCH_FIELD* refField = symbol->GetField( FIELD_T::REFERENCE );
881 symbolInstance.m_Reference = refField->GetShownText( this, true );
882 symbolInstance.m_Unit = symbol->GetUnit();
883
884 wxLogTrace( traceSchSheetPaths,
885 " Legacy format: Using reference '%s' from field, unit %d",
886 symbolInstance.m_Reference, symbolInstance.m_Unit );
887 }
888 else if( !symbol->GetInstances().empty() )
889 {
890 // When a schematic is opened as a different project (e.g., a subsheet opened
891 // directly from File Browser), use the first available instance data.
892 // This provides better UX than showing unannotated references.
893 const SCH_SYMBOL_INSTANCE& firstInstance = symbol->GetInstances()[0];
894 symbolInstance.m_Reference = firstInstance.m_Reference;
895 symbolInstance.m_Unit = firstInstance.m_Unit;
896
897 wxLogTrace( traceSchSheetPaths,
898 " Using first available instance: ref=%s, unit=%d",
899 symbolInstance.m_Reference, symbolInstance.m_Unit );
900 }
901 else
902 {
903 // Fall back to the symbol's reference field and unit if no instance data exists.
904 SCH_FIELD* refField = symbol->GetField( FIELD_T::REFERENCE );
905 symbolInstance.m_Reference = refField->GetText();
906 symbolInstance.m_Unit = symbol->GetUnit();
907
908 wxLogTrace( traceSchSheetPaths,
909 " No instance data: Using reference '%s' from field, unit %d",
910 symbolInstance.m_Reference, symbolInstance.m_Unit );
911 }
912
913 symbolInstance.m_ProjectName = aProjectName;
914 symbolInstance.m_Path = Path();
915 symbol->AddHierarchicalReference( symbolInstance );
916
917 wxLogTrace( traceSchSheetPaths,
918 " Created instance: ref=%s, path=%s",
919 symbolInstance.m_Reference, symbolInstance.m_Path.AsString() );
920 }
921 else
922 {
923 wxLogTrace( traceSchSheetPaths,
924 " Symbol %s already has instance: ref=%s, path=%s",
925 symbol->m_Uuid.AsString(),
926 symbolInstance.m_Reference,
927 symbolInstance.m_Path.AsString() );
928 }
929 }
930}
931
932
934{
935 wxCHECK( m_sheets.size() > 1, /* void */ );
936
937 wxFileName sheetFileName = Last()->GetFileName();
938
939 // If the sheet file name is absolute, then the user requested is so don't make it relative.
940 if( sheetFileName.IsAbsolute() )
941 return;
942
943 SCH_SCREEN* screen = LastScreen();
944 SCH_SCREEN* parentScreen = m_sheets[ m_sheets.size() - 2 ]->GetScreen();
945
946 wxCHECK( screen && parentScreen, /* void */ );
947
948 wxFileName fileName = screen->GetFileName();
949 wxFileName parentFileName = parentScreen->GetFileName();
950
951 // SCH_SCREEN file names must be absolute. If they are not, someone set them incorrectly
952 // on load or on creation.
953 wxCHECK( fileName.IsAbsolute() && parentFileName.IsAbsolute(), /* void */ );
954
955 if( fileName.GetPath() == parentFileName.GetPath() )
956 {
957 Last()->SetFileName( fileName.GetFullName() );
958 }
959 else if( fileName.MakeRelativeTo( parentFileName.GetPath() ) )
960 {
961 Last()->SetFileName( fileName.GetFullPath() );
962 }
963 else
964 {
965 Last()->SetFileName( screen->GetFileName() );
966 }
967
968 wxLogTrace( tracePathsAndFiles,
969 wxT( "\n File name: '%s'"
970 "\n parent file name '%s',"
971 "\n sheet '%s' file name '%s'." ),
972 screen->GetFileName(), parentScreen->GetFileName(), PathHumanReadable(),
973 Last()->GetFileName() );
974}
975
976
978{
979 if( aSheet != nullptr )
980 BuildSheetList( aSheet, false );
981}
982
983
984void SCH_SHEET_LIST::BuildSheetList( SCH_SHEET* aSheet, bool aCheckIntegrity )
985{
986 if( !aSheet )
987 return;
988
989 wxLogTrace( traceSchSheetPaths,
990 "BuildSheetList called with sheet '%s' (UUID=%s, isVirtualRoot=%d)",
991 aSheet->GetName(),
992 aSheet->m_Uuid.AsString(),
993 aSheet->m_Uuid == niluuid ? 1 : 0 );
994
995 // Special handling for virtual root: process its children without adding the root itself
996 if( aSheet->IsVirtualRootSheet() )
997 {
998 wxLogTrace( traceSchSheetPaths, " Skipping virtual root, processing children only" );
999
1000 if( aSheet->GetScreen() )
1001 {
1002 std::vector<SCH_ITEM*> childSheets;
1003 aSheet->GetScreen()->GetSheets( &childSheets );
1004
1005 for( SCH_ITEM* item : childSheets )
1006 {
1007 SCH_SHEET* sheet = static_cast<SCH_SHEET*>( item );
1008 BuildSheetList( sheet, aCheckIntegrity );
1009 }
1010 }
1011
1012 return;
1013 }
1014
1015 std::vector<SCH_SHEET*> badSheets;
1016
1017 m_currentSheetPath.push_back( aSheet );
1018 m_currentSheetPath.SetVirtualPageNumber( static_cast<int>( size() ) + 1 );
1020
1021 if( m_currentSheetPath.LastScreen() )
1022 {
1023 wxString parentFileName = aSheet->GetFileName();
1024 std::vector<SCH_ITEM*> childSheets;
1025 m_currentSheetPath.LastScreen()->GetSheets( &childSheets );
1026
1027 for( SCH_ITEM* item : childSheets )
1028 {
1029 SCH_SHEET* sheet = static_cast<SCH_SHEET*>( item );
1030
1031 if( aCheckIntegrity )
1032 {
1033 if( !m_currentSheetPath.TestForRecursion( sheet->GetFileName(), parentFileName ) )
1034 BuildSheetList( sheet, true );
1035 else
1036 badSheets.push_back( sheet );
1037 }
1038 else
1039 {
1040 // If we are not performing a full recursion test, at least check if we are in
1041 // a simple recursion scenario to prevent stack overflow crashes
1042 wxCHECK2_MSG( sheet->GetFileName() != aSheet->GetFileName(), continue,
1043 wxT( "Recursion prevented in SCH_SHEET_LIST::BuildSheetList" ) );
1044
1045 BuildSheetList( sheet, false );
1046 }
1047 }
1048 }
1049
1050 if( aCheckIntegrity )
1051 {
1052 for( SCH_SHEET* sheet : badSheets )
1053 {
1054 m_currentSheetPath.LastScreen()->Remove( sheet );
1055 m_currentSheetPath.LastScreen()->SetContentModified();
1056 }
1057 }
1058
1059 m_currentSheetPath.pop_back();
1060}
1061
1062
1063void SCH_SHEET_LIST::SortByHierarchicalPageNumbers( bool aUpdateVirtualPageNums )
1064{
1065 for( const SCH_SHEET_PATH& path : *this )
1066 path.CachePageNumber();
1067
1068 std::sort( begin(), end(),
1069 []( const SCH_SHEET_PATH& a, const SCH_SHEET_PATH& b ) -> bool
1070 {
1071 // Find the divergence point in the paths
1072 size_t common_len = 0;
1073 size_t min_len = std::min( a.size(), b.size() );
1074
1075 while( common_len < min_len && a.at( common_len )->m_Uuid == b.at( common_len )->m_Uuid )
1076 common_len++;
1077
1078 // If one path is a prefix of the other, the shorter one comes first
1079 // This ensures parents come before children
1080 if( common_len == a.size() )
1081 return true; // a is a prefix of b - a is the parent
1082 if( common_len == b.size() )
1083 return false; // b is a prefix of a - b is the parent
1084
1085 // Paths diverge at common_len
1086 // If they share the same parent, sort by page number
1087 // This ensures siblings are sorted by page number
1088 SCH_SHEET* sheet_a = a.at( common_len );
1089 SCH_SHEET* sheet_b = b.at( common_len );
1090
1091 // Create partial paths to get to these sheets for page number comparison
1092 KIID_PATH ancestor;
1093 for( size_t i = 0; i < common_len; i++ )
1094 ancestor.push_back( a.at( i )->m_Uuid );
1095
1096 // Compare page numbers - use the last sheet's page number
1097 wxString page_a = sheet_a->getPageNumber( ancestor );
1098 wxString page_b = sheet_b->getPageNumber( ancestor );
1099
1100 int retval = SCH_SHEET::ComparePageNum( page_a, page_b );
1101
1102 if( retval != 0 )
1103 return retval < 0;
1104
1105 // If page numbers are the same, use virtual page numbers as a tie-breaker
1107 return true;
1108 else if( a.GetVirtualPageNumber() > b.GetVirtualPageNumber() )
1109 return false;
1110
1111 // Finally, use UUIDs for stable ordering when everything else is equal
1112 return a.GetCurrentHash() < b.GetCurrentHash();
1113 } );
1114
1115 if( aUpdateVirtualPageNums )
1116 {
1117 int virtualPageNum = 1;
1118
1119 for( SCH_SHEET_PATH& sheet : *this )
1120 sheet.SetVirtualPageNumber( virtualPageNum++ );
1121 }
1122}
1123
1124
1125void SCH_SHEET_LIST::SortByPageNumbers( bool aUpdateVirtualPageNums )
1126{
1127 for( const SCH_SHEET_PATH& path : *this )
1128 path.CachePageNumber();
1129
1130 std::sort( begin(), end(),
1131 []( const SCH_SHEET_PATH& a, const SCH_SHEET_PATH& b ) -> bool
1132 {
1134 b.GetCachedPageNumber() );
1135
1136 if( retval < 0 )
1137 return true;
1138 else if( retval > 0 )
1139 return false;
1140
1142 return true;
1143 else if( a.GetVirtualPageNumber() > b.GetVirtualPageNumber() )
1144 return false;
1145
1146 // Enforce strict ordering. If the page numbers are the same, use UUIDs
1147 return a.GetCurrentHash() < b.GetCurrentHash();
1148 } );
1149
1150 if( aUpdateVirtualPageNums )
1151 {
1152 int virtualPageNum = 1;
1153
1154 for( SCH_SHEET_PATH& sheet : *this )
1155 sheet.SetVirtualPageNumber( virtualPageNum++ );
1156 }
1157}
1158
1159
1160bool SCH_SHEET_LIST::NameExists( const wxString& aSheetName ) const
1161{
1162 for( const SCH_SHEET_PATH& sheet : *this )
1163 {
1164 if( sheet.Last()->GetName() == aSheetName )
1165 return true;
1166 }
1167
1168 return false;
1169}
1170
1171
1172bool SCH_SHEET_LIST::PageNumberExists( const wxString& aPageNumber ) const
1173{
1174 for( const SCH_SHEET_PATH& sheet : *this )
1175 {
1176 if( sheet.GetPageNumber() == aPageNumber )
1177 return true;
1178 }
1179
1180 return false;
1181}
1182
1183
1184void SCH_SHEET_LIST::TrimToPageNumbers( const std::vector<wxString>& aPageInclusions )
1185{
1186 auto it = std::remove_if( begin(), end(),
1187 [&]( const SCH_SHEET_PATH& sheet )
1188 {
1189 return std::find( aPageInclusions.begin(),
1190 aPageInclusions.end(),
1191 sheet.GetPageNumber() ) == aPageInclusions.end();
1192 } );
1193
1194 erase( it, end() );
1195}
1196
1197
1199{
1200 wxString pageNumber;
1201
1202 // Find the next available page number by checking all existing page numbers
1203 std::set<int> usedPageNumbers;
1204
1205 for( const SCH_SHEET_PATH& path : *this )
1206 {
1207 wxString existingPageNum = path.GetPageNumber();
1208 long pageNum = 0;
1209
1210 if( existingPageNum.ToLong( &pageNum ) && pageNum > 0 )
1211 usedPageNumbers.insert( static_cast<int>( pageNum ) );
1212 }
1213
1214 // Find the first available number starting from 1
1215 int nextAvailable = 1;
1216
1217 while( usedPageNumbers.count( nextAvailable ) > 0 )
1218 nextAvailable++;
1219
1220 pageNumber.Printf( wxT( "%d" ), nextAvailable );
1221 return pageNumber;
1222}
1223
1224
1226{
1227 for( const SCH_SHEET_PATH& sheet : *this )
1228 {
1229 if( sheet.LastScreen() && sheet.LastScreen()->IsContentModified() )
1230 return true;
1231 }
1232
1233 return false;
1234}
1235
1236
1238{
1239 for( const SCH_SHEET_PATH& sheet : *this )
1240 {
1241 if( sheet.LastScreen() )
1242 sheet.LastScreen()->SetContentModified( false );
1243 }
1244}
1245
1246
1247SCH_ITEM* SCH_SHEET_LIST::ResolveItem( const KIID& aID, SCH_SHEET_PATH* aPathOut, bool aAllowNullptrReturn ) const
1248{
1249 for( const SCH_SHEET_PATH& sheet : *this )
1250 {
1251 SCH_ITEM* item = sheet.ResolveItem( aID );
1252
1253 if( item )
1254 {
1255 if( aPathOut )
1256 *aPathOut = sheet;
1257
1258 return item;
1259 }
1260 }
1261
1262 // Not found; weak reference has been deleted.
1263 if( aAllowNullptrReturn )
1264 return nullptr;
1265 else
1267}
1268
1269
1271{
1272 for( SCH_ITEM* aItem : LastScreen()->Items() )
1273 {
1274 if( aItem->m_Uuid == aID )
1275 return aItem;
1276
1277 SCH_ITEM* childMatch = nullptr;
1278
1279 aItem->RunOnChildren(
1280 [&]( SCH_ITEM* aChild )
1281 {
1282 if( aChild->m_Uuid == aID )
1283 childMatch = aChild;
1284 },
1286
1287 if( childMatch )
1288 return childMatch;
1289 }
1290
1291 return nullptr;
1292}
1293
1294
1295void SCH_SHEET_LIST::FillItemMap( std::map<KIID, EDA_ITEM*>& aMap )
1296{
1297 for( const SCH_SHEET_PATH& sheet : *this )
1298 {
1299 SCH_SCREEN* screen = sheet.LastScreen();
1300
1301 for( SCH_ITEM* aItem : screen->Items() )
1302 {
1303 aMap[ aItem->m_Uuid ] = aItem;
1304
1305 aItem->RunOnChildren(
1306 [&]( SCH_ITEM* aChild )
1307 {
1308 aMap[ aChild->m_Uuid ] = aChild;
1309 },
1311 }
1312 }
1313}
1314
1315
1317{
1318 // List of reference for power symbols
1319 SCH_REFERENCE_LIST references;
1320
1321 // Map of locked symbols (not used, but needed by Annotate()
1322 SCH_MULTI_UNIT_REFERENCE_MAP lockedSymbols;
1323
1324 // Build the list of power symbols:
1325 for( SCH_SHEET_PATH& sheet : *this )
1326 {
1327 for( SCH_ITEM* item : sheet.LastScreen()->Items().OfType( SCH_SYMBOL_T ) )
1328 {
1329 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
1330 LIB_SYMBOL* libSymbol = symbol->GetLibSymbolRef().get();
1331
1332 if( libSymbol && libSymbol->IsPower() )
1333 {
1334 SCH_REFERENCE schReference( symbol, sheet );
1335 references.AddItem( schReference );
1336 }
1337 }
1338 }
1339
1340 // Find duplicate, and silently clear annotation of duplicate
1341 std::map<wxString, int> ref_list; // stores the existing references
1342
1343 for( unsigned ii = 0; ii< references.GetCount(); ++ii )
1344 {
1345 wxString curr_ref = references[ii].GetRef();
1346
1347 if( curr_ref.IsEmpty() )
1348 continue;
1349
1350 if( ref_list.find( curr_ref ) == ref_list.end() )
1351 {
1352 ref_list[curr_ref] = ii;
1353 continue;
1354 }
1355
1356 // Possible duplicate, if the ref ends by a number:
1357 if( curr_ref.Last() < '0' && curr_ref.Last() > '9' )
1358 continue; // not annotated
1359
1360 // Duplicate: clear annotation by removing the number ending the ref
1361 while( !curr_ref.IsEmpty() && curr_ref.Last() >= '0' && curr_ref.Last() <= '9' )
1362 curr_ref.RemoveLast();
1363
1364 references[ii].SetRef( curr_ref );
1365 }
1366
1367 // Break full symbol reference into name (prefix) and number:
1368 // example: IC1 become IC, and 1
1369 references.SplitReferences();
1370
1371 // Ensure all power symbols have the reference starting by '#'
1372 // (Not sure this is really useful)
1373 for( unsigned ii = 0; ii< references.GetCount(); ++ii )
1374 {
1375 SCH_REFERENCE& ref_unit = references[ii];
1376
1377 if( ref_unit.GetRef()[0] != '#' )
1378 {
1379 wxString new_ref = "#" + ref_unit.GetRef();
1380 ref_unit.SetRef( new_ref );
1381 ref_unit.SetRefNum( ii );
1382 }
1383 }
1384}
1385
1386
1388 bool aForceIncludeOrphanSymbols ) const
1389{
1390 for( const SCH_SHEET_PATH& sheet : *this )
1391 sheet.GetSymbols( aReferences, aSymbolFilter, aForceIncludeOrphanSymbols );
1392}
1393
1394
1396 SYMBOL_FILTER aSymbolFilter, bool aForceIncludeOrphanSymbols ) const
1397{
1398 for( const SCH_SHEET_PATH& sheet : *this )
1399 {
1400 if( sheet.IsContainedWithin( aSheetPath ) )
1401 sheet.GetSymbols( aReferences, aSymbolFilter, aForceIncludeOrphanSymbols );
1402 }
1403}
1404
1405
1406void SCH_SHEET_LIST::GetSheetsWithinPath( std::vector<SCH_SHEET_PATH>& aSheets,
1407 const SCH_SHEET_PATH& aSheetPath ) const
1408{
1409 for( const SCH_SHEET_PATH& sheet : *this )
1410 {
1411 if( sheet.IsContainedWithin( aSheetPath ) )
1412 aSheets.push_back( sheet );
1413 }
1414}
1415
1416
1417std::optional<SCH_SHEET_PATH> SCH_SHEET_LIST::GetSheetPathByKIIDPath( const KIID_PATH& aPath,
1418 bool aIncludeLastSheet ) const
1419{
1420 for( const SCH_SHEET_PATH& sheet : *this )
1421 {
1422 KIID_PATH testPath = sheet.Path();
1423
1424 if( !aIncludeLastSheet )
1425 testPath.pop_back();
1426
1427 if( testPath == aPath )
1428 return SCH_SHEET_PATH( sheet );
1429 }
1430
1431 return std::nullopt;
1432}
1433
1434
1436{
1437 for( auto it = begin(); it != end(); ++it )
1438 {
1440 ( *it ).GetMultiUnitSymbols( tempMap, aSymbolFilter );
1441
1442 for( SCH_MULTI_UNIT_REFERENCE_MAP::value_type& pair : tempMap )
1443 {
1444 // Merge this list into the main one
1445 unsigned n_refs = pair.second.GetCount();
1446
1447 for( unsigned thisRef = 0; thisRef < n_refs; ++thisRef )
1448 aRefList[pair.first].AddItem( pair.second[thisRef] );
1449 }
1450 }
1451}
1452
1453
1454bool SCH_SHEET_LIST::TestForRecursion( const SCH_SHEET_LIST& aSrcSheetHierarchy,
1455 const wxString& aDestFileName )
1456{
1457 if( empty() )
1458 return false;
1459
1460 SCHEMATIC* sch = at( 0 ).LastScreen()->Schematic();
1461
1462 wxCHECK_MSG( sch, false, "No SCHEMATIC found in SCH_SHEET_LIST::TestForRecursion!" );
1463
1464 wxFileName rootFn = sch->GetFileName();
1465 wxFileName destFn = aDestFileName;
1466
1467 if( destFn.IsRelative() )
1468 destFn.MakeAbsolute( rootFn.GetPath() );
1469
1470 // Test each SCH_SHEET_PATH in this SCH_SHEET_LIST for potential recursion.
1471 for( unsigned i = 0; i < size(); i++ )
1472 {
1473 // Test each SCH_SHEET_PATH in the source sheet.
1474 for( unsigned j = 0; j < aSrcSheetHierarchy.size(); j++ )
1475 {
1476 const SCH_SHEET_PATH* sheetPath = &aSrcSheetHierarchy[j];
1477
1478 for( unsigned k = 0; k < sheetPath->size(); k++ )
1479 {
1480 if( at( i ).TestForRecursion( sheetPath->GetSheet( k )->GetFileName(),
1481 aDestFileName ) )
1482 {
1483 return true;
1484 }
1485 }
1486 }
1487 }
1488
1489 // The source sheet file can safely be added to the destination sheet file.
1490 return false;
1491}
1492
1493
1495{
1496 for( SCH_SHEET_PATH& path : *this )
1497 {
1498 if( path.Path() == aPath->Path() )
1499 return &path;
1500 }
1501
1502 return nullptr;
1503}
1504
1505
1507{
1508 for( SCH_SHEET_PATH& sheetpath : *this )
1509 {
1510 if( sheetpath.LastScreen() == aScreen )
1511 return sheetpath;
1512 }
1513
1514 return SCH_SHEET_PATH();
1515}
1516
1517
1519{
1520 SCH_SHEET_LIST retval;
1521
1522 for( const SCH_SHEET_PATH& sheetpath : *this )
1523 {
1524 if( sheetpath.LastScreen() == aScreen )
1525 retval.push_back( sheetpath );
1526 }
1527
1528 return retval;
1529}
1530
1531
1533 const std::vector<SCH_SYMBOL_INSTANCE>& aSymbolInstances )
1534{
1535 for( SCH_SHEET_PATH& sheetPath : *this )
1536 {
1537 for( SCH_ITEM* item : sheetPath.LastScreen()->Items().OfType( SCH_SYMBOL_T ) )
1538 {
1539 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
1540
1541 wxCHECK2( symbol, continue );
1542
1543 KIID_PATH sheetPathWithSymbolUuid = sheetPath.Path();
1544 sheetPathWithSymbolUuid.push_back( symbol->m_Uuid );
1545
1546 auto it = std::find_if( aSymbolInstances.begin(), aSymbolInstances.end(),
1547 [ sheetPathWithSymbolUuid ]( const SCH_SYMBOL_INSTANCE& r ) -> bool
1548 {
1549 return sheetPathWithSymbolUuid == r.m_Path;
1550 } );
1551
1552 if( it == aSymbolInstances.end() )
1553 {
1554 wxLogTrace( traceSchSheetPaths, "No symbol instance found for symbol '%s'",
1555 sheetPathWithSymbolUuid.AsString() );
1556 continue;
1557 }
1558
1559 // Symbol instance paths are stored and looked up in memory with the root path so use
1560 // the full path here.
1561 symbol->AddHierarchicalReference( sheetPath.Path(), it->m_Reference, it->m_Unit );
1562 symbol->GetField( FIELD_T::REFERENCE )->SetText( it->m_Reference );
1563
1564 if( !it->m_Value.IsEmpty() )
1565 symbol->SetValueFieldText( it->m_Value );
1566
1567 if( !it->m_Footprint.IsEmpty() )
1568 symbol->SetFootprintFieldText( it->m_Footprint );
1569
1570 symbol->UpdatePrefix();
1571 }
1572 }
1573}
1574
1575
1576void SCH_SHEET_LIST::UpdateSheetInstanceData( const std::vector<SCH_SHEET_INSTANCE>& aSheetInstances )
1577{
1578
1579 for( SCH_SHEET_PATH& path : *this )
1580 {
1581 SCH_SHEET* sheet = path.Last();
1582
1583 wxCHECK2( sheet && path.Last(), continue );
1584
1585 auto it = std::find_if( aSheetInstances.begin(), aSheetInstances.end(),
1586 [&path]( const SCH_SHEET_INSTANCE& r ) -> bool
1587 {
1588 return path.Path() == r.m_Path;
1589 } );
1590
1591 if( it == aSheetInstances.end() )
1592 {
1593 wxLogTrace( traceSchSheetPaths, "No sheet instance found for path '%s'",
1594 path.Path().AsString() );
1595 continue;
1596 }
1597
1598 wxLogTrace( traceSchSheetPaths, "Setting sheet '%s' instance '%s' page number '%s'",
1599 ( sheet->GetName().IsEmpty() ) ? wxString( wxT( "root" ) ) : sheet->GetName(),
1600 path.Path().AsString(), it->m_PageNumber );
1601 path.SetPageNumber( it->m_PageNumber );
1602 }
1603}
1604
1605
1606std::vector<KIID_PATH> SCH_SHEET_LIST::GetPaths() const
1607{
1608 std::vector<KIID_PATH> paths;
1609
1610 for( const SCH_SHEET_PATH& sheetPath : *this )
1611 paths.emplace_back( sheetPath.Path() );
1612
1613 return paths;
1614}
1615
1616
1617std::vector<SCH_SHEET_INSTANCE> SCH_SHEET_LIST::GetSheetInstances() const
1618{
1619 std::vector<SCH_SHEET_INSTANCE> retval;
1620
1621 for( const SCH_SHEET_PATH& path : *this )
1622 {
1623 const SCH_SHEET* sheet = path.Last();
1624
1625 wxCHECK2( sheet, continue );
1626
1627 SCH_SHEET_INSTANCE instance;
1628 SCH_SHEET_PATH tmpPath = path;
1629
1630 tmpPath.pop_back();
1631 instance.m_Path = tmpPath.Path();
1632 instance.m_PageNumber = path.GetPageNumber();
1633
1634 retval.push_back( std::move( instance ) );
1635 }
1636
1637 return retval;
1638}
1639
1640
1642{
1643 for( const SCH_SHEET_PATH& instance : *this )
1644 {
1645 if( !instance.GetPageNumber().IsEmpty() )
1646 return false;
1647 }
1648
1649 return true;
1650}
1651
1652
1654{
1655 // Don't accidentally renumber existing sheets.
1656 wxCHECK( AllSheetPageNumbersEmpty(), /* void */ );
1657
1658 wxString tmp;
1659 int pageNumber = 1;
1660
1661 for( SCH_SHEET_PATH& instance : *this )
1662 {
1663 if( instance.Last()->IsVirtualRootSheet() )
1664 continue;
1665
1666 tmp.Printf( "%d", pageNumber );
1667 instance.SetPageNumber( tmp );
1668 pageNumber += 1;
1669 }
1670}
1671
1672
1674 const wxString& aProjectName )
1675{
1676 for( SCH_SHEET_PATH& sheetPath : *this )
1677 sheetPath.AddNewSymbolInstances( aPrefixSheetPath, aProjectName );
1678}
1679
1680
1682{
1683 for( SCH_SHEET_PATH& sheetPath : *this )
1684 sheetPath.RemoveSymbolInstances( aPrefixSheetPath );
1685}
1686
1687
1689 int aLastVirtualPageNumber )
1690{
1691 wxString pageNumber;
1692 int lastUsedPageNumber = 1;
1693 int nextVirtualPageNumber = aLastVirtualPageNumber;
1694
1695 // Fetch the list of page numbers already in use.
1696 std::vector< wxString > usedPageNumbers;
1697
1698 if( aPrefixSheetPath.size() )
1699 {
1700 SCH_SHEET_LIST prefixHierarchy( aPrefixSheetPath.at( 0 ) );
1701
1702 for( const SCH_SHEET_PATH& path : prefixHierarchy )
1703 {
1704 pageNumber = path.GetPageNumber();
1705
1706 if( !pageNumber.IsEmpty() )
1707 usedPageNumbers.emplace_back( pageNumber );
1708 }
1709 }
1710
1711 for( SCH_SHEET_PATH& sheetPath : *this )
1712 {
1713 KIID_PATH tmp = sheetPath.Path();
1714 SCH_SHEET_PATH newSheetPath( aPrefixSheetPath );
1715
1716 // Prefix the new hierarchical path.
1717 newSheetPath = newSheetPath + sheetPath;
1718
1719 // Sheets cannot have themselves in the path.
1720 tmp.pop_back();
1721
1722 SCH_SHEET* sheet = sheetPath.Last();
1723
1724 wxCHECK2( sheet, continue );
1725
1726 nextVirtualPageNumber += 1;
1727
1728 SCH_SHEET_INSTANCE instance;
1729
1730 // Add the instance if it doesn't already exist
1731 if( !sheet->getInstance( instance, tmp, true ) )
1732 {
1733 sheet->addInstance( tmp );
1734 sheet->getInstance( instance, tmp, true );
1735 }
1736
1737 // Get a new page number if we don't have one
1738 if( instance.m_PageNumber.IsEmpty() )
1739 {
1740 // Generate the next available page number.
1741 do
1742 {
1743 pageNumber.Printf( wxT( "%d" ), lastUsedPageNumber );
1744 lastUsedPageNumber += 1;
1745 } while( std::find( usedPageNumbers.begin(), usedPageNumbers.end(), pageNumber ) !=
1746 usedPageNumbers.end() );
1747
1748 instance.m_PageNumber = pageNumber;
1749 newSheetPath.SetVirtualPageNumber( nextVirtualPageNumber );
1750 }
1751
1752 newSheetPath.SetPageNumber( instance.m_PageNumber );
1753 usedPageNumbers.push_back( instance.m_PageNumber );
1754 }
1755}
1756
1757
1758void SCH_SHEET_LIST::CheckForMissingSymbolInstances( const wxString& aProjectName )
1759{
1760 wxLogTrace( traceSchSheetPaths,
1761 "SCH_SHEET_LIST::CheckForMissingSymbolInstances: Processing %zu sheet paths",
1762 size() );
1763
1764 for( SCH_SHEET_PATH& sheetPath : *this )
1765 {
1766 wxLogTrace( traceSchSheetPaths,
1767 " Processing sheet path: '%s' (size=%zu, KIID_PATH='%s')",
1768 sheetPath.PathHumanReadable( false ),
1769 sheetPath.size(),
1770 sheetPath.Path().AsString() );
1771 sheetPath.CheckForMissingSymbolInstances( aProjectName );
1772 }
1773}
1774
1775
1777{
1778 int lastVirtualPageNumber = 1;
1779
1780 for( const SCH_SHEET_PATH& sheetPath : *this )
1781 {
1782 if( sheetPath.GetVirtualPageNumber() > lastVirtualPageNumber )
1783 lastVirtualPageNumber = sheetPath.GetVirtualPageNumber();
1784 }
1785
1786 return lastVirtualPageNumber;
1787}
1788
1789
1790bool SCH_SHEET_LIST::HasPath( const KIID_PATH& aPath ) const
1791{
1792 for( const SCH_SHEET_PATH& path : *this )
1793 {
1794 if( path.Path() == aPath )
1795 return true;
1796 }
1797
1798 return false;
1799}
1800
1801
1802bool SCH_SHEET_LIST::ContainsSheet( const SCH_SHEET* aSheet ) const
1803{
1804 for( const SCH_SHEET_PATH& path : *this )
1805 {
1806 for( size_t i = 0; i < path.size(); i++ )
1807 {
1808 if( path.at( i ) == aSheet )
1809 return true;
1810 }
1811 }
1812
1813 return false;
1814}
1815
1816
1817std::optional<SCH_SHEET_PATH> SCH_SHEET_LIST::GetOrdinalPath( const SCH_SCREEN* aScreen ) const
1818{
1819 // Sheet paths with sheets that do not have a screen object are not valid.
1820 if( !aScreen )
1821 return std::nullopt;
1822
1823 for( const SCH_SHEET_PATH& path: *this )
1824 {
1825 if( path.LastScreen() == aScreen )
1826 return std::optional<SCH_SHEET_PATH>( path );
1827 }
1828
1829 return std::nullopt;
1830}
bool IsContentModified() const
Definition base_screen.h:60
void SetContentModified(bool aModified=true)
Definition base_screen.h:59
wxString GetClass() const override
Return the class name.
void SetPosition(const VECTOR2I &) override
static DELETED_SHEET_ITEM * GetInstance()
double Similarity(const SCH_ITEM &aOther) const override
Return a measure of how likely the other object is to represent the same object.
void Rotate(const VECTOR2I &aCenter, bool aRotateCCW) override
Rotate the item around aCenter 90 degrees in the clockwise direction.
void Move(const VECTOR2I &aMoveVector) override
Move the item by aMoveVector to a new position.
wxString GetItemDescription(UNITS_PROVIDER *aUnitsProvider, bool aFull) const override
Return a user-visible description string of this item.
bool operator==(const SCH_ITEM &aOther) const override
void MirrorVertically(int aCenter) override
Mirror item vertically about aCenter.
void MirrorHorizontally(int aCenter) override
Mirror item horizontally about aCenter.
const KIID m_Uuid
Definition eda_item.h:528
KICAD_T Type() const
Returns the type of object.
Definition eda_item.h:112
virtual void UpdateHatching() const
virtual bool IsVisible() const
Definition eda_text.h:212
virtual void SetVisible(bool aVisible)
Definition eda_text.cpp:385
EE_TYPE OfType(KICAD_T aType) const
Definition sch_rtree.h:225
wxString AsString() const
Definition kiid.cpp:365
Definition kiid.h:48
wxString AsString() const
Definition kiid.cpp:244
Define a library symbol object.
Definition lib_symbol.h:83
bool IsPower() const override
int GetUnitCount() const override
Holds all the data relating to one schematic.
Definition schematic.h:89
wxString GetFileName() const
Helper to retrieve the filename from the root sheet screen.
SCHEMATIC_SETTINGS & Settings() const
wxString GetCurrentVariant() const
Return the current variant being edited.
VECTOR2I GetPosition() const override
virtual const wxString & GetText() const override
Return the string associated with the text object.
Definition sch_field.h:126
wxString GetShownText(const SCH_SHEET_PATH *aPath, bool aAllowExtraText, int aDepth=0, const wxString &aVariantName=wxEmptyString) const
void SetText(const wxString &aText) override
SCH_FIELD * GetField(FIELD_T aFieldType)
Return a mandatory field in this label.
Base class for any item which can be embedded within the SCHEMATIC container class,...
Definition sch_item.h:168
virtual void RunOnChildren(const std::function< void(SCH_ITEM *)> &aFunction, RECURSE_MODE aMode)
Definition sch_item.h:634
SCHEMATIC * Schematic() const
Search the item hierarchy to find a SCHEMATIC.
Definition sch_item.cpp:272
int GetUnit() const
Definition sch_item.h:239
virtual void SetUnit(int aUnit)
Definition sch_item.h:238
SCH_ITEM(EDA_ITEM *aParent, KICAD_T aType, int aUnit=0, int aBodyStyle=0)
Definition sch_item.cpp:56
void AutoplaceFields(SCH_SCREEN *aScreen, AUTOPLACE_ALGO aAlgo) override
std::vector< SCH_FIELD > & GetFields()
Definition sch_label.h:214
Container to create a flattened list of symbols because in a complex hierarchy, a symbol can be used ...
void SplitReferences()
Attempt to split all reference designators into a name (U) and number (1).
void AddItem(const SCH_REFERENCE &aItem)
A helper to define a symbol's reference designator in a schematic.
void SetRef(const wxString &aReference)
void SetRefNum(int aNum)
wxString GetRef() const
void SetSheetNumber(int aSheetNumber)
EE_RTREE & Items()
Get the full RTree, usually for iterating.
Definition sch_screen.h:119
const wxString & GetFileName() const
Definition sch_screen.h:154
SCHEMATIC * Schematic() const
void Update(SCH_ITEM *aItem, bool aUpdateLibSymbol=true)
Update aItem's bounding box in the tree.
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,...
std::optional< SCH_SHEET_PATH > GetSheetPathByKIIDPath(const KIID_PATH &aPath, bool aIncludeLastSheet=true) const
Finds a SCH_SHEET_PATH that matches the provided KIID_PATH.
SCH_ITEM * ResolveItem(const KIID &aID, SCH_SHEET_PATH *aPathOut=nullptr, bool aAllowNullptrReturn=false) const
Fetch a SCH_ITEM by ID.
std::optional< SCH_SHEET_PATH > GetOrdinalPath(const SCH_SCREEN *aScreen) const
Return the ordinal sheet path of aScreen.
void FillItemMap(std::map< KIID, EDA_ITEM * > &aMap)
Fill an item cache for temporary use when many items need to be fetched.
SCH_SHEET_PATH m_currentSheetPath
void TrimToPageNumbers(const std::vector< wxString > &aPageInclusions)
Truncates the list by removing sheet's with page numbers not in the given list.
void SortByPageNumbers(bool aUpdateVirtualPageNums=true)
Sort the list of sheets by page number.
void AddNewSymbolInstances(const SCH_SHEET_PATH &aPrefixSheetPath, const wxString &aProjectName)
Attempt to add new symbol instances for all symbols in this list of sheet paths prefixed with aPrefix...
bool NameExists(const wxString &aSheetName) const
void GetSymbolsWithinPath(SCH_REFERENCE_LIST &aReferences, const SCH_SHEET_PATH &aSheetPath, SYMBOL_FILTER aSymbolFilter, bool aForceIncludeOrphanSymbols=false) const
Add a SCH_REFERENCE object to aReferences for each symbol in the list of sheets that are contained wi...
std::vector< SCH_SHEET_INSTANCE > GetSheetInstances() const
Fetch the instance information for all of the sheets in the hierarchy.
void UpdateSheetInstanceData(const std::vector< SCH_SHEET_INSTANCE > &aSheetInstances)
Update all of the sheet instance information using aSheetInstances.
void SetInitialPageNumbers()
Set initial sheet page numbers.
void RemoveSymbolInstances(const SCH_SHEET_PATH &aPrefixSheetPath)
SCH_SHEET_LIST FindAllSheetsForScreen(const SCH_SCREEN *aScreen) const
Return a SCH_SHEET_LIST with a copy of all the SCH_SHEET_PATH using a particular screen.
wxString GetNextPageNumber() const
bool AllSheetPageNumbersEmpty() const
Check all of the sheet instance for empty page numbers.
bool IsModified() const
Check the entire hierarchy for any modifications.
SCH_SHEET_LIST(SCH_SHEET *aSheet=nullptr)
Construct a flattened list of SCH_SHEET_PATH objects from aSheet.
void AnnotatePowerSymbols()
Silently annotate the not yet annotated power symbols of the entire hierarchy of the sheet path list.
int GetLastVirtualPageNumber() const
void UpdateSymbolInstanceData(const std::vector< SCH_SYMBOL_INSTANCE > &aSymbolInstances)
Update all of the symbol instance information using aSymbolInstances.
void GetSheetsWithinPath(std::vector< SCH_SHEET_PATH > &aSheets, const SCH_SHEET_PATH &aSheetPath) const
Add a SCH_SHEET_PATH object to aSheets for each sheet in the list that are contained within aSheetPat...
bool PageNumberExists(const wxString &aPageNumber) const
void SortByHierarchicalPageNumbers(bool aUpdateVirtualPageNums=true)
This works like SortByPageNumbers, but it sorts the sheets first by their hierarchical depth and then...
void AddNewSheetInstances(const SCH_SHEET_PATH &aPrefixSheetPath, int aLastVirtualPageNumber)
void GetMultiUnitSymbols(SCH_MULTI_UNIT_REFERENCE_MAP &aRefList, SYMBOL_FILTER aSymbolFilter) const
Add a SCH_REFERENCE_LIST object to aRefList for each same-reference set of multi-unit parts in the li...
bool ContainsSheet(const SCH_SHEET *aSheet) const
std::vector< KIID_PATH > GetPaths() const
void BuildSheetList(SCH_SHEET *aSheet, bool aCheckIntegrity)
Build the list of sheets and their sheet path from aSheet.
SCH_SHEET_PATH FindSheetForScreen(const SCH_SCREEN *aScreen)
Return the first SCH_SHEET_PATH object (not necessarily the only one) using a particular screen.
void CheckForMissingSymbolInstances(const wxString &aProjectName)
bool HasPath(const KIID_PATH &aPath) const
SCH_SHEET_PATH * FindSheetForPath(const SCH_SHEET_PATH *aPath)
Return a pointer to the first SCH_SHEET_PATH object (not necessarily the only one) matching the provi...
void GetSymbols(SCH_REFERENCE_LIST &aReferences, SYMBOL_FILTER aSymbolFilter, bool aForceIncludeOrphanSymbols=false) const
Add a SCH_REFERENCE object to aReferences for each symbol in the list of sheets.
bool TestForRecursion(const SCH_SHEET_LIST &aSrcSheetHierarchy, const wxString &aDestFileName)
Test every SCH_SHEET_PATH in this SCH_SHEET_LIST to verify if adding the sheets stored in aSrcSheetHi...
Handle access to a stack of flattened SCH_SHEET objects by way of a path for creating a flattened sch...
void AppendSymbol(SCH_REFERENCE_LIST &aReferences, SCH_SYMBOL *aSymbol, SYMBOL_FILTER aSymbolFilter, bool aForceIncludeOrphanSymbols=false) const
Append a SCH_REFERENCE object to aReferences based on aSymbol.
bool GetExcludedFromBOM() const
const SCH_SHEET * GetSheet(unsigned aIndex) const
bool empty() const
Forwarded method from std::vector.
int ComparePageNum(const SCH_SHEET_PATH &aSheetPathToTest) const
Compare sheets by their page number.
size_t GetCurrentHash() const
void GetMultiUnitSymbols(SCH_MULTI_UNIT_REFERENCE_MAP &aRefList, SYMBOL_FILTER aSymbolFilter) const
Add a SCH_REFERENCE_LIST object to aRefList for each same-reference set of multi-unit parts in the sh...
void GetSymbols(SCH_REFERENCE_LIST &aReferences, SYMBOL_FILTER aSymbolFilter, bool aForceIncludeOrphanSymbols=false) const
Adds SCH_REFERENCE object to aReferences for each symbol in the sheet.
bool operator==(const SCH_SHEET_PATH &d1) const
void AddNewSymbolInstances(const SCH_SHEET_PATH &aPrefixSheetPath, const wxString &aProjectName)
Attempt to add new symbol instances for all symbols in this sheet path prefixed with aPrefixSheetPath...
KIID_PATH Path() const
Get the sheet path as an KIID_PATH.
bool TestForRecursion(const wxString &aSrcFileName, const wxString &aDestFileName)
Test the SCH_SHEET_PATH file names to check adding the sheet stored in the file aSrcFileName to the s...
void UpdateAllScreenReferences() const
Update all the symbol references for this sheet path.
void MakeFilePathRelativeToParentSheet()
Make the sheet file name relative to its parent sheet.
SCH_ITEM * ResolveItem(const KIID &aID) const
Fetch a SCH_ITEM by ID.
wxString GetCachedPageNumber() const
std::vector< SCH_SHEET * > m_sheets
SCH_SCREEN * LastScreen()
int Cmp(const SCH_SHEET_PATH &aSheetPathToTest) const
Compare if this is the same sheet path as aSheetPathToTest.
void initFromOther(const SCH_SHEET_PATH &aOther)
wxString m_cached_page_number
wxString GetPageNumber() const
void RemoveSymbolInstances(const SCH_SHEET_PATH &aPrefixSheetPath)
void CheckForMissingSymbolInstances(const wxString &aProjectName)
bool IsContainedWithin(const SCH_SHEET_PATH &aSheetPathToTest) const
Check if this path is contained inside aSheetPathToTest.
SCH_SHEET * at(size_t aIndex) const
Forwarded method from std::vector.
void SetVirtualPageNumber(int aPageNumber)
Set the sheet instance virtual page number.
wxString PathHumanReadable(bool aUseShortRootName=true, bool aStripTrailingSeparator=false, bool aEscapeSheetNames=false) const
Return the sheet path in a human readable form made from the sheet names.
std::map< std::pair< wxString, wxString >, bool > m_recursion_test_cache
bool GetExcludedFromSim() const
wxString PathAsString() const
Return the path of time stamps which do not changes even when editing sheet parameters.
void AppendMultiUnitSymbol(SCH_MULTI_UNIT_REFERENCE_MAP &aRefList, SCH_SYMBOL *aSymbol, SYMBOL_FILTER aSymbolFilter) const
Append a SCH_REFERENCE_LIST object to aRefList based on aSymbol, storing same-reference set of multi-...
bool GetExcludedFromBoard() const
void SetPageNumber(const wxString &aPageNumber)
Set the sheet instance user definable page number.
SCH_SHEET_PATH & operator=(const SCH_SHEET_PATH &aOther)
int GetPageNumberAsInt() const
bool GetDNP() const
SCH_SHEET * Last() const
Return a pointer to the last SCH_SHEET of the list.
SCH_SHEET_PATH operator+(const SCH_SHEET_PATH &aOther)
int m_virtualPageNumber
Page numbers are maintained by the sheet load order.
void push_back(SCH_SHEET *aSheet)
Forwarded method from std::vector.
size_t size() const
Forwarded method from std::vector.
int GetVirtualPageNumber() const
void pop_back()
Forwarded method from std::vector.
void InitializeAttributes(const SCH_SHEET &aSheet)
Sheet symbol placed in a schematic, and is the entry point for a sub schematic.
Definition sch_sheet.h:48
void SetFileName(const wxString &aFilename)
Definition sch_sheet.h:380
wxString GetFileName() const
Return the filename corresponding to this sheet.
Definition sch_sheet.h:374
bool getInstance(SCH_SHEET_INSTANCE &aInstance, const KIID_PATH &aSheetPath, bool aTestFromEnd=false) const
bool addInstance(const KIID_PATH &aInstance)
Add a new instance aSheetPath to the instance list.
wxString getPageNumber(const KIID_PATH &aParentPath) const
Return the sheet page number for aParentPath.
SCH_FIELD * GetField(FIELD_T aFieldType)
Return a mandatory field in this sheet.
wxString GetName() const
Definition sch_sheet.h:140
bool GetExcludedFromBOM(const SCH_SHEET_PATH *aInstance=nullptr, const wxString &aVariantName=wxEmptyString) const override
bool GetExcludedFromSim(const SCH_SHEET_PATH *aInstance=nullptr, const wxString &aVariantName=wxEmptyString) const override
SCH_SCREEN * GetScreen() const
Definition sch_sheet.h:143
static int ComparePageNum(const wxString &aPageNumberA, const wxString &aPageNumberB)
Compare page numbers of schematic sheets.
void setPageNumber(const KIID_PATH &aInstance, const wxString &aPageNumber)
Set the page number for the sheet instance aInstance.
bool IsVirtualRootSheet() const
bool GetDNP(const SCH_SHEET_PATH *aInstance=nullptr, const wxString &aVariantName=wxEmptyString) const override
Set or clear the 'Do Not Populate' flags.
bool GetExcludedFromBoard(const SCH_SHEET_PATH *aInstance=nullptr, const wxString &aVariantName=wxEmptyString) const override
Definition sch_sheet.h:465
void InitializeAttributes(const SCH_SYMBOL &aSymbol)
Schematic symbol object.
Definition sch_symbol.h:76
void UpdatePrefix()
Set the prefix based on the current reference designator.
bool GetExcludedFromSim(const SCH_SHEET_PATH *aInstance=nullptr, const wxString &aVariantName=wxEmptyString) const override
const std::vector< SCH_SYMBOL_INSTANCE > & GetInstances() const
Definition sch_symbol.h:135
void RemoveInstance(const SCH_SHEET_PATH &aInstancePath)
bool GetExcludedFromBOM(const SCH_SHEET_PATH *aInstance=nullptr, const wxString &aVariantName=wxEmptyString) const override
void SetFootprintFieldText(const wxString &aFootprint)
void AddHierarchicalReference(const KIID_PATH &aPath, const wxString &aRef, int aUnit)
Add a full hierarchical reference to this symbol.
void SetValueFieldText(const wxString &aValue, const SCH_SHEET_PATH *aInstance=nullptr, const wxString &aVariantName=wxEmptyString)
bool GetExcludedFromPosFiles(const SCH_SHEET_PATH *aInstance=nullptr, const wxString &aVariantName=wxEmptyString) const override
bool GetInstance(SCH_SYMBOL_INSTANCE &aInstance, const KIID_PATH &aSheetPath, bool aTestFromEnd=false) const
bool GetExcludedFromBoard(const SCH_SHEET_PATH *aInstance=nullptr, const wxString &aVariantName=wxEmptyString) const override
int GetUnitSelection(const SCH_SHEET_PATH *aSheet) const
Return the instance-specific unit selection for the given sheet path.
std::unique_ptr< LIB_SYMBOL > & GetLibSymbolRef()
Definition sch_symbol.h:184
virtual bool GetDNP(const SCH_SHEET_PATH *aInstance=nullptr, const wxString &aVariantName=wxEmptyString) const override
Set or clear the 'Do Not Populate' flag.
const wxString GetRef(const SCH_SHEET_PATH *aSheet, bool aIncludeUnit=false) const override
SCH_FIELD * GetField(FIELD_T aFieldType)
Return a mandatory field in this symbol.
bool m_ExcludedFromBOM
bool m_ExcludedFromPosFiles
bool m_ExcludedFromSim
bool m_ExcludedFromBoard
static bool empty(const wxTextEntryBase *aCtrl)
#define _(s)
@ NO_RECURSE
Definition eda_item.h:54
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
KIID niluuid(0)
STL namespace.
Collection of utility functions for component reference designators (refdes)
@ AUTOPLACE_AUTO
Definition sch_item.h:71
static bool matchesSymbolFilter(const wxString &aReference, SYMBOL_FILTER aSymbolFilter)
Definition of the SCH_SHEET_PATH and SCH_SHEET_LIST classes for Eeschema.
std::map< wxString, SCH_REFERENCE_LIST > SCH_MULTI_UNIT_REFERENCE_MAP
Container to map reference designators for multi-unit parts.
SYMBOL_FILTER
@ SYMBOL_FILTER_NON_POWER
@ SYMBOL_FILTER_ALL
@ SYMBOL_FILTER_POWER
wxString EscapeString(const wxString &aSource, ESCAPE_CONTEXT aContext)
The Escape/Unescape routines use HTML-entity-reference-style encoding to handle characters which are:...
@ CTX_NETNAME
A simple container for sheet instance information.
A simple container for schematic symbol instance information.
size_t operator()(const SCH_SHEET_PATH &path) const
@ INTERSHEET_REFS
Global label cross-reference page numbers.
@ REFERENCE
Field Reference of part, i.e. "IC21".
std::string path
table push_back({ "Source", "Layer", "Vertices", "Strategy", "Build(us)", "ns/query", "Mquery/s", "Inside" })
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:76
@ SCH_GLOBAL_LABEL_T
Definition typeinfo.h:169
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:687