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
565void SCH_SHEET_PATH::GetSymbols( SCH_REFERENCE_LIST& aReferences, bool aIncludePowerSymbols,
566 bool aForceIncludeOrphanSymbols ) const
567{
568 for( SCH_ITEM* item : LastScreen()->Items().OfType( SCH_SYMBOL_T ) )
569 {
570 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
571 AppendSymbol( aReferences, symbol, aIncludePowerSymbols, aForceIncludeOrphanSymbols );
572 }
573}
574
575
577 bool aIncludePowerSymbols,
578 bool aForceIncludeOrphanSymbols ) const
579{
580 // Skip pseudo-symbols, which have a reference starting with #. This mainly
581 // affects power symbols.
582 if( aIncludePowerSymbols || aSymbol->GetRef( this )[0] != wxT( '#' ) )
583 {
584 if( aSymbol->GetLibSymbolRef() || aForceIncludeOrphanSymbols )
585 {
586 SCH_REFERENCE schReference( aSymbol, *this );
587
588 schReference.SetSheetNumber( GetPageNumberAsInt() );
589 aReferences.AddItem( schReference );
590 }
591 }
592}
593
594
596 bool aIncludePowerSymbols ) const
597{
598 for( SCH_ITEM* item : LastScreen()->Items().OfType( SCH_SYMBOL_T ) )
599 {
600 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
601 AppendMultiUnitSymbol( aRefList, symbol, aIncludePowerSymbols );
602 }
603}
604
605
607 SCH_SYMBOL* aSymbol,
608 bool aIncludePowerSymbols ) const
609{
610 // Skip pseudo-symbols, which have a reference starting with #. This mainly
611 // affects power symbols.
612 if( !aIncludePowerSymbols && aSymbol->GetRef( this )[0] == wxT( '#' ) )
613 return;
614
615 LIB_SYMBOL* symbol = aSymbol->GetLibSymbolRef().get();
616
617 if( symbol && symbol->GetUnitCount() > 1 )
618 {
619 SCH_REFERENCE schReference = SCH_REFERENCE( aSymbol, *this );
620 schReference.SetSheetNumber( GetPageNumberAsInt() );
621 wxString reference_str = schReference.GetRef();
622
623 // Never lock unassigned references
624 if( reference_str[reference_str.Len() - 1] == '?' )
625 return;
626
627 aRefList[reference_str].AddItem( schReference );
628 }
629}
630
631
633{
634 return m_current_hash == d1.GetCurrentHash();
635}
636
637
638bool SCH_SHEET_PATH::TestForRecursion( const wxString& aSrcFileName, const wxString& aDestFileName )
639{
640 auto pair = std::make_pair( aSrcFileName, aDestFileName );
641
642 if( m_recursion_test_cache.count( pair ) )
643 return m_recursion_test_cache.at( pair );
644
645 SCHEMATIC* sch = LastScreen()->Schematic();
646
647 wxCHECK_MSG( sch, false, "No SCHEMATIC found in SCH_SHEET_PATH::TestForRecursion!" );
648
649 wxFileName rootFn = sch->GetFileName();
650 wxFileName srcFn = aSrcFileName;
651 wxFileName destFn = aDestFileName;
652
653 if( srcFn.IsRelative() )
654 srcFn.MakeAbsolute( rootFn.GetPath() );
655
656 if( destFn.IsRelative() )
657 destFn.MakeAbsolute( rootFn.GetPath() );
658
659 // The source and destination sheet file names cannot be the same.
660 if( srcFn == destFn )
661 {
662 m_recursion_test_cache[pair] = true;
663 return true;
664 }
665
669 unsigned i = 0;
670
671 while( i < size() )
672 {
673 wxFileName cmpFn = at( i )->GetFileName();
674
675 if( cmpFn.IsRelative() )
676 cmpFn.MakeAbsolute( rootFn.GetPath() );
677
678 // Test if the file name of the destination sheet is in anywhere in this sheet path.
679 if( cmpFn == destFn )
680 break;
681
682 i++;
683 }
684
685 // The destination sheet file name was not found in the sheet path or the destination
686 // sheet file name is the root sheet so no recursion is possible.
687 if( i >= size() || i == 0 )
688 {
689 m_recursion_test_cache[pair] = false;
690 return false;
691 }
692
693 // Walk back up to the root sheet to see if the source file name is already a parent in
694 // the sheet path. If so, recursion will occur.
695 do
696 {
697 i -= 1;
698
699 wxFileName cmpFn = at( i )->GetFileName();
700
701 if( cmpFn.IsRelative() )
702 cmpFn.MakeAbsolute( rootFn.GetPath() );
703
704 if( cmpFn == srcFn )
705 {
706 m_recursion_test_cache[pair] = true;
707 return true;
708 }
709
710 } while( i != 0 );
711
712 // The source sheet file name is not a parent of the destination sheet file name.
713 m_recursion_test_cache[pair] = false;
714 return false;
715}
716
717
719{
720 SCH_SHEET* sheet = Last();
721
722 wxCHECK( sheet, wxEmptyString );
723
724 KIID_PATH tmpPath = Path();
725
726 if( !tmpPath.empty() )
727 tmpPath.pop_back();
728 else
729 return wxEmptyString;
730
731 return sheet->getPageNumber( tmpPath );
732}
733
735{
736 long page;
737 wxString pageStr = GetPageNumber();
738
739 if( pageStr.ToLong( &page ) )
740 return (int) page;
741
742 return GetVirtualPageNumber();
743}
744
745
746void SCH_SHEET_PATH::SetPageNumber( const wxString& aPageNumber )
747{
748 SCH_SHEET* sheet = Last();
749
750 wxCHECK( sheet, /* void */ );
751
752 KIID_PATH tmpPath = Path();
753
754 if( !tmpPath.empty() )
755 {
756 tmpPath.pop_back();
757 }
758 else
759 {
760 wxCHECK_MSG( false, /* void */, wxS( "Sheet paths must have a least one valid sheet." ) );
761 }
762
763 sheet->addInstance( tmpPath );
764 sheet->setPageNumber( tmpPath, aPageNumber );
765}
766
767
769 const wxString& aProjectName )
770{
771 wxCHECK( !aProjectName.IsEmpty(), /* void */ );
772
773 SCH_SHEET_PATH newSheetPath( aPrefixSheetPath );
774 SCH_SHEET_PATH currentSheetPath( *this );
775
776 // Prefix the new hierarchical path.
777 newSheetPath = newSheetPath + currentSheetPath;
778
779 for( SCH_ITEM* item : LastScreen()->Items().OfType( SCH_SYMBOL_T ) )
780 {
781 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
782
783 wxCHECK2( symbol, continue );
784
785 SCH_SYMBOL_INSTANCE newSymbolInstance;
786
787 if( symbol->GetInstance( newSymbolInstance, Path(), true ) )
788 {
789 newSymbolInstance.m_ProjectName = aProjectName;
790
791 // Use an existing symbol instance for this path if it exists.
792 newSymbolInstance.m_Path = newSheetPath.Path();
793 symbol->AddHierarchicalReference( newSymbolInstance );
794 }
795 else if( !symbol->GetInstances().empty() )
796 {
797 newSymbolInstance.m_ProjectName = aProjectName;
798
799 // Use the first symbol instance if any symbol instance data exists.
800 newSymbolInstance = symbol->GetInstances()[0];
801 newSymbolInstance.m_Path = newSheetPath.Path();
802 symbol->AddHierarchicalReference( newSymbolInstance );
803 }
804 else
805 {
806 newSymbolInstance.m_ProjectName = aProjectName;
807
808 // Fall back to the last saved symbol field and unit settings if there is no
809 // instance data.
810 newSymbolInstance.m_Path = newSheetPath.Path();
811 newSymbolInstance.m_Reference = symbol->GetField( FIELD_T::REFERENCE )->GetText();
812 newSymbolInstance.m_Unit = symbol->GetUnit();
813 symbol->AddHierarchicalReference( newSymbolInstance );
814 }
815 }
816}
817
818
820{
821 for( SCH_ITEM* item : LastScreen()->Items().OfType( SCH_SYMBOL_T ) )
822 {
823 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
824
825 wxCHECK2( symbol, continue );
826
827 SCH_SHEET_PATH fullSheetPath( aPrefixSheetPath );
828 SCH_SHEET_PATH currentSheetPath( *this );
829
830 // Prefix the hierarchical path of the symbol instance to be removed.
831 fullSheetPath = fullSheetPath + currentSheetPath;
832 symbol->RemoveInstance( fullSheetPath );
833 }
834}
835
836
837void SCH_SHEET_PATH::CheckForMissingSymbolInstances( const wxString& aProjectName )
838{
839 // Skip sheet paths without screens (e.g., sheets that haven't been loaded yet or virtual root)
840 if( aProjectName.IsEmpty() || !LastScreen() )
841 return;
842
843 wxLogTrace( traceSchSheetPaths, "CheckForMissingSymbolInstances for path: %s (project: %s)",
844 PathHumanReadable( false ), aProjectName );
845 wxLogTrace( traceSchSheetPaths, " Sheet path size=%zu, Path().AsString()='%s'",
846 size(), Path().AsString() );
847
848 for( SCH_ITEM* item : LastScreen()->Items().OfType( SCH_SYMBOL_T ) )
849 {
850 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
851
852 wxCHECK2( symbol, continue );
853
854 SCH_SYMBOL_INSTANCE symbolInstance;
855
856 if( !symbol->GetInstance( symbolInstance, Path() ) )
857 {
858 wxLogTrace( traceSchSheetPaths, "Adding missing symbol \"%s\" instance data for "
859 "sheet path '%s'.",
860 symbol->m_Uuid.AsString(), PathHumanReadable( false ) );
861
862 // Legacy schematics that are not shared do not contain separate instance data.
863 // The symbol reference and unit are saved in the reference field and unit entries.
864 if( ( LastScreen()->GetRefCount() <= 1 ) &&
865 ( LastScreen()->GetFileFormatVersionAtLoad() <= 20200310 ) )
866 {
867 SCH_FIELD* refField = symbol->GetField( FIELD_T::REFERENCE );
868 symbolInstance.m_Reference = refField->GetShownText( this, true );
869 symbolInstance.m_Unit = symbol->GetUnit();
870
871 wxLogTrace( traceSchSheetPaths,
872 " Legacy format: Using reference '%s' from field, unit %d",
873 symbolInstance.m_Reference, symbolInstance.m_Unit );
874 }
875 else if( !symbol->GetInstances().empty() )
876 {
877 // When a schematic is opened as a different project (e.g., a subsheet opened
878 // directly from File Browser), use the first available instance data.
879 // This provides better UX than showing unannotated references.
880 const SCH_SYMBOL_INSTANCE& firstInstance = symbol->GetInstances()[0];
881 symbolInstance.m_Reference = firstInstance.m_Reference;
882 symbolInstance.m_Unit = firstInstance.m_Unit;
883
884 wxLogTrace( traceSchSheetPaths,
885 " Using first available instance: ref=%s, unit=%d",
886 symbolInstance.m_Reference, symbolInstance.m_Unit );
887 }
888 else
889 {
890 // Fall back to the symbol's reference field and unit if no instance data exists.
891 SCH_FIELD* refField = symbol->GetField( FIELD_T::REFERENCE );
892 symbolInstance.m_Reference = refField->GetText();
893 symbolInstance.m_Unit = symbol->GetUnit();
894
895 wxLogTrace( traceSchSheetPaths,
896 " No instance data: Using reference '%s' from field, unit %d",
897 symbolInstance.m_Reference, symbolInstance.m_Unit );
898 }
899
900 symbolInstance.m_ProjectName = aProjectName;
901 symbolInstance.m_Path = Path();
902 symbol->AddHierarchicalReference( symbolInstance );
903
904 wxLogTrace( traceSchSheetPaths,
905 " Created instance: ref=%s, path=%s",
906 symbolInstance.m_Reference, symbolInstance.m_Path.AsString() );
907 }
908 else
909 {
910 wxLogTrace( traceSchSheetPaths,
911 " Symbol %s already has instance: ref=%s, path=%s",
912 symbol->m_Uuid.AsString(),
913 symbolInstance.m_Reference,
914 symbolInstance.m_Path.AsString() );
915 }
916 }
917}
918
919
921{
922 wxCHECK( m_sheets.size() > 1, /* void */ );
923
924 wxFileName sheetFileName = Last()->GetFileName();
925
926 // If the sheet file name is absolute, then the user requested is so don't make it relative.
927 if( sheetFileName.IsAbsolute() )
928 return;
929
930 SCH_SCREEN* screen = LastScreen();
931 SCH_SCREEN* parentScreen = m_sheets[ m_sheets.size() - 2 ]->GetScreen();
932
933 wxCHECK( screen && parentScreen, /* void */ );
934
935 wxFileName fileName = screen->GetFileName();
936 wxFileName parentFileName = parentScreen->GetFileName();
937
938 // SCH_SCREEN file names must be absolute. If they are not, someone set them incorrectly
939 // on load or on creation.
940 wxCHECK( fileName.IsAbsolute() && parentFileName.IsAbsolute(), /* void */ );
941
942 if( fileName.GetPath() == parentFileName.GetPath() )
943 {
944 Last()->SetFileName( fileName.GetFullName() );
945 }
946 else if( fileName.MakeRelativeTo( parentFileName.GetPath() ) )
947 {
948 Last()->SetFileName( fileName.GetFullPath() );
949 }
950 else
951 {
952 Last()->SetFileName( screen->GetFileName() );
953 }
954
955 wxLogTrace( tracePathsAndFiles,
956 wxT( "\n File name: '%s'"
957 "\n parent file name '%s',"
958 "\n sheet '%s' file name '%s'." ),
959 screen->GetFileName(), parentScreen->GetFileName(), PathHumanReadable(),
960 Last()->GetFileName() );
961}
962
963
965{
966 if( aSheet != nullptr )
967 BuildSheetList( aSheet, false );
968}
969
970
971void SCH_SHEET_LIST::BuildSheetList( SCH_SHEET* aSheet, bool aCheckIntegrity )
972{
973 if( !aSheet )
974 return;
975
976 wxLogTrace( traceSchSheetPaths,
977 "BuildSheetList called with sheet '%s' (UUID=%s, isVirtualRoot=%d)",
978 aSheet->GetName(),
979 aSheet->m_Uuid.AsString(),
980 aSheet->m_Uuid == niluuid ? 1 : 0 );
981
982 // Special handling for virtual root: process its children without adding the root itself
983 if( aSheet->IsVirtualRootSheet() )
984 {
985 wxLogTrace( traceSchSheetPaths, " Skipping virtual root, processing children only" );
986
987 if( aSheet->GetScreen() )
988 {
989 std::vector<SCH_ITEM*> childSheets;
990 aSheet->GetScreen()->GetSheets( &childSheets );
991
992 for( SCH_ITEM* item : childSheets )
993 {
994 SCH_SHEET* sheet = static_cast<SCH_SHEET*>( item );
995 BuildSheetList( sheet, aCheckIntegrity );
996 }
997 }
998
999 return;
1000 }
1001
1002 std::vector<SCH_SHEET*> badSheets;
1003
1004 m_currentSheetPath.push_back( aSheet );
1005 m_currentSheetPath.SetVirtualPageNumber( static_cast<int>( size() ) + 1 );
1006 push_back( m_currentSheetPath );
1007
1008 if( m_currentSheetPath.LastScreen() )
1009 {
1010 wxString parentFileName = aSheet->GetFileName();
1011 std::vector<SCH_ITEM*> childSheets;
1012 m_currentSheetPath.LastScreen()->GetSheets( &childSheets );
1013
1014 for( SCH_ITEM* item : childSheets )
1015 {
1016 SCH_SHEET* sheet = static_cast<SCH_SHEET*>( item );
1017
1018 if( aCheckIntegrity )
1019 {
1020 if( !m_currentSheetPath.TestForRecursion( sheet->GetFileName(), parentFileName ) )
1021 BuildSheetList( sheet, true );
1022 else
1023 badSheets.push_back( sheet );
1024 }
1025 else
1026 {
1027 // If we are not performing a full recursion test, at least check if we are in
1028 // a simple recursion scenario to prevent stack overflow crashes
1029 wxCHECK2_MSG( sheet->GetFileName() != aSheet->GetFileName(), continue,
1030 wxT( "Recursion prevented in SCH_SHEET_LIST::BuildSheetList" ) );
1031
1032 BuildSheetList( sheet, false );
1033 }
1034 }
1035 }
1036
1037 if( aCheckIntegrity )
1038 {
1039 for( SCH_SHEET* sheet : badSheets )
1040 {
1041 m_currentSheetPath.LastScreen()->Remove( sheet );
1042 m_currentSheetPath.LastScreen()->SetContentModified();
1043 }
1044 }
1045
1046 m_currentSheetPath.pop_back();
1047}
1048
1049
1050void SCH_SHEET_LIST::SortByHierarchicalPageNumbers( bool aUpdateVirtualPageNums )
1051{
1052 for( const SCH_SHEET_PATH& path : *this )
1053 path.CachePageNumber();
1054
1055 std::sort( begin(), end(),
1056 []( const SCH_SHEET_PATH& a, const SCH_SHEET_PATH& b ) -> bool
1057 {
1058 // Find the divergence point in the paths
1059 size_t common_len = 0;
1060 size_t min_len = std::min( a.size(), b.size() );
1061
1062 while( common_len < min_len && a.at( common_len )->m_Uuid == b.at( common_len )->m_Uuid )
1063 common_len++;
1064
1065 // If one path is a prefix of the other, the shorter one comes first
1066 // This ensures parents come before children
1067 if( common_len == a.size() )
1068 return true; // a is a prefix of b - a is the parent
1069 if( common_len == b.size() )
1070 return false; // b is a prefix of a - b is the parent
1071
1072 // Paths diverge at common_len
1073 // If they share the same parent, sort by page number
1074 // This ensures siblings are sorted by page number
1075 SCH_SHEET* sheet_a = a.at( common_len );
1076 SCH_SHEET* sheet_b = b.at( common_len );
1077
1078 // Create partial paths to get to these sheets for page number comparison
1079 KIID_PATH ancestor;
1080 for( size_t i = 0; i < common_len; i++ )
1081 ancestor.push_back( a.at( i )->m_Uuid );
1082
1083 // Compare page numbers - use the last sheet's page number
1084 wxString page_a = sheet_a->getPageNumber( ancestor );
1085 wxString page_b = sheet_b->getPageNumber( ancestor );
1086
1087 int retval = SCH_SHEET::ComparePageNum( page_a, page_b );
1088
1089 if( retval != 0 )
1090 return retval < 0;
1091
1092 // If page numbers are the same, use virtual page numbers as a tie-breaker
1094 return true;
1095 else if( a.GetVirtualPageNumber() > b.GetVirtualPageNumber() )
1096 return false;
1097
1098 // Finally, use UUIDs for stable ordering when everything else is equal
1099 return a.GetCurrentHash() < b.GetCurrentHash();
1100 } );
1101
1102 if( aUpdateVirtualPageNums )
1103 {
1104 int virtualPageNum = 1;
1105
1106 for( SCH_SHEET_PATH& sheet : *this )
1107 sheet.SetVirtualPageNumber( virtualPageNum++ );
1108 }
1109}
1110
1111
1112void SCH_SHEET_LIST::SortByPageNumbers( bool aUpdateVirtualPageNums )
1113{
1114 for( const SCH_SHEET_PATH& path : *this )
1115 path.CachePageNumber();
1116
1117 std::sort( begin(), end(),
1118 []( const SCH_SHEET_PATH& a, const SCH_SHEET_PATH& b ) -> bool
1119 {
1121 b.GetCachedPageNumber() );
1122
1123 if( retval < 0 )
1124 return true;
1125 else if( retval > 0 )
1126 return false;
1127
1129 return true;
1130 else if( a.GetVirtualPageNumber() > b.GetVirtualPageNumber() )
1131 return false;
1132
1133 // Enforce strict ordering. If the page numbers are the same, use UUIDs
1134 return a.GetCurrentHash() < b.GetCurrentHash();
1135 } );
1136
1137 if( aUpdateVirtualPageNums )
1138 {
1139 int virtualPageNum = 1;
1140
1141 for( SCH_SHEET_PATH& sheet : *this )
1142 sheet.SetVirtualPageNumber( virtualPageNum++ );
1143 }
1144}
1145
1146
1147bool SCH_SHEET_LIST::NameExists( const wxString& aSheetName ) const
1148{
1149 for( const SCH_SHEET_PATH& sheet : *this )
1150 {
1151 if( sheet.Last()->GetName() == aSheetName )
1152 return true;
1153 }
1154
1155 return false;
1156}
1157
1158
1159bool SCH_SHEET_LIST::PageNumberExists( const wxString& aPageNumber ) const
1160{
1161 for( const SCH_SHEET_PATH& sheet : *this )
1162 {
1163 if( sheet.GetPageNumber() == aPageNumber )
1164 return true;
1165 }
1166
1167 return false;
1168}
1169
1170
1171void SCH_SHEET_LIST::TrimToPageNumbers( const std::vector<wxString>& aPageInclusions )
1172{
1173 auto it = std::remove_if( begin(), end(),
1174 [&]( const SCH_SHEET_PATH& sheet )
1175 {
1176 return std::find( aPageInclusions.begin(),
1177 aPageInclusions.end(),
1178 sheet.GetPageNumber() ) == aPageInclusions.end();
1179 } );
1180
1181 erase( it, end() );
1182}
1183
1184
1186{
1187 for( const SCH_SHEET_PATH& sheet : *this )
1188 {
1189 if( sheet.LastScreen() && sheet.LastScreen()->IsContentModified() )
1190 return true;
1191 }
1192
1193 return false;
1194}
1195
1196
1198{
1199 for( const SCH_SHEET_PATH& sheet : *this )
1200 {
1201 if( sheet.LastScreen() )
1202 sheet.LastScreen()->SetContentModified( false );
1203 }
1204}
1205
1206
1207SCH_ITEM* SCH_SHEET_LIST::ResolveItem( const KIID& aID, SCH_SHEET_PATH* aPathOut, bool aAllowNullptrReturn ) const
1208{
1209 for( const SCH_SHEET_PATH& sheet : *this )
1210 {
1211 SCH_ITEM* item = sheet.ResolveItem( aID );
1212
1213 if( item )
1214 {
1215 if( aPathOut )
1216 *aPathOut = sheet;
1217
1218 return item;
1219 }
1220 }
1221
1222 // Not found; weak reference has been deleted.
1223 if( aAllowNullptrReturn )
1224 return nullptr;
1225 else
1227}
1228
1229
1231{
1232 for( SCH_ITEM* aItem : LastScreen()->Items() )
1233 {
1234 if( aItem->m_Uuid == aID )
1235 return aItem;
1236
1237 SCH_ITEM* childMatch = nullptr;
1238
1239 aItem->RunOnChildren(
1240 [&]( SCH_ITEM* aChild )
1241 {
1242 if( aChild->m_Uuid == aID )
1243 childMatch = aChild;
1244 },
1246
1247 if( childMatch )
1248 return childMatch;
1249 }
1250
1251 return nullptr;
1252}
1253
1254
1255void SCH_SHEET_LIST::FillItemMap( std::map<KIID, EDA_ITEM*>& aMap )
1256{
1257 for( const SCH_SHEET_PATH& sheet : *this )
1258 {
1259 SCH_SCREEN* screen = sheet.LastScreen();
1260
1261 for( SCH_ITEM* aItem : screen->Items() )
1262 {
1263 aMap[ aItem->m_Uuid ] = aItem;
1264
1265 aItem->RunOnChildren(
1266 [&]( SCH_ITEM* aChild )
1267 {
1268 aMap[ aChild->m_Uuid ] = aChild;
1269 },
1271 }
1272 }
1273}
1274
1275
1277{
1278 // List of reference for power symbols
1279 SCH_REFERENCE_LIST references;
1280
1281 // Map of locked symbols (not used, but needed by Annotate()
1282 SCH_MULTI_UNIT_REFERENCE_MAP lockedSymbols;
1283
1284 // Build the list of power symbols:
1285 for( SCH_SHEET_PATH& sheet : *this )
1286 {
1287 for( SCH_ITEM* item : sheet.LastScreen()->Items().OfType( SCH_SYMBOL_T ) )
1288 {
1289 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
1290 LIB_SYMBOL* libSymbol = symbol->GetLibSymbolRef().get();
1291
1292 if( libSymbol && libSymbol->IsPower() )
1293 {
1294 SCH_REFERENCE schReference( symbol, sheet );
1295 references.AddItem( schReference );
1296 }
1297 }
1298 }
1299
1300 // Find duplicate, and silently clear annotation of duplicate
1301 std::map<wxString, int> ref_list; // stores the existing references
1302
1303 for( unsigned ii = 0; ii< references.GetCount(); ++ii )
1304 {
1305 wxString curr_ref = references[ii].GetRef();
1306
1307 if( curr_ref.IsEmpty() )
1308 continue;
1309
1310 if( ref_list.find( curr_ref ) == ref_list.end() )
1311 {
1312 ref_list[curr_ref] = ii;
1313 continue;
1314 }
1315
1316 // Possible duplicate, if the ref ends by a number:
1317 if( curr_ref.Last() < '0' && curr_ref.Last() > '9' )
1318 continue; // not annotated
1319
1320 // Duplicate: clear annotation by removing the number ending the ref
1321 while( !curr_ref.IsEmpty() && curr_ref.Last() >= '0' && curr_ref.Last() <= '9' )
1322 curr_ref.RemoveLast();
1323
1324 references[ii].SetRef( curr_ref );
1325 }
1326
1327 // Break full symbol reference into name (prefix) and number:
1328 // example: IC1 become IC, and 1
1329 references.SplitReferences();
1330
1331 // Ensure all power symbols have the reference starting by '#'
1332 // (Not sure this is really useful)
1333 for( unsigned ii = 0; ii< references.GetCount(); ++ii )
1334 {
1335 SCH_REFERENCE& ref_unit = references[ii];
1336
1337 if( ref_unit.GetRef()[0] != '#' )
1338 {
1339 wxString new_ref = "#" + ref_unit.GetRef();
1340 ref_unit.SetRef( new_ref );
1341 ref_unit.SetRefNum( ii );
1342 }
1343 }
1344}
1345
1346
1347void SCH_SHEET_LIST::GetSymbols( SCH_REFERENCE_LIST& aReferences, bool aIncludePowerSymbols,
1348 bool aForceIncludeOrphanSymbols ) const
1349{
1350 for( const SCH_SHEET_PATH& sheet : *this )
1351 sheet.GetSymbols( aReferences, aIncludePowerSymbols, aForceIncludeOrphanSymbols );
1352}
1353
1354
1356 const SCH_SHEET_PATH& aSheetPath,
1357 bool aIncludePowerSymbols,
1358 bool aForceIncludeOrphanSymbols ) const
1359{
1360 for( const SCH_SHEET_PATH& sheet : *this )
1361 {
1362 if( sheet.IsContainedWithin( aSheetPath ) )
1363 sheet.GetSymbols( aReferences, aIncludePowerSymbols, aForceIncludeOrphanSymbols );
1364 }
1365}
1366
1367
1368void SCH_SHEET_LIST::GetSheetsWithinPath( std::vector<SCH_SHEET_PATH>& aSheets,
1369 const SCH_SHEET_PATH& aSheetPath ) const
1370{
1371 for( const SCH_SHEET_PATH& sheet : *this )
1372 {
1373 if( sheet.IsContainedWithin( aSheetPath ) )
1374 aSheets.push_back( sheet );
1375 }
1376}
1377
1378
1379std::optional<SCH_SHEET_PATH> SCH_SHEET_LIST::GetSheetPathByKIIDPath( const KIID_PATH& aPath,
1380 bool aIncludeLastSheet ) const
1381{
1382 for( const SCH_SHEET_PATH& sheet : *this )
1383 {
1384 KIID_PATH testPath = sheet.Path();
1385
1386 if( !aIncludeLastSheet )
1387 testPath.pop_back();
1388
1389 if( testPath == aPath )
1390 return SCH_SHEET_PATH( sheet );
1391 }
1392
1393 return std::nullopt;
1394}
1395
1396
1398 bool aIncludePowerSymbols ) const
1399{
1400 for( auto it = begin(); it != end(); ++it )
1401 {
1403 ( *it ).GetMultiUnitSymbols( tempMap, aIncludePowerSymbols );
1404
1405 for( SCH_MULTI_UNIT_REFERENCE_MAP::value_type& pair : tempMap )
1406 {
1407 // Merge this list into the main one
1408 unsigned n_refs = pair.second.GetCount();
1409
1410 for( unsigned thisRef = 0; thisRef < n_refs; ++thisRef )
1411 aRefList[pair.first].AddItem( pair.second[thisRef] );
1412 }
1413 }
1414}
1415
1416
1417bool SCH_SHEET_LIST::TestForRecursion( const SCH_SHEET_LIST& aSrcSheetHierarchy,
1418 const wxString& aDestFileName )
1419{
1420 if( empty() )
1421 return false;
1422
1423 SCHEMATIC* sch = at( 0 ).LastScreen()->Schematic();
1424
1425 wxCHECK_MSG( sch, false, "No SCHEMATIC found in SCH_SHEET_LIST::TestForRecursion!" );
1426
1427 wxFileName rootFn = sch->GetFileName();
1428 wxFileName destFn = aDestFileName;
1429
1430 if( destFn.IsRelative() )
1431 destFn.MakeAbsolute( rootFn.GetPath() );
1432
1433 // Test each SCH_SHEET_PATH in this SCH_SHEET_LIST for potential recursion.
1434 for( unsigned i = 0; i < size(); i++ )
1435 {
1436 // Test each SCH_SHEET_PATH in the source sheet.
1437 for( unsigned j = 0; j < aSrcSheetHierarchy.size(); j++ )
1438 {
1439 const SCH_SHEET_PATH* sheetPath = &aSrcSheetHierarchy[j];
1440
1441 for( unsigned k = 0; k < sheetPath->size(); k++ )
1442 {
1443 if( at( i ).TestForRecursion( sheetPath->GetSheet( k )->GetFileName(),
1444 aDestFileName ) )
1445 {
1446 return true;
1447 }
1448 }
1449 }
1450 }
1451
1452 // The source sheet file can safely be added to the destination sheet file.
1453 return false;
1454}
1455
1456
1458{
1459 for( SCH_SHEET_PATH& path : *this )
1460 {
1461 if( path.Path() == aPath->Path() )
1462 return &path;
1463 }
1464
1465 return nullptr;
1466}
1467
1468
1470{
1471 for( SCH_SHEET_PATH& sheetpath : *this )
1472 {
1473 if( sheetpath.LastScreen() == aScreen )
1474 return sheetpath;
1475 }
1476
1477 return SCH_SHEET_PATH();
1478}
1479
1480
1482{
1483 SCH_SHEET_LIST retval;
1484
1485 for( const SCH_SHEET_PATH& sheetpath : *this )
1486 {
1487 if( sheetpath.LastScreen() == aScreen )
1488 retval.push_back( sheetpath );
1489 }
1490
1491 return retval;
1492}
1493
1494
1496 const std::vector<SCH_SYMBOL_INSTANCE>& aSymbolInstances )
1497{
1498 for( SCH_SHEET_PATH& sheetPath : *this )
1499 {
1500 for( SCH_ITEM* item : sheetPath.LastScreen()->Items().OfType( SCH_SYMBOL_T ) )
1501 {
1502 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
1503
1504 wxCHECK2( symbol, continue );
1505
1506 KIID_PATH sheetPathWithSymbolUuid = sheetPath.Path();
1507 sheetPathWithSymbolUuid.push_back( symbol->m_Uuid );
1508
1509 auto it = std::find_if( aSymbolInstances.begin(), aSymbolInstances.end(),
1510 [ sheetPathWithSymbolUuid ]( const SCH_SYMBOL_INSTANCE& r ) -> bool
1511 {
1512 return sheetPathWithSymbolUuid == r.m_Path;
1513 } );
1514
1515 if( it == aSymbolInstances.end() )
1516 {
1517 wxLogTrace( traceSchSheetPaths, "No symbol instance found for symbol '%s'",
1518 sheetPathWithSymbolUuid.AsString() );
1519 continue;
1520 }
1521
1522 // Symbol instance paths are stored and looked up in memory with the root path so use
1523 // the full path here.
1524 symbol->AddHierarchicalReference( sheetPath.Path(), it->m_Reference, it->m_Unit );
1525 symbol->GetField( FIELD_T::REFERENCE )->SetText( it->m_Reference );
1526
1527 if( !it->m_Value.IsEmpty() )
1528 symbol->SetValueFieldText( it->m_Value );
1529
1530 if( !it->m_Footprint.IsEmpty() )
1531 symbol->SetFootprintFieldText( it->m_Footprint );
1532
1533 symbol->UpdatePrefix();
1534 }
1535 }
1536}
1537
1538
1539void SCH_SHEET_LIST::UpdateSheetInstanceData( const std::vector<SCH_SHEET_INSTANCE>& aSheetInstances )
1540{
1541
1542 for( SCH_SHEET_PATH& path : *this )
1543 {
1544 SCH_SHEET* sheet = path.Last();
1545
1546 wxCHECK2( sheet && path.Last(), continue );
1547
1548 auto it = std::find_if( aSheetInstances.begin(), aSheetInstances.end(),
1549 [&path]( const SCH_SHEET_INSTANCE& r ) -> bool
1550 {
1551 return path.Path() == r.m_Path;
1552 } );
1553
1554 if( it == aSheetInstances.end() )
1555 {
1556 wxLogTrace( traceSchSheetPaths, "No sheet instance found for path '%s'",
1557 path.Path().AsString() );
1558 continue;
1559 }
1560
1561 wxLogTrace( traceSchSheetPaths, "Setting sheet '%s' instance '%s' page number '%s'",
1562 ( sheet->GetName().IsEmpty() ) ? wxString( wxT( "root" ) ) : sheet->GetName(),
1563 path.Path().AsString(), it->m_PageNumber );
1564 path.SetPageNumber( it->m_PageNumber );
1565 }
1566}
1567
1568
1569std::vector<KIID_PATH> SCH_SHEET_LIST::GetPaths() const
1570{
1571 std::vector<KIID_PATH> paths;
1572
1573 for( const SCH_SHEET_PATH& sheetPath : *this )
1574 paths.emplace_back( sheetPath.Path() );
1575
1576 return paths;
1577}
1578
1579
1580std::vector<SCH_SHEET_INSTANCE> SCH_SHEET_LIST::GetSheetInstances() const
1581{
1582 std::vector<SCH_SHEET_INSTANCE> retval;
1583
1584 for( const SCH_SHEET_PATH& path : *this )
1585 {
1586 const SCH_SHEET* sheet = path.Last();
1587
1588 wxCHECK2( sheet, continue );
1589
1590 SCH_SHEET_INSTANCE instance;
1591 SCH_SHEET_PATH tmpPath = path;
1592
1593 tmpPath.pop_back();
1594 instance.m_Path = tmpPath.Path();
1595 instance.m_PageNumber = path.GetPageNumber();
1596
1597 retval.push_back( std::move( instance ) );
1598 }
1599
1600 return retval;
1601}
1602
1603
1605{
1606 for( const SCH_SHEET_PATH& instance : *this )
1607 {
1608 if( !instance.GetPageNumber().IsEmpty() )
1609 return false;
1610 }
1611
1612 return true;
1613}
1614
1615
1617{
1618 // Don't accidentally renumber existing sheets.
1619 wxCHECK( AllSheetPageNumbersEmpty(), /* void */ );
1620
1621 wxString tmp;
1622 int pageNumber = 1;
1623
1624 for( SCH_SHEET_PATH& instance : *this )
1625 {
1626 if( instance.Last()->IsVirtualRootSheet() )
1627 continue;
1628
1629 tmp.Printf( "%d", pageNumber );
1630 instance.SetPageNumber( tmp );
1631 pageNumber += 1;
1632 }
1633}
1634
1635
1637 const wxString& aProjectName )
1638{
1639 for( SCH_SHEET_PATH& sheetPath : *this )
1640 sheetPath.AddNewSymbolInstances( aPrefixSheetPath, aProjectName );
1641}
1642
1643
1645{
1646 for( SCH_SHEET_PATH& sheetPath : *this )
1647 sheetPath.RemoveSymbolInstances( aPrefixSheetPath );
1648}
1649
1650
1652 int aLastVirtualPageNumber )
1653{
1654 wxString pageNumber;
1655 int lastUsedPageNumber = 1;
1656 int nextVirtualPageNumber = aLastVirtualPageNumber;
1657
1658 // Fetch the list of page numbers already in use.
1659 std::vector< wxString > usedPageNumbers;
1660
1661 if( aPrefixSheetPath.size() )
1662 {
1663 SCH_SHEET_LIST prefixHierarchy( aPrefixSheetPath.at( 0 ) );
1664
1665 for( const SCH_SHEET_PATH& path : prefixHierarchy )
1666 {
1667 pageNumber = path.GetPageNumber();
1668
1669 if( !pageNumber.IsEmpty() )
1670 usedPageNumbers.emplace_back( pageNumber );
1671 }
1672 }
1673
1674 for( SCH_SHEET_PATH& sheetPath : *this )
1675 {
1676 KIID_PATH tmp = sheetPath.Path();
1677 SCH_SHEET_PATH newSheetPath( aPrefixSheetPath );
1678
1679 // Prefix the new hierarchical path.
1680 newSheetPath = newSheetPath + sheetPath;
1681
1682 // Sheets cannot have themselves in the path.
1683 tmp.pop_back();
1684
1685 SCH_SHEET* sheet = sheetPath.Last();
1686
1687 wxCHECK2( sheet, continue );
1688
1689 nextVirtualPageNumber += 1;
1690
1691 SCH_SHEET_INSTANCE instance;
1692
1693 // Add the instance if it doesn't already exist
1694 if( !sheet->getInstance( instance, tmp, true ) )
1695 {
1696 sheet->addInstance( tmp );
1697 sheet->getInstance( instance, tmp, true );
1698 }
1699
1700 // Get a new page number if we don't have one
1701 if( instance.m_PageNumber.IsEmpty() )
1702 {
1703 // Generate the next available page number.
1704 do
1705 {
1706 pageNumber.Printf( wxT( "%d" ), lastUsedPageNumber );
1707 lastUsedPageNumber += 1;
1708 } while( std::find( usedPageNumbers.begin(), usedPageNumbers.end(), pageNumber ) !=
1709 usedPageNumbers.end() );
1710
1711 instance.m_PageNumber = pageNumber;
1712 newSheetPath.SetVirtualPageNumber( nextVirtualPageNumber );
1713 }
1714
1715 newSheetPath.SetPageNumber( instance.m_PageNumber );
1716 usedPageNumbers.push_back( instance.m_PageNumber );
1717 }
1718}
1719
1720
1721void SCH_SHEET_LIST::CheckForMissingSymbolInstances( const wxString& aProjectName )
1722{
1723 wxLogTrace( traceSchSheetPaths,
1724 "SCH_SHEET_LIST::CheckForMissingSymbolInstances: Processing %zu sheet paths",
1725 size() );
1726
1727 for( SCH_SHEET_PATH& sheetPath : *this )
1728 {
1729 wxLogTrace( traceSchSheetPaths,
1730 " Processing sheet path: '%s' (size=%zu, KIID_PATH='%s')",
1731 sheetPath.PathHumanReadable( false ),
1732 sheetPath.size(),
1733 sheetPath.Path().AsString() );
1734 sheetPath.CheckForMissingSymbolInstances( aProjectName );
1735 }
1736}
1737
1738
1740{
1741 int lastVirtualPageNumber = 1;
1742
1743 for( const SCH_SHEET_PATH& sheetPath : *this )
1744 {
1745 if( sheetPath.GetVirtualPageNumber() > lastVirtualPageNumber )
1746 lastVirtualPageNumber = sheetPath.GetVirtualPageNumber();
1747 }
1748
1749 return lastVirtualPageNumber;
1750}
1751
1752
1753bool SCH_SHEET_LIST::HasPath( const KIID_PATH& aPath ) const
1754{
1755 for( const SCH_SHEET_PATH& path : *this )
1756 {
1757 if( path.Path() == aPath )
1758 return true;
1759 }
1760
1761 return false;
1762}
1763
1764
1765bool SCH_SHEET_LIST::ContainsSheet( const SCH_SHEET* aSheet ) const
1766{
1767 for( const SCH_SHEET_PATH& path : *this )
1768 {
1769 for( size_t i = 0; i < path.size(); i++ )
1770 {
1771 if( path.at( i ) == aSheet )
1772 return true;
1773 }
1774 }
1775
1776 return false;
1777}
1778
1779
1780std::optional<SCH_SHEET_PATH> SCH_SHEET_LIST::GetOrdinalPath( const SCH_SCREEN* aScreen ) const
1781{
1782 // Sheet paths with sheets that do not have a screen object are not valid.
1783 if( !aScreen )
1784 return std::nullopt;
1785
1786 for( const SCH_SHEET_PATH& path: *this )
1787 {
1788 if( path.LastScreen() == aScreen )
1789 return std::optional<SCH_SHEET_PATH>( path );
1790 }
1791
1792 return std::nullopt;
1793}
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:527
KICAD_T Type() const
Returns the type of object.
Definition eda_item.h:111
virtual void UpdateHatching() const
virtual bool IsVisible() const
Definition eda_text.h:187
virtual void SetVisible(bool aVisible)
Definition eda_text.cpp:400
EE_TYPE OfType(KICAD_T aType) const
Definition sch_rtree.h:241
wxString AsString() const
Definition kiid.cpp:365
Definition kiid.h:49
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:88
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:116
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:631
SCHEMATIC * Schematic() const
Search the item hierarchy to find a SCHEMATIC.
Definition sch_item.cpp:254
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:212
Container to create a flattened list of symbols because in a complex hierarchy, a symbol can be used ...
void SplitReferences()
Attempt to split all reference designators into a name (U) and number (1).
void AddItem(const SCH_REFERENCE &aItem)
A helper to define a symbol's reference designator in a schematic.
void SetRef(const wxString &aReference)
void SetRefNum(int aNum)
wxString GetRef() const
void SetSheetNumber(int aSheetNumber)
EE_RTREE & Items()
Get the full RTree, usually for iterating.
Definition sch_screen.h: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.
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
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 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.
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.
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:377
wxString GetFileName() const
Return the filename corresponding to this sheet.
Definition sch_sheet.h:371
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:137
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:140
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:462
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:53
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
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.
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
VECTOR2I end
wxLogTrace helper definitions.
@ SCH_SYMBOL_T
Definition typeinfo.h:176
@ SCH_SHAPE_T
Definition typeinfo.h:153
@ NOT_USED
the 3d code uses this value
Definition typeinfo.h:79
@ SCH_GLOBAL_LABEL_T
Definition typeinfo.h:172
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:695