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