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 <core/profile.h>
26#include <sch_collectors.h>
27#include <erc/erc_settings.h>
28#include <font/outline_font.h>
30#include <progress_reporter.h>
31#include <project.h>
34#include <schematic.h>
35#include <sch_bus_entry.h>
36#include <sch_commit.h>
37#include <sch_junction.h>
38#include <sch_label.h>
39#include <sch_line.h>
40#include <sch_marker.h>
41#include <sch_no_connect.h>
42#include <sch_rule_area.h>
43#include <sch_screen.h>
44#include <sch_sheet_pin.h>
45#include <sch_selection_tool.h>
46#include <sim/spice_settings.h>
47#include <sim/spice_value.h>
48#include <tool/tool_manager.h>
49#include <undo_redo_container.h>
50
51#include <wx/log.h>
52
54
56 EDA_ITEM( nullptr, SCHEMATIC_T ),
57 m_project( nullptr ),
58 m_rootSheet( nullptr ),
59 m_schematicHolder( nullptr )
60{
64
65 SetProject( aPrj );
66
68 [&]( INSPECTABLE* aItem, PROPERTY_BASE* aProperty, COMMIT* aCommit )
69 {
70 // Special case: propagate value, footprint, and datasheet fields to other units
71 // of a given symbol if they aren't in the selection
72
73 SCH_FIELD* field = dynamic_cast<SCH_FIELD*>( aItem );
74
75 if( !field || !IsValid() )
76 return;
77
78 SCH_SYMBOL* symbol = dynamic_cast<SCH_SYMBOL*>( field->GetParent() );
79
80 if( !symbol || aProperty->Name() != _HKI( "Text" ) )
81 return;
82
83 // TODO(JE) This will need to get smarter to enable API access
84 SCH_SHEET_PATH sheetPath = CurrentSheet();
85
86 wxString newValue = aItem->Get<wxString>( aProperty );
87
88 if( field->GetId() == FIELD_T::REFERENCE )
89 {
90 symbol->SetRef( &sheetPath, newValue );
91
92 // The user might want to change all the units to the new ref. Or they
93 // might not. Since we have no way of knowing, we default to the most
94 // concrete action (change only the selected reference).
95 return;
96 }
97
98 wxString ref = symbol->GetRef( &sheetPath );
99 int unit = symbol->GetUnit();
100 LIB_ID libId = symbol->GetLibId();
101
102 for( SCH_SHEET_PATH& sheet : Hierarchy() )
103 {
104 std::vector<SCH_SYMBOL*> otherUnits;
105
106 CollectOtherUnits( ref, unit, libId, sheet, &otherUnits );
107
108 for( SCH_SYMBOL* otherUnit : otherUnits )
109 {
110 switch( field->GetId() )
111 {
112 case FIELD_T::VALUE:
113 case FIELD_T::FOOTPRINT:
114 case FIELD_T::DATASHEET:
115 {
116 if( aCommit )
117 aCommit->Modify( otherUnit, sheet.LastScreen() );
118
119 otherUnit->GetField( field->GetId() )->SetText( newValue );
120 break;
121 }
122
123 default:
124 break;
125 }
126 }
127 }
128 } );
129}
130
131
133{
135
136 delete m_currentSheet;
137 delete m_connectionGraph;
138
139 m_IsSchematicExists = false;
140}
141
142
144{
146 {
148
149 // d'tor will save settings to file
150 delete project.m_ErcSettings;
151 project.m_ErcSettings = nullptr;
152
153 // d'tor will save settings to file
154 delete project.m_SchematicSettings;
155 project.m_SchematicSettings = nullptr;
156
157 m_project = nullptr; // clear the project, so we don't do this again when setting a new one
158 }
159
160 delete m_rootSheet;
161
162 m_rootSheet = nullptr;
163
166}
167
168
170{
171 if( m_project )
172 {
174
175 // d'tor will save settings to file
176 delete project.m_ErcSettings;
177 project.m_ErcSettings = nullptr;
178
179 // d'tor will save settings to file
180 delete project.m_SchematicSettings;
181 project.m_SchematicSettings = nullptr;
182 }
183
184 m_project = aPrj;
185
186 if( m_project )
187 {
189 project.m_ErcSettings = new ERC_SETTINGS( &project, "erc" );
190 project.m_SchematicSettings = new SCHEMATIC_SETTINGS( &project, "schematic" );
191
192 project.m_SchematicSettings->LoadFromFile();
193 project.m_SchematicSettings->m_NgspiceSettings->LoadFromFile();
194 project.m_ErcSettings->LoadFromFile();
195 }
196}
197
198
199void SCHEMATIC::SetRoot( SCH_SHEET* aRootSheet )
200{
201 wxCHECK_RET( aRootSheet, wxS( "Call to SetRoot with null SCH_SHEET!" ) );
202
203 m_rootSheet = aRootSheet;
204
207
210}
211
212
214{
215 return IsValid() ? m_rootSheet->GetScreen() : nullptr;
216}
217
218
220{
221 wxCHECK( !m_hierarchy.empty(), m_hierarchy );
222
223 return m_hierarchy;
224}
225
226
228{
230}
231
232
233void SCHEMATIC::GetContextualTextVars( wxArrayString* aVars ) const
234{
235 auto add =
236 [&]( const wxString& aVar )
237 {
238 if( !alg::contains( *aVars, aVar ) )
239 aVars->push_back( aVar );
240 };
241
242 add( wxT( "#" ) );
243 add( wxT( "##" ) );
244 add( wxT( "SHEETPATH" ) );
245 add( wxT( "SHEETNAME" ) );
246 add( wxT( "FILENAME" ) );
247 add( wxT( "FILEPATH" ) );
248 add( wxT( "PROJECTNAME" ) );
249
250 if( !CurrentSheet().empty() )
252
253 for( std::pair<wxString, wxString> entry : m_project->GetTextVars() )
254 add( entry.first );
255}
256
257
258bool SCHEMATIC::ResolveTextVar( const SCH_SHEET_PATH* aSheetPath, wxString* token,
259 int aDepth ) const
260{
261 wxCHECK( aSheetPath, false );
262
263 if( token->IsSameAs( wxT( "#" ) ) )
264 {
265 *token = aSheetPath->GetPageNumber();
266 return true;
267 }
268 else if( token->IsSameAs( wxT( "##" ) ) )
269 {
270 *token = wxString::Format( "%i", Root().CountSheets() );
271 return true;
272 }
273 else if( token->IsSameAs( wxT( "SHEETPATH" ) ) )
274 {
275 *token = aSheetPath->PathHumanReadable();
276 return true;
277 }
278 else if( token->IsSameAs( wxT( "SHEETNAME" ) ) )
279 {
280 *token = aSheetPath->Last()->GetName();
281 return true;
282 }
283 else if( token->IsSameAs( wxT( "FILENAME" ) ) )
284 {
285 wxFileName fn( GetFileName() );
286 *token = fn.GetFullName();
287 return true;
288 }
289 else if( token->IsSameAs( wxT( "FILEPATH" ) ) )
290 {
291 wxFileName fn( GetFileName() );
292 *token = fn.GetFullPath();
293 return true;
294 }
295 else if( token->IsSameAs( wxT( "PROJECTNAME" ) ) )
296 {
297 *token = m_project->GetProjectName();
298 return true;
299 }
300
301 if( aSheetPath->LastScreen()->GetTitleBlock().TextVarResolver( token, m_project ) )
302 return true;
303
304 if( m_project->TextVarResolver( token ) )
305 return true;
306
307 return false;
308}
309
310
312{
313 return IsValid() ? m_rootSheet->GetScreen()->GetFileName() : wxString( wxEmptyString );
314}
315
316
318{
319 wxASSERT( m_project );
321}
322
323
325{
326 wxASSERT( m_project );
328}
329
330
331std::vector<SCH_MARKER*> SCHEMATIC::ResolveERCExclusions()
332{
333 SCH_SHEET_LIST sheetList = Hierarchy();
334 ERC_SETTINGS& settings = ErcSettings();
335
336 // Migrate legacy marker exclusions to new format to ensure exclusion matching functions across
337 // file versions. Silently drops any legacy exclusions which can not be mapped to the new format
338 // without risking an incorrect exclusion - this is preferable to silently dropping
339 // new ERC errors / warnings due to an incorrect match between a legacy and new
340 // marker serialization format
341 std::set<wxString> migratedExclusions;
342
343 for( auto it = settings.m_ErcExclusions.begin(); it != settings.m_ErcExclusions.end(); )
344 {
345 SCH_MARKER* testMarker = SCH_MARKER::DeserializeFromString( sheetList, *it );
346
347 if( !testMarker )
348 {
349 it = settings.m_ErcExclusions.erase( it );
350 continue;
351 }
352
353 if( testMarker->IsLegacyMarker() )
354 {
355 const wxString settingsKey = testMarker->GetRCItem()->GetSettingsKey();
356
357 if( settingsKey != wxT( "pin_to_pin" )
358 && settingsKey != wxT( "hier_label_mismatch" )
359 && settingsKey != wxT( "different_unit_net" ) )
360 {
361 migratedExclusions.insert( testMarker->SerializeToString() );
362 }
363
364 it = settings.m_ErcExclusions.erase( it );
365 }
366 else
367 {
368 ++it;
369 }
370
371 delete testMarker;
372 }
373
374 settings.m_ErcExclusions.insert( migratedExclusions.begin(), migratedExclusions.end() );
375
376 // End of legacy exclusion removal / migrations
377
378 for( const SCH_SHEET_PATH& sheet : sheetList )
379 {
380 for( SCH_ITEM* item : sheet.LastScreen()->Items().OfType( SCH_MARKER_T ) )
381 {
382 SCH_MARKER* marker = static_cast<SCH_MARKER*>( item );
383 wxString serialized = marker->SerializeToString();
384 std::set<wxString>::iterator it = settings.m_ErcExclusions.find( serialized );
385
386 if( it != settings.m_ErcExclusions.end() )
387 {
388 marker->SetExcluded( true, settings.m_ErcExclusionComments[serialized] );
389 settings.m_ErcExclusions.erase( it );
390 }
391 }
392 }
393
394 std::vector<SCH_MARKER*> newMarkers;
395
396 for( const wxString& serialized : settings.m_ErcExclusions )
397 {
398 SCH_MARKER* marker = SCH_MARKER::DeserializeFromString( sheetList, serialized );
399
400 if( marker )
401 {
402 marker->SetExcluded( true, settings.m_ErcExclusionComments[serialized] );
403 newMarkers.push_back( marker );
404 }
405 }
406
407 settings.m_ErcExclusions.clear();
408
409 return newMarkers;
410}
411
412
413std::shared_ptr<BUS_ALIAS> SCHEMATIC::GetBusAlias( const wxString& aLabel ) const
414{
415 for( const SCH_SHEET_PATH& sheet : Hierarchy() )
416 {
417 for( const std::shared_ptr<BUS_ALIAS>& alias : sheet.LastScreen()->GetBusAliases() )
418 {
419 if( alias->GetName() == aLabel )
420 return alias;
421 }
422 }
423
424 return nullptr;
425}
426
427
429{
430 std::set<wxString> names;
431
432 for( const auto& [ key, subgraphList ] : m_connectionGraph->GetNetMap() )
433 {
434 CONNECTION_SUBGRAPH* firstSubgraph = subgraphList[0];
435
436 if( !firstSubgraph->GetDriverConnection()->IsBus()
438 {
439 names.insert( key.Name );
440 }
441 }
442
443 return names;
444}
445
446
447bool SCHEMATIC::ResolveCrossReference( wxString* token, int aDepth ) const
448{
449 wxString remainder;
450 wxString ref = token->BeforeFirst( ':', &remainder );
451 KIID_PATH path( ref );
452 KIID uuid = path.back();
453 SCH_SHEET_PATH sheetPath;
454 SCH_ITEM* refItem = ResolveItem( KIID( uuid ), &sheetPath, true );
455
456 if( path.size() > 1 )
457 {
458 path.pop_back();
459 sheetPath = Hierarchy().GetSheetPathByKIIDPath( path ).value_or( sheetPath );
460 }
461
462 if( refItem && refItem->Type() == SCH_SYMBOL_T )
463 {
464 SCH_SYMBOL* refSymbol = static_cast<SCH_SYMBOL*>( refItem );
465
466 if( refSymbol->ResolveTextVar( &sheetPath, &remainder, aDepth + 1 ) )
467 *token = std::move( remainder );
468 else
469 *token = refSymbol->GetRef( &sheetPath, true ) + wxS( ":" ) + remainder;
470
471 return true; // Cross-reference is resolved whether or not the actual textvar was
472 }
473 else if( refItem && refItem->Type() == SCH_SHEET_T )
474 {
475 SCH_SHEET* refSheet = static_cast<SCH_SHEET*>( refItem );
476
477 sheetPath.push_back( refSheet );
478
479 if( refSheet->ResolveTextVar( &sheetPath, &remainder, aDepth + 1 ) )
480 *token = std::move( remainder );
481
482 return true; // Cross-reference is resolved whether or not the actual textvar was
483 }
484
485 return false;
486}
487
488
489std::map<int, wxString> SCHEMATIC::GetVirtualPageToSheetNamesMap() const
490{
491 std::map<int, wxString> namesMap;
492
493 for( const SCH_SHEET_PATH& sheet : Hierarchy() )
494 {
495 if( sheet.size() == 1 )
496 namesMap[sheet.GetVirtualPageNumber()] = _( "<root sheet>" );
497 else
498 namesMap[sheet.GetVirtualPageNumber()] = sheet.Last()->GetName();
499 }
500
501 return namesMap;
502}
503
504
505std::map<int, wxString> SCHEMATIC::GetVirtualPageToSheetPagesMap() const
506{
507 std::map<int, wxString> pagesMap;
508
509 for( const SCH_SHEET_PATH& sheet : Hierarchy() )
510 pagesMap[sheet.GetVirtualPageNumber()] = sheet.GetPageNumber();
511
512 return pagesMap;
513}
514
515
516wxString SCHEMATIC::ConvertRefsToKIIDs( const wxString& aSource ) const
517{
518 wxString newbuf;
519 size_t sourceLen = aSource.length();
520
521 for( size_t i = 0; i < sourceLen; ++i )
522 {
523 if( aSource[i] == '$' && i + 1 < sourceLen && aSource[i+1] == '{' )
524 {
525 wxString token;
526 bool isCrossRef = false;
527 int nesting = 0;
528
529 for( i = i + 2; i < sourceLen; ++i )
530 {
531 if( aSource[i] == '{'
532 && ( aSource[i-1] == '_' || aSource[i-1] == '^' || aSource[i-1] == '~' ) )
533 {
534 nesting++;
535 }
536
537 if( aSource[i] == '}' )
538 {
539 nesting--;
540
541 if( nesting < 0 )
542 break;
543 }
544
545 if( aSource[i] == ':' )
546 isCrossRef = true;
547
548 token.append( aSource[i] );
549 }
550
551 if( isCrossRef )
552 {
553 wxString remainder;
554 wxString ref = token.BeforeFirst( ':', &remainder );
555 SCH_REFERENCE_LIST references;
556
557 Hierarchy().GetSymbols( references );
558
559 for( size_t jj = 0; jj < references.GetCount(); jj++ )
560 {
561 SCH_SYMBOL* refSymbol = references[ jj ].GetSymbol();
562
563 if( ref == refSymbol->GetRef( &references[ jj ].GetSheetPath(), true ) )
564 {
565 KIID_PATH path = references[ jj ].GetSheetPath().Path();
566 path.push_back( refSymbol->m_Uuid );
567
568 token = path.AsString() + wxS( ":" ) + remainder;
569 break;
570 }
571 }
572 }
573
574 newbuf.append( wxS( "${" ) + token + wxS( "}" ) );
575 }
576 else
577 {
578 newbuf.append( aSource[i] );
579 }
580 }
581
582 return newbuf;
583}
584
585
586wxString SCHEMATIC::ConvertKIIDsToRefs( const wxString& aSource ) const
587{
588 wxString newbuf;
589 size_t sourceLen = aSource.length();
590
591 for( size_t i = 0; i < sourceLen; ++i )
592 {
593 if( aSource[i] == '$' && i + 1 < sourceLen && aSource[i+1] == '{' )
594 {
595 wxString token;
596 bool isCrossRef = false;
597
598 for( i = i + 2; i < sourceLen; ++i )
599 {
600 if( aSource[i] == '}' )
601 break;
602
603 if( aSource[i] == ':' )
604 isCrossRef = true;
605
606 token.append( aSource[i] );
607 }
608
609 if( isCrossRef )
610 {
611 wxString remainder;
612 wxString ref = token.BeforeFirst( ':', &remainder );
613 KIID_PATH path( ref );
614 KIID uuid = path.back();
615 SCH_SHEET_PATH sheetPath;
616 SCH_ITEM* refItem = ResolveItem( uuid, &sheetPath, true );
617
618 if( path.size() > 1 )
619 {
620 path.pop_back();
621 sheetPath = Hierarchy().GetSheetPathByKIIDPath( path ).value_or( sheetPath );
622 }
623
624 if( refItem && refItem->Type() == SCH_SYMBOL_T )
625 {
626 SCH_SYMBOL* refSymbol = static_cast<SCH_SYMBOL*>( refItem );
627 token = refSymbol->GetRef( &sheetPath, true ) + wxS( ":" ) + remainder;
628 }
629 }
630
631 newbuf.append( wxS( "${" ) + token + wxS( "}" ) );
632 }
633 else
634 {
635 newbuf.append( aSource[i] );
636 }
637 }
638
639 return newbuf;
640}
641
642
644{
645 SCH_SCREENS screens( m_rootSheet );
646
648}
649
650
652{
653 // Filename is rootSheetName-sheetName-...-sheetName
654 // Note that we need to fetch the rootSheetName out of its filename, as the root SCH_SHEET's
655 // name is just a timestamp.
656
657 wxFileName rootFn( CurrentSheet().at( 0 )->GetFileName() );
658 wxString filename = rootFn.GetName();
659
660 for( unsigned i = 1; i < CurrentSheet().size(); i++ )
661 filename += wxT( "-" ) + CurrentSheet().at( i )->GetName();
662
663 return filename;
664}
665
666
668{
669 SCH_SCREEN* screen;
670 SCH_SCREENS s_list( Root() );
671
672 // Set the sheet count, and the sheet number (1 for root sheet)
673 int sheet_count = Root().CountSheets();
674 int sheet_number = 1;
675 const KIID_PATH& current_sheetpath = CurrentSheet().Path();
676
677 // @todo Remove all pseudo page number system is left over from prior to real page number
678 // implementation.
679 for( const SCH_SHEET_PATH& sheet : Hierarchy() )
680 {
681 if( sheet.Path() == current_sheetpath ) // Current sheet path found
682 break;
683
684 sheet_number++; // Not found, increment before this current path
685 }
686
687 for( screen = s_list.GetFirst(); screen != nullptr; screen = s_list.GetNext() )
688 screen->SetPageCount( sheet_count );
689
690 CurrentSheet().SetVirtualPageNumber( sheet_number );
691 CurrentSheet().LastScreen()->SetVirtualPageNumber( sheet_number );
692 CurrentSheet().LastScreen()->SetPageNumber( CurrentSheet().GetPageNumber() );
693}
694
695
697{
698 std::map<wxString, std::set<int>>& pageRefsMap = GetPageRefsMap();
699
700 pageRefsMap.clear();
701
702 for( const SCH_SHEET_PATH& sheet : Hierarchy() )
703 {
704 for( SCH_ITEM* item : sheet.LastScreen()->Items().OfType( SCH_GLOBAL_LABEL_T ) )
705 {
706 SCH_GLOBALLABEL* global = static_cast<SCH_GLOBALLABEL*>( item );
707 wxString resolvedLabel = global->GetShownText( &sheet, false );
708
709 pageRefsMap[ resolvedLabel ].insert( sheet.GetVirtualPageNumber() );
710 }
711 }
712
713 bool show = Settings().m_IntersheetRefsShow;
714
715 // Refresh all visible global labels. Note that we have to collect them first as the
716 // SCH_SCREEN::Update() call is going to invalidate the RTree iterator.
717
718 std::vector<SCH_GLOBALLABEL*> currentSheetGlobalLabels;
719
720 for( EDA_ITEM* item : CurrentSheet().LastScreen()->Items().OfType( SCH_GLOBAL_LABEL_T ) )
721 currentSheetGlobalLabels.push_back( static_cast<SCH_GLOBALLABEL*>( item ) );
722
723 for( SCH_GLOBALLABEL* globalLabel : currentSheetGlobalLabels )
724 {
725 std::vector<SCH_FIELD>& fields = globalLabel->GetFields();
726
727 fields[0].SetVisible( show );
728
729 if( show )
730 {
731 if( fields.size() == 1 && fields[0].GetTextPos() == globalLabel->GetPosition() )
732 globalLabel->AutoplaceFields( CurrentSheet().LastScreen(), AUTOPLACE_AUTO );
733
734 CurrentSheet().LastScreen()->Update( globalLabel );
735
736 for( SCH_FIELD& field : globalLabel->GetFields() )
737 field.ClearBoundingBoxCache();
738
739 globalLabel->ClearBoundingBoxCache();
740
743 }
744 }
745}
746
747
748wxString SCHEMATIC::GetOperatingPoint( const wxString& aNetName, int aPrecision,
749 const wxString& aRange )
750{
751 wxString spiceNetName( aNetName.Lower() );
753
754 if( spiceNetName == wxS( "gnd" ) || spiceNetName == wxS( "0" ) )
755 return wxEmptyString;
756
757 auto it = m_operatingPoints.find( spiceNetName );
758
759 if( it != m_operatingPoints.end() )
760 return SPICE_VALUE( it->second ).ToString( { aPrecision, aRange } );
761 else if( m_operatingPoints.empty() )
762 return wxS( "--" );
763 else
764 return wxS( "?" );
765}
766
767
769{
770 SCH_SCREENS screens( Root() );
771
772 for( SCH_SCREEN* screen = screens.GetFirst(); screen; screen = screens.GetNext() )
773 {
774 std::deque<EDA_ITEM*> allItems;
775
776 for( SCH_ITEM* item : screen->Items() )
777 allItems.push_back( item );
778
779 // Add missing junctions and breakup wires as needed
780 for( const VECTOR2I& point : screen->GetNeededJunctions( allItems ) )
781 {
782 SCH_JUNCTION* junction = new SCH_JUNCTION( point );
783 screen->Append( junction );
784
785 // Breakup wires
786 for( SCH_LINE* wire : screen->GetBusesAndWires( point, true ) )
787 {
788 SCH_LINE* newSegment = wire->BreakAt( nullptr, point );
789 screen->Append( newSegment );
790 }
791 }
792 }
793}
794
795
796void SCHEMATIC::OnItemsAdded( std::vector<SCH_ITEM*>& aNewItems )
797{
799}
800
801
802void SCHEMATIC::OnItemsRemoved( std::vector<SCH_ITEM*>& aRemovedItems )
803{
805}
806
807
808void SCHEMATIC::OnItemsChanged( std::vector<SCH_ITEM*>& aItems )
809{
811}
812
813
815{
817}
818
819
821{
822 if( !alg::contains( m_listeners, aListener ) )
823 m_listeners.push_back( aListener );
824}
825
826
828{
829 auto i = std::find( m_listeners.begin(), m_listeners.end(), aListener );
830
831 if( i != m_listeners.end() )
832 {
833 std::iter_swap( i, m_listeners.end() - 1 );
834 m_listeners.pop_back();
835 }
836}
837
838
840{
841 m_listeners.clear();
842}
843
844
846{
847 // Use a sorted sheetList to reduce file churn
848 SCH_SHEET_LIST sheetList = Hierarchy();
849 ERC_SETTINGS& ercSettings = ErcSettings();
850
851 ercSettings.m_ErcExclusions.clear();
852 ercSettings.m_ErcExclusionComments.clear();
853
854 for( unsigned i = 0; i < sheetList.size(); i++ )
855 {
856 for( SCH_ITEM* item : sheetList[i].LastScreen()->Items().OfType( SCH_MARKER_T ) )
857 {
858 SCH_MARKER* marker = static_cast<SCH_MARKER*>( item );
859
860 if( marker->IsExcluded() )
861 {
862 wxString serialized = marker->SerializeToString();
863 ercSettings.m_ErcExclusions.insert( serialized );
864 ercSettings.m_ErcExclusionComments[ serialized ] = marker->GetComment();
865 }
866 }
867 }
868}
869
870
872{
873 SCH_SHEET_LIST sheetList = Hierarchy();
874
875 for( SCH_MARKER* marker : ResolveERCExclusions() )
876 {
877 SCH_SHEET_PATH errorPath;
878 ignore_unused( sheetList.ResolveItem( marker->GetRCItem()->GetMainItemID(), &errorPath ) );
879
880 if( errorPath.LastScreen() )
881 errorPath.LastScreen()->Append( marker );
882 else
883 RootScreen()->Append( marker );
884 }
885}
886
887
889{
890 return static_cast<EMBEDDED_FILES*>( this );
891}
892
893
895{
896 return static_cast<const EMBEDDED_FILES*>( this );
897}
898
899
900std::set<KIFONT::OUTLINE_FONT*> SCHEMATIC::GetFonts() const
901{
902 std::set<KIFONT::OUTLINE_FONT*> fonts;
903
904 SCH_SHEET_LIST sheetList = Hierarchy();
905
906 for( const SCH_SHEET_PATH& sheet : sheetList )
907 {
908 for( SCH_ITEM* item : sheet.LastScreen()->Items() )
909 {
910 if( EDA_TEXT* text = dynamic_cast<EDA_TEXT*>( item ) )
911 {
912 KIFONT::FONT* font = text->GetFont();
913
914 if( !font || font->IsStroke() )
915 continue;
916
917 using EMBEDDING_PERMISSION = KIFONT::OUTLINE_FONT::EMBEDDING_PERMISSION;
918 auto* outline = static_cast<KIFONT::OUTLINE_FONT*>( font );
919
920 if( outline->GetEmbeddingPermission() == EMBEDDING_PERMISSION::EDITABLE
921 || outline->GetEmbeddingPermission() == EMBEDDING_PERMISSION::INSTALLABLE )
922 {
923 fonts.insert( outline );
924 }
925 }
926 }
927 }
928
929 return fonts;
930}
931
932
934{
935 std::set<KIFONT::OUTLINE_FONT*> fonts = GetFonts();
936
937 for( KIFONT::OUTLINE_FONT* font : fonts )
938 {
939 auto file = GetEmbeddedFiles()->AddFile( font->GetFileName(), false );
940
941 if( !file )
942 {
943 wxLogTrace( "EMBED", "Failed to add font file: %s", font->GetFileName() );
944 continue;
945 }
946
948 }
949}
950
951
952std::set<const SCH_SCREEN*> SCHEMATIC::GetSchematicsSharedByMultipleProjects() const
953{
954 std::set<const SCH_SCREEN*> retv;
955
956 wxCHECK( m_rootSheet, retv );
957
958 SCH_SHEET_LIST hierarchy( m_rootSheet );
959 SCH_SCREENS screens( m_rootSheet );
960
961 for( const SCH_SCREEN* screen = screens.GetFirst(); screen; screen = screens.GetNext() )
962 {
963 for( const SCH_ITEM* item : screen->Items().OfType( SCH_SYMBOL_T ) )
964 {
965 const SCH_SYMBOL* symbol = static_cast<const SCH_SYMBOL*>( item );
966
967 const std::vector<SCH_SYMBOL_INSTANCE> symbolInstances = symbol->GetInstances();
968
969 for( const SCH_SYMBOL_INSTANCE& instance : symbolInstances )
970 {
971 if( !hierarchy.HasPath( instance.m_Path ) )
972 {
973 retv.insert( screen );
974 break;
975 }
976 }
977
978 if( retv.count( screen ) )
979 break;
980 }
981 }
982
983 return retv;
984}
985
986
988{
989 wxCHECK( m_rootSheet, false );
990
991 SCH_SCREENS screens( m_rootSheet );
992
993 for( const SCH_SCREEN* screen = screens.GetFirst(); screen; screen = screens.GetNext() )
994 {
995 wxCHECK2( screen, continue );
996
997 if( screen->GetRefCount() > 1 )
998 return true;
999 }
1000
1001 return false;
1002}
1003
1004
1005void SCHEMATIC::BreakSegment( SCH_COMMIT* aCommit, SCH_LINE* aSegment, const VECTOR2I& aPoint,
1006 SCH_LINE** aNewSegment, SCH_SCREEN* aScreen )
1007{
1008 // Save the copy of aSegment before breaking it
1009 aCommit->Modify( aSegment, aScreen );
1010
1011 SCH_LINE* newSegment = aSegment->BreakAt( aCommit, aPoint );
1012
1013 aSegment->SetFlags( IS_CHANGED | IS_BROKEN );
1014 newSegment->SetFlags( IS_NEW | IS_BROKEN );
1015
1016 if( m_schematicHolder )
1017 m_schematicHolder->AddToScreen( newSegment, aScreen );
1018
1019 aCommit->Added( newSegment, aScreen );
1020
1021 *aNewSegment = newSegment;
1022}
1023
1024
1025bool SCHEMATIC::BreakSegments( SCH_COMMIT* aCommit, const VECTOR2I& aPos, SCH_SCREEN* aScreen )
1026{
1027 bool brokenSegments = false;
1028 SCH_LINE* new_line;
1029
1030 for( SCH_LINE* wire : aScreen->GetBusesAndWires( aPos, true ) )
1031 {
1032 BreakSegment( aCommit, wire, aPos, &new_line, aScreen );
1033 brokenSegments = true;
1034 }
1035
1036 return brokenSegments;
1037}
1038
1039
1041{
1042 bool brokenSegments = false;
1043
1044 std::set<VECTOR2I> point_set;
1045
1046 for( SCH_ITEM* item : aScreen->Items().OfType( SCH_JUNCTION_T ) )
1047 point_set.insert( item->GetPosition() );
1048
1049 for( SCH_ITEM* item : aScreen->Items().OfType( SCH_BUS_WIRE_ENTRY_T ) )
1050 {
1051 SCH_BUS_WIRE_ENTRY* entry = static_cast<SCH_BUS_WIRE_ENTRY*>( item );
1052 point_set.insert( entry->GetPosition() );
1053 point_set.insert( entry->GetEnd() );
1054 }
1055
1056 for( const VECTOR2I& pt : point_set )
1057 {
1058 BreakSegments( aCommit, pt, aScreen );
1059 brokenSegments = true;
1060 }
1061
1062 return brokenSegments;
1063}
1064
1065
1066void SCHEMATIC::CleanUp( SCH_COMMIT* aCommit, SCH_SCREEN* aScreen )
1067{
1069 std::vector<SCH_LINE*> lines;
1070 std::vector<SCH_JUNCTION*> junctions;
1071 std::vector<SCH_NO_CONNECT*> ncs;
1072 std::vector<SCH_ITEM*> items_to_remove;
1073 bool changed = true;
1074
1075 if( aScreen == nullptr )
1076 aScreen = GetCurrentScreen();
1077
1078 auto remove_item = [&]( SCH_ITEM* aItem ) -> void
1079 {
1080 changed = true;
1081
1082 if( !( aItem->GetFlags() & STRUCT_DELETED ) )
1083 {
1084 aItem->SetFlags( STRUCT_DELETED );
1085
1086 if( aItem->IsSelected() && selectionTool )
1087 selectionTool->RemoveItemFromSel( aItem, true /*quiet mode*/ );
1088
1089 if( m_schematicHolder )
1090 {
1091 m_schematicHolder->RemoveFromScreen( aItem, aScreen );
1092 }
1093 aCommit->Removed( aItem, aScreen );
1094 }
1095 };
1096
1097 BreakSegmentsOnJunctions( aCommit, aScreen );
1098
1099 for( SCH_ITEM* item : aScreen->Items().OfType( SCH_JUNCTION_T ) )
1100 {
1101 if( !aScreen->IsExplicitJunction( item->GetPosition() ) )
1102 items_to_remove.push_back( item );
1103 else
1104 junctions.push_back( static_cast<SCH_JUNCTION*>( item ) );
1105 }
1106
1107 for( SCH_ITEM* item : items_to_remove )
1108 remove_item( item );
1109
1110 for( SCH_ITEM* item : aScreen->Items().OfType( SCH_NO_CONNECT_T ) )
1111 ncs.push_back( static_cast<SCH_NO_CONNECT*>( item ) );
1112
1113 alg::for_all_pairs( junctions.begin(), junctions.end(),
1114 [&]( SCH_JUNCTION* aFirst, SCH_JUNCTION* aSecond )
1115 {
1116 if( ( aFirst->GetEditFlags() & STRUCT_DELETED )
1117 || ( aSecond->GetEditFlags() & STRUCT_DELETED ) )
1118 {
1119 return;
1120 }
1121
1122 if( aFirst->GetPosition() == aSecond->GetPosition() )
1123 remove_item( aSecond );
1124 } );
1125
1126 alg::for_all_pairs( ncs.begin(), ncs.end(),
1127 [&]( SCH_NO_CONNECT* aFirst, SCH_NO_CONNECT* aSecond )
1128 {
1129 if( ( aFirst->GetEditFlags() & STRUCT_DELETED )
1130 || ( aSecond->GetEditFlags() & STRUCT_DELETED ) )
1131 {
1132 return;
1133 }
1134
1135 if( aFirst->GetPosition() == aSecond->GetPosition() )
1136 remove_item( aSecond );
1137 } );
1138
1139
1140 auto minX = []( const SCH_LINE* l )
1141 {
1142 return std::min( l->GetStartPoint().x, l->GetEndPoint().x );
1143 };
1144
1145 auto maxX = []( const SCH_LINE* l )
1146 {
1147 return std::max( l->GetStartPoint().x, l->GetEndPoint().x );
1148 };
1149
1150 auto minY = []( const SCH_LINE* l )
1151 {
1152 return std::min( l->GetStartPoint().y, l->GetEndPoint().y );
1153 };
1154
1155 auto maxY = []( const SCH_LINE* l )
1156 {
1157 return std::max( l->GetStartPoint().y, l->GetEndPoint().y );
1158 };
1159
1160 // Would be nice to put lines in a canonical form here by swapping
1161 // start <-> end as needed but I don't know what swapping breaks.
1162 while( changed )
1163 {
1164 changed = false;
1165 lines.clear();
1166
1167 for( SCH_ITEM* item : aScreen->Items().OfType( SCH_LINE_T ) )
1168 {
1169 if( item->GetLayer() == LAYER_WIRE || item->GetLayer() == LAYER_BUS )
1170 lines.push_back( static_cast<SCH_LINE*>( item ) );
1171 }
1172
1173 // Sort by minimum X position
1174 std::sort( lines.begin(), lines.end(),
1175 [&]( const SCH_LINE* a, const SCH_LINE* b )
1176 {
1177 return minX( a ) < minX( b );
1178 } );
1179
1180 for( auto it1 = lines.begin(); it1 != lines.end(); ++it1 )
1181 {
1182 SCH_LINE* firstLine = *it1;
1183
1184 if( firstLine->GetEditFlags() & STRUCT_DELETED )
1185 continue;
1186
1187 if( firstLine->IsNull() )
1188 {
1189 remove_item( firstLine );
1190 continue;
1191 }
1192
1193 int firstRightXEdge = maxX( firstLine );
1194 auto it2 = it1;
1195
1196 for( ++it2; it2 != lines.end(); ++it2 )
1197 {
1198 SCH_LINE* secondLine = *it2;
1199 int secondLeftXEdge = minX( secondLine );
1200
1201 // impossible to overlap remaining lines
1202 if( secondLeftXEdge > firstRightXEdge )
1203 break;
1204
1205 // No Y axis overlap
1206 if( !( std::max( minY( firstLine ), minY( secondLine ) )
1207 <= std::min( maxY( firstLine ), maxY( secondLine ) ) ) )
1208 {
1209 continue;
1210 }
1211
1212 if( secondLine->GetFlags() & STRUCT_DELETED )
1213 continue;
1214
1215 if( !secondLine->IsParallel( firstLine )
1216 || !secondLine->IsStrokeEquivalent( firstLine )
1217 || secondLine->GetLayer() != firstLine->GetLayer() )
1218 {
1219 continue;
1220 }
1221
1222 // Remove identical lines
1223 if( firstLine->IsEndPoint( secondLine->GetStartPoint() )
1224 && firstLine->IsEndPoint( secondLine->GetEndPoint() ) )
1225 {
1226 remove_item( secondLine );
1227 continue;
1228 }
1229
1230 // See if we can merge an overlap (or two colinear touching segments with
1231 // no junction where they meet).
1232 SCH_LINE* mergedLine = secondLine->MergeOverlap( aScreen, firstLine, true );
1233
1234 if( mergedLine != nullptr )
1235 {
1236 remove_item( firstLine );
1237 remove_item( secondLine );
1238
1239 if( m_schematicHolder )
1240 {
1241 m_schematicHolder->AddToScreen( mergedLine, aScreen );
1242 }
1243
1244 aCommit->Added( mergedLine, aScreen );
1245
1246 if( firstLine->IsSelected() || secondLine->IsSelected() )
1247 selectionTool->AddItemToSel( mergedLine, true /*quiet mode*/ );
1248
1249 break;
1250 }
1251 }
1252 }
1253 }
1254}
1255
1256
1258 TOOL_MANAGER* aToolManager,
1259 PROGRESS_REPORTER* aProgressReporter,
1260 KIGFX::SCH_VIEW* aSchView,
1261 std::function<void( SCH_ITEM* )>* aChangedItemHandler,
1262 PICKED_ITEMS_LIST* aLastChangeList )
1263{
1264 SCHEMATIC_SETTINGS& settings = Settings();
1265 SCH_SHEET_LIST list = Hierarchy();
1266 SCH_COMMIT localCommit( aToolManager );
1267
1268 if( !aCommit )
1269 aCommit = &localCommit;
1270
1271 PROF_TIMER timer;
1272
1273 // Ensure schematic graph is accurate
1274 if( aCleanupFlags == LOCAL_CLEANUP )
1275 {
1276 CleanUp( aCommit, GetCurrentScreen() );
1277 }
1278 else if( aCleanupFlags == GLOBAL_CLEANUP )
1279 {
1280 for( const SCH_SHEET_PATH& sheet : list )
1281 CleanUp( aCommit, sheet.LastScreen() );
1282 }
1283
1284 timer.Stop();
1285 wxLogTrace( "CONN_PROFILE", "SchematicCleanUp() %0.4f ms", timer.msecs() );
1286
1287 if( settings.m_IntersheetRefsShow )
1289
1290 if( !ADVANCED_CFG::GetCfg().m_IncrementalConnectivity
1291 || aCleanupFlags == GLOBAL_CLEANUP
1292 || aLastChangeList == nullptr
1293 || ConnectionGraph()->IsMinor() )
1294 {
1295 // Clear all resolved netclass caches in case labels have changed
1296 m_project->GetProjectFile().NetSettings()->ClearAllCaches();
1297
1298 // Update all rule areas so we can cascade implied connectivity changes
1299 std::unordered_set<SCH_SCREEN*> all_screens;
1300
1301 for( const SCH_SHEET_PATH& path : list )
1302 all_screens.insert( path.LastScreen() );
1303
1304 SCH_RULE_AREA::UpdateRuleAreasInScreens( all_screens, aSchView );
1305
1306 // Recalculate all connectivity
1307 ConnectionGraph()->Recalculate( list, true, aChangedItemHandler, aProgressReporter );
1308 }
1309 else
1310 {
1311 struct CHANGED_ITEM
1312 {
1313 SCH_ITEM* item;
1314 SCH_ITEM* linked_item;
1315 SCH_SCREEN* screen;
1316 };
1317
1318 // Final change sets
1319 std::set<SCH_ITEM*> changed_items;
1320 std::set<VECTOR2I> pts;
1321 std::set<std::pair<SCH_SHEET_PATH, SCH_ITEM*>> item_paths;
1322
1323 // Working change sets
1324 std::unordered_set<SCH_SCREEN*> changed_screens;
1325 std::set<std::pair<SCH_RULE_AREA*, SCH_SCREEN*>> changed_rule_areas;
1326 std::vector<CHANGED_ITEM> changed_connectable_items;
1327
1328 // Lambda to add an item to the connectivity update sets
1329 auto addItemToChangeSet = [&changed_items, &pts, &item_paths]( CHANGED_ITEM itemData )
1330 {
1331 std::vector<SCH_SHEET_PATH>& paths = itemData.screen->GetClientSheetPaths();
1332
1333 std::vector<VECTOR2I> tmp_pts = itemData.item->GetConnectionPoints();
1334 pts.insert( tmp_pts.begin(), tmp_pts.end() );
1335 changed_items.insert( itemData.item );
1336
1337 for( SCH_SHEET_PATH& path : paths )
1338 item_paths.insert( std::make_pair( path, itemData.item ) );
1339
1340 if( !itemData.linked_item || !itemData.linked_item->IsConnectable() )
1341 return;
1342
1343 tmp_pts = itemData.linked_item->GetConnectionPoints();
1344 pts.insert( tmp_pts.begin(), tmp_pts.end() );
1345 changed_items.insert( itemData.linked_item );
1346
1347 // We have to directly add the pins here because the link may not exist on the schematic
1348 // anymore and so won't be picked up by GetScreen()->Items().Overlapping() below.
1349 if( SCH_SYMBOL* symbol = dynamic_cast<SCH_SYMBOL*>( itemData.linked_item ) )
1350 {
1351 std::vector<SCH_PIN*> pins = symbol->GetPins();
1352 changed_items.insert( pins.begin(), pins.end() );
1353 }
1354
1355 for( SCH_SHEET_PATH& path : paths )
1356 item_paths.insert( std::make_pair( path, itemData.linked_item ) );
1357 };
1358
1359 // Get all changed connectable items and determine all changed screens
1360 for( unsigned ii = 0; ii < aLastChangeList->GetCount(); ++ii )
1361 {
1362 switch( aLastChangeList->GetPickedItemStatus( ii ) )
1363 {
1364 // Only care about changed, new, and deleted items, the other
1365 // cases are not connectivity-related
1366 case UNDO_REDO::CHANGED:
1367 case UNDO_REDO::NEWITEM:
1368 case UNDO_REDO::DELETED:
1369 break;
1370
1371 default:
1372 continue;
1373 }
1374
1375 SCH_ITEM* item = dynamic_cast<SCH_ITEM*>( aLastChangeList->GetPickedItem( ii ) );
1376
1377 if( item )
1378 {
1379 SCH_SCREEN* screen = static_cast<SCH_SCREEN*>( aLastChangeList->GetScreenForItem( ii ) );
1380 changed_screens.insert( screen );
1381
1382 if( item->Type() == SCH_RULE_AREA_T )
1383 {
1384 SCH_RULE_AREA* ruleArea = static_cast<SCH_RULE_AREA*>( item );
1385 changed_rule_areas.insert( { ruleArea, screen } );
1386 }
1387 else if( item->IsConnectable() )
1388 {
1389 SCH_ITEM* linked_item = dynamic_cast<SCH_ITEM*>( aLastChangeList->GetPickedItemLink( ii ) );
1390 changed_connectable_items.push_back( { item, linked_item, screen } );
1391 }
1392 }
1393 }
1394
1395 // Update rule areas in changed screens to propagate any directive connectivity changes
1396 std::vector<std::pair<SCH_RULE_AREA*, SCH_SCREEN*>> forceUpdateRuleAreas =
1397 SCH_RULE_AREA::UpdateRuleAreasInScreens( changed_screens, aSchView );
1398
1399 std::for_each( forceUpdateRuleAreas.begin(), forceUpdateRuleAreas.end(),
1400 [&]( std::pair<SCH_RULE_AREA*, SCH_SCREEN*>& updatedRuleArea )
1401 {
1402 changed_rule_areas.insert( updatedRuleArea );
1403 } );
1404
1405 // If a SCH_RULE_AREA was changed, we need to add all past and present contained items to
1406 // update their connectivity
1407 std::map<KIID, EDA_ITEM*> itemMap;
1408 list.FillItemMap( itemMap );
1409
1410 auto addPastAndPresentContainedItems =
1411 [&]( SCH_RULE_AREA* changedRuleArea, SCH_SCREEN* screen )
1412 {
1413 for( const KIID& pastItem : changedRuleArea->GetPastContainedItems() )
1414 {
1415 if( itemMap.contains( pastItem ) )
1416 addItemToChangeSet( { static_cast<SCH_ITEM*>( itemMap[pastItem] ), nullptr, screen } );
1417 }
1418
1419 for( SCH_ITEM* containedItem : changedRuleArea->GetContainedItems() )
1420 addItemToChangeSet( { containedItem, nullptr, screen } );
1421 };
1422
1423 for( const auto& [changedRuleArea, screen] : changed_rule_areas )
1424 addPastAndPresentContainedItems( changedRuleArea, screen );
1425
1426 // Add all changed items, and associated items, to the change set
1427 for( CHANGED_ITEM& changed_item_data : changed_connectable_items )
1428 {
1429 addItemToChangeSet( changed_item_data );
1430
1431 // If a SCH_DIRECTIVE_LABEL was changed which is attached to a SCH_RULE_AREA, we need
1432 // to add the contained items to the change set to force update of their connectivity
1433 if( changed_item_data.item->Type() == SCH_DIRECTIVE_LABEL_T )
1434 {
1435 const std::vector<VECTOR2I> labelConnectionPoints =
1436 changed_item_data.item->GetConnectionPoints();
1437
1438 auto candidateRuleAreas =
1439 changed_item_data.screen->Items().Overlapping( SCH_RULE_AREA_T,
1440 changed_item_data.item->GetBoundingBox() );
1441
1442 for( SCH_ITEM* candidateRuleArea : candidateRuleAreas )
1443 {
1444 SCH_RULE_AREA* ruleArea = static_cast<SCH_RULE_AREA*>( candidateRuleArea );
1445 std::vector<SHAPE*> borderShapes = ruleArea->MakeEffectiveShapes( true );
1446
1447 if( ruleArea->GetPolyShape().CollideEdge( labelConnectionPoints[0], nullptr, 5 ) )
1448 addPastAndPresentContainedItems( ruleArea, changed_item_data.screen );
1449 }
1450 }
1451 }
1452
1453 for( const VECTOR2I& pt: pts )
1454 {
1455 for( SCH_ITEM* item : GetCurrentScreen()->Items().Overlapping( pt ) )
1456 {
1457 // Leave this check in place. Overlapping items are not necessarily connectable.
1458 if( !item->IsConnectable() )
1459 continue;
1460
1461 if( item->Type() == SCH_LINE_T )
1462 {
1463 if( item->HitTest( pt ) )
1464 changed_items.insert( item );
1465 }
1466 else if( item->Type() == SCH_SYMBOL_T && item->IsConnected( pt ) )
1467 {
1468 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
1469 std::vector<SCH_PIN*> pins = symbol->GetPins();
1470
1471 changed_items.insert( pins.begin(), pins.end() );
1472 }
1473 else if( item->Type() == SCH_SHEET_T )
1474 {
1475 SCH_SHEET* sheet = static_cast<SCH_SHEET*>( item );
1476
1477 wxCHECK2( sheet, continue );
1478
1479 std::vector<SCH_SHEET_PIN*> sheetPins = sheet->GetPins();
1480 changed_items.insert( sheetPins.begin(), sheetPins.end() );
1481 }
1482 else
1483 {
1484 if( item->IsConnected( pt ) )
1485 changed_items.insert( item );
1486 }
1487 }
1488 }
1489
1490 std::set<std::pair<SCH_SHEET_PATH, SCH_ITEM*>> all_items =
1491 ConnectionGraph()->ExtractAffectedItems( changed_items );
1492
1493 all_items.insert( item_paths.begin(), item_paths.end() );
1494
1495 CONNECTION_GRAPH new_graph( this );
1496
1497 new_graph.SetLastCodes( ConnectionGraph() );
1498
1499 std::shared_ptr<NET_SETTINGS> netSettings = m_project->GetProjectFile().NetSettings();
1500
1501 std::set<wxString> affectedNets;
1502
1503 for( auto&[ path, item ] : all_items )
1504 {
1505 wxCHECK2( item, continue );
1506 item->SetConnectivityDirty();
1507 SCH_CONNECTION* conn = item->Connection();
1508
1509 if( conn )
1510 affectedNets.insert( conn->Name() );
1511 }
1512
1513 // Reset resolved netclass cache for this connection
1514 for( const wxString& netName : affectedNets )
1515 netSettings->ClearCacheForNet( netName );
1516
1517 new_graph.Recalculate( list, false, aChangedItemHandler, aProgressReporter );
1518 ConnectionGraph()->Merge( new_graph );
1519 }
1520
1521 if( !localCommit.Empty() )
1522 localCommit.Push( _( "Schematic Cleanup" ) );
1523}
static const ADVANCED_CFG & GetCfg()
Get the singleton instance's config, which is shared by all consumers.
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:73
COMMIT & Added(EDA_ITEM *aItem, BASE_SCREEN *aScreen=nullptr)
Notify observers that aItem has been added.
Definition: commit.h:85
bool Empty() const
Definition: commit.h:150
COMMIT & Modify(EDA_ITEM *aItem, BASE_SCREEN *aScreen=nullptr, RECURSE_MODE aRecurse=RECURSE_MODE::NO_RECURSE)
Modify a given item in the model.
Definition: commit.h:107
COMMIT & Removed(EDA_ITEM *aItem, BASE_SCREEN *aScreen=nullptr)
Definition: commit.h:97
Calculate the connectivity of a schematic and generates netlists.
const NET_MAP & GetNetMap() const
void Recalculate(const SCH_SHEET_LIST &aSheetList, bool aUnconditional=false, std::function< void(SCH_ITEM *)> *aChangedItemHandler=nullptr, PROGRESS_REPORTER *aProgressReporter=nullptr)
Update the connection graph for the given list of sheets.
std::set< std::pair< SCH_SHEET_PATH, SCH_ITEM * > > ExtractAffectedItems(const std::set< SCH_ITEM * > &aItems)
For a set of items, this will remove the connected items and their associated data including subgraph...
void SetLastCodes(const CONNECTION_GRAPH *aOther)
void Merge(CONNECTION_GRAPH &aGraph)
Combine the input graph contents into the current graph.
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:97
EDA_ITEM_FLAGS GetEditFlags() const
Definition: eda_item.h:147
void SetFlags(EDA_ITEM_FLAGS aMask)
Definition: eda_item.h:141
const KIID m_Uuid
Definition: eda_item.h:507
KICAD_T Type() const
Returns the type of object.
Definition: eda_item.h:109
bool IsSelected() const
Definition: eda_item.h:126
EDA_ITEM * GetParent() const
Definition: eda_item.h:111
EDA_ITEM_FLAGS GetFlags() const
Definition: eda_item.h:144
SHAPE_POLY_SET & GetPolyShape()
Definition: eda_shape.h:337
A mix-in class (via multiple inheritance) that handles texts such as labels, parts,...
Definition: eda_text.h:79
EE_TYPE Overlapping(const BOX2I &aRect) const
Definition: sch_rtree.h:246
EE_TYPE OfType(KICAD_T aType) const
Definition: sch_rtree.h:241
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:93
std::shared_ptr< RC_ITEM > GetRCItem() const
Definition: marker_base.h:107
void SetExcluded(bool aExcluded, const wxString &aComment=wxEmptyString)
Definition: marker_base.h:94
wxString GetComment() const
Definition: marker_base.h:100
static void ConvertToSpiceMarkup(wxString *aNetName)
Remove formatting wrappers and replace illegal spice net name characters with underscores.
A holder to handle information on schematic or board items.
UNDO_REDO GetPickedItemStatus(unsigned int aIdx) const
EDA_ITEM * GetPickedItemLink(unsigned int aIdx) const
unsigned GetCount() const
BASE_SCREEN * GetScreenForItem(unsigned int aIdx) const
EDA_ITEM * GetPickedItem(unsigned int aIdx) const
A small class to help profiling.
Definition: profile.h:49
void Stop()
Save the time when this function was called, and set the counter stane to stop.
Definition: profile.h:88
double msecs(bool aSinceLast=false)
Definition: profile.h:149
A progress reporter interface for use in multi-threaded environments.
The backing store for a PROJECT, in JSON format.
Definition: project_file.h:74
ERC_SETTINGS * m_ErcSettings
Eeschema params.
Definition: project_file.h:154
SCHEMATIC_SETTINGS * m_SchematicSettings
Definition: project_file.h:157
std::shared_ptr< NET_SETTINGS > & NetSettings()
Definition: project_file.h:105
Container for project specific data.
Definition: project.h:65
virtual const wxString GetProjectName() const
Return the short name of the project.
Definition: project.cpp:160
virtual bool TextVarResolver(wxString *aToken) const
Definition: project.cpp:75
virtual PROJECT_FILE & GetProjectFile() const
Definition: project.h:204
virtual std::map< wxString, wxString > & GetTextVars() const
Definition: project.cpp:97
virtual bool IsNullProject() const
Check if this project is a null project (i.e.
Definition: project.cpp:166
const wxString & Name() const
Definition: property.h:218
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 AddToScreen(EDA_ITEM *aItem, SCH_SCREEN *aScreen=nullptr)=0
Add an item to the screen (and view) aScreen is the screen the item is located on,...
virtual void IntersheetRefUpdate(SCH_GLOBALLABEL *aItem)
virtual void RemoveFromScreen(EDA_ITEM *aItem, SCH_SCREEN *aScreen)=0
virtual SCH_SELECTION_TOOL * GetSelectionTool()
virtual void OnSchItemsRemoved(SCHEMATIC &aSch, std::vector< SCH_ITEM * > &aSchItem)
Definition: schematic.h:64
virtual void OnSchItemsChanged(SCHEMATIC &aSch, std::vector< SCH_ITEM * > &aSchItem)
Definition: schematic.h:65
virtual void OnSchSheetChanged(SCHEMATIC &aSch)
Definition: schematic.h:69
virtual void OnSchItemsAdded(SCHEMATIC &aSch, std::vector< SCH_ITEM * > &aSchItem)
Definition: schematic.h:63
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:143
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:952
void SetLegacySymbolInstanceData()
Update the symbol value and footprint instance data for legacy designs.
Definition: schematic.cpp:643
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:796
CONNECTION_GRAPH * m_connectionGraph
Hold and calculate connectivity information of this schematic.
Definition: schematic.h:460
void BreakSegment(SCH_COMMIT *aCommit, SCH_LINE *aSegment, const VECTOR2I &aPoint, SCH_LINE **aNewSegment, SCH_SCREEN *aScreen)
Break a single segment into two at the specified point.
Definition: schematic.cpp:1005
SCH_SHEET_LIST m_hierarchy
Cache of the entire schematic hierarchy sorted by sheet page number.
Definition: schematic.h:482
void ResolveERCExclusionsPostUpdate()
Update markers to match recorded exclusions.
Definition: schematic.cpp:871
void RecomputeIntersheetRefs()
Update the schematic's page reference map for all global labels, and refresh the labels so that they ...
Definition: schematic.cpp:696
SCH_SHEET_LIST BuildSheetListSortedByPageNumbers() const
Definition: schematic.h:107
void RemoveListener(SCHEMATIC_LISTENER *aListener)
Remove the specified listener.
Definition: schematic.cpp:827
bool BreakSegmentsOnJunctions(SCH_COMMIT *aCommit, SCH_SCREEN *aScreen)
Test all junctions and bus entries in the schematic for intersections with wires and buses and breaks...
Definition: schematic.cpp:1040
bool IsComplexHierarchy() const
Test if the schematic is a complex hierarchy.
Definition: schematic.cpp:987
void OnSchSheetChanged()
Notify the schematic and its listeners that the current sheet has been changed.
Definition: schematic.cpp:814
wxString GetFileName() const
Helper to retrieve the filename from the root sheet screen.
Definition: schematic.cpp:311
SCH_SHEET_PATH * m_currentSheet
The sheet path of the sheet currently being edited or displayed.
Definition: schematic.h:457
wxString GetOperatingPoint(const wxString &aNetName, int aPrecision, const wxString &aRange)
Definition: schematic.cpp:748
void CleanUp(SCH_COMMIT *aCommit, SCH_SCREEN *aScreen=nullptr)
Perform routine schematic cleaning including breaking wire and buses and deleting identical objects s...
Definition: schematic.cpp:1066
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:802
virtual ~SCHEMATIC()
Definition: schematic.cpp:132
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:413
std::vector< SCH_MARKER * > ResolveERCExclusions()
Definition: schematic.cpp:331
void EmbedFonts() override
Embed fonts in the schematic.
Definition: schematic.cpp:933
SCHEMATIC_SETTINGS & Settings() const
Definition: schematic.cpp:317
SCH_SCREEN * GetCurrentScreen() const
Definition: schematic.h:177
wxString ConvertKIIDsToRefs(const wxString &aSource) const
Definition: schematic.cpp:586
SCH_ITEM * ResolveItem(const KIID &aID, SCH_SHEET_PATH *aPathOut=nullptr, bool aAllowNullptrReturn=false) const
Definition: schematic.h:130
void RecordERCExclusions()
Scan existing markers and record data from any that are Excluded.
Definition: schematic.cpp:845
SCH_SHEET_LIST Hierarchy() const
Return the full schematic flattened hierarchical sheet list.
Definition: schematic.cpp:219
std::map< wxString, std::set< int > > & GetPageRefsMap()
Definition: schematic.h:215
void FixupJunctions()
Add junctions to this schematic where required.
Definition: schematic.cpp:768
std::set< KIFONT::OUTLINE_FONT * > GetFonts() const override
Get a set of fonts used in the schematic.
Definition: schematic.cpp:900
wxString ConvertRefsToKIIDs(const wxString &aSource) const
Definition: schematic.cpp:516
void SetRoot(SCH_SHEET *aRootSheet)
Initialize the schematic with a new root sheet.
Definition: schematic.cpp:199
void SetProject(PROJECT *aPrj)
Definition: schematic.cpp:169
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:820
std::map< int, wxString > GetVirtualPageToSheetPagesMap() const
Definition: schematic.cpp:505
EMBEDDED_FILES * GetEmbeddedFiles() override
Definition: schematic.cpp:888
PROJECT * m_project
Definition: schematic.h:445
CONNECTION_GRAPH * ConnectionGraph() const
Definition: schematic.h:179
SCH_SCREEN * RootScreen() const
Helper to retrieve the screen of the root sheet.
Definition: schematic.cpp:213
SCHEMATIC(PROJECT *aPrj)
Definition: schematic.cpp:55
bool ResolveTextVar(const SCH_SHEET_PATH *aSheetPath, wxString *token, int aDepth) const
Definition: schematic.cpp:258
std::set< wxString > GetNetClassAssignmentCandidates()
Return the set of netname candidates for netclass assignment.
Definition: schematic.cpp:428
void InvokeListeners(Func &&aFunc, Args &&... args)
Definition: schematic.h:439
bool IsValid() const
A simple test if the schematic is loaded, not a complete one.
Definition: schematic.h:152
static bool m_IsSchematicExists
True if a SCHEMATIC exists, false if not.
Definition: schematic.h:427
void RemoveAllListeners()
Remove all listeners.
Definition: schematic.cpp:839
void GetContextualTextVars(wxArrayString *aVars) const
Definition: schematic.cpp:233
SCH_SHEET & Root() const
Definition: schematic.h:136
std::map< int, wxString > GetVirtualPageToSheetNamesMap() const
Definition: schematic.cpp:489
SCHEMATIC_HOLDER * m_schematicHolder
What currently "Holds" the schematic, i.e.
Definition: schematic.h:492
wxString GetUniqueFilenameForCurrentSheet()
Get the unique file name for the current sheet.
Definition: schematic.cpp:651
void SetSheetNumberAndCount()
Set the m_ScreenNumber and m_NumberOfScreens members for screens.
Definition: schematic.cpp:667
bool BreakSegments(SCH_COMMIT *aCommit, const VECTOR2I &aPoint, SCH_SCREEN *aScreen)
Check every wire and bus for a intersection at aPoint and break into two segments at aPoint if an int...
Definition: schematic.cpp:1025
std::vector< SCHEMATIC_LISTENER * > m_listeners
Currently installed listeners.
Definition: schematic.h:487
SCH_SHEET_PATH & CurrentSheet() const
Definition: schematic.h:167
bool ResolveCrossReference(wxString *token, int aDepth) const
Resolves text vars that refer to other items.
Definition: schematic.cpp:447
void RecalculateConnections(SCH_COMMIT *aCommit, SCH_CLEANUP_FLAGS aCleanupFlags, TOOL_MANAGER *aToolManager, PROGRESS_REPORTER *aProgressReporter=nullptr, KIGFX::SCH_VIEW *aSchView=nullptr, std::function< void(SCH_ITEM *)> *aChangedItemHandler=nullptr, PICKED_ITEMS_LIST *aLastChangeList=nullptr)
Generate the connection data for the entire schematic hierarchy.
Definition: schematic.cpp:1257
std::map< wxString, double > m_operatingPoints
Simulation operating points for text variable substitution.
Definition: schematic.h:477
ERC_SETTINGS & ErcSettings() const
Definition: schematic.cpp:324
void RefreshHierarchy()
Definition: schematic.cpp:227
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:808
SCH_SHEET * m_rootSheet
The top-level sheet in this schematic hierarchy (or potentially the only one)
Definition: schematic.h:448
VECTOR2I GetPosition() const override
VECTOR2I GetEnd() const
Class for a wire to bus entry.
virtual void Push(const wxString &aMessage=wxT("A commit"), int aCommitFlags=0) override
Execute the changes.
Definition: sch_commit.cpp:488
Each graphical item can have a SCH_CONNECTION describing its logical connection (to a bus or net).
wxString Name(bool aIgnoreSheet=false) const
bool IsBus() const
FIELD_T GetId() const
Definition: sch_field.h:115
Base class for any item which can be embedded within the SCHEMATIC container class,...
Definition: sch_item.h:168
virtual bool IsConnectable() const
Definition: sch_item.h:494
int GetUnit() const
Definition: sch_item.h:242
SCH_LAYER_ID GetLayer() const
Return the layer this item is on.
Definition: sch_item.h:309
VECTOR2I GetPosition() const override
Definition: sch_junction.h:107
wxString GetShownText(const SCH_SHEET_PATH *aPath, bool aAllowExtraText, int aDepth=0) const override
Definition: sch_label.cpp:878
Segment description base class to describe items which have 2 end points (track, wire,...
Definition: sch_line.h:42
bool IsParallel(const SCH_LINE *aLine) const
Definition: sch_line.cpp:412
VECTOR2I GetEndPoint() const
Definition: sch_line.h:144
VECTOR2I GetStartPoint() const
Definition: sch_line.h:139
SCH_LINE * MergeOverlap(SCH_SCREEN *aScreen, SCH_LINE *aLine, bool aCheckJunctions)
Check line against aLine to see if it overlaps and merge if it does.
Definition: sch_line.cpp:425
bool IsNull() const
Definition: sch_line.h:137
SCH_LINE * BreakAt(SCH_COMMIT *aCommit, const VECTOR2I &aPoint)
Break this segment into two at the specified point.
Definition: sch_line.cpp:546
bool IsStrokeEquivalent(const SCH_LINE *aLine)
Definition: sch_line.h:196
bool IsEndPoint(const VECTOR2I &aPoint) const override
Test if aPt is an end point of this schematic object.
Definition: sch_line.h:91
static SCH_MARKER * DeserializeFromString(const SCH_SHEET_LIST &aSheetList, const wxString &data)
Definition: sch_marker.cpp:145
wxString SerializeToString() const
Definition: sch_marker.cpp:90
bool IsLegacyMarker() const
Determine if this marker is legacy (i.e.
Definition: sch_marker.h:121
VECTOR2I GetPosition() const override
Container to create a flattened list of symbols because in a complex hierarchy, a symbol can be used ...
size_t GetCount() const
virtual std::vector< SHAPE * > MakeEffectiveShapes(bool aEdgeOnly=false) const override
Make a set of SHAPE objects representing the EDA_SHAPE.
const std::unordered_set< SCH_ITEM * > & GetContainedItems() const
Return a set of all items contained within the rule area.
static std::vector< std::pair< SCH_RULE_AREA *, SCH_SCREEN * > > UpdateRuleAreasInScreens(std::unordered_set< SCH_SCREEN * > &screens, KIGFX::SCH_VIEW *view)
Update all rule area connectvity / caches in the given sheet paths.
const std::unordered_set< KIID > & GetPastContainedItems() const
Container class that holds multiple SCH_SCREEN objects in a hierarchy.
Definition: sch_screen.h:753
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:158
std::vector< SCH_SHEET_PATH > & GetClientSheetPaths()
Return the number of times this screen is used.
Definition: sch_screen.h:181
std::vector< SCH_LINE * > GetBusesAndWires(const VECTOR2I &aPosition, bool aIgnoreEndpoints=false) const
Return buses and wires passing through aPosition.
bool IsExplicitJunction(const VECTOR2I &aPosition) const
Indicate that a junction dot is necessary at the given location.
Definition: sch_screen.cpp:480
EE_RTREE & Items()
Get the full RTree, usually for iterating.
Definition: sch_screen.h:112
const wxString & GetFileName() const
Definition: sch_screen.h:147
const TITLE_BLOCK & GetTitleBlock() const
Definition: sch_screen.h:158
void Update(SCH_ITEM *aItem, bool aUpdateLibSymbol=true)
Update aItem's bounding box in the tree.
Definition: sch_screen.cpp:321
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 * ResolveItem(const KIID &aID, SCH_SHEET_PATH *aPathOut=nullptr, bool aAllowNullptrReturn=false) const
Fetch a SCH_ITEM by ID.
void FillItemMap(std::map< KIID, EDA_ITEM * > &aMap)
Fill an item cache for temporary use when many items need to be fetched.
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:47
wxString GetName() const
Definition: sch_sheet.h:113
int CountSheets() const
Count the number of sheets found in "this" sheet including all of the subsheets.
Definition: sch_sheet.cpp:828
SCH_SCREEN * GetScreen() const
Definition: sch_sheet.h:116
std::vector< SCH_SHEET_PIN * > & GetPins()
Definition: sch_sheet.h:187
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:220
Schematic symbol object.
Definition: sch_symbol.h:75
const std::vector< SCH_SYMBOL_INSTANCE > & GetInstances() const
Definition: sch_symbol.h:134
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:592
bool ResolveTextVar(const SCH_SHEET_PATH *aPath, wxString *token, int aDepth=0) const
Resolve any references to system tokens supported by the symbol.
std::vector< SCH_PIN * > GetPins(const SCH_SHEET_PATH *aSheet) const
Retrieve a list of the SCH_PINs for the given sheet path.
const LIB_ID & GetLibId() const override
Definition: sch_symbol.h:164
const wxString GetRef(const SCH_SHEET_PATH *aSheet, bool aIncludeUnit=false) const override
Definition: sch_symbol.cpp:550
int RemoveItemFromSel(const TOOL_EVENT &aEvent)
bool CollideEdge(const VECTOR2I &aPoint, VERTEX_INDEX *aClosestVertex=nullptr, int aClearance=0) const
Check whether aPoint collides with any edge of any of the contours of the polygon.
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
Master controller class:
Definition: tool_manager.h:62
#define _HKI(x)
static bool empty(const wxTextEntryBase *aCtrl)
#define _(s)
#define IS_CHANGED
Item was edited, and modified.
#define IS_NEW
New item, just created.
#define IS_BROKEN
Is a segment just broken by BreakSegment.
#define STRUCT_DELETED
flag indication structures to be erased
void ignore_unused(const T &)
Definition: ignore.h:24
@ LAYER_WIRE
Definition: layer_ids.h:441
@ LAYER_BUS
Definition: layer_ids.h:442
bool contains(const _Container &__container, _Value __value)
Returns true if the container contains the given value.
Definition: kicad_algo.h:100
void for_all_pairs(_InputIterator __first, _InputIterator __last, _Function __f)
Apply a function to every possible pair of elements of a sequence.
Definition: kicad_algo.h:84
#define TYPE_HASH(x)
Definition: property.h:72
void CollectOtherUnits(const wxString &aRef, int aUnit, const LIB_ID &aLibId, SCH_SHEET_PATH &aSheet, std::vector< SCH_SYMBOL * > *otherUnits)
@ AUTOPLACE_AUTO
Definition: sch_item.h:71
SCH_CLEANUP_FLAGS
Definition: schematic.h:73
@ LOCAL_CLEANUP
Definition: schematic.h:75
@ GLOBAL_CLEANUP
Definition: schematic.h:76
A simple container for schematic symbol instance information.
@ SCH_LINE_T
Definition: typeinfo.h:163
@ SCH_NO_CONNECT_T
Definition: typeinfo.h:160
@ SCH_SYMBOL_T
Definition: typeinfo.h:172
@ SCH_DIRECTIVE_LABEL_T
Definition: typeinfo.h:171
@ SCH_SHEET_T
Definition: typeinfo.h:175
@ SCH_MARKER_T
Definition: typeinfo.h:158
@ SCH_RULE_AREA_T
Definition: typeinfo.h:170
@ SCHEMATIC_T
Definition: typeinfo.h:204
@ SCH_BUS_WIRE_ENTRY_T
Definition: typeinfo.h:161
@ SCH_GLOBAL_LABEL_T
Definition: typeinfo.h:168
@ SCH_JUNCTION_T
Definition: typeinfo.h:159