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 // Prefer an instance from the current project; shared schematics may carry
905 // instance data for several projects. Copying the full instance carries
906 // variant DNP / value / field overrides across when v9-imported files have
907 // been re-rooted and their stored paths no longer match.
908 const std::vector<SCH_SYMBOL_INSTANCE>& instances = symbol->GetInstances();
909
910 auto sourceIt = std::find_if( instances.begin(), instances.end(),
911 [&aProjectName]( const SCH_SYMBOL_INSTANCE& aInstance )
912 {
913 return aInstance.m_ProjectName == aProjectName;
914 } );
915
916 if( sourceIt == instances.end() )
917 sourceIt = instances.begin();
918
919 symbolInstance = *sourceIt;
920
921 wxLogTrace( traceSchSheetPaths,
922 " Using available instance (project '%s'): ref=%s, unit=%d, variants=%zu",
923 sourceIt->m_ProjectName, symbolInstance.m_Reference,
924 symbolInstance.m_Unit, symbolInstance.m_Variants.size() );
925 }
926 else
927 {
928 // Fall back to the symbol's reference field and unit if no instance data exists.
929 SCH_FIELD* refField = symbol->GetField( FIELD_T::REFERENCE );
930 symbolInstance.m_Reference = refField->GetText();
931 symbolInstance.m_Unit = symbol->GetUnit();
932
933 wxLogTrace( traceSchSheetPaths,
934 " No instance data: Using reference '%s' from field, unit %d",
935 symbolInstance.m_Reference, symbolInstance.m_Unit );
936 }
937
938 symbolInstance.m_ProjectName = aProjectName;
939 symbolInstance.m_Path = Path();
940 symbol->AddHierarchicalReference( symbolInstance );
941
942 wxLogTrace( traceSchSheetPaths,
943 " Created instance: ref=%s, path=%s",
944 symbolInstance.m_Reference, symbolInstance.m_Path.AsString() );
945 }
946 else
947 {
948 wxLogTrace( traceSchSheetPaths,
949 " Symbol %s already has instance: ref=%s, path=%s",
950 symbol->m_Uuid.AsString(),
951 symbolInstance.m_Reference,
952 symbolInstance.m_Path.AsString() );
953 }
954 }
955}
956
957
959{
960 wxCHECK( m_sheets.size() > 1, /* void */ );
961
962 wxFileName sheetFileName = Last()->GetFileName();
963
964 // If the sheet file name is absolute, then the user requested is so don't make it relative.
965 if( sheetFileName.IsAbsolute() )
966 return;
967
968 SCH_SCREEN* screen = LastScreen();
969 SCH_SCREEN* parentScreen = m_sheets[ m_sheets.size() - 2 ]->GetScreen();
970
971 wxCHECK( screen && parentScreen, /* void */ );
972
973 wxFileName fileName = screen->GetFileName();
974 wxFileName parentFileName = parentScreen->GetFileName();
975
976 // SCH_SCREEN file names must be absolute. If they are not, someone set them incorrectly
977 // on load or on creation.
978 wxCHECK( fileName.IsAbsolute() && parentFileName.IsAbsolute(), /* void */ );
979
980 if( fileName.GetPath() == parentFileName.GetPath() )
981 {
982 Last()->SetFileName( fileName.GetFullName() );
983 }
984 else if( fileName.MakeRelativeTo( parentFileName.GetPath() ) )
985 {
986 Last()->SetFileName( fileName.GetFullPath() );
987 }
988 else
989 {
990 Last()->SetFileName( screen->GetFileName() );
991 }
992
993 wxLogTrace( tracePathsAndFiles,
994 wxT( "\n File name: '%s'"
995 "\n parent file name '%s',"
996 "\n sheet '%s' file name '%s'." ),
997 screen->GetFileName(), parentScreen->GetFileName(), PathHumanReadable(),
998 Last()->GetFileName() );
999}
1000
1001
1003{
1004 if( aSheet != nullptr )
1005 BuildSheetList( aSheet, false );
1006}
1007
1008
1009void SCH_SHEET_LIST::BuildSheetList( SCH_SHEET* aSheet, bool aCheckIntegrity )
1010{
1011 if( !aSheet )
1012 return;
1013
1014 wxLogTrace( traceSchSheetPaths,
1015 "BuildSheetList called with sheet '%s' (UUID=%s, isVirtualRoot=%d)",
1016 aSheet->GetName(),
1017 aSheet->m_Uuid.AsString(),
1018 aSheet->m_Uuid == niluuid ? 1 : 0 );
1019
1020 // Special handling for virtual root: process its children without adding the root itself
1021 if( aSheet->IsVirtualRootSheet() )
1022 {
1023 wxLogTrace( traceSchSheetPaths, " Skipping virtual root, processing children only" );
1024
1025 if( aSheet->GetScreen() )
1026 {
1027 std::vector<SCH_ITEM*> childSheets;
1028 aSheet->GetScreen()->GetSheets( &childSheets );
1029
1030 for( SCH_ITEM* item : childSheets )
1031 {
1032 SCH_SHEET* sheet = static_cast<SCH_SHEET*>( item );
1033 BuildSheetList( sheet, aCheckIntegrity );
1034 }
1035 }
1036
1037 return;
1038 }
1039
1040 std::vector<SCH_SHEET*> badSheets;
1041
1042 m_currentSheetPath.push_back( aSheet );
1043 m_currentSheetPath.SetVirtualPageNumber( static_cast<int>( size() ) + 1 );
1045
1046 if( m_currentSheetPath.LastScreen() )
1047 {
1048 wxString parentFileName = aSheet->GetFileName();
1049 std::vector<SCH_ITEM*> childSheets;
1050 m_currentSheetPath.LastScreen()->GetSheets( &childSheets );
1051
1052 for( SCH_ITEM* item : childSheets )
1053 {
1054 SCH_SHEET* sheet = static_cast<SCH_SHEET*>( item );
1055
1056 if( aCheckIntegrity )
1057 {
1058 if( !m_currentSheetPath.TestForRecursion( sheet->GetFileName(), parentFileName ) )
1059 BuildSheetList( sheet, true );
1060 else
1061 badSheets.push_back( sheet );
1062 }
1063 else
1064 {
1065 // If we are not performing a full recursion test, at least check if we are in
1066 // a simple recursion scenario to prevent stack overflow crashes
1067 wxCHECK2_MSG( sheet->GetFileName() != aSheet->GetFileName(), continue,
1068 wxT( "Recursion prevented in SCH_SHEET_LIST::BuildSheetList" ) );
1069
1070 BuildSheetList( sheet, false );
1071 }
1072 }
1073 }
1074
1075 if( aCheckIntegrity )
1076 {
1077 for( SCH_SHEET* sheet : badSheets )
1078 {
1079 m_currentSheetPath.LastScreen()->Remove( sheet );
1080 m_currentSheetPath.LastScreen()->SetContentModified();
1081 }
1082 }
1083
1084 m_currentSheetPath.pop_back();
1085}
1086
1087
1088void SCH_SHEET_LIST::SortByHierarchicalPageNumbers( bool aUpdateVirtualPageNums )
1089{
1090 for( const SCH_SHEET_PATH& path : *this )
1091 path.CachePageNumber();
1092
1093 std::sort( begin(), end(),
1094 []( const SCH_SHEET_PATH& a, const SCH_SHEET_PATH& b ) -> bool
1095 {
1096 // Find the divergence point in the paths
1097 size_t common_len = 0;
1098 size_t min_len = std::min( a.size(), b.size() );
1099
1100 while( common_len < min_len && a.at( common_len )->m_Uuid == b.at( common_len )->m_Uuid )
1101 common_len++;
1102
1103 // If one path is a prefix of the other, the shorter one comes first
1104 // This ensures parents come before children
1105 if( common_len == a.size() )
1106 return true; // a is a prefix of b - a is the parent
1107 if( common_len == b.size() )
1108 return false; // b is a prefix of a - b is the parent
1109
1110 // Paths diverge at common_len
1111 // If they share the same parent, sort by page number
1112 // This ensures siblings are sorted by page number
1113 SCH_SHEET* sheet_a = a.at( common_len );
1114 SCH_SHEET* sheet_b = b.at( common_len );
1115
1116 // Create partial paths to get to these sheets for page number comparison
1117 KIID_PATH ancestor;
1118 for( size_t i = 0; i < common_len; i++ )
1119 ancestor.push_back( a.at( i )->m_Uuid );
1120
1121 // Compare page numbers - use the last sheet's page number
1122 wxString page_a = sheet_a->getPageNumber( ancestor );
1123 wxString page_b = sheet_b->getPageNumber( ancestor );
1124
1125 int retval = SCH_SHEET::ComparePageNum( page_a, page_b );
1126
1127 if( retval != 0 )
1128 return retval < 0;
1129
1130 // If page numbers are the same, use virtual page numbers as a tie-breaker
1132 return true;
1133 else if( a.GetVirtualPageNumber() > b.GetVirtualPageNumber() )
1134 return false;
1135
1136 // Finally, use UUIDs for stable ordering when everything else is equal
1137 return a.GetCurrentHash() < b.GetCurrentHash();
1138 } );
1139
1140 if( aUpdateVirtualPageNums )
1141 {
1142 int virtualPageNum = 1;
1143
1144 for( SCH_SHEET_PATH& sheet : *this )
1145 sheet.SetVirtualPageNumber( virtualPageNum++ );
1146 }
1147}
1148
1149
1150void SCH_SHEET_LIST::SortByPageNumbers( bool aUpdateVirtualPageNums )
1151{
1152 for( const SCH_SHEET_PATH& path : *this )
1153 path.CachePageNumber();
1154
1155 std::sort( begin(), end(),
1156 []( const SCH_SHEET_PATH& a, const SCH_SHEET_PATH& b ) -> bool
1157 {
1159 b.GetCachedPageNumber() );
1160
1161 if( retval < 0 )
1162 return true;
1163 else if( retval > 0 )
1164 return false;
1165
1167 return true;
1168 else if( a.GetVirtualPageNumber() > b.GetVirtualPageNumber() )
1169 return false;
1170
1171 // Enforce strict ordering. If the page numbers are the same, use UUIDs
1172 return a.GetCurrentHash() < b.GetCurrentHash();
1173 } );
1174
1175 if( aUpdateVirtualPageNums )
1176 {
1177 int virtualPageNum = 1;
1178
1179 for( SCH_SHEET_PATH& sheet : *this )
1180 sheet.SetVirtualPageNumber( virtualPageNum++ );
1181 }
1182}
1183
1184
1185bool SCH_SHEET_LIST::NameExists( const wxString& aSheetName ) const
1186{
1187 for( const SCH_SHEET_PATH& sheet : *this )
1188 {
1189 if( sheet.Last()->GetName() == aSheetName )
1190 return true;
1191 }
1192
1193 return false;
1194}
1195
1196
1197bool SCH_SHEET_LIST::PageNumberExists( const wxString& aPageNumber ) const
1198{
1199 for( const SCH_SHEET_PATH& sheet : *this )
1200 {
1201 if( sheet.GetPageNumber() == aPageNumber )
1202 return true;
1203 }
1204
1205 return false;
1206}
1207
1208
1209void SCH_SHEET_LIST::TrimToPageNumbers( const std::vector<wxString>& aPageInclusions )
1210{
1211 auto it = std::remove_if( begin(), end(),
1212 [&]( const SCH_SHEET_PATH& sheet )
1213 {
1214 return std::find( aPageInclusions.begin(),
1215 aPageInclusions.end(),
1216 sheet.GetPageNumber() ) == aPageInclusions.end();
1217 } );
1218
1219 erase( it, end() );
1220}
1221
1222
1224{
1225 wxString pageNumber;
1226
1227 // Find the next available page number by checking all existing page numbers
1228 std::set<int> usedPageNumbers;
1229
1230 for( const SCH_SHEET_PATH& path : *this )
1231 {
1232 wxString existingPageNum = path.GetPageNumber();
1233 long pageNum = 0;
1234
1235 if( existingPageNum.ToLong( &pageNum ) && pageNum > 0 )
1236 usedPageNumbers.insert( static_cast<int>( pageNum ) );
1237 }
1238
1239 // Find the first available number starting from 1
1240 int nextAvailable = 1;
1241
1242 while( usedPageNumbers.count( nextAvailable ) > 0 )
1243 nextAvailable++;
1244
1245 pageNumber.Printf( wxT( "%d" ), nextAvailable );
1246 return pageNumber;
1247}
1248
1249
1251{
1252 for( const SCH_SHEET_PATH& sheet : *this )
1253 {
1254 if( sheet.LastScreen() && sheet.LastScreen()->IsContentModified() )
1255 return true;
1256 }
1257
1258 return false;
1259}
1260
1261
1263{
1264 for( const SCH_SHEET_PATH& sheet : *this )
1265 {
1266 if( sheet.LastScreen() )
1267 sheet.LastScreen()->SetContentModified( false );
1268 }
1269}
1270
1271
1272SCH_ITEM* SCH_SHEET_LIST::ResolveItem( const KIID& aID, SCH_SHEET_PATH* aPathOut, bool aAllowNullptrReturn ) const
1273{
1274 for( const SCH_SHEET_PATH& sheet : *this )
1275 {
1276 SCH_ITEM* item = sheet.ResolveItem( aID );
1277
1278 if( item )
1279 {
1280 if( aPathOut )
1281 *aPathOut = sheet;
1282
1283 return item;
1284 }
1285 }
1286
1287 // Not found; weak reference has been deleted.
1288 if( aAllowNullptrReturn )
1289 return nullptr;
1290 else
1292}
1293
1294
1296{
1297 for( SCH_ITEM* aItem : LastScreen()->Items() )
1298 {
1299 if( aItem->m_Uuid == aID )
1300 return aItem;
1301
1302 SCH_ITEM* childMatch = nullptr;
1303
1304 aItem->RunOnChildren(
1305 [&]( SCH_ITEM* aChild )
1306 {
1307 if( aChild->m_Uuid == aID )
1308 childMatch = aChild;
1309 },
1311
1312 if( childMatch )
1313 return childMatch;
1314 }
1315
1316 return nullptr;
1317}
1318
1319
1320void SCH_SHEET_LIST::FillItemMap( std::map<KIID, EDA_ITEM*>& aMap )
1321{
1322 for( const SCH_SHEET_PATH& sheet : *this )
1323 {
1324 SCH_SCREEN* screen = sheet.LastScreen();
1325
1326 for( SCH_ITEM* aItem : screen->Items() )
1327 {
1328 aMap[ aItem->m_Uuid ] = aItem;
1329
1330 aItem->RunOnChildren(
1331 [&]( SCH_ITEM* aChild )
1332 {
1333 aMap[ aChild->m_Uuid ] = aChild;
1334 },
1336 }
1337 }
1338}
1339
1340
1342{
1343 // List of reference for power symbols
1344 SCH_REFERENCE_LIST references;
1345
1346 // Map of locked symbols (not used, but needed by Annotate()
1347 SCH_MULTI_UNIT_REFERENCE_MAP lockedSymbols;
1348
1349 // Build the list of power symbols:
1350 for( SCH_SHEET_PATH& sheet : *this )
1351 {
1352 for( SCH_ITEM* item : sheet.LastScreen()->Items().OfType( SCH_SYMBOL_T ) )
1353 {
1354 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
1355 LIB_SYMBOL* libSymbol = symbol->GetLibSymbolRef().get();
1356
1357 if( libSymbol && libSymbol->IsPower() )
1358 {
1359 SCH_REFERENCE schReference( symbol, sheet );
1360 references.AddItem( schReference );
1361 }
1362 }
1363 }
1364
1365 // Find duplicate, and silently clear annotation of duplicate
1366 std::map<wxString, int> ref_list; // stores the existing references
1367
1368 for( unsigned ii = 0; ii< references.GetCount(); ++ii )
1369 {
1370 wxString curr_ref = references[ii].GetRef();
1371
1372 if( curr_ref.IsEmpty() )
1373 continue;
1374
1375 if( ref_list.find( curr_ref ) == ref_list.end() )
1376 {
1377 ref_list[curr_ref] = ii;
1378 continue;
1379 }
1380
1381 // Possible duplicate, if the ref ends by a number:
1382 if( curr_ref.Last() < '0' && curr_ref.Last() > '9' )
1383 continue; // not annotated
1384
1385 // Duplicate: clear annotation by removing the number ending the ref
1386 while( !curr_ref.IsEmpty() && curr_ref.Last() >= '0' && curr_ref.Last() <= '9' )
1387 curr_ref.RemoveLast();
1388
1389 references[ii].SetRef( curr_ref );
1390 }
1391
1392 // Break full symbol reference into name (prefix) and number:
1393 // example: IC1 become IC, and 1
1394 references.SplitReferences();
1395
1396 // Ensure all power symbols have the reference starting by '#'
1397 // (Not sure this is really useful)
1398 for( unsigned ii = 0; ii< references.GetCount(); ++ii )
1399 {
1400 SCH_REFERENCE& ref_unit = references[ii];
1401
1402 if( ref_unit.GetRef()[0] != '#' )
1403 {
1404 wxString new_ref = "#" + ref_unit.GetRef();
1405 ref_unit.SetRef( new_ref );
1406 ref_unit.SetRefNum( ii );
1407 }
1408 }
1409}
1410
1411
1413 bool aForceIncludeOrphanSymbols ) const
1414{
1415 for( const SCH_SHEET_PATH& sheet : *this )
1416 sheet.GetSymbols( aReferences, aSymbolFilter, aForceIncludeOrphanSymbols );
1417}
1418
1419
1421 SYMBOL_FILTER aSymbolFilter, bool aForceIncludeOrphanSymbols ) const
1422{
1423 for( const SCH_SHEET_PATH& sheet : *this )
1424 {
1425 if( sheet.IsContainedWithin( aSheetPath ) )
1426 sheet.GetSymbols( aReferences, aSymbolFilter, aForceIncludeOrphanSymbols );
1427 }
1428}
1429
1430
1431void SCH_SHEET_LIST::GetSheetsWithinPath( std::vector<SCH_SHEET_PATH>& aSheets,
1432 const SCH_SHEET_PATH& aSheetPath ) const
1433{
1434 for( const SCH_SHEET_PATH& sheet : *this )
1435 {
1436 if( sheet.IsContainedWithin( aSheetPath ) )
1437 aSheets.push_back( sheet );
1438 }
1439}
1440
1441
1442std::optional<SCH_SHEET_PATH> SCH_SHEET_LIST::GetSheetPathByKIIDPath( const KIID_PATH& aPath,
1443 bool aIncludeLastSheet ) const
1444{
1445 for( const SCH_SHEET_PATH& sheet : *this )
1446 {
1447 KIID_PATH testPath = sheet.Path();
1448
1449 if( !aIncludeLastSheet )
1450 testPath.pop_back();
1451
1452 if( testPath == aPath )
1453 return SCH_SHEET_PATH( sheet );
1454 }
1455
1456 return std::nullopt;
1457}
1458
1459
1461{
1462 for( auto it = begin(); it != end(); ++it )
1463 {
1465 ( *it ).GetMultiUnitSymbols( tempMap, aSymbolFilter );
1466
1467 for( SCH_MULTI_UNIT_REFERENCE_MAP::value_type& pair : tempMap )
1468 {
1469 // Merge this list into the main one
1470 unsigned n_refs = pair.second.GetCount();
1471
1472 for( unsigned thisRef = 0; thisRef < n_refs; ++thisRef )
1473 aRefList[pair.first].AddItem( pair.second[thisRef] );
1474 }
1475 }
1476}
1477
1478
1479bool SCH_SHEET_LIST::TestForRecursion( const SCH_SHEET_LIST& aSrcSheetHierarchy,
1480 const wxString& aDestFileName )
1481{
1482 if( empty() )
1483 return false;
1484
1485 SCHEMATIC* sch = at( 0 ).LastScreen()->Schematic();
1486
1487 wxCHECK_MSG( sch, false, "No SCHEMATIC found in SCH_SHEET_LIST::TestForRecursion!" );
1488
1489 wxFileName rootFn = sch->GetFileName();
1490 wxFileName destFn = aDestFileName;
1491
1492 if( destFn.IsRelative() )
1493 destFn.MakeAbsolute( rootFn.GetPath() );
1494
1495 // Test each SCH_SHEET_PATH in this SCH_SHEET_LIST for potential recursion.
1496 for( unsigned i = 0; i < size(); i++ )
1497 {
1498 // Test each SCH_SHEET_PATH in the source sheet.
1499 for( unsigned j = 0; j < aSrcSheetHierarchy.size(); j++ )
1500 {
1501 const SCH_SHEET_PATH* sheetPath = &aSrcSheetHierarchy[j];
1502
1503 for( unsigned k = 0; k < sheetPath->size(); k++ )
1504 {
1505 if( at( i ).TestForRecursion( sheetPath->GetSheet( k )->GetFileName(),
1506 aDestFileName ) )
1507 {
1508 return true;
1509 }
1510 }
1511 }
1512 }
1513
1514 // The source sheet file can safely be added to the destination sheet file.
1515 return false;
1516}
1517
1518
1520{
1521 for( SCH_SHEET_PATH& path : *this )
1522 {
1523 if( path.Path() == aPath->Path() )
1524 return &path;
1525 }
1526
1527 return nullptr;
1528}
1529
1530
1532{
1533 for( SCH_SHEET_PATH& sheetpath : *this )
1534 {
1535 if( sheetpath.LastScreen() == aScreen )
1536 return sheetpath;
1537 }
1538
1539 return SCH_SHEET_PATH();
1540}
1541
1542
1544{
1545 SCH_SHEET_LIST retval;
1546
1547 for( const SCH_SHEET_PATH& sheetpath : *this )
1548 {
1549 if( sheetpath.LastScreen() == aScreen )
1550 retval.push_back( sheetpath );
1551 }
1552
1553 return retval;
1554}
1555
1556
1558 const std::vector<SCH_SYMBOL_INSTANCE>& aSymbolInstances )
1559{
1560 for( SCH_SHEET_PATH& sheetPath : *this )
1561 {
1562 for( SCH_ITEM* item : sheetPath.LastScreen()->Items().OfType( SCH_SYMBOL_T ) )
1563 {
1564 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
1565
1566 wxCHECK2( symbol, continue );
1567
1568 KIID_PATH sheetPathWithSymbolUuid = sheetPath.Path();
1569 sheetPathWithSymbolUuid.push_back( symbol->m_Uuid );
1570
1571 auto it = std::find_if( aSymbolInstances.begin(), aSymbolInstances.end(),
1572 [ sheetPathWithSymbolUuid ]( const SCH_SYMBOL_INSTANCE& r ) -> bool
1573 {
1574 return sheetPathWithSymbolUuid == r.m_Path;
1575 } );
1576
1577 if( it == aSymbolInstances.end() )
1578 {
1579 wxLogTrace( traceSchSheetPaths, "No symbol instance found for symbol '%s'",
1580 sheetPathWithSymbolUuid.AsString() );
1581 continue;
1582 }
1583
1584 // Symbol instance paths are stored and looked up in memory with the root path so use
1585 // the full path here.
1586 symbol->AddHierarchicalReference( sheetPath.Path(), it->m_Reference, it->m_Unit );
1587 symbol->GetField( FIELD_T::REFERENCE )->SetText( it->m_Reference );
1588
1589 if( !it->m_Value.IsEmpty() )
1590 symbol->SetValueFieldText( it->m_Value );
1591
1592 if( !it->m_Footprint.IsEmpty() )
1593 symbol->SetFootprintFieldText( it->m_Footprint );
1594
1595 symbol->UpdatePrefix();
1596 }
1597 }
1598}
1599
1600
1601void SCH_SHEET_LIST::UpdateSheetInstanceData( const std::vector<SCH_SHEET_INSTANCE>& aSheetInstances )
1602{
1603
1604 for( SCH_SHEET_PATH& path : *this )
1605 {
1606 SCH_SHEET* sheet = path.Last();
1607
1608 wxCHECK2( sheet && path.Last(), continue );
1609
1610 auto it = std::find_if( aSheetInstances.begin(), aSheetInstances.end(),
1611 [&path]( const SCH_SHEET_INSTANCE& r ) -> bool
1612 {
1613 return path.Path() == r.m_Path;
1614 } );
1615
1616 if( it == aSheetInstances.end() )
1617 {
1618 wxLogTrace( traceSchSheetPaths, "No sheet instance found for path '%s'",
1619 path.Path().AsString() );
1620 continue;
1621 }
1622
1623 wxLogTrace( traceSchSheetPaths, "Setting sheet '%s' instance '%s' page number '%s'",
1624 ( sheet->GetName().IsEmpty() ) ? wxString( wxT( "root" ) ) : sheet->GetName(),
1625 path.Path().AsString(), it->m_PageNumber );
1626 path.SetPageNumber( it->m_PageNumber );
1627 }
1628}
1629
1630
1631std::vector<KIID_PATH> SCH_SHEET_LIST::GetPaths() const
1632{
1633 std::vector<KIID_PATH> paths;
1634
1635 for( const SCH_SHEET_PATH& sheetPath : *this )
1636 paths.emplace_back( sheetPath.Path() );
1637
1638 return paths;
1639}
1640
1641
1642std::vector<SCH_SHEET_INSTANCE> SCH_SHEET_LIST::GetSheetInstances() const
1643{
1644 std::vector<SCH_SHEET_INSTANCE> retval;
1645
1646 for( const SCH_SHEET_PATH& path : *this )
1647 {
1648 const SCH_SHEET* sheet = path.Last();
1649
1650 wxCHECK2( sheet, continue );
1651
1652 SCH_SHEET_INSTANCE instance;
1653 SCH_SHEET_PATH tmpPath = path;
1654
1655 tmpPath.pop_back();
1656 instance.m_Path = tmpPath.Path();
1657 instance.m_PageNumber = path.GetPageNumber();
1658
1659 retval.push_back( std::move( instance ) );
1660 }
1661
1662 return retval;
1663}
1664
1665
1667{
1668 for( const SCH_SHEET_PATH& instance : *this )
1669 {
1670 if( !instance.GetPageNumber().IsEmpty() )
1671 return false;
1672 }
1673
1674 return true;
1675}
1676
1677
1679{
1680 // Don't accidentally renumber existing sheets.
1681 wxCHECK( AllSheetPageNumbersEmpty(), /* void */ );
1682
1683 wxString tmp;
1684 int pageNumber = 1;
1685
1686 for( SCH_SHEET_PATH& instance : *this )
1687 {
1688 if( instance.Last()->IsVirtualRootSheet() )
1689 continue;
1690
1691 tmp.Printf( "%d", pageNumber );
1692 instance.SetPageNumber( tmp );
1693 pageNumber += 1;
1694 }
1695}
1696
1697
1699 const wxString& aProjectName )
1700{
1701 for( SCH_SHEET_PATH& sheetPath : *this )
1702 sheetPath.AddNewSymbolInstances( aPrefixSheetPath, aProjectName );
1703}
1704
1705
1707{
1708 for( SCH_SHEET_PATH& sheetPath : *this )
1709 sheetPath.RemoveSymbolInstances( aPrefixSheetPath );
1710}
1711
1712
1714 int aLastVirtualPageNumber )
1715{
1716 wxString pageNumber;
1717 int lastUsedPageNumber = 1;
1718 int nextVirtualPageNumber = aLastVirtualPageNumber;
1719
1720 // Fetch the list of page numbers already in use.
1721 std::vector< wxString > usedPageNumbers;
1722
1723 if( aPrefixSheetPath.size() )
1724 {
1725 SCH_SHEET_LIST prefixHierarchy( aPrefixSheetPath.at( 0 ) );
1726
1727 for( const SCH_SHEET_PATH& path : prefixHierarchy )
1728 {
1729 pageNumber = path.GetPageNumber();
1730
1731 if( !pageNumber.IsEmpty() )
1732 usedPageNumbers.emplace_back( pageNumber );
1733 }
1734 }
1735
1736 for( SCH_SHEET_PATH& sheetPath : *this )
1737 {
1738 KIID_PATH tmp = sheetPath.Path();
1739 SCH_SHEET_PATH newSheetPath( aPrefixSheetPath );
1740
1741 // Prefix the new hierarchical path.
1742 newSheetPath = newSheetPath + sheetPath;
1743
1744 // Sheets cannot have themselves in the path.
1745 tmp.pop_back();
1746
1747 SCH_SHEET* sheet = sheetPath.Last();
1748
1749 wxCHECK2( sheet, continue );
1750
1751 nextVirtualPageNumber += 1;
1752
1753 SCH_SHEET_INSTANCE instance;
1754
1755 // Add the instance if it doesn't already exist
1756 if( !sheet->getInstance( instance, tmp, true ) )
1757 {
1758 sheet->addInstance( tmp );
1759 sheet->getInstance( instance, tmp, true );
1760 }
1761
1762 // Get a new page number if we don't have one
1763 if( instance.m_PageNumber.IsEmpty() )
1764 {
1765 // Generate the next available page number.
1766 do
1767 {
1768 pageNumber.Printf( wxT( "%d" ), lastUsedPageNumber );
1769 lastUsedPageNumber += 1;
1770 } while( std::find( usedPageNumbers.begin(), usedPageNumbers.end(), pageNumber ) !=
1771 usedPageNumbers.end() );
1772
1773 instance.m_PageNumber = pageNumber;
1774 newSheetPath.SetVirtualPageNumber( nextVirtualPageNumber );
1775 }
1776
1777 newSheetPath.SetPageNumber( instance.m_PageNumber );
1778 usedPageNumbers.push_back( instance.m_PageNumber );
1779 }
1780}
1781
1782
1783void SCH_SHEET_LIST::CheckForMissingSymbolInstances( const wxString& aProjectName )
1784{
1785 wxLogTrace( traceSchSheetPaths,
1786 "SCH_SHEET_LIST::CheckForMissingSymbolInstances: Processing %zu sheet paths",
1787 size() );
1788
1789 for( SCH_SHEET_PATH& sheetPath : *this )
1790 {
1791 wxLogTrace( traceSchSheetPaths,
1792 " Processing sheet path: '%s' (size=%zu, KIID_PATH='%s')",
1793 sheetPath.PathHumanReadable( false ),
1794 sheetPath.size(),
1795 sheetPath.Path().AsString() );
1796 sheetPath.CheckForMissingSymbolInstances( aProjectName );
1797 }
1798}
1799
1800
1802{
1803 int lastVirtualPageNumber = 1;
1804
1805 for( const SCH_SHEET_PATH& sheetPath : *this )
1806 {
1807 if( sheetPath.GetVirtualPageNumber() > lastVirtualPageNumber )
1808 lastVirtualPageNumber = sheetPath.GetVirtualPageNumber();
1809 }
1810
1811 return lastVirtualPageNumber;
1812}
1813
1814
1815bool SCH_SHEET_LIST::HasPath( const KIID_PATH& aPath ) const
1816{
1817 for( const SCH_SHEET_PATH& path : *this )
1818 {
1819 if( path.Path() == aPath )
1820 return true;
1821 }
1822
1823 return false;
1824}
1825
1826
1827bool SCH_SHEET_LIST::ContainsSheet( const SCH_SHEET* aSheet ) const
1828{
1829 for( const SCH_SHEET_PATH& path : *this )
1830 {
1831 for( size_t i = 0; i < path.size(); i++ )
1832 {
1833 if( path.at( i ) == aSheet )
1834 return true;
1835 }
1836 }
1837
1838 return false;
1839}
1840
1841
1842std::optional<SCH_SHEET_PATH> SCH_SHEET_LIST::GetOrdinalPath( const SCH_SCREEN* aScreen ) const
1843{
1844 // Sheet paths with sheets that do not have a screen object are not valid.
1845 if( !aScreen )
1846 return std::nullopt;
1847
1848 for( const SCH_SHEET_PATH& path: *this )
1849 {
1850 if( path.LastScreen() == aScreen )
1851 return std::optional<SCH_SHEET_PATH>( path );
1852 }
1853
1854 return std::nullopt;
1855}
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:535
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:132
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:166
virtual void RunOnChildren(const std::function< void(SCH_ITEM *)> &aFunction, RECURSE_MODE aMode)
Definition sch_item.h:632
SCHEMATIC * Schematic() const
Search the item hierarchy to find a SCHEMATIC.
Definition sch_item.cpp:272
int GetUnit() const
Definition sch_item.h:237
virtual void SetUnit(int aUnit)
Definition sch_item.h:236
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:73
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:132
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:181
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.
std::map< wxString, SCH_SYMBOL_VARIANT > m_Variants
A list of symbol variants.
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