KiCad PCB EDA Suite
Loading...
Searching...
No Matches
board_netlist_updater.cpp
Go to the documentation of this file.
1/*
2 * This program source code file is part of KiCad, a free EDA CAD application.
3 *
4 * Copyright (C) 2015 Jean-Pierre Charras, jp.charras at wanadoo.fr
5 * Copyright (C) 2015 CERN
6 * Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck <[email protected]>
7 * Copyright (C) 2011 Wayne Stambaugh <[email protected]>
8 *
9 * Copyright (C) 1992-2024 KiCad Developers, see AUTHORS.txt for contributors.
10 *
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License
13 * as published by the Free Software Foundation; either version 2
14 * of the License, or (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, you may find one here:
23 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
24 * or you may search the http://www.gnu.org website for the version 2 license,
25 * or you may write to the Free Software Foundation, Inc.,
26 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
27 */
28
29
30#include <common.h> // for PAGE_INFO
31
32#include <base_units.h>
33#include <board.h>
35#include <netinfo.h>
36#include <footprint.h>
37#include <pad.h>
38#include <pcb_track.h>
39#include <zone.h>
40#include <string_utils.h>
41#include <pcbnew_settings.h>
42#include <pcb_edit_frame.h>
45#include <reporter.h>
46
48
49
51 m_frame( aFrame ),
52 m_commit( aFrame ),
53 m_board( aBoard )
54{
56
58 m_isDryRun = false;
60 m_lookupByTimestamp = false;
61 m_overrideLocks = false;
62
64 m_errorCount = 0;
66}
67
68
70{
71}
72
73
74// These functions allow inspection of pad nets during dry runs by keeping a cache of
75// current pad netnames indexed by pad.
76
77void BOARD_NETLIST_UPDATER::cacheNetname( PAD* aPad, const wxString& aNetname )
78{
79 m_padNets[ aPad ] = aNetname;
80}
81
82
84{
85 if( m_isDryRun && m_padNets.count( aPad ) )
86 return m_padNets[ aPad ];
87 else
88 return aPad->GetNetname();
89}
90
91
92void BOARD_NETLIST_UPDATER::cachePinFunction( PAD* aPad, const wxString& aPinFunction )
93{
94 m_padPinFunctions[ aPad ] = aPinFunction;
95}
96
97
99{
100 if( m_isDryRun && m_padPinFunctions.count( aPad ) )
101 return m_padPinFunctions[ aPad ];
102 else
103 return aPad->GetPinFunction();
104}
105
106
108{
109 VECTOR2I bestPosition;
110
111 if( !m_board->IsEmpty() )
112 {
113 // Position new components below any existing board features.
115
116 if( bbox.GetWidth() || bbox.GetHeight() )
117 {
118 bestPosition.x = bbox.Centre().x;
119 bestPosition.y = bbox.GetBottom() + pcbIUScale.mmToIU( 10 );
120 }
121 }
122 else
123 {
124 // Position new components in the center of the page when the board is empty.
126
127 bestPosition.x = pageSize.x / 2;
128 bestPosition.y = pageSize.y / 2;
129 }
130
131 return bestPosition;
132}
133
134
136{
137 wxString msg;
138
139 if( aComponent->GetFPID().empty() )
140 {
141 msg.Printf( _( "Cannot add %s (no footprint assigned)." ),
142 aComponent->GetReference() );
144 ++m_errorCount;
145 return nullptr;
146 }
147
148 FOOTPRINT* footprint = m_frame->LoadFootprint( aComponent->GetFPID() );
149
150 if( footprint == nullptr )
151 {
152 msg.Printf( _( "Cannot add %s (footprint '%s' not found)." ),
153 aComponent->GetReference(),
154 EscapeHTML( aComponent->GetFPID().Format().wx_str() ) );
156 ++m_errorCount;
157 return nullptr;
158 }
159
161
162 if( m_isDryRun )
163 {
164 msg.Printf( _( "Add %s (footprint '%s')." ),
165 aComponent->GetReference(),
166 EscapeHTML( aComponent->GetFPID().Format().wx_str() ) );
167
168 delete footprint;
169 footprint = nullptr;
170 }
171 else
172 {
173 for( PAD* pad : footprint->Pads() )
174 {
175 // Set the pads ratsnest settings to the global settings
176 pad->SetLocalRatsnestVisible( m_frame->GetPcbNewSettings()->m_Display.m_ShowGlobalRatsnest );
177
178 // Pads in the library all have orphaned nets. Replace with Default.
179 pad->SetNetCode( 0 );
180 }
181
182 footprint->SetParent( m_board );
184
185 // This flag is used to prevent connectivity from considering the footprint during its
186 // initial build after the footprint is committed, because we're going to immediately start
187 // a move operation on the footprint and don't want its pads to drive nets onto vias/tracks
188 // it happens to land on at the initial position.
189 footprint->SetAttributes( footprint->GetAttributes() | FP_JUST_ADDED );
190
191 m_addedFootprints.push_back( footprint );
192 m_commit.Add( footprint );
193
194 msg.Printf( _( "Added %s (footprint '%s')." ),
195 aComponent->GetReference(),
196 EscapeHTML( aComponent->GetFPID().Format().wx_str() ) );
197 }
198
201 return footprint;
202}
203
204
206{
207 wxString curClassName, newClassName;
208 COMPONENT_CLASS* newClass = nullptr;
209
210 if( const COMPONENT_CLASS* curClass = aFootprint->GetComponentClass() )
211 curClassName = curClass->GetFullName();
212
213 // Calculate the new component class
214 if( m_isDryRun )
215 {
217 aNewComponent->GetComponentClassNames() );
218 }
219 else
220 {
222 aNewComponent->GetComponentClassNames() );
223 newClassName = newClass->GetFullName();
224 }
225
226 if( curClassName == newClassName )
227 return;
228
229 wxString msg;
230
231 if( m_isDryRun )
232 {
233 if( curClassName == wxEmptyString && newClassName != wxEmptyString )
234 {
235 msg.Printf( _( "Change %s component class to '%s'." ),
236 aFootprint->GetReference(),
237 EscapeHTML( newClassName ) );
238 }
239 else if( curClassName != wxEmptyString && newClassName == wxEmptyString )
240 {
241 msg.Printf( _( "Remove %s component class (currently '%s')." ),
242 aFootprint->GetReference(),
243 EscapeHTML( curClassName ) );
244 }
245 else
246 {
247 msg.Printf( _( "Change %s component class from '%s' to '%s'." ),
248 aFootprint->GetReference(),
249 EscapeHTML( curClassName ),
250 EscapeHTML( newClassName ) );
251 }
252 }
253 else
254 {
255 wxASSERT_MSG( newClass != nullptr, "Component class should not be nullptr" );
256
257 aFootprint->SetComponentClass( newClass );
258
259 if( curClassName == wxEmptyString && newClassName != wxEmptyString )
260 {
261 msg.Printf( _( "Changed %s component class to '%s'." ),
262 aFootprint->GetReference(),
263 EscapeHTML( newClassName ) );
264 }
265 else if( curClassName != wxEmptyString && newClassName == wxEmptyString )
266 {
267 msg.Printf( _( "Removed %s component class (was '%s')." ),
268 aFootprint->GetReference(),
269 EscapeHTML( curClassName ) );
270 }
271 else
272 {
273 msg.Printf( _( "Changed %s component class from '%s' to '%s'." ),
274 aFootprint->GetReference(),
275 EscapeHTML( curClassName ),
276 EscapeHTML( newClassName ) );
277 }
278 }
279
281}
282
283
285 COMPONENT* aNewComponent )
286{
287 wxString msg;
288
289 if( aNewComponent->GetFPID().empty() )
290 {
291 msg.Printf( _( "Cannot update %s (no footprint assigned)." ),
292 aNewComponent->GetReference() );
294 ++m_errorCount;
295 return nullptr;
296 }
297
298 FOOTPRINT* newFootprint = m_frame->LoadFootprint( aNewComponent->GetFPID() );
299
300 if( newFootprint == nullptr )
301 {
302 msg.Printf( _( "Cannot update %s (footprint '%s' not found)." ),
303 aNewComponent->GetReference(),
304 EscapeHTML( aNewComponent->GetFPID().Format().wx_str() ) );
306 ++m_errorCount;
307 return nullptr;
308 }
309
310 if( m_isDryRun )
311 {
312 if( aFootprint->IsLocked() && !m_overrideLocks )
313 {
314 msg.Printf( _( "Cannot change %s footprint from '%s' to '%s' (footprint is locked)."),
315 aFootprint->GetReference(),
316 EscapeHTML( aFootprint->GetFPID().Format().wx_str() ),
317 EscapeHTML( aNewComponent->GetFPID().Format().wx_str() ) );
320 delete newFootprint;
321 return nullptr;
322 }
323 else
324 {
325 msg.Printf( _( "Change %s footprint from '%s' to '%s'."),
326 aFootprint->GetReference(),
327 EscapeHTML( aFootprint->GetFPID().Format().wx_str() ),
328 EscapeHTML( aNewComponent->GetFPID().Format().wx_str() ) );
331 delete newFootprint;
332 return nullptr;
333 }
334 }
335 else
336 {
337 if( aFootprint->IsLocked() && !m_overrideLocks )
338 {
339 msg.Printf( _( "Could not change %s footprint from '%s' to '%s' (footprint is locked)."),
340 aFootprint->GetReference(),
341 EscapeHTML( aFootprint->GetFPID().Format().wx_str() ),
342 EscapeHTML( aNewComponent->GetFPID().Format().wx_str() ) );
345 delete newFootprint;
346 return nullptr;
347 }
348 else
349 {
350 m_frame->ExchangeFootprint( aFootprint, newFootprint, m_commit );
351
352 msg.Printf( _( "Changed %s footprint from '%s' to '%s'."),
353 aFootprint->GetReference(),
354 EscapeHTML( aFootprint->GetFPID().Format().wx_str() ),
355 EscapeHTML( aNewComponent->GetFPID().Format().wx_str() ) );
358 return newFootprint;
359 }
360 }
361}
362
363
365 COMPONENT* aNetlistComponent )
366{
367 wxString msg;
368
369 // Create a copy only if the footprint has not been added during this update
370 FOOTPRINT* copy = nullptr;
371
372 if( !m_commit.GetStatus( aPcbFootprint ) )
373 {
374 copy = static_cast<FOOTPRINT*>( aPcbFootprint->Clone() );
375 copy->SetParentGroup( nullptr );
376 }
377
378 bool changed = false;
379
380 // Test for reference designator field change.
381 if( aPcbFootprint->GetReference() != aNetlistComponent->GetReference() )
382 {
383 if( m_isDryRun )
384 {
385 msg.Printf( _( "Change %s reference designator to %s." ),
386 aPcbFootprint->GetReference(),
387 aNetlistComponent->GetReference() );
388 }
389 else
390 {
391 msg.Printf( _( "Changed %s reference designator to %s." ),
392 aPcbFootprint->GetReference(),
393 aNetlistComponent->GetReference() );
394
395 changed = true;
396 aPcbFootprint->SetReference( aNetlistComponent->GetReference() );
397 }
398
400 }
401
402 // Test for value field change.
403 if( aPcbFootprint->GetValue() != aNetlistComponent->GetValue() )
404 {
405 if( m_isDryRun )
406 {
407 msg.Printf( _( "Change %s value from %s to %s." ),
408 aPcbFootprint->GetReference(),
409 EscapeHTML( aPcbFootprint->GetValue() ),
410 EscapeHTML( aNetlistComponent->GetValue() ) );
411 }
412 else
413 {
414 msg.Printf( _( "Changed %s value from %s to %s." ),
415 aPcbFootprint->GetReference(),
416 EscapeHTML( aPcbFootprint->GetValue() ),
417 EscapeHTML( aNetlistComponent->GetValue() ) );
418
419 changed = true;
420 aPcbFootprint->SetValue( aNetlistComponent->GetValue() );
421 }
422
424 }
425
426 // Test for footprint change. This is controlled by a separate flag, that will output
427 // its own message if the footprint is changed, so we just set the field here.
428 if( ( m_replaceFootprints || ( aPcbFootprint->GetAttributes() & FP_JUST_ADDED ) )
429 && !m_isDryRun )
430 {
431 // Update FOOTPRINT_FIELD (if exists in the netlist)
432 try
433 {
434 aPcbFootprint->Footprint().SetText(
435 aNetlistComponent->GetFields()[GetCanonicalFieldName( FOOTPRINT_FIELD )] );
436 }
437 catch( ... )
438 {
439 // If not exist (old netlist), just skip it: What else?
440 }
441 }
442
443 // Test for time stamp change.
444 KIID_PATH new_path = aNetlistComponent->GetPath();
445
446 if( !aNetlistComponent->GetKIIDs().empty() )
447 new_path.push_back( aNetlistComponent->GetKIIDs().front() );
448
449 if( aPcbFootprint->GetPath() != new_path )
450 {
451 if( m_isDryRun )
452 {
453 msg.Printf( _( "Update %s symbol association from %s to %s." ),
454 aPcbFootprint->GetReference(),
455 EscapeHTML( aPcbFootprint->GetPath().AsString() ),
456 EscapeHTML( new_path.AsString() ) );
457 }
458 else
459 {
460 msg.Printf( _( "Updated %s symbol association from %s to %s." ),
461 aPcbFootprint->GetReference(),
462 EscapeHTML( aPcbFootprint->GetPath().AsString() ),
463 EscapeHTML( new_path.AsString() ) );
464
465 changed = true;
466 aPcbFootprint->SetPath( new_path );
467 }
468
470 }
471
472 nlohmann::ordered_map<wxString, wxString> fpFieldsAsMap;
473
474 for( PCB_FIELD* field : aPcbFootprint->GetFields() )
475 {
476 // These fields are individually checked above
477 if( field->IsReference() || field->IsValue() || field->IsFootprint()
478 || field->IsComponentClass() )
479 {
480 continue;
481 }
482
483 fpFieldsAsMap[field->GetName()] = field->GetText();
484 }
485
486 // Remove the ref/value/footprint fields that are individually handled
487 nlohmann::ordered_map<wxString, wxString> compFields = aNetlistComponent->GetFields();
488 compFields.erase( GetCanonicalFieldName( REFERENCE_FIELD ) );
489 compFields.erase( GetCanonicalFieldName( VALUE_FIELD ) );
490 compFields.erase( GetCanonicalFieldName( FOOTPRINT_FIELD ) );
491
492 // Remove any component class fields - these are not editable in the pcb editor
493 compFields.erase( wxT( "Component Class" ) );
494
495 // Fields are stored as an ordered map, but we don't (yet) support reordering
496 // the footprint fields to match the symbol, so we manually check the fields
497 // in the order they are stored in the symbol.
498 bool same = true;
499
500 for( std::pair<wxString, wxString> field : compFields )
501 {
502 if( fpFieldsAsMap.count( field.first ) == 0 || fpFieldsAsMap[field.first] != field.second )
503 {
504 same = false;
505 break;
506 }
507 }
508
509 if( !same )
510 {
511 if( m_isDryRun )
512 {
513 msg.Printf( _( "Update %s fields." ), aPcbFootprint->GetReference() );
515
516 // Remove fields that aren't present in the symbol
517 for( PCB_FIELD* field : aPcbFootprint->GetFields() )
518 {
519 if( field->IsMandatoryField() )
520 continue;
521
522 if( compFields.count( field->GetName() ) == 0 )
523 {
524 msg.Printf( _( "Remove %s footprint fields not in symbol." ),
525 aPcbFootprint->GetReference() );
527 break;
528 }
529 }
530 }
531 else
532 {
533 msg.Printf( _( "Updated %s fields." ), aPcbFootprint->GetReference() );
535
536 changed = true;
537
538 // Add or change field value
539 for( auto& [name, value] : compFields )
540 {
541 if( aPcbFootprint->HasFieldByName( name ) )
542 {
543 aPcbFootprint->GetFieldByName( name )->SetText( value );
544 }
545 else
546 {
547 int idx = aPcbFootprint->GetFieldCount();
548 PCB_FIELD* newField = aPcbFootprint->AddField( PCB_FIELD( aPcbFootprint, idx ) );
549
550 newField->SetName( name );
551 newField->SetText( value );
552 newField->SetVisible( false );
553 newField->SetLayer( aPcbFootprint->GetLayer() == F_Cu ? F_Fab : B_Fab );
554
555 // Give the relative position (0,0) in footprint
556 newField->SetPosition( aPcbFootprint->GetPosition() );
557 // Give the footprint orientation
558 newField->Rotate( aPcbFootprint->GetPosition(), aPcbFootprint->GetOrientation() );
559
560 if( m_frame )
562 }
563 }
564
565 // Remove fields that aren't present in the symbol
566 bool warned = false;
567
568 for( PCB_FIELD* field : aPcbFootprint->GetFields() )
569 {
570 if( field->IsMandatoryField() )
571 continue;
572
573 if( compFields.count( field->GetName() ) == 0 )
574 {
575 if( !warned )
576 {
577 warned = true;
578 msg.Printf( _( "Removed %s footprint fields not in symbol." ),
579 aPcbFootprint->GetReference() );
581 }
582
583 aPcbFootprint->RemoveField( field->GetCanonicalName() );
584
585 if( m_frame )
586 m_frame->GetCanvas()->GetView()->Remove( field );
587 }
588 }
589 }
590 }
591
592 wxString sheetname;
593 wxString sheetfile;
594 wxString fpFilters;
595
596 wxString humanSheetPath = aNetlistComponent->GetHumanReadablePath();
597
598 if( !humanSheetPath.empty() )
599 sheetname = humanSheetPath;
600 else if( aNetlistComponent->GetProperties().count( wxT( "Sheetname" ) ) > 0 )
601 sheetname = aNetlistComponent->GetProperties().at( wxT( "Sheetname" ) );
602
603 if( aNetlistComponent->GetProperties().count( wxT( "Sheetfile" ) ) > 0 )
604 sheetfile = aNetlistComponent->GetProperties().at( wxT( "Sheetfile" ) );
605
606 if( aNetlistComponent->GetProperties().count( wxT( "ki_fp_filters" ) ) > 0 )
607 fpFilters = aNetlistComponent->GetProperties().at( wxT( "ki_fp_filters" ) );
608
609 if( sheetname != aPcbFootprint->GetSheetname() )
610 {
611 if( m_isDryRun )
612 {
613 msg.Printf( _( "Update %s sheetname to '%s'." ),
614 aPcbFootprint->GetReference(),
615 EscapeHTML( sheetname ) );
616 }
617 else
618 {
619 aPcbFootprint->SetSheetname( sheetname );
620 msg.Printf( _( "Updated %s sheetname to '%s'." ),
621 aPcbFootprint->GetReference(),
622 EscapeHTML( sheetname ) );
623 }
624
626 }
627
628 if( sheetfile != aPcbFootprint->GetSheetfile() )
629 {
630 if( m_isDryRun )
631 {
632 msg.Printf( _( "Update %s sheetfile to '%s'." ),
633 aPcbFootprint->GetReference(),
634 EscapeHTML( sheetfile ) );
635 }
636 else
637 {
638 aPcbFootprint->SetSheetfile( sheetfile );
639 msg.Printf( _( "Updated %s sheetfile to '%s'." ),
640 aPcbFootprint->GetReference(),
641 EscapeHTML( sheetfile ) );
642 }
643
645 }
646
647 if( fpFilters != aPcbFootprint->GetFilters() )
648 {
649 if( m_isDryRun )
650 {
651 msg.Printf( _( "Update %s footprint filters to '%s'." ),
652 aPcbFootprint->GetReference(),
653 EscapeHTML( fpFilters ) );
654 }
655 else
656 {
657 aPcbFootprint->SetFilters( fpFilters );
658 msg.Printf( _( "Updated %s footprint filters to '%s'." ),
659 aPcbFootprint->GetReference(),
660 EscapeHTML( fpFilters ) );
661 }
662
664 }
665
666 if( ( aNetlistComponent->GetProperties().count( wxT( "exclude_from_bom" ) ) > 0 )
667 != ( ( aPcbFootprint->GetAttributes() & FP_EXCLUDE_FROM_BOM ) > 0 ) )
668 {
669 if( m_isDryRun )
670 {
671 if( aNetlistComponent->GetProperties().count( wxT( "exclude_from_bom" ) ) )
672 {
673 msg.Printf( _( "Add %s 'exclude from BOM' fabrication attribute." ),
674 aPcbFootprint->GetReference() );
675 }
676 else
677 {
678 msg.Printf( _( "Remove %s 'exclude from BOM' fabrication attribute." ),
679 aPcbFootprint->GetReference() );
680 }
681 }
682 else
683 {
684 int attributes = aPcbFootprint->GetAttributes();
685
686 if( aNetlistComponent->GetProperties().count( wxT( "exclude_from_bom" ) ) )
687 {
688 attributes |= FP_EXCLUDE_FROM_BOM;
689 msg.Printf( _( "Added %s 'exclude from BOM' fabrication attribute." ),
690 aPcbFootprint->GetReference() );
691 }
692 else
693 {
694 attributes &= ~FP_EXCLUDE_FROM_BOM;
695 msg.Printf( _( "Removed %s 'exclude from BOM' fabrication attribute." ),
696 aPcbFootprint->GetReference() );
697 }
698
699 changed = true;
700 aPcbFootprint->SetAttributes( attributes );
701 }
702
704 }
705
706 if( ( aNetlistComponent->GetProperties().count( wxT( "dnp" ) ) > 0 )
707 != ( ( aPcbFootprint->GetAttributes() & FP_DNP ) > 0 ) )
708 {
709 if( m_isDryRun )
710 {
711 if( aNetlistComponent->GetProperties().count( wxT( "dnp" ) ) )
712 {
713 msg.Printf( _( "Add %s 'Do not place' fabrication attribute." ),
714 aPcbFootprint->GetReference() );
715 }
716 else
717 {
718 msg.Printf( _( "Remove %s 'Do not place' fabrication attribute." ),
719 aPcbFootprint->GetReference() );
720 }
721 }
722 else
723 {
724 int attributes = aPcbFootprint->GetAttributes();
725
726 if( aNetlistComponent->GetProperties().count( wxT( "dnp" ) ) )
727 {
728 attributes |= FP_DNP;
729 msg.Printf( _( "Added %s 'Do not place' fabrication attribute." ),
730 aPcbFootprint->GetReference() );
731 }
732 else
733 {
734 attributes &= ~FP_DNP;
735 msg.Printf( _( "Removed %s 'Do not place' fabrication attribute." ),
736 aPcbFootprint->GetReference() );
737 }
738
739 changed = true;
740 aPcbFootprint->SetAttributes( attributes );
741 }
742
744 }
745
746 if( changed && copy )
747 m_commit.Modified( aPcbFootprint, copy );
748 else if( copy )
749 delete copy;
750
751 return true;
752}
753
754
756 COMPONENT* aNewComponent )
757{
758 wxString msg;
759
760 // Create a copy only if the footprint has not been added during this update
761 FOOTPRINT* copy = nullptr;
762
763 if( !m_isDryRun && !m_commit.GetStatus( aFootprint ) )
764 {
765 copy = static_cast<FOOTPRINT*>( aFootprint->Clone() );
766 copy->SetParentGroup( nullptr );
767 }
768
769 bool changed = false;
770
771 // At this point, the component footprint is updated. Now update the nets.
772 std::deque<PAD*> pads = aFootprint->Pads();
773 std::set<wxString> padNetnames;
774
775 std::sort( pads.begin(), pads.end(),
776 []( PAD* a, PAD* b )
777 {
778 return a->m_Uuid < b->m_Uuid;
779 } );
780
781 for( PAD* pad : pads )
782 {
783 const COMPONENT_NET& net = aNewComponent->GetNet( pad->GetNumber() );
784
785 wxString pinFunction;
786 wxString pinType;
787
788 if( net.IsValid() ) // i.e. the pad has a name
789 {
790 pinFunction = net.GetPinFunction();
791 pinType = net.GetPinType();
792 }
793
794 if( !m_isDryRun )
795 {
796 if( pad->GetPinFunction() != pinFunction )
797 {
798 changed = true;
799 pad->SetPinFunction( pinFunction );
800 }
801
802 if( pad->GetPinType() != pinType )
803 {
804 changed = true;
805 pad->SetPinType( pinType );
806 }
807 }
808 else
809 {
810 cachePinFunction( pad, pinFunction );
811 }
812
813 // Test if new footprint pad has no net (pads not on copper layers have no net).
814 if( !net.IsValid() || !pad->IsOnCopperLayer() )
815 {
816 if( !pad->GetNetname().IsEmpty() )
817 {
818 if( m_isDryRun )
819 {
820 msg.Printf( _( "Disconnect %s pin %s." ),
821 aFootprint->GetReference(),
822 EscapeHTML( pad->GetNumber() ) );
823 }
824 else
825 {
826 msg.Printf( _( "Disconnected %s pin %s." ),
827 aFootprint->GetReference(),
828 EscapeHTML( pad->GetNumber() ) );
829 }
830
832 }
833 else if( pad->IsOnCopperLayer() && !pad->GetNumber().IsEmpty() )
834 {
835 // pad is connectable but has no net found in netlist
836 msg.Printf( _( "No net found for component %s pad %s (no pin %s in symbol)." ),
837 aFootprint->GetReference(),
838 EscapeHTML( pad->GetNumber() ),
839 EscapeHTML( pad->GetNumber() ) );
842 }
843
844 if( !m_isDryRun )
845 {
846 changed = true;
847 pad->SetNetCode( NETINFO_LIST::UNCONNECTED );
848
849 // If the pad has no net from netlist (i.e. not in netlist
850 // it cannot have a pin function
851 if( pad->GetNetname().IsEmpty() )
852 pad->SetPinFunction( wxEmptyString );
853
854 }
855 else
856 {
857 cacheNetname( pad, wxEmptyString );
858 }
859 }
860 else // New footprint pad has a net.
861 {
862 wxString netName = net.GetNetName();
863
864 if( pad->IsNoConnectPad() )
865 {
866 netName = wxString::Format( wxS( "%s" ),
867 EscapeHTML( net.GetNetName() ) );
868
869 for( int jj = 1; !padNetnames.insert( netName ).second; jj++ )
870 {
871 netName = wxString::Format( wxS( "%s_%d" ),
872 EscapeHTML( net.GetNetName() ), jj );
873 }
874 }
875
876 NETINFO_ITEM* netinfo = m_board->FindNet( netName );
877
878 if( netinfo && !m_isDryRun )
879 netinfo->SetIsCurrent( true );
880
881 if( pad->GetNetname() != netName )
882 {
883
884 if( netinfo == nullptr )
885 {
886 // It might be a new net that has not been added to the board yet
887 if( m_addedNets.count( netName ) )
888 netinfo = m_addedNets[ netName ];
889 }
890
891 if( netinfo == nullptr )
892 {
893 netinfo = new NETINFO_ITEM( m_board, netName );
894
895 // It is a new net, we have to add it
896 if( !m_isDryRun )
897 {
898 changed = true;
899 m_commit.Add( netinfo );
900 }
901
902 m_addedNets[netName] = netinfo;
903 msg.Printf( _( "Add net %s." ),
904 EscapeHTML( UnescapeString( netName ) ) );
906 }
907
908 if( !pad->GetNetname().IsEmpty() )
909 {
910 m_oldToNewNets[ pad->GetNetname() ] = netName;
911
912 if( m_isDryRun )
913 {
914 msg.Printf( _( "Reconnect %s pin %s from %s to %s."),
915 aFootprint->GetReference(),
916 EscapeHTML( pad->GetNumber() ),
917 EscapeHTML( UnescapeString( pad->GetNetname() ) ),
918 EscapeHTML( UnescapeString( netName ) ) );
919 }
920 else
921 {
922 msg.Printf( _( "Reconnected %s pin %s from %s to %s."),
923 aFootprint->GetReference(),
924 EscapeHTML( pad->GetNumber() ),
925 EscapeHTML( UnescapeString( pad->GetNetname() ) ),
926 EscapeHTML( UnescapeString( netName ) ) );
927 }
928 }
929 else
930 {
931 if( m_isDryRun )
932 {
933 msg.Printf( _( "Connect %s pin %s to %s."),
934 aFootprint->GetReference(),
935 EscapeHTML( pad->GetNumber() ),
936 EscapeHTML( UnescapeString( netName ) ) );
937 }
938 else
939 {
940 msg.Printf( _( "Connected %s pin %s to %s."),
941 aFootprint->GetReference(),
942 EscapeHTML( pad->GetNumber() ),
943 EscapeHTML( UnescapeString( netName ) ) );
944 }
945 }
946
948
949 if( !m_isDryRun )
950 {
951 changed = true;
952 pad->SetNet( netinfo );
953 }
954 else
955 {
956 cacheNetname( pad, netName );
957 }
958 }
959 }
960 }
961
962 if( changed && copy )
963 m_commit.Modified( aFootprint, copy );
964 else if( copy )
965 delete copy;
966
967 return true;
968}
969
970
972{
973 for( ZONE* zone : m_board->Zones() )
974 {
975 if( !zone->IsOnCopperLayer() || zone->GetIsRuleArea() )
976 continue;
977
978 m_zoneConnectionsCache[ zone ] = m_board->GetConnectivity()->GetConnectedPads( zone );
979 }
980}
981
982
984{
985 wxString msg;
986 std::set<wxString> netlistNetnames;
987
988 for( int ii = 0; ii < (int) aNetlist.GetCount(); ii++ )
989 {
990 const COMPONENT* component = aNetlist.GetComponent( ii );
991
992 for( unsigned jj = 0; jj < component->GetNetCount(); jj++ )
993 {
994 const COMPONENT_NET& net = component->GetNet( jj );
995 netlistNetnames.insert( net.GetNetName() );
996 }
997 }
998
999 for( PCB_TRACK* via : m_board->Tracks() )
1000 {
1001 if( via->Type() != PCB_VIA_T )
1002 continue;
1003
1004 if( netlistNetnames.count( via->GetNetname() ) == 0 )
1005 {
1006 wxString updatedNetname = wxEmptyString;
1007
1008 // Take via name from name change map if it didn't match to a new pad
1009 // (this is useful for stitching vias that don't connect to tracks)
1010 if( m_oldToNewNets.count( via->GetNetname() ) )
1011 {
1012 updatedNetname = m_oldToNewNets[via->GetNetname()];
1013 }
1014
1015 if( !updatedNetname.IsEmpty() )
1016 {
1017 if( m_isDryRun )
1018 {
1019 wxString originalNetname = via->GetNetname();
1020
1021 msg.Printf( _( "Reconnect via from %s to %s." ),
1022 EscapeHTML( UnescapeString( originalNetname ) ),
1023 EscapeHTML( UnescapeString( updatedNetname ) ) );
1024
1026 }
1027 else
1028 {
1029 NETINFO_ITEM* netinfo = m_board->FindNet( updatedNetname );
1030
1031 if( !netinfo )
1032 netinfo = m_addedNets[updatedNetname];
1033
1034 if( netinfo )
1035 {
1036 wxString originalNetname = via->GetNetname();
1037
1038 m_commit.Modify( via );
1039 via->SetNet( netinfo );
1040
1041 msg.Printf( _( "Reconnected via from %s to %s." ),
1042 EscapeHTML( UnescapeString( originalNetname ) ),
1043 EscapeHTML( UnescapeString( updatedNetname ) ) );
1044
1046 }
1047 }
1048 }
1049 else
1050 {
1051 msg.Printf( _( "Via connected to unknown net (%s)." ),
1052 EscapeHTML( UnescapeString( via->GetNetname() ) ) );
1055 }
1056 }
1057 }
1058
1059 // Test copper zones to detect "dead" nets (nets without any pad):
1060 for( ZONE* zone : m_board->Zones() )
1061 {
1062 if( !zone->IsOnCopperLayer() || zone->GetIsRuleArea() )
1063 continue;
1064
1065 if( netlistNetnames.count( zone->GetNetname() ) == 0 )
1066 {
1067 // Look for a pad in the zone's connected-pad-cache which has been updated to
1068 // a new net and use that. While this won't always be the right net, the dead
1069 // net is guaranteed to be wrong.
1070 wxString updatedNetname = wxEmptyString;
1071
1072 for( PAD* pad : m_zoneConnectionsCache[ zone ] )
1073 {
1074 if( getNetname( pad ) != zone->GetNetname() )
1075 {
1076 updatedNetname = getNetname( pad );
1077 break;
1078 }
1079 }
1080
1081 // Take zone name from name change map if it didn't match to a new pad
1082 // (this is useful for zones on internal layers)
1083 if( updatedNetname.IsEmpty() && m_oldToNewNets.count( zone->GetNetname() ) )
1084 {
1085 updatedNetname = m_oldToNewNets[ zone->GetNetname() ];
1086 }
1087
1088 if( !updatedNetname.IsEmpty() )
1089 {
1090 if( m_isDryRun )
1091 {
1092 wxString originalNetname = zone->GetNetname();
1093
1094 if( !zone->GetZoneName().IsEmpty() )
1095 {
1096 msg.Printf( _( "Reconnect copper zone '%s' from %s to %s." ),
1097 zone->GetZoneName(),
1098 EscapeHTML( UnescapeString( originalNetname ) ),
1099 EscapeHTML( UnescapeString( updatedNetname ) ) );
1100 }
1101 else
1102 {
1103 msg.Printf( _( "Reconnect copper zone from %s to %s." ),
1104 EscapeHTML( UnescapeString( originalNetname ) ),
1105 EscapeHTML( UnescapeString( updatedNetname ) ) );
1106 }
1107
1109 }
1110 else
1111 {
1112 NETINFO_ITEM* netinfo = m_board->FindNet( updatedNetname );
1113
1114 if( !netinfo )
1115 netinfo = m_addedNets[ updatedNetname ];
1116
1117 if( netinfo )
1118 {
1119 wxString originalNetname = zone->GetNetname();
1120
1121 m_commit.Modify( zone );
1122 zone->SetNet( netinfo );
1123
1124 if( !zone->GetZoneName().IsEmpty() )
1125 {
1126 msg.Printf( _( "Reconnected copper zone '%s' from %s to %s." ),
1127 EscapeHTML( zone->GetZoneName() ),
1128 EscapeHTML( UnescapeString( originalNetname ) ),
1129 EscapeHTML( UnescapeString( updatedNetname ) ) );
1130 }
1131 else
1132 {
1133 msg.Printf( _( "Reconnected copper zone from %s to %s." ),
1134 EscapeHTML( UnescapeString( originalNetname ) ),
1135 EscapeHTML( UnescapeString( updatedNetname ) ) );
1136 }
1137
1139 }
1140 }
1141 }
1142 else
1143 {
1144 if( !zone->GetZoneName().IsEmpty() )
1145 {
1146 msg.Printf( _( "Copper zone '%s' has no pads connected." ),
1147 EscapeHTML( zone->GetZoneName() ) );
1148 }
1149 else
1150 {
1151 PCB_LAYER_ID layer = zone->GetLayer();
1152 VECTOR2I pos = zone->GetPosition();
1153
1155 {
1157 pos.x *= -1;
1158
1160 pos.y *= -1;
1161 }
1162
1163 msg.Printf( _( "Copper zone on layer %s at (%s, %s) has no pads connected." ),
1164 EscapeHTML( m_board->GetLayerName( layer ) ),
1166 m_frame->MessageTextFromValue( pos.y ) );
1167 }
1168
1171 }
1172 }
1173 }
1174
1175 return true;
1176}
1177
1178
1180 std::map<COMPONENT*, FOOTPRINT*>& aFootprintMap )
1181{
1182 // Verify that board contains all pads in netlist: if it doesn't then footprints are
1183 // wrong or missing.
1184
1185 wxString msg;
1186 wxString padNumber;
1187
1188 for( int i = 0; i < (int) aNetlist.GetCount(); i++ )
1189 {
1190 COMPONENT* component = aNetlist.GetComponent( i );
1191 FOOTPRINT* footprint = aFootprintMap[component];
1192
1193 if( !footprint ) // It can be missing in partial designs
1194 continue;
1195
1196 // Explore all pins/pads in component
1197 for( unsigned jj = 0; jj < component->GetNetCount(); jj++ )
1198 {
1199 padNumber = component->GetNet( jj ).GetPinName();
1200
1201 if( padNumber.IsEmpty() )
1202 {
1203 // bad symbol, report error
1204 msg.Printf( _( "Symbol %s has pins with no number. These pins can not be matched "
1205 "to pads in %s." ),
1206 component->GetReference(),
1207 EscapeHTML( footprint->GetFPID().Format().wx_str() ) );
1209 ++m_errorCount;
1210 }
1211 else if( !footprint->FindPadByNumber( padNumber ) )
1212 {
1213 // not found: bad footprint, report error
1214 msg.Printf( _( "%s pad %s not found in %s." ),
1215 component->GetReference(),
1216 EscapeHTML( padNumber ),
1217 EscapeHTML( footprint->GetFPID().Format().wx_str() ) );
1219 ++m_errorCount;
1220 }
1221 }
1222 }
1223
1224 return true;
1225}
1226
1227
1229{
1230 FOOTPRINT* lastPreexistingFootprint = nullptr;
1231 COMPONENT* component = nullptr;
1232 wxString msg;
1233
1234 m_errorCount = 0;
1235 m_warningCount = 0;
1237
1238 std::map<COMPONENT*, FOOTPRINT*> footprintMap;
1239
1240 if( !m_board->Footprints().empty() )
1241 lastPreexistingFootprint = m_board->Footprints().back();
1242
1244
1245 // First mark all nets (except <no net>) as stale; we'll update those which are current
1246 // in the following two loops. Also prepare the component class manager for updates.
1247 //
1248 if( !m_isDryRun )
1249 {
1250 for( NETINFO_ITEM* net : m_board->GetNetInfo() )
1251 net->SetIsCurrent( net->GetNetCode() == 0 );
1252
1254 }
1255
1256 // Next go through the netlist updating all board footprints which have matching component
1257 // entries and adding new footprints for those that don't.
1258 //
1259 for( unsigned i = 0; i < aNetlist.GetCount(); i++ )
1260 {
1261 component = aNetlist.GetComponent( i );
1262
1263 if( component->GetProperties().count( wxT( "exclude_from_board" ) ) )
1264 continue;
1265
1266 msg.Printf( _( "Processing symbol '%s:%s'." ),
1267 component->GetReference(),
1268 EscapeHTML( component->GetFPID().Format().wx_str() ) );
1270
1271 int matchCount = 0;
1272
1273 for( FOOTPRINT* footprint : m_board->Footprints() )
1274 {
1275 bool match = false;
1276
1278 {
1279 for( const KIID& uuid : component->GetKIIDs() )
1280 {
1281 KIID_PATH base = component->GetPath();
1282 base.push_back( uuid );
1283
1284 if( footprint->GetPath() == base )
1285 {
1286 match = true;
1287 break;
1288 }
1289 }
1290 }
1291 else
1292 {
1293 match = footprint->GetReference().CmpNoCase( component->GetReference() ) == 0;
1294 }
1295
1296 if( match )
1297 {
1298 FOOTPRINT* tmp = footprint;
1299
1300 if( m_replaceFootprints && component->GetFPID() != footprint->GetFPID() )
1301 tmp = replaceFootprint( aNetlist, footprint, component );
1302
1303 if( tmp )
1304 {
1305 footprintMap[ component ] = tmp;
1306
1307 updateFootprintParameters( tmp, component );
1308 updateComponentPadConnections( tmp, component );
1309 updateComponentClass( tmp, component );
1310 }
1311
1312 matchCount++;
1313 }
1314
1315 if( footprint == lastPreexistingFootprint )
1316 {
1317 // No sense going through the newly-created footprints: end of loop
1318 break;
1319 }
1320 }
1321
1322 if( matchCount == 0 )
1323 {
1324 FOOTPRINT* footprint = addNewFootprint( component );
1325
1326 if( footprint )
1327 {
1328 footprintMap[ component ] = footprint;
1329
1330 updateFootprintParameters( footprint, component );
1331 updateComponentPadConnections( footprint, component );
1332 updateComponentClass( footprint, component );
1333 }
1334 }
1335 else if( matchCount > 1 )
1336 {
1337 msg.Printf( _( "Multiple footprints found for %s." ),
1338 component->GetReference() );
1340 m_errorCount++;
1341 }
1342 }
1343
1344 updateCopperZoneNets( aNetlist );
1345
1346 // Finally go through the board footprints and update all those that *don't* have matching
1347 // component entries.
1348 //
1349 for( FOOTPRINT* footprint : m_board->Footprints() )
1350 {
1351 bool matched = false;
1352 bool doDelete = m_deleteUnusedFootprints;
1353
1354 if( ( footprint->GetAttributes() & FP_BOARD_ONLY ) > 0 )
1355 doDelete = false;
1356
1358 component = aNetlist.GetComponentByPath( footprint->GetPath() );
1359 else
1360 component = aNetlist.GetComponentByReference( footprint->GetReference() );
1361
1362 if( component && component->GetProperties().count( wxT( "exclude_from_board" ) ) == 0 )
1363 matched = true;
1364
1365 if( doDelete && !matched && footprint->IsLocked() && !m_overrideLocks )
1366 {
1367 if( m_isDryRun )
1368 {
1369 msg.Printf( _( "Cannot remove unused footprint %s (footprint is locked)." ),
1370 footprint->GetReference() );
1371 }
1372 else
1373 {
1374 msg.Printf( _( "Could not remove unused footprint %s (footprint is locked)." ),
1375 footprint->GetReference() );
1376 }
1377
1380 doDelete = false;
1381 }
1382
1383 if( doDelete && !matched )
1384 {
1385 if( m_isDryRun )
1386 {
1387 msg.Printf( _( "Remove unused footprint %s." ),
1388 footprint->GetReference() );
1389 }
1390 else
1391 {
1392 if( footprint->GetParentGroup() )
1393 m_commit.Stage( footprint, CHT_UNGROUP );
1394
1395 m_commit.Remove( footprint );
1396 msg.Printf( _( "Removed unused footprint %s." ),
1397 footprint->GetReference() );
1398 }
1399
1401 }
1402 else if( !m_isDryRun )
1403 {
1404 if( !matched )
1405 footprint->SetPath( KIID_PATH() );
1406
1407 for( PAD* pad : footprint->Pads() )
1408 {
1409 if( pad->GetNet() )
1410 pad->GetNet()->SetIsCurrent( true );
1411 }
1412 }
1413 }
1414
1415 if( !m_isDryRun )
1416 {
1417 // Finalise the component class manager
1419
1421 testConnectivity( aNetlist, footprintMap );
1422
1423 for( NETINFO_ITEM* net : m_board->GetNetInfo() )
1424 {
1425 if( !net->IsCurrent() )
1426 {
1427 msg.Printf( _( "Removed unused net %s." ),
1428 EscapeHTML( net->GetNetname() ) );
1430 }
1431 }
1432
1434
1435 // When new footprints are added, the automatic zone refill is disabled because:
1436 // * it creates crashes when calculating dynamic ratsnests if auto refill is enabled.
1437 // (the auto refills rebuild the connectivity with incomplete data)
1438 // * it is useless because zones will be refilled after placing new footprints
1439 m_commit.Push( _( "Update Netlist" ), m_newFootprintsCount ? ZONE_FILL_OP : 0 );
1440
1441 // Update net, netcode and netclass data after commiting the netlist
1443 m_board->GetConnectivity()->RefreshNetcodeMap( m_board );
1444
1445 // Although m_commit will probably also set this, it's not guaranteed, and we need to make
1446 // sure any modification to netclasses gets persisted to project settings through a save.
1447 m_frame->OnModify();
1448 }
1449
1450 if( m_isDryRun )
1451 {
1452 for( const std::pair<const wxString, NETINFO_ITEM*>& addedNet : m_addedNets )
1453 delete addedNet.second;
1454
1455 m_addedNets.clear();
1456 }
1457
1458 // Update the ratsnest
1461
1462 msg.Printf( _( "Total warnings: %d, errors: %d." ), m_warningCount, m_errorCount );
1464
1465 return true;
1466}
const char * name
Definition: DXF_plotter.cpp:57
constexpr EDA_IU_SCALE pcbIUScale
Definition: base_units.h:108
#define ZONE_FILL_OP
Definition: board_commit.h:43
virtual void Push(const wxString &aMessage=wxEmptyString, int aCommitFlags=0) override
Revert the commit by restoring the modified items state.
COMMIT & Stage(EDA_ITEM *aItem, CHANGE_TYPE aChangeType, BASE_SCREEN *aScreen=nullptr) override
virtual void SetLayer(PCB_LAYER_ID aLayer)
Set the layer this item is on.
Definition: board_item.h:288
std::map< PAD *, wxString > m_padNets
void cacheNetname(PAD *aPad, const wxString &aNetname)
bool UpdateNetlist(NETLIST &aNetlist)
Update the board's components according to the new netlist.
wxString getNetname(PAD *aPad)
wxString getPinFunction(PAD *aPad)
std::vector< FOOTPRINT * > m_addedFootprints
std::map< wxString, wxString > m_oldToNewNets
void updateComponentClass(FOOTPRINT *aFootprint, COMPONENT *aNewComponent)
bool updateFootprintParameters(FOOTPRINT *aPcbFootprint, COMPONENT *aNetlistComponent)
std::map< wxString, NETINFO_ITEM * > m_addedNets
bool testConnectivity(NETLIST &aNetlist, std::map< COMPONENT *, FOOTPRINT * > &aFootprintMap)
bool updateCopperZoneNets(NETLIST &aNetlist)
void cachePinFunction(PAD *aPad, const wxString &aPinFunction)
BOARD_NETLIST_UPDATER(PCB_EDIT_FRAME *aFrame, BOARD *aBoard)
bool updateComponentPadConnections(FOOTPRINT *aFootprint, COMPONENT *aNewComponent)
std::map< PAD *, wxString > m_padPinFunctions
std::map< ZONE *, std::vector< PAD * > > m_zoneConnectionsCache
FOOTPRINT * replaceFootprint(NETLIST &aNetlist, FOOTPRINT *aFootprint, COMPONENT *aNewComponent)
FOOTPRINT * addNewFootprint(COMPONENT *aComponent)
Information pertinent to a Pcbnew printed circuit board.
Definition: board.h:290
const NETINFO_LIST & GetNetInfo() const
Definition: board.h:871
const BOX2I GetBoardEdgesBoundingBox() const
Return the board bounding box calculated using exclusively the board edges (graphics on Edge....
Definition: board.h:929
const PAGE_INFO & GetPageSettings() const
Definition: board.h:689
NETINFO_ITEM * FindNet(int aNetcode) const
Search for a net with the given netcode.
Definition: board.cpp:1918
const ZONES & Zones() const
Definition: board.h:335
bool BuildConnectivity(PROGRESS_REPORTER *aReporter=nullptr)
Build or rebuild the board connectivity database for the board, especially the list of connected item...
Definition: board.cpp:187
void SynchronizeNetsAndNetClasses(bool aResetTrackAndViaSizes)
Copy NETCLASS info to each NET, based on NET membership in a NETCLASS.
Definition: board.cpp:2051
void RemoveUnusedNets(BOARD_COMMIT *aCommit)
Definition: board.h:876
const FOOTPRINTS & Footprints() const
Definition: board.h:331
const TRACKS & Tracks() const
Definition: board.h:329
const wxString GetLayerName(PCB_LAYER_ID aLayer) const
Return the name of a aLayer.
Definition: board.cpp:579
bool IsEmpty() const
Definition: board.h:386
COMPONENT_CLASS_MANAGER & GetComponentClassManager()
Gets the component class manager.
Definition: board.h:1275
std::shared_ptr< CONNECTIVITY_DATA > GetConnectivity() const
Return a list of missing connections between components/tracks.
Definition: board.h:475
constexpr size_type GetWidth() const
Definition: box2.h:214
constexpr Vec Centre() const
Definition: box2.h:97
constexpr size_type GetHeight() const
Definition: box2.h:215
constexpr coord_type GetBottom() const
Definition: box2.h:222
COMMIT & Remove(EDA_ITEM *aItem, BASE_SCREEN *aScreen=nullptr)
Notify observers that aItem has been removed.
Definition: commit.h:92
COMMIT & Modify(EDA_ITEM *aItem, BASE_SCREEN *aScreen=nullptr)
Create an undo entry for an item that has been already modified.
Definition: commit.h:105
COMMIT & Modified(EDA_ITEM *aItem, EDA_ITEM *aCopy, BASE_SCREEN *aScreen=nullptr)
Definition: commit.h:112
COMMIT & Add(EDA_ITEM *aItem, BASE_SCREEN *aScreen=nullptr)
Notify observers that aItem has been added.
Definition: commit.h:80
int GetStatus(EDA_ITEM *aItem, BASE_SCREEN *aScreen=nullptr)
Definition: commit.cpp:130
void FinishNetlistUpdate()
Cleans up the manager after a board update Must be called after updating the PCB from the netlist.
static wxString GetFullClassNameForConstituents(std::unordered_set< wxString > &classNames)
Gets the full effective class name for the given set of constituent classes.
const COMPONENT_CLASS * GetNoneComponentClass() const
Returns the unassigned component class.
void InitNetlistUpdate()
Prepare the manager for a board update Must be called prior to updating the PCB from the netlist.
COMPONENT_CLASS * GetEffectiveComponentClass(std::unordered_set< wxString > &classNames)
Gets an effective component class for the given constituent class names.
const wxString & GetFullName() const
Fetches the full name of this component class.
Used to store the component pin name to net name (and pin function) associations stored in a netlist.
Definition: pcb_netlist.h:47
const wxString & GetNetName() const
Definition: pcb_netlist.h:61
bool IsValid() const
Definition: pcb_netlist.h:65
const wxString & GetPinFunction() const
Definition: pcb_netlist.h:62
const wxString & GetPinName() const
Definition: pcb_netlist.h:60
const wxString & GetPinType() const
Definition: pcb_netlist.h:63
Store all of the related footprint information found in a netlist.
Definition: pcb_netlist.h:88
const wxString & GetHumanReadablePath() const
Definition: pcb_netlist.h:177
const COMPONENT_NET & GetNet(unsigned aIndex) const
Definition: pcb_netlist.h:114
const KIID_PATH & GetPath() const
Definition: pcb_netlist.h:152
const wxString & GetReference() const
Definition: pcb_netlist.h:129
const wxString & GetValue() const
Definition: pcb_netlist.h:132
const nlohmann::ordered_map< wxString, wxString > & GetFields() const
Definition: pcb_netlist.h:138
const std::map< wxString, wxString > & GetProperties() const
Definition: pcb_netlist.h:144
const std::vector< KIID > & GetKIIDs() const
Definition: pcb_netlist.h:154
const LIB_ID & GetFPID() const
Definition: pcb_netlist.h:147
unsigned GetNetCount() const
Definition: pcb_netlist.h:112
std::unordered_set< wxString > & GetComponentClassNames()
Definition: pcb_netlist.h:184
virtual void SetParent(EDA_ITEM *aParent)
Definition: eda_item.h:104
virtual void SetVisible(bool aVisible)
Definition: eda_text.cpp:290
virtual void SetText(const wxString &aText)
Definition: eda_text.cpp:182
void SetPosition(const VECTOR2I &aPos) override
Definition: footprint.cpp:2345
int GetFieldCount() const
Return the number of fields in this symbol.
Definition: footprint.h:720
EDA_ANGLE GetOrientation() const
Definition: footprint.h:227
bool HasFieldByName(const wxString &aFieldName) const
Definition: footprint.cpp:541
void SetComponentClass(const COMPONENT_CLASS *aClass)
Definition: footprint.h:997
PCB_FIELD * GetFieldByName(const wxString &aFieldName)
Return a field in this symbol.
Definition: footprint.cpp:552
PCB_FIELD * AddField(const PCB_FIELD &aField)
Add a field to the symbol.
Definition: footprint.cpp:594
wxString GetSheetname() const
Definition: footprint.h:266
void SetPath(const KIID_PATH &aPath)
Definition: footprint.h:264
void SetFilters(const wxString &aFilters)
Definition: footprint.h:273
PCB_FIELD & Footprint()
Definition: footprint.h:640
void SetAttributes(int aAttributes)
Definition: footprint.h:291
void SetSheetfile(const wxString &aSheetfile)
Definition: footprint.h:270
EDA_ITEM * Clone() const override
Invoke a function on all children.
Definition: footprint.cpp:2032
std::deque< PAD * > & Pads()
Definition: footprint.h:206
int GetAttributes() const
Definition: footprint.h:290
const COMPONENT_CLASS * GetComponentClass() const
Definition: footprint.h:999
PCB_LAYER_ID GetLayer() const override
Return the primary layer this item is on.
Definition: footprint.h:236
wxString GetSheetfile() const
Definition: footprint.h:269
const LIB_ID & GetFPID() const
Definition: footprint.h:248
void SetReference(const wxString &aReference)
Definition: footprint.h:608
bool IsLocked() const override
Definition: footprint.h:411
void GetFields(std::vector< PCB_FIELD * > &aVector, bool aVisibleOnly)
Populate a std::vector with PCB_TEXTs.
Definition: footprint.cpp:579
void SetValue(const wxString &aValue)
Definition: footprint.h:629
void RemoveField(const wxString &aFieldName)
Remove a user field from the footprint.
Definition: footprint.cpp:603
wxString GetFilters() const
Definition: footprint.h:272
void SetSheetname(const wxString &aSheetname)
Definition: footprint.h:267
const wxString & GetValue() const
Definition: footprint.h:624
const wxString & GetReference() const
Definition: footprint.h:602
const KIID_PATH & GetPath() const
Definition: footprint.h:263
VECTOR2I GetPosition() const override
Definition: footprint.h:224
PAD * FindPadByNumber(const wxString &aPadNumber, PAD *aSearchAfterMe=nullptr) const
Return a PAD with a matching number.
Definition: footprint.cpp:1809
virtual void Remove(VIEW_ITEM *aItem) override
Remove a VIEW_ITEM from the view.
Definition: pcb_view.cpp:74
wxString AsString() const
Definition: kiid.cpp:348
Definition: kiid.h:49
bool empty() const
Definition: lib_id.h:193
UTF8 Format() const
Definition: lib_id.cpp:118
Handle the data for a net.
Definition: netinfo.h:56
void SetIsCurrent(bool isCurrent)
Definition: netinfo.h:152
static const int UNCONNECTED
Constant that holds the "unconnected net" number (typically 0) all items "connected" to this net are ...
Definition: netinfo.h:381
Store information read from a netlist along with the flags used to update the NETLIST in the BOARD.
Definition: pcb_netlist.h:241
unsigned GetCount() const
Definition: pcb_netlist.h:262
COMPONENT * GetComponentByPath(const KIID_PATH &aPath)
Return a COMPONENT by aPath.
COMPONENT * GetComponentByReference(const wxString &aReference)
Return a COMPONENT by aReference.
COMPONENT * GetComponent(unsigned aIndex)
Return the COMPONENT at aIndex.
Definition: pcb_netlist.h:270
static REPORTER & GetInstance()
Definition: reporter.cpp:115
Definition: pad.h:54
const wxString & GetPinFunction() const
Definition: pad.h:145
const VECTOR2D GetSizeIU(double aIUScale) const
Gets the page size in internal units.
Definition: page_info.h:171
DISPLAY_OPTIONS m_Display
PCBNEW_SETTINGS * GetPcbNewSettings() const
FOOTPRINT * LoadFootprint(const LIB_ID &aFootprintId)
Attempt to load aFootprintId from the footprint library table.
PCB_DRAW_PANEL_GAL * GetCanvas() const override
Return a pointer to GAL-based canvas of given EDA draw frame.
virtual BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Returns the BOARD_DESIGN_SETTINGS for the open project.
virtual KIGFX::PCB_VIEW * GetView() const override
Return a pointer to the #VIEW instance used in the panel.
The main frame for Pcbnew.
void OnModify() override
Must be called after a board change to set the modified flag.
void ExchangeFootprint(FOOTPRINT *aExisting, FOOTPRINT *aNew, BOARD_COMMIT &aCommit, bool deleteExtraTexts=true, bool resetTextLayers=true, bool resetTextEffects=true, bool resetFabricationAttrs=true, bool resetTextContent=true, bool reset3DModels=true, bool *aUpdated=nullptr)
Replace aExisting footprint by aNew footprint using the Existing footprint settings (position,...
void SetName(const wxString &aName)
Definition: pcb_field.h:108
void StyleFromSettings(const BOARD_DESIGN_SETTINGS &settings) override
Definition: pcb_text.cpp:358
virtual void SetPosition(const VECTOR2I &aPos) override
Definition: pcb_text.h:87
void Rotate(const VECTOR2I &aRotCentre, const EDA_ANGLE &aAngle) override
Rotate this object.
Definition: pcb_text.cpp:426
virtual REPORTER & ReportTail(const wxString &aText, SEVERITY aSeverity=RPT_SEVERITY_UNDEFINED)
Places the report at the end of the list, for objects that support report ordering.
Definition: reporter.h:100
virtual REPORTER & Report(const wxString &aText, SEVERITY aSeverity=RPT_SEVERITY_UNDEFINED)=0
Report a string with a given severity.
wxString MessageTextFromValue(double aValue, bool aAddUnitLabel=true, EDA_DATA_TYPE aType=EDA_DATA_TYPE::DISTANCE) const
A lower-precision version of StringFromValue().
wxString wx_str() const
Definition: utf8.cpp:45
Handle a list of polygons defining a copper zone.
Definition: zone.h:73
@ CHT_UNGROUP
Definition: commit.h:46
The common library.
#define _(s)
@ FP_DNP
Definition: footprint.h:83
@ FP_BOARD_ONLY
Definition: footprint.h:79
@ FP_EXCLUDE_FROM_BOM
Definition: footprint.h:78
@ FP_JUST_ADDED
Definition: footprint.h:80
PCB_LAYER_ID
A quick note on layer IDs:
Definition: layer_ids.h:60
@ F_Fab
Definition: layer_ids.h:119
@ F_Cu
Definition: layer_ids.h:64
@ B_Fab
Definition: layer_ids.h:118
@ RPT_SEVERITY_WARNING
@ RPT_SEVERITY_ERROR
@ RPT_SEVERITY_INFO
@ RPT_SEVERITY_ACTION
wxString EscapeHTML(const wxString &aString)
Return a new wxString escaped for embedding in HTML.
wxString UnescapeString(const wxString &aSource)
const double IU_PER_MILS
Definition: base_units.h:77
constexpr int mmToIU(double mm) const
Definition: base_units.h:88
wxString GetCanonicalFieldName(int idx)
@ 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".
@ PCB_VIA_T
class PCB_VIA, a via (like a track segment on a copper layer)
Definition: typeinfo.h:97