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 time stamp change.
427 KIID_PATH new_path = aNetlistComponent->GetPath();
428
429 if( !aNetlistComponent->GetKIIDs().empty() )
430 new_path.push_back( aNetlistComponent->GetKIIDs().front() );
431
432 if( aPcbFootprint->GetPath() != new_path )
433 {
434 if( m_isDryRun )
435 {
436 msg.Printf( _( "Update %s symbol association from %s to %s." ),
437 aPcbFootprint->GetReference(),
438 EscapeHTML( aPcbFootprint->GetPath().AsString() ),
439 EscapeHTML( new_path.AsString() ) );
440 }
441 else
442 {
443 msg.Printf( _( "Updated %s symbol association from %s to %s." ),
444 aPcbFootprint->GetReference(),
445 EscapeHTML( aPcbFootprint->GetPath().AsString() ),
446 EscapeHTML( new_path.AsString() ) );
447
448 changed = true;
449 aPcbFootprint->SetPath( new_path );
450 }
451
453 }
454
455 nlohmann::ordered_map<wxString, wxString> fpFieldsAsMap;
456
457 for( PCB_FIELD* field : aPcbFootprint->GetFields() )
458 {
459 // These fields are individually checked above
460 if( field->IsReference() || field->IsValue() || field->IsComponentClass() )
461 {
462 continue;
463 }
464
465 fpFieldsAsMap[field->GetName()] = field->GetText();
466 }
467
468 // Remove the ref/value/footprint fields that are individually handled
469 nlohmann::ordered_map<wxString, wxString> compFields = aNetlistComponent->GetFields();
470 compFields.erase( GetCanonicalFieldName( REFERENCE_FIELD ) );
471 compFields.erase( GetCanonicalFieldName( VALUE_FIELD ) );
472 compFields.erase( GetCanonicalFieldName( FOOTPRINT_FIELD ) );
473
474 // Remove any component class fields - these are not editable in the pcb editor
475 compFields.erase( wxT( "Component Class" ) );
476
477 // Fields are stored as an ordered map, but we don't (yet) support reordering
478 // the footprint fields to match the symbol, so we manually check the fields
479 // in the order they are stored in the symbol.
480 bool same = true;
481
482 for( std::pair<wxString, wxString> field : compFields )
483 {
484 if( fpFieldsAsMap.count( field.first ) == 0 || fpFieldsAsMap[field.first] != field.second )
485 {
486 same = false;
487 break;
488 }
489 }
490
491 if( !same )
492 {
493 if( m_isDryRun )
494 {
495 msg.Printf( _( "Update %s fields." ), aPcbFootprint->GetReference() );
497
498 // Remove fields that aren't present in the symbol
499 for( PCB_FIELD* field : aPcbFootprint->GetFields() )
500 {
501 if( field->IsMandatoryField() )
502 continue;
503
504 if( compFields.count( field->GetName() ) == 0 )
505 {
506 msg.Printf( _( "Remove %s footprint fields not in symbol." ),
507 aPcbFootprint->GetReference() );
509 break;
510 }
511 }
512 }
513 else
514 {
515 msg.Printf( _( "Updated %s fields." ), aPcbFootprint->GetReference() );
517
518 changed = true;
519
520 // Add or change field value
521 for( auto& [name, value] : compFields )
522 {
523 if( aPcbFootprint->HasFieldByName( name ) )
524 {
525 aPcbFootprint->GetFieldByName( name )->SetText( value );
526 }
527 else
528 {
529 int idx = aPcbFootprint->GetFieldCount();
530 PCB_FIELD* newField = aPcbFootprint->AddField( PCB_FIELD( aPcbFootprint, idx ) );
531
532 newField->SetName( name );
533 newField->SetText( value );
534 newField->SetVisible( false );
535 newField->SetLayer( aPcbFootprint->GetLayer() == F_Cu ? F_Fab : B_Fab );
536
537 // Give the relative position (0,0) in footprint
538 newField->SetPosition( aPcbFootprint->GetPosition() );
539 // Give the footprint orientation
540 newField->Rotate( aPcbFootprint->GetPosition(), aPcbFootprint->GetOrientation() );
541
542 if( m_frame )
544 }
545 }
546
547 // Remove fields that aren't present in the symbol
548 bool warned = false;
549
550 for( PCB_FIELD* field : aPcbFootprint->GetFields() )
551 {
552 if( field->IsMandatoryField() )
553 continue;
554
555 if( compFields.count( field->GetName() ) == 0 )
556 {
557 if( !warned )
558 {
559 warned = true;
560 msg.Printf( _( "Removed %s footprint fields not in symbol." ),
561 aPcbFootprint->GetReference() );
563 }
564
565 aPcbFootprint->RemoveField( field->GetCanonicalName() );
566
567 if( m_frame )
568 m_frame->GetCanvas()->GetView()->Remove( field );
569 }
570 }
571 }
572 }
573
574 wxString sheetname;
575 wxString sheetfile;
576 wxString fpFilters;
577
578 wxString humanSheetPath = aNetlistComponent->GetHumanReadablePath();
579
580 if( !humanSheetPath.empty() )
581 sheetname = humanSheetPath;
582 else if( aNetlistComponent->GetProperties().count( wxT( "Sheetname" ) ) > 0 )
583 sheetname = aNetlistComponent->GetProperties().at( wxT( "Sheetname" ) );
584
585 if( aNetlistComponent->GetProperties().count( wxT( "Sheetfile" ) ) > 0 )
586 sheetfile = aNetlistComponent->GetProperties().at( wxT( "Sheetfile" ) );
587
588 if( aNetlistComponent->GetProperties().count( wxT( "ki_fp_filters" ) ) > 0 )
589 fpFilters = aNetlistComponent->GetProperties().at( wxT( "ki_fp_filters" ) );
590
591 if( sheetname != aPcbFootprint->GetSheetname() )
592 {
593 if( m_isDryRun )
594 {
595 msg.Printf( _( "Update %s sheetname to '%s'." ),
596 aPcbFootprint->GetReference(),
597 EscapeHTML( sheetname ) );
598 }
599 else
600 {
601 aPcbFootprint->SetSheetname( sheetname );
602 msg.Printf( _( "Updated %s sheetname to '%s'." ),
603 aPcbFootprint->GetReference(),
604 EscapeHTML( sheetname ) );
605 }
606
608 }
609
610 if( sheetfile != aPcbFootprint->GetSheetfile() )
611 {
612 if( m_isDryRun )
613 {
614 msg.Printf( _( "Update %s sheetfile to '%s'." ),
615 aPcbFootprint->GetReference(),
616 EscapeHTML( sheetfile ) );
617 }
618 else
619 {
620 aPcbFootprint->SetSheetfile( sheetfile );
621 msg.Printf( _( "Updated %s sheetfile to '%s'." ),
622 aPcbFootprint->GetReference(),
623 EscapeHTML( sheetfile ) );
624 }
625
627 }
628
629 if( fpFilters != aPcbFootprint->GetFilters() )
630 {
631 if( m_isDryRun )
632 {
633 msg.Printf( _( "Update %s footprint filters to '%s'." ),
634 aPcbFootprint->GetReference(),
635 EscapeHTML( fpFilters ) );
636 }
637 else
638 {
639 aPcbFootprint->SetFilters( fpFilters );
640 msg.Printf( _( "Updated %s footprint filters to '%s'." ),
641 aPcbFootprint->GetReference(),
642 EscapeHTML( fpFilters ) );
643 }
644
646 }
647
648 if( ( aNetlistComponent->GetProperties().count( wxT( "exclude_from_bom" ) ) > 0 )
649 != ( ( aPcbFootprint->GetAttributes() & FP_EXCLUDE_FROM_BOM ) > 0 ) )
650 {
651 if( m_isDryRun )
652 {
653 if( aNetlistComponent->GetProperties().count( wxT( "exclude_from_bom" ) ) )
654 {
655 msg.Printf( _( "Add %s 'exclude from BOM' fabrication attribute." ),
656 aPcbFootprint->GetReference() );
657 }
658 else
659 {
660 msg.Printf( _( "Remove %s 'exclude from BOM' fabrication attribute." ),
661 aPcbFootprint->GetReference() );
662 }
663 }
664 else
665 {
666 int attributes = aPcbFootprint->GetAttributes();
667
668 if( aNetlistComponent->GetProperties().count( wxT( "exclude_from_bom" ) ) )
669 {
670 attributes |= FP_EXCLUDE_FROM_BOM;
671 msg.Printf( _( "Added %s 'exclude from BOM' fabrication attribute." ),
672 aPcbFootprint->GetReference() );
673 }
674 else
675 {
676 attributes &= ~FP_EXCLUDE_FROM_BOM;
677 msg.Printf( _( "Removed %s 'exclude from BOM' fabrication attribute." ),
678 aPcbFootprint->GetReference() );
679 }
680
681 changed = true;
682 aPcbFootprint->SetAttributes( attributes );
683 }
684
686 }
687
688 if( ( aNetlistComponent->GetProperties().count( wxT( "dnp" ) ) > 0 )
689 != ( ( aPcbFootprint->GetAttributes() & FP_DNP ) > 0 ) )
690 {
691 if( m_isDryRun )
692 {
693 if( aNetlistComponent->GetProperties().count( wxT( "dnp" ) ) )
694 {
695 msg.Printf( _( "Add %s 'Do not place' fabrication attribute." ),
696 aPcbFootprint->GetReference() );
697 }
698 else
699 {
700 msg.Printf( _( "Remove %s 'Do not place' fabrication attribute." ),
701 aPcbFootprint->GetReference() );
702 }
703 }
704 else
705 {
706 int attributes = aPcbFootprint->GetAttributes();
707
708 if( aNetlistComponent->GetProperties().count( wxT( "dnp" ) ) )
709 {
710 attributes |= FP_DNP;
711 msg.Printf( _( "Added %s 'Do not place' fabrication attribute." ),
712 aPcbFootprint->GetReference() );
713 }
714 else
715 {
716 attributes &= ~FP_DNP;
717 msg.Printf( _( "Removed %s 'Do not place' fabrication attribute." ),
718 aPcbFootprint->GetReference() );
719 }
720
721 changed = true;
722 aPcbFootprint->SetAttributes( attributes );
723 }
724
726 }
727
728 if( changed && copy )
729 m_commit.Modified( aPcbFootprint, copy );
730 else if( copy )
731 delete copy;
732
733 return true;
734}
735
736
738 COMPONENT* aNewComponent )
739{
740 wxString msg;
741
742 // Create a copy only if the footprint has not been added during this update
743 FOOTPRINT* copy = nullptr;
744
745 if( !m_isDryRun && !m_commit.GetStatus( aFootprint ) )
746 {
747 copy = static_cast<FOOTPRINT*>( aFootprint->Clone() );
748 copy->SetParentGroup( nullptr );
749 }
750
751 bool changed = false;
752
753 // At this point, the component footprint is updated. Now update the nets.
754 std::deque<PAD*> pads = aFootprint->Pads();
755 std::set<wxString> padNetnames;
756
757 std::sort( pads.begin(), pads.end(),
758 []( PAD* a, PAD* b )
759 {
760 return a->m_Uuid < b->m_Uuid;
761 } );
762
763 for( PAD* pad : pads )
764 {
765 const COMPONENT_NET& net = aNewComponent->GetNet( pad->GetNumber() );
766
767 wxString pinFunction;
768 wxString pinType;
769
770 if( net.IsValid() ) // i.e. the pad has a name
771 {
772 pinFunction = net.GetPinFunction();
773 pinType = net.GetPinType();
774 }
775
776 if( !m_isDryRun )
777 {
778 if( pad->GetPinFunction() != pinFunction )
779 {
780 changed = true;
781 pad->SetPinFunction( pinFunction );
782 }
783
784 if( pad->GetPinType() != pinType )
785 {
786 changed = true;
787 pad->SetPinType( pinType );
788 }
789 }
790 else
791 {
792 cachePinFunction( pad, pinFunction );
793 }
794
795 // Test if new footprint pad has no net (pads not on copper layers have no net).
796 if( !net.IsValid() || !pad->IsOnCopperLayer() )
797 {
798 if( !pad->GetNetname().IsEmpty() )
799 {
800 if( m_isDryRun )
801 {
802 msg.Printf( _( "Disconnect %s pin %s." ),
803 aFootprint->GetReference(),
804 EscapeHTML( pad->GetNumber() ) );
805 }
806 else
807 {
808 msg.Printf( _( "Disconnected %s pin %s." ),
809 aFootprint->GetReference(),
810 EscapeHTML( pad->GetNumber() ) );
811 }
812
814 }
815 else if( pad->IsOnCopperLayer() && !pad->GetNumber().IsEmpty() )
816 {
817 // pad is connectable but has no net found in netlist
818 msg.Printf( _( "No net found for component %s pad %s (no pin %s in symbol)." ),
819 aFootprint->GetReference(),
820 EscapeHTML( pad->GetNumber() ),
821 EscapeHTML( pad->GetNumber() ) );
824 }
825
826 if( !m_isDryRun )
827 {
828 changed = true;
829 pad->SetNetCode( NETINFO_LIST::UNCONNECTED );
830
831 // If the pad has no net from netlist (i.e. not in netlist
832 // it cannot have a pin function
833 if( pad->GetNetname().IsEmpty() )
834 pad->SetPinFunction( wxEmptyString );
835
836 }
837 else
838 {
839 cacheNetname( pad, wxEmptyString );
840 }
841 }
842 else // New footprint pad has a net.
843 {
844 wxString netName = net.GetNetName();
845
846 if( pad->IsNoConnectPad() )
847 {
848 netName = wxString::Format( wxS( "%s" ),
849 EscapeHTML( net.GetNetName() ) );
850
851 for( int jj = 1; !padNetnames.insert( netName ).second; jj++ )
852 {
853 netName = wxString::Format( wxS( "%s_%d" ),
854 EscapeHTML( net.GetNetName() ), jj );
855 }
856 }
857
858 NETINFO_ITEM* netinfo = m_board->FindNet( netName );
859
860 if( netinfo && !m_isDryRun )
861 netinfo->SetIsCurrent( true );
862
863 if( pad->GetNetname() != netName )
864 {
865
866 if( netinfo == nullptr )
867 {
868 // It might be a new net that has not been added to the board yet
869 if( m_addedNets.count( netName ) )
870 netinfo = m_addedNets[ netName ];
871 }
872
873 if( netinfo == nullptr )
874 {
875 netinfo = new NETINFO_ITEM( m_board, netName );
876
877 // It is a new net, we have to add it
878 if( !m_isDryRun )
879 {
880 changed = true;
881 m_commit.Add( netinfo );
882 }
883
884 m_addedNets[netName] = netinfo;
885 msg.Printf( _( "Add net %s." ),
886 EscapeHTML( UnescapeString( netName ) ) );
888 }
889
890 if( !pad->GetNetname().IsEmpty() )
891 {
892 m_oldToNewNets[ pad->GetNetname() ] = netName;
893
894 if( m_isDryRun )
895 {
896 msg.Printf( _( "Reconnect %s pin %s from %s to %s."),
897 aFootprint->GetReference(),
898 EscapeHTML( pad->GetNumber() ),
899 EscapeHTML( UnescapeString( pad->GetNetname() ) ),
900 EscapeHTML( UnescapeString( netName ) ) );
901 }
902 else
903 {
904 msg.Printf( _( "Reconnected %s pin %s from %s to %s."),
905 aFootprint->GetReference(),
906 EscapeHTML( pad->GetNumber() ),
907 EscapeHTML( UnescapeString( pad->GetNetname() ) ),
908 EscapeHTML( UnescapeString( netName ) ) );
909 }
910 }
911 else
912 {
913 if( m_isDryRun )
914 {
915 msg.Printf( _( "Connect %s pin %s to %s."),
916 aFootprint->GetReference(),
917 EscapeHTML( pad->GetNumber() ),
918 EscapeHTML( UnescapeString( netName ) ) );
919 }
920 else
921 {
922 msg.Printf( _( "Connected %s pin %s to %s."),
923 aFootprint->GetReference(),
924 EscapeHTML( pad->GetNumber() ),
925 EscapeHTML( UnescapeString( netName ) ) );
926 }
927 }
928
930
931 if( !m_isDryRun )
932 {
933 changed = true;
934 pad->SetNet( netinfo );
935 }
936 else
937 {
938 cacheNetname( pad, netName );
939 }
940 }
941 }
942 }
943
944 if( changed && copy )
945 m_commit.Modified( aFootprint, copy );
946 else if( copy )
947 delete copy;
948
949 return true;
950}
951
952
954{
955 for( ZONE* zone : m_board->Zones() )
956 {
957 if( !zone->IsOnCopperLayer() || zone->GetIsRuleArea() )
958 continue;
959
960 m_zoneConnectionsCache[ zone ] = m_board->GetConnectivity()->GetConnectedPads( zone );
961 }
962}
963
964
966{
967 wxString msg;
968 std::set<wxString> netlistNetnames;
969
970 for( int ii = 0; ii < (int) aNetlist.GetCount(); ii++ )
971 {
972 const COMPONENT* component = aNetlist.GetComponent( ii );
973
974 for( unsigned jj = 0; jj < component->GetNetCount(); jj++ )
975 {
976 const COMPONENT_NET& net = component->GetNet( jj );
977 netlistNetnames.insert( net.GetNetName() );
978 }
979 }
980
981 for( PCB_TRACK* via : m_board->Tracks() )
982 {
983 if( via->Type() != PCB_VIA_T )
984 continue;
985
986 if( netlistNetnames.count( via->GetNetname() ) == 0 )
987 {
988 wxString updatedNetname = wxEmptyString;
989
990 // Take via name from name change map if it didn't match to a new pad
991 // (this is useful for stitching vias that don't connect to tracks)
992 if( m_oldToNewNets.count( via->GetNetname() ) )
993 {
994 updatedNetname = m_oldToNewNets[via->GetNetname()];
995 }
996
997 if( !updatedNetname.IsEmpty() )
998 {
999 if( m_isDryRun )
1000 {
1001 wxString originalNetname = via->GetNetname();
1002
1003 msg.Printf( _( "Reconnect via from %s to %s." ),
1004 EscapeHTML( UnescapeString( originalNetname ) ),
1005 EscapeHTML( UnescapeString( updatedNetname ) ) );
1006
1008 }
1009 else
1010 {
1011 NETINFO_ITEM* netinfo = m_board->FindNet( updatedNetname );
1012
1013 if( !netinfo )
1014 netinfo = m_addedNets[updatedNetname];
1015
1016 if( netinfo )
1017 {
1018 wxString originalNetname = via->GetNetname();
1019
1020 m_commit.Modify( via );
1021 via->SetNet( netinfo );
1022
1023 msg.Printf( _( "Reconnected via from %s to %s." ),
1024 EscapeHTML( UnescapeString( originalNetname ) ),
1025 EscapeHTML( UnescapeString( updatedNetname ) ) );
1026
1028 }
1029 }
1030 }
1031 else
1032 {
1033 msg.Printf( _( "Via connected to unknown net (%s)." ),
1034 EscapeHTML( UnescapeString( via->GetNetname() ) ) );
1037 }
1038 }
1039 }
1040
1041 // Test copper zones to detect "dead" nets (nets without any pad):
1042 for( ZONE* zone : m_board->Zones() )
1043 {
1044 if( !zone->IsOnCopperLayer() || zone->GetIsRuleArea() )
1045 continue;
1046
1047 if( netlistNetnames.count( zone->GetNetname() ) == 0 )
1048 {
1049 // Look for a pad in the zone's connected-pad-cache which has been updated to
1050 // a new net and use that. While this won't always be the right net, the dead
1051 // net is guaranteed to be wrong.
1052 wxString updatedNetname = wxEmptyString;
1053
1054 for( PAD* pad : m_zoneConnectionsCache[ zone ] )
1055 {
1056 if( getNetname( pad ) != zone->GetNetname() )
1057 {
1058 updatedNetname = getNetname( pad );
1059 break;
1060 }
1061 }
1062
1063 // Take zone name from name change map if it didn't match to a new pad
1064 // (this is useful for zones on internal layers)
1065 if( updatedNetname.IsEmpty() && m_oldToNewNets.count( zone->GetNetname() ) )
1066 {
1067 updatedNetname = m_oldToNewNets[ zone->GetNetname() ];
1068 }
1069
1070 if( !updatedNetname.IsEmpty() )
1071 {
1072 if( m_isDryRun )
1073 {
1074 wxString originalNetname = zone->GetNetname();
1075
1076 if( !zone->GetZoneName().IsEmpty() )
1077 {
1078 msg.Printf( _( "Reconnect copper zone '%s' from %s to %s." ),
1079 zone->GetZoneName(),
1080 EscapeHTML( UnescapeString( originalNetname ) ),
1081 EscapeHTML( UnescapeString( updatedNetname ) ) );
1082 }
1083 else
1084 {
1085 msg.Printf( _( "Reconnect copper zone from %s to %s." ),
1086 EscapeHTML( UnescapeString( originalNetname ) ),
1087 EscapeHTML( UnescapeString( updatedNetname ) ) );
1088 }
1089
1091 }
1092 else
1093 {
1094 NETINFO_ITEM* netinfo = m_board->FindNet( updatedNetname );
1095
1096 if( !netinfo )
1097 netinfo = m_addedNets[ updatedNetname ];
1098
1099 if( netinfo )
1100 {
1101 wxString originalNetname = zone->GetNetname();
1102
1103 m_commit.Modify( zone );
1104 zone->SetNet( netinfo );
1105
1106 if( !zone->GetZoneName().IsEmpty() )
1107 {
1108 msg.Printf( _( "Reconnected copper zone '%s' from %s to %s." ),
1109 EscapeHTML( zone->GetZoneName() ),
1110 EscapeHTML( UnescapeString( originalNetname ) ),
1111 EscapeHTML( UnescapeString( updatedNetname ) ) );
1112 }
1113 else
1114 {
1115 msg.Printf( _( "Reconnected copper zone from %s to %s." ),
1116 EscapeHTML( UnescapeString( originalNetname ) ),
1117 EscapeHTML( UnescapeString( updatedNetname ) ) );
1118 }
1119
1121 }
1122 }
1123 }
1124 else
1125 {
1126 if( !zone->GetZoneName().IsEmpty() )
1127 {
1128 msg.Printf( _( "Copper zone '%s' has no pads connected." ),
1129 EscapeHTML( zone->GetZoneName() ) );
1130 }
1131 else
1132 {
1133 PCB_LAYER_ID layer = zone->GetLayer();
1134 VECTOR2I pos = zone->GetPosition();
1135
1137 {
1139 pos.x *= -1;
1140
1142 pos.y *= -1;
1143 }
1144
1145 msg.Printf( _( "Copper zone on layer %s at (%s, %s) has no pads connected." ),
1146 EscapeHTML( m_board->GetLayerName( layer ) ),
1148 m_frame->MessageTextFromValue( pos.y ) );
1149 }
1150
1153 }
1154 }
1155 }
1156
1157 return true;
1158}
1159
1160
1162 std::map<COMPONENT*, FOOTPRINT*>& aFootprintMap )
1163{
1164 // Verify that board contains all pads in netlist: if it doesn't then footprints are
1165 // wrong or missing.
1166
1167 wxString msg;
1168 wxString padNumber;
1169
1170 for( int i = 0; i < (int) aNetlist.GetCount(); i++ )
1171 {
1172 COMPONENT* component = aNetlist.GetComponent( i );
1173 FOOTPRINT* footprint = aFootprintMap[component];
1174
1175 if( !footprint ) // It can be missing in partial designs
1176 continue;
1177
1178 // Explore all pins/pads in component
1179 for( unsigned jj = 0; jj < component->GetNetCount(); jj++ )
1180 {
1181 padNumber = component->GetNet( jj ).GetPinName();
1182
1183 if( padNumber.IsEmpty() )
1184 {
1185 // bad symbol, report error
1186 msg.Printf( _( "Symbol %s has pins with no number. These pins can not be matched "
1187 "to pads in %s." ),
1188 component->GetReference(),
1189 EscapeHTML( footprint->GetFPID().Format().wx_str() ) );
1191 ++m_errorCount;
1192 }
1193 else if( !footprint->FindPadByNumber( padNumber ) )
1194 {
1195 // not found: bad footprint, report error
1196 msg.Printf( _( "%s pad %s not found in %s." ),
1197 component->GetReference(),
1198 EscapeHTML( padNumber ),
1199 EscapeHTML( footprint->GetFPID().Format().wx_str() ) );
1201 ++m_errorCount;
1202 }
1203 }
1204 }
1205
1206 return true;
1207}
1208
1209
1211{
1212 FOOTPRINT* lastPreexistingFootprint = nullptr;
1213 COMPONENT* component = nullptr;
1214 wxString msg;
1215
1216 m_errorCount = 0;
1217 m_warningCount = 0;
1219
1220 std::map<COMPONENT*, FOOTPRINT*> footprintMap;
1221
1222 if( !m_board->Footprints().empty() )
1223 lastPreexistingFootprint = m_board->Footprints().back();
1224
1226
1227 // First mark all nets (except <no net>) as stale; we'll update those which are current
1228 // in the following two loops. Also prepare the component class manager for updates.
1229 //
1230 if( !m_isDryRun )
1231 {
1232 for( NETINFO_ITEM* net : m_board->GetNetInfo() )
1233 net->SetIsCurrent( net->GetNetCode() == 0 );
1234
1236 }
1237
1238 // Next go through the netlist updating all board footprints which have matching component
1239 // entries and adding new footprints for those that don't.
1240 //
1241 for( unsigned i = 0; i < aNetlist.GetCount(); i++ )
1242 {
1243 component = aNetlist.GetComponent( i );
1244
1245 if( component->GetProperties().count( wxT( "exclude_from_board" ) ) )
1246 continue;
1247
1248 msg.Printf( _( "Processing symbol '%s:%s'." ),
1249 component->GetReference(),
1250 EscapeHTML( component->GetFPID().Format().wx_str() ) );
1252
1253 int matchCount = 0;
1254
1255 for( FOOTPRINT* footprint : m_board->Footprints() )
1256 {
1257 bool match = false;
1258
1260 {
1261 for( const KIID& uuid : component->GetKIIDs() )
1262 {
1263 KIID_PATH base = component->GetPath();
1264 base.push_back( uuid );
1265
1266 if( footprint->GetPath() == base )
1267 {
1268 match = true;
1269 break;
1270 }
1271 }
1272 }
1273 else
1274 {
1275 match = footprint->GetReference().CmpNoCase( component->GetReference() ) == 0;
1276 }
1277
1278 if( match )
1279 {
1280 FOOTPRINT* tmp = footprint;
1281
1282 if( m_replaceFootprints && component->GetFPID() != footprint->GetFPID() )
1283 tmp = replaceFootprint( aNetlist, footprint, component );
1284
1285 if( tmp )
1286 {
1287 footprintMap[ component ] = tmp;
1288
1289 updateFootprintParameters( tmp, component );
1290 updateComponentPadConnections( tmp, component );
1291 updateComponentClass( tmp, component );
1292 }
1293
1294 matchCount++;
1295 }
1296
1297 if( footprint == lastPreexistingFootprint )
1298 {
1299 // No sense going through the newly-created footprints: end of loop
1300 break;
1301 }
1302 }
1303
1304 if( matchCount == 0 )
1305 {
1306 FOOTPRINT* footprint = addNewFootprint( component );
1307
1308 if( footprint )
1309 {
1310 footprintMap[ component ] = footprint;
1311
1312 updateFootprintParameters( footprint, component );
1313 updateComponentPadConnections( footprint, component );
1314 updateComponentClass( footprint, component );
1315 }
1316 }
1317 else if( matchCount > 1 )
1318 {
1319 msg.Printf( _( "Multiple footprints found for %s." ),
1320 component->GetReference() );
1322 m_errorCount++;
1323 }
1324 }
1325
1326 updateCopperZoneNets( aNetlist );
1327
1328 // Finally go through the board footprints and update all those that *don't* have matching
1329 // component entries.
1330 //
1331 for( FOOTPRINT* footprint : m_board->Footprints() )
1332 {
1333 bool matched = false;
1334 bool doDelete = m_deleteUnusedFootprints;
1335
1336 if( ( footprint->GetAttributes() & FP_BOARD_ONLY ) > 0 )
1337 doDelete = false;
1338
1340 component = aNetlist.GetComponentByPath( footprint->GetPath() );
1341 else
1342 component = aNetlist.GetComponentByReference( footprint->GetReference() );
1343
1344 if( component && component->GetProperties().count( wxT( "exclude_from_board" ) ) == 0 )
1345 matched = true;
1346
1347 if( doDelete && !matched && footprint->IsLocked() && !m_overrideLocks )
1348 {
1349 if( m_isDryRun )
1350 {
1351 msg.Printf( _( "Cannot remove unused footprint %s (footprint is locked)." ),
1352 footprint->GetReference() );
1353 }
1354 else
1355 {
1356 msg.Printf( _( "Could not remove unused footprint %s (footprint is locked)." ),
1357 footprint->GetReference() );
1358 }
1359
1362 doDelete = false;
1363 }
1364
1365 if( doDelete && !matched )
1366 {
1367 if( m_isDryRun )
1368 {
1369 msg.Printf( _( "Remove unused footprint %s." ),
1370 footprint->GetReference() );
1371 }
1372 else
1373 {
1374 if( footprint->GetParentGroup() )
1375 m_commit.Stage( footprint, CHT_UNGROUP );
1376
1377 m_commit.Remove( footprint );
1378 msg.Printf( _( "Removed unused footprint %s." ),
1379 footprint->GetReference() );
1380 }
1381
1383 }
1384 else if( !m_isDryRun )
1385 {
1386 if( !matched )
1387 footprint->SetPath( KIID_PATH() );
1388
1389 for( PAD* pad : footprint->Pads() )
1390 {
1391 if( pad->GetNet() )
1392 pad->GetNet()->SetIsCurrent( true );
1393 }
1394 }
1395 }
1396
1397 if( !m_isDryRun )
1398 {
1399 // Finalise the component class manager
1401
1403 testConnectivity( aNetlist, footprintMap );
1404
1405 for( NETINFO_ITEM* net : m_board->GetNetInfo() )
1406 {
1407 if( !net->IsCurrent() )
1408 {
1409 msg.Printf( _( "Removed unused net %s." ),
1410 EscapeHTML( net->GetNetname() ) );
1412 }
1413 }
1414
1416
1417 // When new footprints are added, the automatic zone refill is disabled because:
1418 // * it creates crashes when calculating dynamic ratsnests if auto refill is enabled.
1419 // (the auto refills rebuild the connectivity with incomplete data)
1420 // * it is useless because zones will be refilled after placing new footprints
1421 m_commit.Push( _( "Update Netlist" ), m_newFootprintsCount ? ZONE_FILL_OP : 0 );
1422
1423 // Update net, netcode and netclass data after commiting the netlist
1425 m_board->GetConnectivity()->RefreshNetcodeMap( m_board );
1426
1427 // Although m_commit will probably also set this, it's not guaranteed, and we need to make
1428 // sure any modification to netclasses gets persisted to project settings through a save.
1429 m_frame->OnModify();
1430 }
1431
1432 if( m_isDryRun )
1433 {
1434 for( const std::pair<const wxString, NETINFO_ITEM*>& addedNet : m_addedNets )
1435 delete addedNet.second;
1436
1437 m_addedNets.clear();
1438 }
1439
1440 // Update the ratsnest
1443
1444 msg.Printf( _( "Total warnings: %d, errors: %d." ), m_warningCount, m_errorCount );
1446
1447 return true;
1448}
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:1922
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:2055
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:574
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:377
virtual void SetText(const wxString &aText)
Definition: eda_text.cpp:269
void SetPosition(const VECTOR2I &aPos) override
Definition: footprint.cpp:2388
int GetFieldCount() const
Return the number of fields in this symbol.
Definition: footprint.h:738
EDA_ANGLE GetOrientation() const
Definition: footprint.h:227
bool HasFieldByName(const wxString &aFieldName) const
Definition: footprint.cpp:578
void SetComponentClass(const COMPONENT_CLASS *aClass)
Definition: footprint.h:1015
PCB_FIELD * GetFieldByName(const wxString &aFieldName)
Return a field in this symbol.
Definition: footprint.cpp:589
PCB_FIELD * AddField(const PCB_FIELD &aField)
Add a field to the symbol.
Definition: footprint.cpp:637
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
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:2075
std::deque< PAD * > & Pads()
Definition: footprint.h:206
int GetAttributes() const
Definition: footprint.h:290
const COMPONENT_CLASS * GetComponentClass() const
Definition: footprint.h:1017
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:628
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:616
void SetValue(const wxString &aValue)
Definition: footprint.h:649
void RemoveField(const wxString &aFieldName)
Remove a user field from the footprint.
Definition: footprint.cpp:646
wxString GetFilters() const
Definition: footprint.h:272
void SetSheetname(const wxString &aSheetname)
Definition: footprint.h:267
const wxString & GetValue() const
Definition: footprint.h:644
const wxString & GetReference() const
Definition: footprint.h:622
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:1852
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:356
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:105
void StyleFromSettings(const BOARD_DESIGN_SETTINGS &settings) override
Definition: pcb_text.cpp:305
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:373
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