KiCad PCB EDA Suite
Loading...
Searching...
No Matches
schematic.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 The KiCad Developers, see AUTHORS.txt for contributors.
5 *
6 * This program is free software: you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation, either version 3 of the License, or (at your
9 * option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20#include <bus_alias.h>
21#include <commit.h>
22#include <connection_graph.h>
23#include <core/ignore.h>
24#include <core/kicad_algo.h>
25#include <ee_collectors.h>
26#include <erc/erc_settings.h>
27#include <font/outline_font.h>
29#include <project.h>
32#include <schematic.h>
33#include <sch_junction.h>
34#include <sch_label.h>
35#include <sch_line.h>
36#include <sch_marker.h>
37#include <sch_screen.h>
38#include <sim/spice_settings.h>
39#include <sim/spice_value.h>
40
41#include <wx/log.h>
42
44
46 EDA_ITEM( nullptr, SCHEMATIC_T ),
47 m_project( nullptr ),
48 m_rootSheet( nullptr )
49{
53
54 SetProject( aPrj );
55
57 [&]( INSPECTABLE* aItem, PROPERTY_BASE* aProperty, COMMIT* aCommit )
58 {
59 // Special case: propagate value, footprint, and datasheet fields to other units
60 // of a given symbol if they aren't in the selection
61
62 SCH_FIELD* field = dynamic_cast<SCH_FIELD*>( aItem );
63
64 if( !field || !IsValid() )
65 return;
66
67 SCH_SYMBOL* symbol = dynamic_cast<SCH_SYMBOL*>( field->GetParent() );
68
69 if( !symbol || aProperty->Name() != _HKI( "Text" ) )
70 return;
71
72 // TODO(JE) This will need to get smarter to enable API access
73 SCH_SHEET_PATH sheetPath = CurrentSheet();
74
75 wxString newValue = aItem->Get<wxString>( aProperty );
76
77 if( field->GetId() == REFERENCE_FIELD )
78 {
79 symbol->SetRef( &sheetPath, newValue );
80
81 // The user might want to change all the units to the new ref. Or they
82 // might not. Since we have no way of knowing, we default to the most
83 // concrete action (change only the selected reference).
84 return;
85 }
86
87 wxString ref = symbol->GetRef( &sheetPath );
88 int unit = symbol->GetUnit();
89 LIB_ID libId = symbol->GetLibId();
90
91 for( SCH_SHEET_PATH& sheet : Hierarchy() )
92 {
93 std::vector<SCH_SYMBOL*> otherUnits;
94
95 CollectOtherUnits( ref, unit, libId, sheet, &otherUnits );
96
97 for( SCH_SYMBOL* otherUnit : otherUnits )
98 {
99 switch( field->GetId() )
100 {
101 case VALUE_FIELD:
102 {
103 if( aCommit )
104 aCommit->Modify( otherUnit, sheet.LastScreen() );
105
106 otherUnit->SetValueFieldText( newValue );
107 break;
108 }
109
110 case FOOTPRINT_FIELD:
111 {
112 if( aCommit )
113 aCommit->Modify( otherUnit, sheet.LastScreen() );
114
115 otherUnit->SetFootprintFieldText( newValue );
116 break;
117 }
118
119 case DATASHEET_FIELD:
120 {
121 if( aCommit )
122 aCommit->Modify( otherUnit, sheet.LastScreen() );
123
124 otherUnit->GetField( DATASHEET_FIELD )->SetText( newValue );
125 break;
126 }
127
128 default:
129 break;
130 }
131 }
132 }
133 } );
134}
135
136
138{
140
141 delete m_currentSheet;
142 delete m_connectionGraph;
143
144 m_IsSchematicExists = false;
145}
146
147
149{
150 if( m_project )
151 {
153
154 // d'tor will save settings to file
155 delete project.m_ErcSettings;
156 project.m_ErcSettings = nullptr;
157
158 // d'tor will save settings to file
159 delete project.m_SchematicSettings;
160 project.m_SchematicSettings = nullptr;
161
162 m_project = nullptr; // clear the project, so we don't do this again when setting a new one
163 }
164
165 delete m_rootSheet;
166
167 m_rootSheet = nullptr;
168
171}
172
173
175{
176 if( m_project )
177 {
179
180 // d'tor will save settings to file
181 delete project.m_ErcSettings;
182 project.m_ErcSettings = nullptr;
183
184 // d'tor will save settings to file
185 delete project.m_SchematicSettings;
186 project.m_SchematicSettings = nullptr;
187 }
188
189 m_project = aPrj;
190
191 if( m_project )
192 {
194 project.m_ErcSettings = new ERC_SETTINGS( &project, "erc" );
195 project.m_SchematicSettings = new SCHEMATIC_SETTINGS( &project, "schematic" );
196
197 project.m_SchematicSettings->LoadFromFile();
198 project.m_SchematicSettings->m_NgspiceSettings->LoadFromFile();
199 project.m_ErcSettings->LoadFromFile();
200 }
201}
202
203
204void SCHEMATIC::SetRoot( SCH_SHEET* aRootSheet )
205{
206 wxCHECK_RET( aRootSheet, wxS( "Call to SetRoot with null SCH_SHEET!" ) );
207
208 m_rootSheet = aRootSheet;
209
212
215}
216
217
219{
220 return IsValid() ? m_rootSheet->GetScreen() : nullptr;
221}
222
223
225{
226 wxCHECK( !m_hierarchy.empty(), m_hierarchy );
227
228 return m_hierarchy;
229}
230
231
233{
235}
236
237
238void SCHEMATIC::GetContextualTextVars( wxArrayString* aVars ) const
239{
240 auto add =
241 [&]( const wxString& aVar )
242 {
243 if( !alg::contains( *aVars, aVar ) )
244 aVars->push_back( aVar );
245 };
246
247 add( wxT( "#" ) );
248 add( wxT( "##" ) );
249 add( wxT( "SHEETPATH" ) );
250 add( wxT( "SHEETNAME" ) );
251 add( wxT( "FILENAME" ) );
252 add( wxT( "FILEPATH" ) );
253 add( wxT( "PROJECTNAME" ) );
254
255 if( !CurrentSheet().empty() )
257
258 for( std::pair<wxString, wxString> entry : Prj().GetTextVars() )
259 add( entry.first );
260}
261
262
263bool SCHEMATIC::ResolveTextVar( const SCH_SHEET_PATH* aSheetPath, wxString* token,
264 int aDepth ) const
265{
266 wxCHECK( aSheetPath, false );
267
268 if( token->IsSameAs( wxT( "#" ) ) )
269 {
270 *token = aSheetPath->GetPageNumber();
271 return true;
272 }
273 else if( token->IsSameAs( wxT( "##" ) ) )
274 {
275 *token = wxString::Format( "%i", Root().CountSheets() );
276 return true;
277 }
278 else if( token->IsSameAs( wxT( "SHEETPATH" ) ) )
279 {
280 *token = aSheetPath->PathHumanReadable();
281 return true;
282 }
283 else if( token->IsSameAs( wxT( "SHEETNAME" ) ) )
284 {
285 *token = aSheetPath->Last()->GetName();
286 return true;
287 }
288 else if( token->IsSameAs( wxT( "FILENAME" ) ) )
289 {
290 wxFileName fn( GetFileName() );
291 *token = fn.GetFullName();
292 return true;
293 }
294 else if( token->IsSameAs( wxT( "FILEPATH" ) ) )
295 {
296 wxFileName fn( GetFileName() );
297 *token = fn.GetFullPath();
298 return true;
299 }
300 else if( token->IsSameAs( wxT( "PROJECTNAME" ) ) )
301 {
302 *token = Prj().GetProjectName();
303 return true;
304 }
305
306 if( aSheetPath->LastScreen()->GetTitleBlock().TextVarResolver( token, m_project ) )
307 return true;
308
309 if( Prj().TextVarResolver( token ) )
310 return true;
311
312 return false;
313}
314
315
317{
318 return IsValid() ? m_rootSheet->GetScreen()->GetFileName() : wxString( wxEmptyString );
319}
320
321
323{
324 wxASSERT( m_project );
326}
327
328
330{
331 wxASSERT( m_project );
333}
334
335
336std::vector<SCH_MARKER*> SCHEMATIC::ResolveERCExclusions()
337{
338 SCH_SHEET_LIST sheetList = Hierarchy();
339 ERC_SETTINGS& settings = ErcSettings();
340
341 // Migrate legacy marker exclusions to new format to ensure exclusion matching functions across
342 // file versions. Silently drops any legacy exclusions which can not be mapped to the new format
343 // without risking an incorrect exclusion - this is preferable to silently dropping
344 // new ERC errors / warnings due to an incorrect match between a legacy and new
345 // marker serialization format
346 std::set<wxString> migratedExclusions;
347
348 for( auto it = settings.m_ErcExclusions.begin(); it != settings.m_ErcExclusions.end(); )
349 {
350 SCH_MARKER* testMarker = SCH_MARKER::DeserializeFromString( sheetList, *it );
351
352 if( !testMarker )
353 {
354 it = settings.m_ErcExclusions.erase( it );
355 continue;
356 }
357
358 if( testMarker->IsLegacyMarker() )
359 {
360 const wxString settingsKey = testMarker->GetRCItem()->GetSettingsKey();
361
362 if( settingsKey != wxT( "pin_to_pin" )
363 && settingsKey != wxT( "hier_label_mismatch" )
364 && settingsKey != wxT( "different_unit_net" ) )
365 {
366 migratedExclusions.insert( testMarker->SerializeToString() );
367 }
368
369 it = settings.m_ErcExclusions.erase( it );
370 }
371 else
372 {
373 ++it;
374 }
375
376 delete testMarker;
377 }
378
379 settings.m_ErcExclusions.insert( migratedExclusions.begin(), migratedExclusions.end() );
380
381 // End of legacy exclusion removal / migrations
382
383 for( const SCH_SHEET_PATH& sheet : sheetList )
384 {
385 for( SCH_ITEM* item : sheet.LastScreen()->Items().OfType( SCH_MARKER_T ) )
386 {
387 SCH_MARKER* marker = static_cast<SCH_MARKER*>( item );
388 wxString serialized = marker->SerializeToString();
389 std::set<wxString>::iterator it = settings.m_ErcExclusions.find( serialized );
390
391 if( it != settings.m_ErcExclusions.end() )
392 {
393 marker->SetExcluded( true, settings.m_ErcExclusionComments[serialized] );
394 settings.m_ErcExclusions.erase( it );
395 }
396 }
397 }
398
399 std::vector<SCH_MARKER*> newMarkers;
400
401 for( const wxString& serialized : settings.m_ErcExclusions )
402 {
403 SCH_MARKER* marker = SCH_MARKER::DeserializeFromString( sheetList, serialized );
404
405 if( marker )
406 {
407 marker->SetExcluded( true, settings.m_ErcExclusionComments[serialized] );
408 newMarkers.push_back( marker );
409 }
410 }
411
412 settings.m_ErcExclusions.clear();
413
414 return newMarkers;
415}
416
417
418std::shared_ptr<BUS_ALIAS> SCHEMATIC::GetBusAlias( const wxString& aLabel ) const
419{
420 for( const SCH_SHEET_PATH& sheet : Hierarchy() )
421 {
422 for( const std::shared_ptr<BUS_ALIAS>& alias : sheet.LastScreen()->GetBusAliases() )
423 {
424 if( alias->GetName() == aLabel )
425 return alias;
426 }
427 }
428
429 return nullptr;
430}
431
432
434{
435 std::set<wxString> names;
436
437 for( const auto& [ key, subgraphList ] : m_connectionGraph->GetNetMap() )
438 {
439 CONNECTION_SUBGRAPH* firstSubgraph = subgraphList[0];
440
441 if( !firstSubgraph->GetDriverConnection()->IsBus()
443 {
444 names.insert( key.Name );
445 }
446 }
447
448 return names;
449}
450
451
452bool SCHEMATIC::ResolveCrossReference( wxString* token, int aDepth ) const
453{
454 wxString remainder;
455 wxString ref = token->BeforeFirst( ':', &remainder );
456 KIID_PATH path( ref );
457 KIID uuid = path.back();
458 SCH_SHEET_PATH sheetPath;
459 SCH_ITEM* refItem = GetItem( KIID( uuid ), &sheetPath );
460
461 if( path.size() > 1 )
462 {
463 path.pop_back();
464 sheetPath = Hierarchy().GetSheetPathByKIIDPath( path ).value_or( sheetPath );
465 }
466
467 if( refItem && refItem->Type() == SCH_SYMBOL_T )
468 {
469 SCH_SYMBOL* refSymbol = static_cast<SCH_SYMBOL*>( refItem );
470
471 if( refSymbol->ResolveTextVar( &sheetPath, &remainder, aDepth + 1 ) )
472 *token = remainder;
473 else
474 *token = refSymbol->GetRef( &sheetPath, true ) + wxS( ":" ) + remainder;
475
476 return true; // Cross-reference is resolved whether or not the actual textvar was
477 }
478 else if( refItem && refItem->Type() == SCH_SHEET_T )
479 {
480 SCH_SHEET* refSheet = static_cast<SCH_SHEET*>( refItem );
481
482 sheetPath.push_back( refSheet );
483
484 if( refSheet->ResolveTextVar( &sheetPath, &remainder, aDepth + 1 ) )
485 *token = remainder;
486
487 return true; // Cross-reference is resolved whether or not the actual textvar was
488 }
489
490 return false;
491}
492
493
494std::map<int, wxString> SCHEMATIC::GetVirtualPageToSheetNamesMap() const
495{
496 std::map<int, wxString> namesMap;
497
498 for( const SCH_SHEET_PATH& sheet : Hierarchy() )
499 {
500 if( sheet.size() == 1 )
501 namesMap[sheet.GetVirtualPageNumber()] = _( "<root sheet>" );
502 else
503 namesMap[sheet.GetVirtualPageNumber()] = sheet.Last()->GetName();
504 }
505
506 return namesMap;
507}
508
509
510std::map<int, wxString> SCHEMATIC::GetVirtualPageToSheetPagesMap() const
511{
512 std::map<int, wxString> pagesMap;
513
514 for( const SCH_SHEET_PATH& sheet : Hierarchy() )
515 pagesMap[sheet.GetVirtualPageNumber()] = sheet.GetPageNumber();
516
517 return pagesMap;
518}
519
520
521wxString SCHEMATIC::ConvertRefsToKIIDs( const wxString& aSource ) const
522{
523 wxString newbuf;
524 size_t sourceLen = aSource.length();
525
526 for( size_t i = 0; i < sourceLen; ++i )
527 {
528 if( aSource[i] == '$' && i + 1 < sourceLen && aSource[i+1] == '{' )
529 {
530 wxString token;
531 bool isCrossRef = false;
532 int nesting = 0;
533
534 for( i = i + 2; i < sourceLen; ++i )
535 {
536 if( aSource[i] == '{'
537 && ( aSource[i-1] == '_' || aSource[i-1] == '^' || aSource[i-1] == '~' ) )
538 {
539 nesting++;
540 }
541
542 if( aSource[i] == '}' )
543 {
544 nesting--;
545
546 if( nesting < 0 )
547 break;
548 }
549
550 if( aSource[i] == ':' )
551 isCrossRef = true;
552
553 token.append( aSource[i] );
554 }
555
556 if( isCrossRef )
557 {
558 wxString remainder;
559 wxString ref = token.BeforeFirst( ':', &remainder );
560 SCH_REFERENCE_LIST references;
561
562 Hierarchy().GetSymbols( references );
563
564 for( size_t jj = 0; jj < references.GetCount(); jj++ )
565 {
566 SCH_SYMBOL* refSymbol = references[ jj ].GetSymbol();
567
568 if( ref == refSymbol->GetRef( &references[ jj ].GetSheetPath(), true ) )
569 {
570 KIID_PATH path = references[ jj ].GetSheetPath().Path();
571 path.push_back( refSymbol->m_Uuid );
572
573 token = path.AsString() + wxS( ":" ) + remainder;
574 break;
575 }
576 }
577 }
578
579 newbuf.append( wxS( "${" ) + token + wxS( "}" ) );
580 }
581 else
582 {
583 newbuf.append( aSource[i] );
584 }
585 }
586
587 return newbuf;
588}
589
590
591wxString SCHEMATIC::ConvertKIIDsToRefs( const wxString& aSource ) const
592{
593 wxString newbuf;
594 size_t sourceLen = aSource.length();
595
596 for( size_t i = 0; i < sourceLen; ++i )
597 {
598 if( aSource[i] == '$' && i + 1 < sourceLen && aSource[i+1] == '{' )
599 {
600 wxString token;
601 bool isCrossRef = false;
602
603 for( i = i + 2; i < sourceLen; ++i )
604 {
605 if( aSource[i] == '}' )
606 break;
607
608 if( aSource[i] == ':' )
609 isCrossRef = true;
610
611 token.append( aSource[i] );
612 }
613
614 if( isCrossRef )
615 {
616 wxString remainder;
617 wxString ref = token.BeforeFirst( ':', &remainder );
618 KIID_PATH path( ref );
619 KIID uuid = path.back();
620 SCH_SHEET_PATH sheetPath;
621 SCH_ITEM* refItem = GetItem( uuid, &sheetPath );
622
623 if( path.size() > 1 )
624 {
625 path.pop_back();
626 sheetPath = Hierarchy().GetSheetPathByKIIDPath( path ).value_or( sheetPath );
627 }
628
629 if( refItem && refItem->Type() == SCH_SYMBOL_T )
630 {
631 SCH_SYMBOL* refSymbol = static_cast<SCH_SYMBOL*>( refItem );
632 token = refSymbol->GetRef( &sheetPath, true ) + wxS( ":" ) + remainder;
633 }
634 }
635
636 newbuf.append( wxS( "${" ) + token + wxS( "}" ) );
637 }
638 else
639 {
640 newbuf.append( aSource[i] );
641 }
642 }
643
644 return newbuf;
645}
646
647
649{
650 SCH_SCREENS screens( m_rootSheet );
651
653}
654
655
657{
658 // Filename is rootSheetName-sheetName-...-sheetName
659 // Note that we need to fetch the rootSheetName out of its filename, as the root SCH_SHEET's
660 // name is just a timestamp.
661
662 wxFileName rootFn( CurrentSheet().at( 0 )->GetFileName() );
663 wxString filename = rootFn.GetName();
664
665 for( unsigned i = 1; i < CurrentSheet().size(); i++ )
666 filename += wxT( "-" ) + CurrentSheet().at( i )->GetName();
667
668 return filename;
669}
670
671
673{
674 SCH_SCREEN* screen;
675 SCH_SCREENS s_list( Root() );
676
677 // Set the sheet count, and the sheet number (1 for root sheet)
678 int sheet_count = Root().CountSheets();
679 int sheet_number = 1;
680 const KIID_PATH& current_sheetpath = CurrentSheet().Path();
681
682 // @todo Remove all pseudo page number system is left over from prior to real page number
683 // implementation.
684 for( const SCH_SHEET_PATH& sheet : Hierarchy() )
685 {
686 if( sheet.Path() == current_sheetpath ) // Current sheet path found
687 break;
688
689 sheet_number++; // Not found, increment before this current path
690 }
691
692 for( screen = s_list.GetFirst(); screen != nullptr; screen = s_list.GetNext() )
693 screen->SetPageCount( sheet_count );
694
695 CurrentSheet().SetVirtualPageNumber( sheet_number );
696 CurrentSheet().LastScreen()->SetVirtualPageNumber( sheet_number );
697 CurrentSheet().LastScreen()->SetPageNumber( CurrentSheet().GetPageNumber() );
698}
699
700
702 const std::function<void( SCH_GLOBALLABEL* )>& aItemCallback )
703{
704 std::map<wxString, std::set<int>>& pageRefsMap = GetPageRefsMap();
705
706 pageRefsMap.clear();
707
708 for( const SCH_SHEET_PATH& sheet : Hierarchy() )
709 {
710 for( SCH_ITEM* item : sheet.LastScreen()->Items().OfType( SCH_GLOBAL_LABEL_T ) )
711 {
712 SCH_GLOBALLABEL* global = static_cast<SCH_GLOBALLABEL*>( item );
713 wxString resolvedLabel = global->GetShownText( &sheet, false );
714
715 pageRefsMap[ resolvedLabel ].insert( sheet.GetVirtualPageNumber() );
716 }
717 }
718
719 bool show = Settings().m_IntersheetRefsShow;
720
721 // Refresh all visible global labels. Note that we have to collect them first as the
722 // SCH_SCREEN::Update() call is going to invalidate the RTree iterator.
723
724 std::vector<SCH_GLOBALLABEL*> currentSheetGlobalLabels;
725
726 for( EDA_ITEM* item : CurrentSheet().LastScreen()->Items().OfType( SCH_GLOBAL_LABEL_T ) )
727 currentSheetGlobalLabels.push_back( static_cast<SCH_GLOBALLABEL*>( item ) );
728
729 for( SCH_GLOBALLABEL* globalLabel : currentSheetGlobalLabels )
730 {
731 std::vector<SCH_FIELD>& fields = globalLabel->GetFields();
732
733 fields[0].SetVisible( show );
734
735 if( show )
736 {
737 if( fields.size() == 1 && fields[0].GetTextPos() == globalLabel->GetPosition() )
738 globalLabel->AutoplaceFields( CurrentSheet().LastScreen(), AUTOPLACE_AUTO );
739
740 CurrentSheet().LastScreen()->Update( globalLabel );
741 aItemCallback( globalLabel );
742 }
743 }
744}
745
746
747wxString SCHEMATIC::GetOperatingPoint( const wxString& aNetName, int aPrecision,
748 const wxString& aRange )
749{
750 wxString spiceNetName( aNetName.Lower() );
752
753 if( spiceNetName == wxS( "gnd" ) || spiceNetName == wxS( "0" ) )
754 return wxEmptyString;
755
756 auto it = m_operatingPoints.find( spiceNetName );
757
758 if( it != m_operatingPoints.end() )
759 return SPICE_VALUE( it->second ).ToString( { aPrecision, aRange } );
760 else if( m_operatingPoints.empty() )
761 return wxS( "--" );
762 else
763 return wxS( "?" );
764}
765
766
768{
769 SCH_SCREENS screens( Root() );
770
771 for( SCH_SCREEN* screen = screens.GetFirst(); screen; screen = screens.GetNext() )
772 {
773 std::deque<EDA_ITEM*> allItems;
774
775 for( auto item : screen->Items() )
776 allItems.push_back( item );
777
778 // Add missing junctions and breakup wires as needed
779 for( const VECTOR2I& point : screen->GetNeededJunctions( allItems ) )
780 {
781 SCH_JUNCTION* junction = new SCH_JUNCTION( point );
782 screen->Append( junction );
783
784 // Breakup wires
785 for( SCH_LINE* wire : screen->GetBusesAndWires( point, true ) )
786 {
787 SCH_LINE* newSegment = wire->BreakAt( point );
788 screen->Append( newSegment );
789 }
790 }
791 }
792}
793
794
795void SCHEMATIC::OnItemsAdded( std::vector<SCH_ITEM*>& aNewItems )
796{
798}
799
800
801void SCHEMATIC::OnItemsRemoved( std::vector<SCH_ITEM*>& aRemovedItems )
802{
804}
805
806
807void SCHEMATIC::OnItemsChanged( std::vector<SCH_ITEM*>& aItems )
808{
810}
811
812
814{
816}
817
818
820{
821 if( !alg::contains( m_listeners, aListener ) )
822 m_listeners.push_back( aListener );
823}
824
825
827{
828 auto i = std::find( m_listeners.begin(), m_listeners.end(), aListener );
829
830 if( i != m_listeners.end() )
831 {
832 std::iter_swap( i, m_listeners.end() - 1 );
833 m_listeners.pop_back();
834 }
835}
836
837
839{
840 m_listeners.clear();
841}
842
843
845{
846 // Use a sorted sheetList to reduce file churn
847 SCH_SHEET_LIST sheetList = Hierarchy();
848 ERC_SETTINGS& ercSettings = ErcSettings();
849
850 ercSettings.m_ErcExclusions.clear();
851 ercSettings.m_ErcExclusionComments.clear();
852
853 for( unsigned i = 0; i < sheetList.size(); i++ )
854 {
855 for( SCH_ITEM* item : sheetList[i].LastScreen()->Items().OfType( SCH_MARKER_T ) )
856 {
857 SCH_MARKER* marker = static_cast<SCH_MARKER*>( item );
858
859 if( marker->IsExcluded() )
860 {
861 wxString serialized = marker->SerializeToString();
862 ercSettings.m_ErcExclusions.insert( serialized );
863 ercSettings.m_ErcExclusionComments[ serialized ] = marker->GetComment();
864 }
865 }
866 }
867}
868
869
871{
872 SCH_SHEET_LIST sheetList = Hierarchy();
873
874 for( SCH_MARKER* marker : ResolveERCExclusions() )
875 {
876 SCH_SHEET_PATH errorPath;
877 ignore_unused( sheetList.GetItem( marker->GetRCItem()->GetMainItemID(), &errorPath ) );
878
879 if( errorPath.LastScreen() )
880 errorPath.LastScreen()->Append( marker );
881 else
882 RootScreen()->Append( marker );
883 }
884}
885
886
888{
889 return static_cast<EMBEDDED_FILES*>( this );
890}
891
892
894{
895 return static_cast<const EMBEDDED_FILES*>( this );
896}
897
898
899std::set<KIFONT::OUTLINE_FONT*> SCHEMATIC::GetFonts() const
900{
901 std::set<KIFONT::OUTLINE_FONT*> fonts;
902
903 SCH_SHEET_LIST sheetList = Hierarchy();
904
905 for( const SCH_SHEET_PATH& sheet : sheetList )
906 {
907 for( SCH_ITEM* item : sheet.LastScreen()->Items() )
908 {
909 if( EDA_TEXT* text = dynamic_cast<EDA_TEXT*>( item ) )
910 {
911 KIFONT::FONT* font = text->GetFont();
912
913 if( !font || font->IsStroke() )
914 continue;
915
916 using EMBEDDING_PERMISSION = KIFONT::OUTLINE_FONT::EMBEDDING_PERMISSION;
917 auto* outline = static_cast<KIFONT::OUTLINE_FONT*>( font );
918
919 if( outline->GetEmbeddingPermission() == EMBEDDING_PERMISSION::EDITABLE
920 || outline->GetEmbeddingPermission() == EMBEDDING_PERMISSION::INSTALLABLE )
921 {
922 fonts.insert( outline );
923 }
924 }
925 }
926 }
927
928 return fonts;
929}
930
931
933{
934 std::set<KIFONT::OUTLINE_FONT*> fonts = GetFonts();
935
936 for( KIFONT::OUTLINE_FONT* font : fonts )
937 {
938 auto file = GetEmbeddedFiles()->AddFile( font->GetFileName(), false );
939
940 if( !file )
941 {
942 wxLogTrace( "EMBED", "Failed to add font file: %s", font->GetFileName() );
943 continue;
944 }
945
947 }
948}
949
950
951std::set<const SCH_SCREEN*> SCHEMATIC::GetSchematicsSharedByMultipleProjects() const
952{
953 std::set<const SCH_SCREEN*> retv;
954
955 wxCHECK( m_rootSheet, retv );
956
957 SCH_SHEET_LIST hierarchy( m_rootSheet );
958 SCH_SCREENS screens( m_rootSheet );
959
960 for( const SCH_SCREEN* screen = screens.GetFirst(); screen; screen = screens.GetNext() )
961 {
962 for( const SCH_ITEM* item : screen->Items().OfType( SCH_SYMBOL_T ) )
963 {
964 const SCH_SYMBOL* symbol = static_cast<const SCH_SYMBOL*>( item );
965
966 const std::vector<SCH_SYMBOL_INSTANCE> symbolInstances = symbol->GetInstances();
967
968 for( const SCH_SYMBOL_INSTANCE& instance : symbolInstances )
969 {
970 if( !hierarchy.HasPath( instance.m_Path ) )
971 {
972 retv.insert( screen );
973 break;
974 }
975 }
976
977 if( retv.count( screen ) )
978 break;
979 }
980 }
981
982 return retv;
983}
984
985
987{
988 wxCHECK( m_rootSheet, false );
989
990 SCH_SCREENS screens( m_rootSheet );
991
992 for( const SCH_SCREEN* screen = screens.GetFirst(); screen; screen = screens.GetNext() )
993 {
994 wxCHECK2( screen, continue );
995
996 if( screen->GetRefCount() > 1 )
997 return true;
998 }
999
1000 return false;
1001}
void SetPageCount(int aPageCount)
Definition: base_screen.cpp:63
void SetPageNumber(const wxString &aPageNumber)
Definition: base_screen.h:79
void SetVirtualPageNumber(int aPageNumber)
Definition: base_screen.h:76
Represent a set of changes (additions, deletions or modifications) of a data model (e....
Definition: commit.h:74
COMMIT & Modify(EDA_ITEM *aItem, BASE_SCREEN *aScreen=nullptr)
Modify a given item in the model.
Definition: commit.h:108
Calculate the connectivity of a schematic and generates netlists.
const NET_MAP & GetNetMap() const
A subgraph is a set of items that are electrically connected on a single sheet.
static PRIORITY GetDriverPriority(SCH_ITEM *aDriver)
Return the priority (higher is more important) of a candidate driver.
const SCH_CONNECTION * GetDriverConnection() const
A base class for most all the KiCad significant classes used in schematics and boards.
Definition: eda_item.h:89
const KIID m_Uuid
Definition: eda_item.h:488
KICAD_T Type() const
Returns the type of object.
Definition: eda_item.h:101
EDA_ITEM * GetParent() const
Definition: eda_item.h:103
A mix-in class (via multiple inheritance) that handles texts such as labels, parts,...
Definition: eda_text.h:80
EMBEDDED_FILE * AddFile(const wxFileName &aName, bool aOverwrite)
Load a file from disk and adds it to the collection.
Container for ERC settings.
Definition: erc_settings.h:135
std::map< wxString, wxString > m_ErcExclusionComments
Definition: erc_settings.h:214
std::set< wxString > m_ErcExclusions
Definition: erc_settings.h:213
Class that other classes need to inherit from, in order to be inspectable.
Definition: inspectable.h:37
wxAny Get(PROPERTY_BASE *aProperty) const
Definition: inspectable.h:100
FONT is an abstract base class for both outline and stroke fonts.
Definition: font.h:131
virtual bool IsStroke() const
Definition: font.h:138
Class OUTLINE_FONT implements outline font drawing.
Definition: outline_font.h:53
Definition: kiid.h:49
A logical library item identifier and consists of various portions much like a URI.
Definition: lib_id.h:49
bool IsExcluded() const
Definition: marker_base.h:98
std::shared_ptr< RC_ITEM > GetRCItem() const
Definition: marker_base.h:112
void SetExcluded(bool aExcluded, const wxString &aComment=wxEmptyString)
Definition: marker_base.h:99
wxString GetComment() const
Definition: marker_base.h:105
static void ConvertToSpiceMarkup(wxString *aNetName)
Remove formatting wrappers and replace illegal spice net name characters with underscores.
The backing store for a PROJECT, in JSON format.
Definition: project_file.h:72
ERC_SETTINGS * m_ErcSettings
Eeschema params.
Definition: project_file.h:142
SCHEMATIC_SETTINGS * m_SchematicSettings
Definition: project_file.h:145
Container for project specific data.
Definition: project.h:64
virtual const wxString GetProjectName() const
Return the short name of the project.
Definition: project.cpp:158
virtual PROJECT_FILE & GetProjectFile() const
Definition: project.h:200
const wxString & Name() const
Definition: property.h:217
static PROPERTY_MANAGER & Instance()
Definition: property_mgr.h:87
void UnregisterListeners(TYPE_ID aType)
Definition: property_mgr.h:280
void RegisterListener(TYPE_ID aType, PROPERTY_LISTENER aListenerFunc)
Registers a listener for the given type.
Definition: property_mgr.h:275
virtual void OnSchItemsRemoved(SCHEMATIC &aSch, std::vector< SCH_ITEM * > &aSchItem)
Definition: schematic.h:67
virtual void OnSchItemsChanged(SCHEMATIC &aSch, std::vector< SCH_ITEM * > &aSchItem)
Definition: schematic.h:68
virtual void OnSchSheetChanged(SCHEMATIC &aSch)
Definition: schematic.h:72
virtual void OnSchItemsAdded(SCHEMATIC &aSch, std::vector< SCH_ITEM * > &aSchItem)
Definition: schematic.h:66
These are loaded from Eeschema settings but then overwritten by the project settings.
void Reset()
Initialize this schematic to a blank one, unloading anything existing.
Definition: schematic.cpp:148
std::set< const SCH_SCREEN * > GetSchematicsSharedByMultipleProjects() const
Return a list of schematic files in the current project that contain instance data for multiple proje...
Definition: schematic.cpp:951
void SetLegacySymbolInstanceData()
Update the symbol value and footprint instance data for legacy designs.
Definition: schematic.cpp:648
void OnItemsAdded(std::vector< SCH_ITEM * > &aNewItems)
Must be used if Add() is used using a BULK_x ADD_MODE to generate a change event for listeners.
Definition: schematic.cpp:795
CONNECTION_GRAPH * m_connectionGraph
Hold and calculate connectivity information of this schematic.
Definition: schematic.h:397
SCH_SHEET_LIST m_hierarchy
Cache of the entire schematic hierarchy sorted by sheet page number.
Definition: schematic.h:419
SCH_SHEET_PATH & CurrentSheet() const override
Definition: schematic.h:162
void ResolveERCExclusionsPostUpdate()
Update markers to match recorded exclusions.
Definition: schematic.cpp:870
void RemoveListener(SCHEMATIC_LISTENER *aListener)
Remove the specified listener.
Definition: schematic.cpp:826
bool IsComplexHierarchy() const
Test if the schematic is a complex hierarchy.
Definition: schematic.cpp:986
void OnSchSheetChanged()
Notify the schematic and its listeners that the current sheet has been changed.
Definition: schematic.cpp:813
SCH_SHEET_PATH * m_currentSheet
The sheet path of the sheet currently being edited or displayed.
Definition: schematic.h:394
wxString GetOperatingPoint(const wxString &aNetName, int aPrecision, const wxString &aRange)
Definition: schematic.cpp:747
void OnItemsRemoved(std::vector< SCH_ITEM * > &aRemovedItems)
Must be used if Remove() is used using a BULK_x REMOVE_MODE to generate a change event for listeners.
Definition: schematic.cpp:801
virtual ~SCHEMATIC()
Definition: schematic.cpp:137
std::shared_ptr< BUS_ALIAS > GetBusAlias(const wxString &aLabel) const
Return a pointer to a bus alias object for the given label, or null if one doesn't exist.
Definition: schematic.cpp:418
std::vector< SCH_MARKER * > ResolveERCExclusions()
Definition: schematic.cpp:336
wxString GetFileName() const override
Helper to retrieve the filename from the root sheet screen.
Definition: schematic.cpp:316
void EmbedFonts() override
Embed fonts in the schematic.
Definition: schematic.cpp:932
SCHEMATIC_SETTINGS & Settings() const
Definition: schematic.cpp:322
wxString ConvertKIIDsToRefs(const wxString &aSource) const
Definition: schematic.cpp:591
void RecordERCExclusions()
Scan existing markers and record data from any that are Excluded.
Definition: schematic.cpp:844
std::map< wxString, std::set< int > > & GetPageRefsMap()
Definition: schematic.h:208
void FixupJunctions()
Add junctions to this schematic where required.
Definition: schematic.cpp:767
SCH_SHEET_LIST Hierarchy() const override
Return the full schematic flattened hierarchical sheet list.
Definition: schematic.cpp:224
std::set< KIFONT::OUTLINE_FONT * > GetFonts() const override
Get a set of fonts used in the schematic.
Definition: schematic.cpp:899
SCH_ITEM * GetItem(const KIID &aID, SCH_SHEET_PATH *aPathOut=nullptr) const
Definition: schematic.h:126
wxString ConvertRefsToKIIDs(const wxString &aSource) const
Definition: schematic.cpp:521
void SetRoot(SCH_SHEET *aRootSheet)
Initialize the schematic with a new root sheet.
Definition: schematic.cpp:204
void SetProject(PROJECT *aPrj)
Definition: schematic.cpp:174
void AddListener(SCHEMATIC_LISTENER *aListener)
Add a listener to the schematic to receive calls whenever something on the schematic has been modifie...
Definition: schematic.cpp:819
std::map< int, wxString > GetVirtualPageToSheetPagesMap() const
Definition: schematic.cpp:510
EMBEDDED_FILES * GetEmbeddedFiles() override
Definition: schematic.cpp:887
PROJECT * m_project
Definition: schematic.h:382
SCH_SCREEN * RootScreen() const
Helper to retrieve the screen of the root sheet.
Definition: schematic.cpp:218
SCHEMATIC(PROJECT *aPrj)
Definition: schematic.cpp:45
bool ResolveTextVar(const SCH_SHEET_PATH *aSheetPath, wxString *token, int aDepth) const
Definition: schematic.cpp:263
std::set< wxString > GetNetClassAssignmentCandidates()
Return the set of netname candidates for netclass assignment.
Definition: schematic.cpp:433
void RecomputeIntersheetRefs(const std::function< void(SCH_GLOBALLABEL *)> &aItemCallback)
Update the schematic's page reference map for all global labels, and refresh the labels so that they ...
Definition: schematic.cpp:701
void InvokeListeners(Func &&aFunc, Args &&... args)
Definition: schematic.h:376
bool IsValid() const
A simple test if the schematic is loaded, not a complete one.
Definition: schematic.h:147
static bool m_IsSchematicExists
True if a SCHEMATIC exists, false if not.
Definition: schematic.h:366
void RemoveAllListeners()
Remove all listeners.
Definition: schematic.cpp:838
void GetContextualTextVars(wxArrayString *aVars) const
Definition: schematic.cpp:238
SCH_SHEET & Root() const
Definition: schematic.h:131
std::map< int, wxString > GetVirtualPageToSheetNamesMap() const
Definition: schematic.cpp:494
SCH_SHEET_LIST BuildSheetListSortedByPageNumbers() const override
Definition: schematic.h:103
wxString GetUniqueFilenameForCurrentSheet()
Get the unique file name for the current sheet.
Definition: schematic.cpp:656
void SetSheetNumberAndCount()
Set the m_ScreenNumber and m_NumberOfScreens members for screens.
Definition: schematic.cpp:672
std::vector< SCHEMATIC_LISTENER * > m_listeners
Currently installed listeners.
Definition: schematic.h:424
PROJECT & Prj() const override
Return a reference to the project this schematic is part of.
Definition: schematic.h:98
bool ResolveCrossReference(wxString *token, int aDepth) const
Resolves text vars that refer to other items.
Definition: schematic.cpp:452
std::map< wxString, double > m_operatingPoints
Simulation operating points for text variable substitution.
Definition: schematic.h:414
ERC_SETTINGS & ErcSettings() const
Definition: schematic.cpp:329
void RefreshHierarchy()
Definition: schematic.cpp:232
void OnItemsChanged(std::vector< SCH_ITEM * > &aItems)
Notify the schematic and its listeners that an item on the schematic has been modified in some way.
Definition: schematic.cpp:807
SCH_SHEET * m_rootSheet
The top-level sheet in this schematic hierarchy (or potentially the only one)
Definition: schematic.h:385
bool IsBus() const
Instances are attached to a symbol or sheet and provide a place for the symbol's value,...
Definition: sch_field.h:53
int GetId() const
Definition: sch_field.h:141
Base class for any item which can be embedded within the SCHEMATIC container class,...
Definition: sch_item.h:167
int GetUnit() const
Definition: sch_item.h:233
wxString GetShownText(const SCH_SHEET_PATH *aPath, bool aAllowExtraText, int aDepth=0) const override
Definition: sch_label.cpp:819
Segment description base class to describe items which have 2 end points (track, wire,...
Definition: sch_line.h:41
SCH_LINE * BreakAt(const VECTOR2I &aPoint)
Break this segment into two at the specified point.
Definition: sch_line.cpp:571
static SCH_MARKER * DeserializeFromString(const SCH_SHEET_LIST &aSheetList, const wxString &data)
Definition: sch_marker.cpp:143
wxString SerializeToString() const
Definition: sch_marker.cpp:91
bool IsLegacyMarker() const
Determine if this marker is legacy (i.e.
Definition: sch_marker.h:126
Container to create a flattened list of symbols because in a complex hierarchy, a symbol can be used ...
size_t GetCount() const
Container class that holds multiple SCH_SCREEN objects in a hierarchy.
Definition: sch_screen.h:716
SCH_SCREEN * GetNext()
SCH_SCREEN * GetFirst()
void SetLegacySymbolInstanceData()
Update the symbol value and footprint instance data for legacy designs.
void Append(SCH_ITEM *aItem, bool aUpdateLibSymbol=true)
Definition: sch_screen.cpp:155
const wxString & GetFileName() const
Definition: sch_screen.h:144
const TITLE_BLOCK & GetTitleBlock() const
Definition: sch_screen.h:155
void Update(SCH_ITEM *aItem, bool aUpdateLibSymbol=true)
Update aItem's bounding box in the tree.
Definition: sch_screen.cpp:318
A container for handling SCH_SHEET_PATH objects in a flattened hierarchy.
std::optional< SCH_SHEET_PATH > GetSheetPathByKIIDPath(const KIID_PATH &aPath, bool aIncludeLastSheet=true) const
Finds a SCH_SHEET_PATH that matches the provided KIID_PATH.
SCH_ITEM * GetItem(const KIID &aID, SCH_SHEET_PATH *aPathOut=nullptr) const
Fetch a SCH_ITEM by ID.
void GetSymbols(SCH_REFERENCE_LIST &aReferences, bool aIncludePowerSymbols=true, bool aForceIncludeOrphanSymbols=false) const
Add a SCH_REFERENCE object to aReferences for each symbol in the list of sheets.
bool HasPath(const KIID_PATH &aPath) const
Handle access to a stack of flattened SCH_SHEET objects by way of a path for creating a flattened sch...
wxString PathHumanReadable(bool aUseShortRootName=true, bool aStripTrailingSeparator=false) const
Return the sheet path in a human readable form made from the sheet names.
KIID_PATH Path() const
Get the sheet path as an KIID_PATH.
SCH_SCREEN * LastScreen()
wxString GetPageNumber() const
SCH_SHEET * at(size_t aIndex) const
Forwarded method from std::vector.
void SetVirtualPageNumber(int aPageNumber)
Set the sheet instance virtual page number.
SCH_SHEET * Last() const
Return a pointer to the last SCH_SHEET of the list.
void push_back(SCH_SHEET *aSheet)
Forwarded method from std::vector.
void clear()
Forwarded method from std::vector.
size_t size() const
Forwarded method from std::vector.
Sheet symbol placed in a schematic, and is the entry point for a sub schematic.
Definition: sch_sheet.h:59
wxString GetName() const
Definition: sch_sheet.h:110
int CountSheets() const
Count the number of sheets found in "this" sheet including all of the subsheets.
Definition: sch_sheet.cpp:836
SCH_SCREEN * GetScreen() const
Definition: sch_sheet.h:113
bool ResolveTextVar(const SCH_SHEET_PATH *aPath, wxString *token, int aDepth=0) const
Resolve any references to system tokens supported by the sheet.
Definition: sch_sheet.cpp:254
Schematic symbol object.
Definition: sch_symbol.h:77
const std::vector< SCH_SYMBOL_INSTANCE > & GetInstances() const
Definition: sch_symbol.h:136
void SetRef(const SCH_SHEET_PATH *aSheet, const wxString &aReference)
Set the reference for the given sheet path for this symbol.
Definition: sch_symbol.cpp:747
bool ResolveTextVar(const SCH_SHEET_PATH *aPath, wxString *token, int aDepth=0) const
Resolve any references to system tokens supported by the symbol.
const LIB_ID & GetLibId() const override
Definition: sch_symbol.h:166
const wxString GetRef(const SCH_SHEET_PATH *aSheet, bool aIncludeUnit=false) const override
Definition: sch_symbol.cpp:705
Helper class to recognize Spice formatted values.
Definition: spice_value.h:56
wxString ToString() const
Return string value as when converting double to string (e.g.
bool TextVarResolver(wxString *aToken, const PROJECT *aProject, int aFlags=0) const
static void GetContextualTextVars(wxArrayString *aVars)
Definition: title_block.cpp:75
wxString GetTextVars(const wxString &aSource)
Returns any variables unexpanded, e.g.
Definition: common.cpp:121
#define _HKI(x)
static bool empty(const wxTextEntryBase *aCtrl)
#define _(s)
void CollectOtherUnits(const wxString &aRef, int aUnit, const LIB_ID &aLibId, SCH_SHEET_PATH &aSheet, std::vector< SCH_SYMBOL * > *otherUnits)
void ignore_unused(const T &)
Definition: ignore.h:24
bool contains(const _Container &__container, _Value __value)
Returns true if the container contains the given value.
Definition: kicad_algo.h:100
#define TYPE_HASH(x)
Definition: property.h:71
@ AUTOPLACE_AUTO
Definition: sch_item.h:70
A simple container for schematic symbol instance information.
@ DATASHEET_FIELD
name of datasheet
@ FOOTPRINT_FIELD
Field Name Module PCB, i.e. "16DIP300".
@ VALUE_FIELD
Field Value of part, i.e. "3.3K".
@ REFERENCE_FIELD
Field Reference of part, i.e. "IC21".
@ SCH_SYMBOL_T
Definition: typeinfo.h:172
@ SCH_SHEET_T
Definition: typeinfo.h:174
@ SCH_MARKER_T
Definition: typeinfo.h:158
@ SCHEMATIC_T
Definition: typeinfo.h:203
@ SCH_GLOBAL_LABEL_T
Definition: typeinfo.h:168