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 The 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( FIELD_T::REFERENCE ) );
471 compFields.erase( GetCanonicalFieldName( FIELD_T::VALUE ) );
472 compFields.erase( GetCanonicalFieldName( FIELD_T::FOOTPRINT ) );
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->IsMandatory() )
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->HasField( name ) )
524 {
525 aPcbFootprint->GetField( name )->SetText( value );
526 }
527 else
528 {
529 PCB_FIELD* newField = new PCB_FIELD( aPcbFootprint, FIELD_T::USER );
530 aPcbFootprint->Add( newField );
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->IsMandatory() )
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->Remove( field );
566
567 if( m_frame )
568 m_frame->GetCanvas()->GetView()->Remove( field );
569
570 delete field;
571 }
572 }
573 }
574 }
575
576 wxString sheetname;
577 wxString sheetfile;
578 wxString fpFilters;
579
580 wxString humanSheetPath = aNetlistComponent->GetHumanReadablePath();
581
582 if( !humanSheetPath.empty() )
583 sheetname = humanSheetPath;
584 else if( aNetlistComponent->GetProperties().count( wxT( "Sheetname" ) ) > 0 )
585 sheetname = aNetlistComponent->GetProperties().at( wxT( "Sheetname" ) );
586
587 if( aNetlistComponent->GetProperties().count( wxT( "Sheetfile" ) ) > 0 )
588 sheetfile = aNetlistComponent->GetProperties().at( wxT( "Sheetfile" ) );
589
590 if( aNetlistComponent->GetProperties().count( wxT( "ki_fp_filters" ) ) > 0 )
591 fpFilters = aNetlistComponent->GetProperties().at( wxT( "ki_fp_filters" ) );
592
593 if( sheetname != aPcbFootprint->GetSheetname() )
594 {
595 if( m_isDryRun )
596 {
597 msg.Printf( _( "Update %s sheetname to '%s'." ),
598 aPcbFootprint->GetReference(),
599 EscapeHTML( sheetname ) );
600 }
601 else
602 {
603 aPcbFootprint->SetSheetname( sheetname );
604 msg.Printf( _( "Updated %s sheetname to '%s'." ),
605 aPcbFootprint->GetReference(),
606 EscapeHTML( sheetname ) );
607 }
608
610 }
611
612 if( sheetfile != aPcbFootprint->GetSheetfile() )
613 {
614 if( m_isDryRun )
615 {
616 msg.Printf( _( "Update %s sheetfile to '%s'." ),
617 aPcbFootprint->GetReference(),
618 EscapeHTML( sheetfile ) );
619 }
620 else
621 {
622 aPcbFootprint->SetSheetfile( sheetfile );
623 msg.Printf( _( "Updated %s sheetfile to '%s'." ),
624 aPcbFootprint->GetReference(),
625 EscapeHTML( sheetfile ) );
626 }
627
629 }
630
631 if( fpFilters != aPcbFootprint->GetFilters() )
632 {
633 if( m_isDryRun )
634 {
635 msg.Printf( _( "Update %s footprint filters to '%s'." ),
636 aPcbFootprint->GetReference(),
637 EscapeHTML( fpFilters ) );
638 }
639 else
640 {
641 aPcbFootprint->SetFilters( fpFilters );
642 msg.Printf( _( "Updated %s footprint filters to '%s'." ),
643 aPcbFootprint->GetReference(),
644 EscapeHTML( fpFilters ) );
645 }
646
648 }
649
650 if( ( aNetlistComponent->GetProperties().count( wxT( "exclude_from_bom" ) ) > 0 )
651 != ( ( aPcbFootprint->GetAttributes() & FP_EXCLUDE_FROM_BOM ) > 0 ) )
652 {
653 if( m_isDryRun )
654 {
655 if( aNetlistComponent->GetProperties().count( wxT( "exclude_from_bom" ) ) )
656 {
657 msg.Printf( _( "Add %s 'exclude from BOM' fabrication attribute." ),
658 aPcbFootprint->GetReference() );
659 }
660 else
661 {
662 msg.Printf( _( "Remove %s 'exclude from BOM' fabrication attribute." ),
663 aPcbFootprint->GetReference() );
664 }
665 }
666 else
667 {
668 int attributes = aPcbFootprint->GetAttributes();
669
670 if( aNetlistComponent->GetProperties().count( wxT( "exclude_from_bom" ) ) )
671 {
672 attributes |= FP_EXCLUDE_FROM_BOM;
673 msg.Printf( _( "Added %s 'exclude from BOM' fabrication attribute." ),
674 aPcbFootprint->GetReference() );
675 }
676 else
677 {
678 attributes &= ~FP_EXCLUDE_FROM_BOM;
679 msg.Printf( _( "Removed %s 'exclude from BOM' fabrication attribute." ),
680 aPcbFootprint->GetReference() );
681 }
682
683 changed = true;
684 aPcbFootprint->SetAttributes( attributes );
685 }
686
688 }
689
690 if( ( aNetlistComponent->GetProperties().count( wxT( "dnp" ) ) > 0 )
691 != ( ( aPcbFootprint->GetAttributes() & FP_DNP ) > 0 ) )
692 {
693 if( m_isDryRun )
694 {
695 if( aNetlistComponent->GetProperties().count( wxT( "dnp" ) ) )
696 {
697 msg.Printf( _( "Add %s 'Do not place' fabrication attribute." ),
698 aPcbFootprint->GetReference() );
699 }
700 else
701 {
702 msg.Printf( _( "Remove %s 'Do not place' fabrication attribute." ),
703 aPcbFootprint->GetReference() );
704 }
705 }
706 else
707 {
708 int attributes = aPcbFootprint->GetAttributes();
709
710 if( aNetlistComponent->GetProperties().count( wxT( "dnp" ) ) )
711 {
712 attributes |= FP_DNP;
713 msg.Printf( _( "Added %s 'Do not place' fabrication attribute." ),
714 aPcbFootprint->GetReference() );
715 }
716 else
717 {
718 attributes &= ~FP_DNP;
719 msg.Printf( _( "Removed %s 'Do not place' fabrication attribute." ),
720 aPcbFootprint->GetReference() );
721 }
722
723 changed = true;
724 aPcbFootprint->SetAttributes( attributes );
725 }
726
728 }
729
730 if( changed && copy )
731 m_commit.Modified( aPcbFootprint, copy );
732 else if( copy )
733 delete copy;
734
735 return true;
736}
737
738
740 COMPONENT* aNewComponent )
741{
742 wxString msg;
743
744 // Create a copy only if the footprint has not been added during this update
745 FOOTPRINT* copy = nullptr;
746
747 if( !m_isDryRun && !m_commit.GetStatus( aFootprint ) )
748 {
749 copy = static_cast<FOOTPRINT*>( aFootprint->Clone() );
750 copy->SetParentGroup( nullptr );
751 }
752
753 bool changed = false;
754
755 // At this point, the component footprint is updated. Now update the nets.
756 std::deque<PAD*> pads = aFootprint->Pads();
757 std::set<wxString> padNetnames;
758
759 std::sort( pads.begin(), pads.end(),
760 []( PAD* a, PAD* b )
761 {
762 return a->m_Uuid < b->m_Uuid;
763 } );
764
765 for( PAD* pad : pads )
766 {
767 const COMPONENT_NET& net = aNewComponent->GetNet( pad->GetNumber() );
768
769 wxString pinFunction;
770 wxString pinType;
771
772 if( net.IsValid() ) // i.e. the pad has a name
773 {
774 pinFunction = net.GetPinFunction();
775 pinType = net.GetPinType();
776 }
777
778 if( !m_isDryRun )
779 {
780 if( pad->GetPinFunction() != pinFunction )
781 {
782 changed = true;
783 pad->SetPinFunction( pinFunction );
784 }
785
786 if( pad->GetPinType() != pinType )
787 {
788 changed = true;
789 pad->SetPinType( pinType );
790 }
791 }
792 else
793 {
794 cachePinFunction( pad, pinFunction );
795 }
796
797 // Test if new footprint pad has no net (pads not on copper layers have no net).
798 if( !net.IsValid() || !pad->IsOnCopperLayer() )
799 {
800 if( !pad->GetNetname().IsEmpty() )
801 {
802 if( m_isDryRun )
803 {
804 msg.Printf( _( "Disconnect %s pin %s." ),
805 aFootprint->GetReference(),
806 EscapeHTML( pad->GetNumber() ) );
807 }
808 else
809 {
810 msg.Printf( _( "Disconnected %s pin %s." ),
811 aFootprint->GetReference(),
812 EscapeHTML( pad->GetNumber() ) );
813 }
814
816 }
817 else if( pad->IsOnCopperLayer() && !pad->GetNumber().IsEmpty() )
818 {
819 // pad is connectable but has no net found in netlist
820 msg.Printf( _( "No net found for component %s pad %s (no pin %s in symbol)." ),
821 aFootprint->GetReference(),
822 EscapeHTML( pad->GetNumber() ),
823 EscapeHTML( pad->GetNumber() ) );
826 }
827
828 if( !m_isDryRun )
829 {
830 changed = true;
831 pad->SetNetCode( NETINFO_LIST::UNCONNECTED );
832
833 // If the pad has no net from netlist (i.e. not in netlist
834 // it cannot have a pin function
835 if( pad->GetNetname().IsEmpty() )
836 pad->SetPinFunction( wxEmptyString );
837
838 }
839 else
840 {
841 cacheNetname( pad, wxEmptyString );
842 }
843 }
844 else // New footprint pad has a net.
845 {
846 wxString netName = net.GetNetName();
847
848 if( pad->IsNoConnectPad() )
849 {
850 netName = wxString::Format( wxS( "%s" ),
851 EscapeHTML( net.GetNetName() ) );
852
853 for( int jj = 1; !padNetnames.insert( netName ).second; jj++ )
854 {
855 netName = wxString::Format( wxS( "%s_%d" ),
856 EscapeHTML( net.GetNetName() ), jj );
857 }
858 }
859
860 NETINFO_ITEM* netinfo = m_board->FindNet( netName );
861
862 if( netinfo && !m_isDryRun )
863 netinfo->SetIsCurrent( true );
864
865 if( pad->GetNetname() != netName )
866 {
867
868 if( netinfo == nullptr )
869 {
870 // It might be a new net that has not been added to the board yet
871 if( m_addedNets.count( netName ) )
872 netinfo = m_addedNets[ netName ];
873 }
874
875 if( netinfo == nullptr )
876 {
877 netinfo = new NETINFO_ITEM( m_board, netName );
878
879 // It is a new net, we have to add it
880 if( !m_isDryRun )
881 {
882 changed = true;
883 m_commit.Add( netinfo );
884 }
885
886 m_addedNets[netName] = netinfo;
887 msg.Printf( _( "Add net %s." ),
888 EscapeHTML( UnescapeString( netName ) ) );
890 }
891
892 if( !pad->GetNetname().IsEmpty() )
893 {
894 m_oldToNewNets[ pad->GetNetname() ] = netName;
895
896 if( m_isDryRun )
897 {
898 msg.Printf( _( "Reconnect %s pin %s from %s to %s."),
899 aFootprint->GetReference(),
900 EscapeHTML( pad->GetNumber() ),
901 EscapeHTML( UnescapeString( pad->GetNetname() ) ),
902 EscapeHTML( UnescapeString( netName ) ) );
903 }
904 else
905 {
906 msg.Printf( _( "Reconnected %s pin %s from %s to %s."),
907 aFootprint->GetReference(),
908 EscapeHTML( pad->GetNumber() ),
909 EscapeHTML( UnescapeString( pad->GetNetname() ) ),
910 EscapeHTML( UnescapeString( netName ) ) );
911 }
912 }
913 else
914 {
915 if( m_isDryRun )
916 {
917 msg.Printf( _( "Connect %s pin %s to %s."),
918 aFootprint->GetReference(),
919 EscapeHTML( pad->GetNumber() ),
920 EscapeHTML( UnescapeString( netName ) ) );
921 }
922 else
923 {
924 msg.Printf( _( "Connected %s pin %s to %s."),
925 aFootprint->GetReference(),
926 EscapeHTML( pad->GetNumber() ),
927 EscapeHTML( UnescapeString( netName ) ) );
928 }
929 }
930
932
933 if( !m_isDryRun )
934 {
935 changed = true;
936 pad->SetNet( netinfo );
937 }
938 else
939 {
940 cacheNetname( pad, netName );
941 }
942 }
943 }
944 }
945
946 if( changed && copy )
947 m_commit.Modified( aFootprint, copy );
948 else if( copy )
949 delete copy;
950
951 return true;
952}
953
954
956{
957 for( ZONE* zone : m_board->Zones() )
958 {
959 if( !zone->IsOnCopperLayer() || zone->GetIsRuleArea() )
960 continue;
961
962 m_zoneConnectionsCache[ zone ] = m_board->GetConnectivity()->GetConnectedPads( zone );
963 }
964}
965
966
968{
969 wxString msg;
970 std::set<wxString> netlistNetnames;
971
972 for( int ii = 0; ii < (int) aNetlist.GetCount(); ii++ )
973 {
974 const COMPONENT* component = aNetlist.GetComponent( ii );
975
976 for( unsigned jj = 0; jj < component->GetNetCount(); jj++ )
977 {
978 const COMPONENT_NET& net = component->GetNet( jj );
979 netlistNetnames.insert( net.GetNetName() );
980 }
981 }
982
983 for( PCB_TRACK* via : m_board->Tracks() )
984 {
985 if( via->Type() != PCB_VIA_T )
986 continue;
987
988 if( netlistNetnames.count( via->GetNetname() ) == 0 )
989 {
990 wxString updatedNetname = wxEmptyString;
991
992 // Take via name from name change map if it didn't match to a new pad
993 // (this is useful for stitching vias that don't connect to tracks)
994 if( m_oldToNewNets.count( via->GetNetname() ) )
995 {
996 updatedNetname = m_oldToNewNets[via->GetNetname()];
997 }
998
999 if( !updatedNetname.IsEmpty() )
1000 {
1001 if( m_isDryRun )
1002 {
1003 wxString originalNetname = via->GetNetname();
1004
1005 msg.Printf( _( "Reconnect via from %s to %s." ),
1006 EscapeHTML( UnescapeString( originalNetname ) ),
1007 EscapeHTML( UnescapeString( updatedNetname ) ) );
1008
1010 }
1011 else
1012 {
1013 NETINFO_ITEM* netinfo = m_board->FindNet( updatedNetname );
1014
1015 if( !netinfo )
1016 netinfo = m_addedNets[updatedNetname];
1017
1018 if( netinfo )
1019 {
1020 wxString originalNetname = via->GetNetname();
1021
1022 m_commit.Modify( via );
1023 via->SetNet( netinfo );
1024
1025 msg.Printf( _( "Reconnected via from %s to %s." ),
1026 EscapeHTML( UnescapeString( originalNetname ) ),
1027 EscapeHTML( UnescapeString( updatedNetname ) ) );
1028
1030 }
1031 }
1032 }
1033 else
1034 {
1035 msg.Printf( _( "Via connected to unknown net (%s)." ),
1036 EscapeHTML( UnescapeString( via->GetNetname() ) ) );
1039 }
1040 }
1041 }
1042
1043 // Test copper zones to detect "dead" nets (nets without any pad):
1044 for( ZONE* zone : m_board->Zones() )
1045 {
1046 if( !zone->IsOnCopperLayer() || zone->GetIsRuleArea() )
1047 continue;
1048
1049 if( netlistNetnames.count( zone->GetNetname() ) == 0 )
1050 {
1051 // Look for a pad in the zone's connected-pad-cache which has been updated to
1052 // a new net and use that. While this won't always be the right net, the dead
1053 // net is guaranteed to be wrong.
1054 wxString updatedNetname = wxEmptyString;
1055
1056 for( PAD* pad : m_zoneConnectionsCache[ zone ] )
1057 {
1058 if( getNetname( pad ) != zone->GetNetname() )
1059 {
1060 updatedNetname = getNetname( pad );
1061 break;
1062 }
1063 }
1064
1065 // Take zone name from name change map if it didn't match to a new pad
1066 // (this is useful for zones on internal layers)
1067 if( updatedNetname.IsEmpty() && m_oldToNewNets.count( zone->GetNetname() ) )
1068 {
1069 updatedNetname = m_oldToNewNets[ zone->GetNetname() ];
1070 }
1071
1072 if( !updatedNetname.IsEmpty() )
1073 {
1074 if( m_isDryRun )
1075 {
1076 wxString originalNetname = zone->GetNetname();
1077
1078 if( !zone->GetZoneName().IsEmpty() )
1079 {
1080 msg.Printf( _( "Reconnect copper zone '%s' from %s to %s." ),
1081 zone->GetZoneName(),
1082 EscapeHTML( UnescapeString( originalNetname ) ),
1083 EscapeHTML( UnescapeString( updatedNetname ) ) );
1084 }
1085 else
1086 {
1087 msg.Printf( _( "Reconnect copper zone from %s to %s." ),
1088 EscapeHTML( UnescapeString( originalNetname ) ),
1089 EscapeHTML( UnescapeString( updatedNetname ) ) );
1090 }
1091
1093 }
1094 else
1095 {
1096 NETINFO_ITEM* netinfo = m_board->FindNet( updatedNetname );
1097
1098 if( !netinfo )
1099 netinfo = m_addedNets[ updatedNetname ];
1100
1101 if( netinfo )
1102 {
1103 wxString originalNetname = zone->GetNetname();
1104
1105 m_commit.Modify( zone );
1106 zone->SetNet( netinfo );
1107
1108 if( !zone->GetZoneName().IsEmpty() )
1109 {
1110 msg.Printf( _( "Reconnected copper zone '%s' from %s to %s." ),
1111 EscapeHTML( zone->GetZoneName() ),
1112 EscapeHTML( UnescapeString( originalNetname ) ),
1113 EscapeHTML( UnescapeString( updatedNetname ) ) );
1114 }
1115 else
1116 {
1117 msg.Printf( _( "Reconnected copper zone from %s to %s." ),
1118 EscapeHTML( UnescapeString( originalNetname ) ),
1119 EscapeHTML( UnescapeString( updatedNetname ) ) );
1120 }
1121
1123 }
1124 }
1125 }
1126 else
1127 {
1128 if( !zone->GetZoneName().IsEmpty() )
1129 {
1130 msg.Printf( _( "Copper zone '%s' has no pads connected." ),
1131 EscapeHTML( zone->GetZoneName() ) );
1132 }
1133 else
1134 {
1135 PCB_LAYER_ID layer = zone->GetLayer();
1136 VECTOR2I pos = zone->GetPosition();
1137
1139 {
1141 pos.x *= -1;
1142
1144 pos.y *= -1;
1145 }
1146
1147 msg.Printf( _( "Copper zone on layer %s at (%s, %s) has no pads connected." ),
1148 EscapeHTML( m_board->GetLayerName( layer ) ),
1150 m_frame->MessageTextFromValue( pos.y ) );
1151 }
1152
1155 }
1156 }
1157 }
1158
1159 return true;
1160}
1161
1162
1164 std::map<COMPONENT*, FOOTPRINT*>& aFootprintMap )
1165{
1166 // Verify that board contains all pads in netlist: if it doesn't then footprints are
1167 // wrong or missing.
1168
1169 wxString msg;
1170 wxString padNumber;
1171
1172 for( int i = 0; i < (int) aNetlist.GetCount(); i++ )
1173 {
1174 COMPONENT* component = aNetlist.GetComponent( i );
1175 FOOTPRINT* footprint = aFootprintMap[component];
1176
1177 if( !footprint ) // It can be missing in partial designs
1178 continue;
1179
1180 // Explore all pins/pads in component
1181 for( unsigned jj = 0; jj < component->GetNetCount(); jj++ )
1182 {
1183 padNumber = component->GetNet( jj ).GetPinName();
1184
1185 if( padNumber.IsEmpty() )
1186 {
1187 // bad symbol, report error
1188 msg.Printf( _( "Symbol %s has pins with no number. These pins can not be matched "
1189 "to pads in %s." ),
1190 component->GetReference(),
1191 EscapeHTML( footprint->GetFPID().Format().wx_str() ) );
1193 ++m_errorCount;
1194 }
1195 else if( !footprint->FindPadByNumber( padNumber ) )
1196 {
1197 // not found: bad footprint, report error
1198 msg.Printf( _( "%s pad %s not found in %s." ),
1199 component->GetReference(),
1200 EscapeHTML( padNumber ),
1201 EscapeHTML( footprint->GetFPID().Format().wx_str() ) );
1203 ++m_errorCount;
1204 }
1205 }
1206 }
1207
1208 return true;
1209}
1210
1211
1213{
1214 FOOTPRINT* lastPreexistingFootprint = nullptr;
1215 COMPONENT* component = nullptr;
1216 wxString msg;
1217
1218 m_errorCount = 0;
1219 m_warningCount = 0;
1221
1222 std::map<COMPONENT*, FOOTPRINT*> footprintMap;
1223
1224 if( !m_board->Footprints().empty() )
1225 lastPreexistingFootprint = m_board->Footprints().back();
1226
1228
1229 // First mark all nets (except <no net>) as stale; we'll update those which are current
1230 // in the following two loops. Also prepare the component class manager for updates.
1231 //
1232 if( !m_isDryRun )
1233 {
1234 for( NETINFO_ITEM* net : m_board->GetNetInfo() )
1235 net->SetIsCurrent( net->GetNetCode() == 0 );
1236
1238 }
1239
1240 // Next go through the netlist updating all board footprints which have matching component
1241 // entries and adding new footprints for those that don't.
1242 //
1243 for( unsigned i = 0; i < aNetlist.GetCount(); i++ )
1244 {
1245 component = aNetlist.GetComponent( i );
1246
1247 if( component->GetProperties().count( wxT( "exclude_from_board" ) ) )
1248 continue;
1249
1250 msg.Printf( _( "Processing symbol '%s:%s'." ),
1251 component->GetReference(),
1252 EscapeHTML( component->GetFPID().Format().wx_str() ) );
1254
1255 int matchCount = 0;
1256
1257 for( FOOTPRINT* footprint : m_board->Footprints() )
1258 {
1259 bool match = false;
1260
1262 {
1263 for( const KIID& uuid : component->GetKIIDs() )
1264 {
1265 KIID_PATH base = component->GetPath();
1266 base.push_back( uuid );
1267
1268 if( footprint->GetPath() == base )
1269 {
1270 match = true;
1271 break;
1272 }
1273 }
1274 }
1275 else
1276 {
1277 match = footprint->GetReference().CmpNoCase( component->GetReference() ) == 0;
1278 }
1279
1280 if( match )
1281 {
1282 FOOTPRINT* tmp = footprint;
1283
1284 if( m_replaceFootprints && component->GetFPID() != footprint->GetFPID() )
1285 tmp = replaceFootprint( aNetlist, footprint, component );
1286
1287 if( !tmp )
1288 tmp = footprint;
1289
1290 if( tmp )
1291 {
1292 footprintMap[ component ] = tmp;
1293
1294 updateFootprintParameters( tmp, component );
1295 updateComponentPadConnections( tmp, component );
1296 updateComponentClass( tmp, component );
1297 }
1298
1299 matchCount++;
1300 }
1301
1302 if( footprint == lastPreexistingFootprint )
1303 {
1304 // No sense going through the newly-created footprints: end of loop
1305 break;
1306 }
1307 }
1308
1309 if( matchCount == 0 )
1310 {
1311 FOOTPRINT* footprint = addNewFootprint( component );
1312
1313 if( footprint )
1314 {
1315 footprintMap[ component ] = footprint;
1316
1317 updateFootprintParameters( footprint, component );
1318 updateComponentPadConnections( footprint, component );
1319 updateComponentClass( footprint, component );
1320 }
1321 }
1322 else if( matchCount > 1 )
1323 {
1324 msg.Printf( _( "Multiple footprints found for %s." ),
1325 component->GetReference() );
1327 m_errorCount++;
1328 }
1329 }
1330
1331 updateCopperZoneNets( aNetlist );
1332
1333 // Finally go through the board footprints and update all those that *don't* have matching
1334 // component entries.
1335 //
1336 for( FOOTPRINT* footprint : m_board->Footprints() )
1337 {
1338 bool matched = false;
1339 bool doDelete = m_deleteUnusedFootprints;
1340
1341 if( ( footprint->GetAttributes() & FP_BOARD_ONLY ) > 0 )
1342 doDelete = false;
1343
1345 component = aNetlist.GetComponentByPath( footprint->GetPath() );
1346 else
1347 component = aNetlist.GetComponentByReference( footprint->GetReference() );
1348
1349 if( component && component->GetProperties().count( wxT( "exclude_from_board" ) ) == 0 )
1350 matched = true;
1351
1352 if( doDelete && !matched && footprint->IsLocked() && !m_overrideLocks )
1353 {
1354 if( m_isDryRun )
1355 {
1356 msg.Printf( _( "Cannot remove unused footprint %s (footprint is locked)." ),
1357 footprint->GetReference() );
1358 }
1359 else
1360 {
1361 msg.Printf( _( "Could not remove unused footprint %s (footprint is locked)." ),
1362 footprint->GetReference() );
1363 }
1364
1367 doDelete = false;
1368 }
1369
1370 if( doDelete && !matched )
1371 {
1372 if( m_isDryRun )
1373 {
1374 msg.Printf( _( "Remove unused footprint %s." ),
1375 footprint->GetReference() );
1376 }
1377 else
1378 {
1379 if( footprint->GetParentGroup() )
1380 m_commit.Stage( footprint, CHT_UNGROUP );
1381
1382 m_commit.Remove( footprint );
1383 msg.Printf( _( "Removed unused footprint %s." ),
1384 footprint->GetReference() );
1385 }
1386
1388 }
1389 else if( !m_isDryRun )
1390 {
1391 if( !matched )
1392 footprint->SetPath( KIID_PATH() );
1393
1394 for( PAD* pad : footprint->Pads() )
1395 {
1396 if( pad->GetNet() )
1397 pad->GetNet()->SetIsCurrent( true );
1398 }
1399 }
1400 }
1401
1402 if( !m_isDryRun )
1403 {
1404 // Finalise the component class manager
1406
1408 testConnectivity( aNetlist, footprintMap );
1409
1410 for( NETINFO_ITEM* net : m_board->GetNetInfo() )
1411 {
1412 if( !net->IsCurrent() )
1413 {
1414 msg.Printf( _( "Removed unused net %s." ),
1415 EscapeHTML( net->GetNetname() ) );
1417 }
1418 }
1419
1421
1422 // When new footprints are added, the automatic zone refill is disabled because:
1423 // * it creates crashes when calculating dynamic ratsnests if auto refill is enabled.
1424 // (the auto refills rebuild the connectivity with incomplete data)
1425 // * it is useless because zones will be refilled after placing new footprints
1426 m_commit.Push( _( "Update Netlist" ), m_newFootprintsCount ? ZONE_FILL_OP : 0 );
1427
1428 // Update net, netcode and netclass data after commiting the netlist
1430 m_board->GetConnectivity()->RefreshNetcodeMap( m_board );
1431
1432 // Although m_commit will probably also set this, it's not guaranteed, and we need to make
1433 // sure any modification to netclasses gets persisted to project settings through a save.
1434 m_frame->OnModify();
1435 }
1436
1437 if( m_isDryRun )
1438 {
1439 for( const std::pair<const wxString, NETINFO_ITEM*>& addedNet : m_addedNets )
1440 delete addedNet.second;
1441
1442 m_addedNets.clear();
1443 }
1444
1445 // Update the ratsnest
1448
1449 msg.Printf( _( "Total warnings: %d, errors: %d." ), m_warningCount, m_errorCount );
1451
1452 return true;
1453}
const char * name
Definition: DXF_plotter.cpp:59
constexpr EDA_IU_SCALE pcbIUScale
Definition: base_units.h:108
#define ZONE_FILL_OP
Definition: board_commit.h:45
virtual void Push(const wxString &aMessage=wxEmptyString, int aCommitFlags=0) override
Execute the changes.
COMMIT & Stage(EDA_ITEM *aItem, CHANGE_TYPE aChangeType, BASE_SCREEN *aScreen=nullptr) override
Add a change of the item aItem of type aChangeType to the change list.
virtual void SetLayer(PCB_LAYER_ID aLayer)
Set the layer this item is on.
Definition: board_item.h:290
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:296
const NETINFO_LIST & GetNetInfo() const
Definition: board.h:894
const BOX2I GetBoardEdgesBoundingBox() const
Return the board bounding box calculated using exclusively the board edges (graphics on Edge....
Definition: board.h:952
const PAGE_INFO & GetPageSettings() const
Definition: board.h:712
NETINFO_ITEM * FindNet(int aNetcode) const
Search for a net with the given netcode.
Definition: board.cpp:2005
const ZONES & Zones() const
Definition: board.h:341
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:190
void SynchronizeNetsAndNetClasses(bool aResetTrackAndViaSizes)
Copy NETCLASS info to each NET, based on NET membership in a NETCLASS.
Definition: board.cpp:2138
void RemoveUnusedNets(BOARD_COMMIT *aCommit)
Definition: board.h:899
const FOOTPRINTS & Footprints() const
Definition: board.h:337
const TRACKS & Tracks() const
Definition: board.h:335
const wxString GetLayerName(PCB_LAYER_ID aLayer) const
Return the name of a aLayer.
Definition: board.cpp:616
bool IsEmpty() const
Definition: board.h:392
COMPONENT_CLASS_MANAGER & GetComponentClassManager()
Gets the component class manager.
Definition: board.h:1303
std::shared_ptr< CONNECTIVITY_DATA > GetConnectivity() const
Return a list of missing connections between components/tracks.
Definition: board.h:495
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)
Remove a new item from the model.
Definition: commit.h:92
COMMIT & Modify(EDA_ITEM *aItem, BASE_SCREEN *aScreen=nullptr)
Modify a given item in the model.
Definition: commit.h:108
COMMIT & Modified(EDA_ITEM *aItem, EDA_ITEM *aCopy, BASE_SCREEN *aScreen=nullptr)
Create an undo entry for an item that has been already modified.
Definition: commit.h:118
COMMIT & Add(EDA_ITEM *aItem, BASE_SCREEN *aScreen=nullptr)
Add a new item to the model.
Definition: commit.h:80
int GetStatus(EDA_ITEM *aItem, BASE_SCREEN *aScreen=nullptr)
Returns status of an item.
Definition: commit.cpp:130
COMPONENT_CLASS * GetEffectiveComponentClass(const std::unordered_set< wxString > &classNames)
Gets an effective component class for the given constituent class names.
static wxString GetFullClassNameForConstituents(const std::unordered_set< wxString > &classNames)
Gets the full effective class name for the given set of constituent classes.
void FinishNetlistUpdate()
Cleans up the manager after a board update Must be called after updating the PCB from the netlist.
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.
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:379
virtual void SetText(const wxString &aText)
Definition: eda_text.cpp:270
void SetPosition(const VECTOR2I &aPos) override
Definition: footprint.cpp:2459
EDA_ANGLE GetOrientation() const
Definition: footprint.h:226
void SetComponentClass(const COMPONENT_CLASS *aClass)
Sets the component class object pointer for this footprint.
Definition: footprint.h:984
void Remove(BOARD_ITEM *aItem, REMOVE_MODE aMode=REMOVE_MODE::NORMAL) override
Removes an item from the container.
Definition: footprint.cpp:1103
wxString GetSheetname() const
Definition: footprint.h:265
void SetPath(const KIID_PATH &aPath)
Definition: footprint.h:263
void SetFilters(const wxString &aFilters)
Definition: footprint.h:272
void SetAttributes(int aAttributes)
Definition: footprint.h:290
void SetSheetfile(const wxString &aSheetfile)
Definition: footprint.h:269
EDA_ITEM * Clone() const override
Invoke a function on all children.
Definition: footprint.cpp:2149
bool HasField(const wxString &aFieldName) const
Definition: footprint.cpp:607
PCB_FIELD * GetField(FIELD_T aFieldType)
Return a mandatory field in this footprint.
Definition: footprint.cpp:580
std::deque< PAD * > & Pads()
Definition: footprint.h:205
int GetAttributes() const
Definition: footprint.h:289
const COMPONENT_CLASS * GetComponentClass() const
Returns the component class for this footprint.
Definition: footprint.h:1011
PCB_LAYER_ID GetLayer() const override
Return the primary layer this item is on.
Definition: footprint.h:235
wxString GetSheetfile() const
Definition: footprint.h:268
const LIB_ID & GetFPID() const
Definition: footprint.h:247
void SetReference(const wxString &aReference)
Definition: footprint.h:627
bool IsLocked() const override
Definition: footprint.h:410
void SetValue(const wxString &aValue)
Definition: footprint.h:648
void Add(BOARD_ITEM *aItem, ADD_MODE aMode=ADD_MODE::INSERT, bool aSkipConnectivity=false) override
Removes an item from the container.
Definition: footprint.cpp:1046
wxString GetFilters() const
Definition: footprint.h:271
void SetSheetname(const wxString &aSheetname)
Definition: footprint.h:266
void GetFields(std::vector< PCB_FIELD * > &aVector, bool aVisibleOnly) const
Populate a std::vector with PCB_TEXTs.
Definition: footprint.cpp:625
const wxString & GetValue() const
Definition: footprint.h:643
const wxString & GetReference() const
Definition: footprint.h:621
const KIID_PATH & GetPath() const
Definition: footprint.h:262
VECTOR2I GetPosition() const override
Definition: footprint.h:223
PAD * FindPadByNumber(const wxString &aPadNumber, PAD *aSearchAfterMe=nullptr) const
Return a PAD with a matching number.
Definition: footprint.cpp:1926
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:118
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
Return 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:106
void StyleFromSettings(const BOARD_DESIGN_SETTINGS &settings) override
Definition: pcb_text.cpp:300
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:370
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:101
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:74
@ CHT_UNGROUP
Definition: commit.h:46
The common library.
#define _(s)
@ FP_DNP
Definition: footprint.h:87
@ FP_BOARD_ONLY
Definition: footprint.h:83
@ FP_EXCLUDE_FROM_BOM
Definition: footprint.h:82
@ FP_JUST_ADDED
Definition: footprint.h:84
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(FIELD_T aFieldType)
@ PCB_VIA_T
class PCB_VIA, a via (like a track segment on a copper layer)
Definition: typeinfo.h:97