KiCad PCB EDA Suite
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages Concepts
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 <dick@softplc.com>
7 * Copyright (C) 2011 Wayne Stambaugh <stambaughw@gmail.com>
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>
36#include <netinfo.h>
37#include <footprint.h>
38#include <pad.h>
39#include <pcb_track.h>
40#include <zone.h>
41#include <string_utils.h>
42#include <pcbnew_settings.h>
43#include <pcb_edit_frame.h>
46#include <reporter.h>
47
49
50
52 m_frame( aFrame ),
53 m_commit( aFrame ),
54 m_board( aBoard )
55{
57
59 m_isDryRun = false;
61 m_lookupByTimestamp = false;
62 m_overrideLocks = false;
63
65 m_errorCount = 0;
67}
68
69
71{
72}
73
74
75// These functions allow inspection of pad nets during dry runs by keeping a cache of
76// current pad netnames indexed by pad.
77
78void BOARD_NETLIST_UPDATER::cacheNetname( PAD* aPad, const wxString& aNetname )
79{
80 m_padNets[ aPad ] = aNetname;
81}
82
83
85{
86 if( m_isDryRun && m_padNets.count( aPad ) )
87 return m_padNets[ aPad ];
88 else
89 return aPad->GetNetname();
90}
91
92
93void BOARD_NETLIST_UPDATER::cachePinFunction( PAD* aPad, const wxString& aPinFunction )
94{
95 m_padPinFunctions[ aPad ] = aPinFunction;
96}
97
98
100{
101 if( m_isDryRun && m_padPinFunctions.count( aPad ) )
102 return m_padPinFunctions[ aPad ];
103 else
104 return aPad->GetPinFunction();
105}
106
107
109{
110 VECTOR2I bestPosition;
111
112 if( !m_board->IsEmpty() )
113 {
114 // Position new components below any existing board features.
116
117 if( bbox.GetWidth() || bbox.GetHeight() )
118 {
119 bestPosition.x = bbox.Centre().x;
120 bestPosition.y = bbox.GetBottom() + pcbIUScale.mmToIU( 10 );
121 }
122 }
123 else
124 {
125 // Position new components in the center of the page when the board is empty.
127
128 bestPosition.x = pageSize.x / 2;
129 bestPosition.y = pageSize.y / 2;
130 }
131
132 return bestPosition;
133}
134
135
137{
138 wxString msg;
139
140 if( aComponent->GetFPID().empty() )
141 {
142 msg.Printf( _( "Cannot add %s (no footprint assigned)." ),
143 aComponent->GetReference() );
145 ++m_errorCount;
146 return nullptr;
147 }
148
149 FOOTPRINT* footprint = m_frame->LoadFootprint( aComponent->GetFPID() );
150
151 if( footprint == nullptr )
152 {
153 msg.Printf( _( "Cannot add %s (footprint '%s' not found)." ),
154 aComponent->GetReference(),
155 EscapeHTML( aComponent->GetFPID().Format().wx_str() ) );
157 ++m_errorCount;
158 return nullptr;
159 }
160
161 footprint->SetStaticComponentClass(
163
164 if( m_isDryRun )
165 {
166 msg.Printf( _( "Add %s (footprint '%s')." ),
167 aComponent->GetReference(),
168 EscapeHTML( aComponent->GetFPID().Format().wx_str() ) );
169
170 delete footprint;
171 footprint = nullptr;
172 }
173 else
174 {
175 for( PAD* pad : footprint->Pads() )
176 {
177 // Set the pads ratsnest settings to the global settings
178 pad->SetLocalRatsnestVisible( m_frame->GetPcbNewSettings()->m_Display.m_ShowGlobalRatsnest );
179
180 // Pads in the library all have orphaned nets. Replace with Default.
181 pad->SetNetCode( 0 );
182 }
183
184 footprint->SetParent( m_board );
186
187 // This flag is used to prevent connectivity from considering the footprint during its
188 // initial build after the footprint is committed, because we're going to immediately start
189 // a move operation on the footprint and don't want its pads to drive nets onto vias/tracks
190 // it happens to land on at the initial position.
191 footprint->SetAttributes( footprint->GetAttributes() | FP_JUST_ADDED );
192
193 m_addedFootprints.push_back( footprint );
194 m_commit.Add( footprint );
195
196 msg.Printf( _( "Added %s (footprint '%s')." ),
197 aComponent->GetReference(),
198 EscapeHTML( aComponent->GetFPID().Format().wx_str() ) );
199 }
200
203 return footprint;
204}
205
206
208{
209 wxString curClassName, newClassName;
210 COMPONENT_CLASS* newClass = nullptr;
211
212 if( const COMPONENT_CLASS* curClass = aFootprint->GetStaticComponentClass() )
213 curClassName = curClass->GetName();
214
215 // Calculate the new component class
216 if( m_isDryRun )
217 {
219 aNewComponent->GetComponentClassNames() );
220 }
221 else
222 {
224 aNewComponent->GetComponentClassNames() );
225 newClassName = newClass->GetName();
226 }
227
228 if( curClassName == newClassName )
229 return;
230
231 wxString msg;
232
233 if( m_isDryRun )
234 {
235 if( curClassName == wxEmptyString && newClassName != wxEmptyString )
236 {
237 msg.Printf( _( "Change %s component class to '%s'." ),
238 aFootprint->GetReference(),
239 EscapeHTML( newClassName ) );
240 }
241 else if( curClassName != wxEmptyString && newClassName == wxEmptyString )
242 {
243 msg.Printf( _( "Remove %s component class (currently '%s')." ),
244 aFootprint->GetReference(),
245 EscapeHTML( curClassName ) );
246 }
247 else
248 {
249 msg.Printf( _( "Change %s component class from '%s' to '%s'." ),
250 aFootprint->GetReference(),
251 EscapeHTML( curClassName ),
252 EscapeHTML( newClassName ) );
253 }
254 }
255 else
256 {
257 wxASSERT_MSG( newClass != nullptr, "Component class should not be nullptr" );
258
259 aFootprint->SetStaticComponentClass( newClass );
260
261 if( curClassName == wxEmptyString && newClassName != wxEmptyString )
262 {
263 msg.Printf( _( "Changed %s component class to '%s'." ),
264 aFootprint->GetReference(),
265 EscapeHTML( newClassName ) );
266 }
267 else if( curClassName != wxEmptyString && newClassName == wxEmptyString )
268 {
269 msg.Printf( _( "Removed %s component class (was '%s')." ),
270 aFootprint->GetReference(),
271 EscapeHTML( curClassName ) );
272 }
273 else
274 {
275 msg.Printf( _( "Changed %s component class from '%s' to '%s'." ),
276 aFootprint->GetReference(),
277 EscapeHTML( curClassName ),
278 EscapeHTML( newClassName ) );
279 }
280 }
281
283}
284
285
287 COMPONENT* aNewComponent )
288{
289 wxString msg;
290
291 if( aNewComponent->GetFPID().empty() )
292 {
293 msg.Printf( _( "Cannot update %s (no footprint assigned)." ),
294 aNewComponent->GetReference() );
296 ++m_errorCount;
297 return nullptr;
298 }
299
300 FOOTPRINT* newFootprint = m_frame->LoadFootprint( aNewComponent->GetFPID() );
301
302 if( newFootprint == nullptr )
303 {
304 msg.Printf( _( "Cannot update %s (footprint '%s' not found)." ),
305 aNewComponent->GetReference(),
306 EscapeHTML( aNewComponent->GetFPID().Format().wx_str() ) );
308 ++m_errorCount;
309 return nullptr;
310 }
311
312 if( m_isDryRun )
313 {
314 if( aFootprint->IsLocked() && !m_overrideLocks )
315 {
316 msg.Printf( _( "Cannot change %s footprint from '%s' to '%s' (footprint is locked)."),
317 aFootprint->GetReference(),
318 EscapeHTML( aFootprint->GetFPID().Format().wx_str() ),
319 EscapeHTML( aNewComponent->GetFPID().Format().wx_str() ) );
322 delete newFootprint;
323 return nullptr;
324 }
325 else
326 {
327 msg.Printf( _( "Change %s footprint from '%s' to '%s'."),
328 aFootprint->GetReference(),
329 EscapeHTML( aFootprint->GetFPID().Format().wx_str() ),
330 EscapeHTML( aNewComponent->GetFPID().Format().wx_str() ) );
333 delete newFootprint;
334 return nullptr;
335 }
336 }
337 else
338 {
339 if( aFootprint->IsLocked() && !m_overrideLocks )
340 {
341 msg.Printf( _( "Could not change %s footprint from '%s' to '%s' (footprint is locked)."),
342 aFootprint->GetReference(),
343 EscapeHTML( aFootprint->GetFPID().Format().wx_str() ),
344 EscapeHTML( aNewComponent->GetFPID().Format().wx_str() ) );
347 delete newFootprint;
348 return nullptr;
349 }
350 else
351 {
352 m_frame->ExchangeFootprint( aFootprint, newFootprint, m_commit );
353
354 msg.Printf( _( "Changed %s footprint from '%s' to '%s'."),
355 aFootprint->GetReference(),
356 EscapeHTML( aFootprint->GetFPID().Format().wx_str() ),
357 EscapeHTML( aNewComponent->GetFPID().Format().wx_str() ) );
360 return newFootprint;
361 }
362 }
363}
364
365
367 COMPONENT* aNetlistComponent )
368{
369 wxString msg;
370
371 // Create a copy only if the footprint has not been added during this update
372 FOOTPRINT* copy = nullptr;
373
374 if( !m_commit.GetStatus( aPcbFootprint ) )
375 {
376 copy = static_cast<FOOTPRINT*>( aPcbFootprint->Clone() );
377 copy->SetParentGroup( nullptr );
378 }
379
380 bool changed = false;
381
382 // Test for reference designator field change.
383 if( aPcbFootprint->GetReference() != aNetlistComponent->GetReference() )
384 {
385 if( m_isDryRun )
386 {
387 msg.Printf( _( "Change %s reference designator to %s." ),
388 aPcbFootprint->GetReference(),
389 aNetlistComponent->GetReference() );
390 }
391 else
392 {
393 msg.Printf( _( "Changed %s reference designator to %s." ),
394 aPcbFootprint->GetReference(),
395 aNetlistComponent->GetReference() );
396
397 changed = true;
398 aPcbFootprint->SetReference( aNetlistComponent->GetReference() );
399 }
400
402 }
403
404 // Test for value field change.
405 if( aPcbFootprint->GetValue() != aNetlistComponent->GetValue() )
406 {
407 if( m_isDryRun )
408 {
409 msg.Printf( _( "Change %s value from %s to %s." ),
410 aPcbFootprint->GetReference(),
411 EscapeHTML( aPcbFootprint->GetValue() ),
412 EscapeHTML( aNetlistComponent->GetValue() ) );
413 }
414 else
415 {
416 msg.Printf( _( "Changed %s value from %s to %s." ),
417 aPcbFootprint->GetReference(),
418 EscapeHTML( aPcbFootprint->GetValue() ),
419 EscapeHTML( aNetlistComponent->GetValue() ) );
420
421 changed = true;
422 aPcbFootprint->SetValue( aNetlistComponent->GetValue() );
423 }
424
426 }
427
428 // Test for time stamp change.
429 KIID_PATH new_path = aNetlistComponent->GetPath();
430
431 if( !aNetlistComponent->GetKIIDs().empty() )
432 new_path.push_back( aNetlistComponent->GetKIIDs().front() );
433
434 if( aPcbFootprint->GetPath() != new_path )
435 {
436 if( m_isDryRun )
437 {
438 msg.Printf( _( "Update %s symbol association from %s to %s." ),
439 aPcbFootprint->GetReference(),
440 EscapeHTML( aPcbFootprint->GetPath().AsString() ),
441 EscapeHTML( new_path.AsString() ) );
442 }
443 else
444 {
445 msg.Printf( _( "Updated %s symbol association from %s to %s." ),
446 aPcbFootprint->GetReference(),
447 EscapeHTML( aPcbFootprint->GetPath().AsString() ),
448 EscapeHTML( new_path.AsString() ) );
449
450 changed = true;
451 aPcbFootprint->SetPath( new_path );
452 }
453
455 }
456
457 nlohmann::ordered_map<wxString, wxString> fpFieldsAsMap;
458
459 for( PCB_FIELD* field : aPcbFootprint->GetFields() )
460 {
461 // These fields are individually checked above
462 if( field->IsReference() || field->IsValue() || field->IsComponentClass() )
463 {
464 continue;
465 }
466
467 fpFieldsAsMap[field->GetName()] = field->GetText();
468 }
469
470 // Remove the ref/value/footprint fields that are individually handled
471 nlohmann::ordered_map<wxString, wxString> compFields = aNetlistComponent->GetFields();
472 compFields.erase( GetCanonicalFieldName( FIELD_T::REFERENCE ) );
473 compFields.erase( GetCanonicalFieldName( FIELD_T::VALUE ) );
474 compFields.erase( GetCanonicalFieldName( FIELD_T::FOOTPRINT ) );
475
476 // Remove any component class fields - these are not editable in the pcb editor
477 compFields.erase( wxT( "Component Class" ) );
478
479 // Fields are stored as an ordered map, but we don't (yet) support reordering
480 // the footprint fields to match the symbol, so we manually check the fields
481 // in the order they are stored in the symbol.
482 bool same = true;
483
484 for( const auto& [name, value] : compFields )
485 {
486 if( fpFieldsAsMap.count( name ) == 0 || fpFieldsAsMap[name] != value )
487 {
488 same = false;
489 break;
490 }
491 }
492
493 for( const auto& [name, value] : fpFieldsAsMap )
494 {
495 if( compFields.count( name ) == 0 )
496 {
497 same = false;
498 break;
499 }
500 }
501
502 if( !same )
503 {
504 if( m_isDryRun )
505 {
506 msg.Printf( _( "Update %s fields." ), aPcbFootprint->GetReference() );
508
509 // Remove fields that aren't present in the symbol
510 for( PCB_FIELD* field : aPcbFootprint->GetFields() )
511 {
512 if( field->IsMandatory() )
513 continue;
514
515 if( compFields.count( field->GetName() ) == 0 )
516 {
517 msg.Printf( _( "Remove %s footprint fields not in symbol." ),
518 aPcbFootprint->GetReference() );
520 break;
521 }
522 }
523 }
524 else
525 {
526 msg.Printf( _( "Updated %s fields." ), aPcbFootprint->GetReference() );
528
529 changed = true;
530
531 // Add or change field value
532 for( auto& [name, value] : compFields )
533 {
534 if( aPcbFootprint->HasField( name ) )
535 {
536 aPcbFootprint->GetField( name )->SetText( value );
537 }
538 else
539 {
540 PCB_FIELD* newField = new PCB_FIELD( aPcbFootprint, FIELD_T::USER );
541 aPcbFootprint->Add( newField );
542
543 newField->SetName( name );
544 newField->SetText( value );
545 newField->SetVisible( false );
546 newField->SetLayer( aPcbFootprint->GetLayer() == F_Cu ? F_Fab : B_Fab );
547
548 // Give the relative position (0,0) in footprint
549 newField->SetPosition( aPcbFootprint->GetPosition() );
550 // Give the footprint orientation
551 newField->Rotate( aPcbFootprint->GetPosition(), aPcbFootprint->GetOrientation() );
552
553 if( m_frame )
555 }
556 }
557
558 // Remove and delete fields that aren't present in the symbol
559 bool warned = false;
560
561 std::vector<PCB_FIELD*> fieldList;
562 aPcbFootprint->GetFields( fieldList, false );
563
564 for( PCB_FIELD* field : fieldList )
565 {
566 if( field->IsMandatory() )
567 continue;
568
569 if( compFields.count( field->GetName() ) == 0 )
570 {
571 if( !warned )
572 {
573 warned = true;
574 msg.Printf( _( "Removed %s footprint fields not in symbol." ),
575 aPcbFootprint->GetReference() );
577 }
578
579 aPcbFootprint->Remove( field );
580
581 if( m_frame )
582 m_frame->GetCanvas()->GetView()->Remove( field );
583
584 delete field;
585 }
586 }
587 }
588 }
589
590 wxString sheetname;
591 wxString sheetfile;
592 wxString fpFilters;
593
594 wxString humanSheetPath = aNetlistComponent->GetHumanReadablePath();
595
596 if( !humanSheetPath.empty() )
597 sheetname = humanSheetPath;
598 else if( aNetlistComponent->GetProperties().count( wxT( "Sheetname" ) ) > 0 )
599 sheetname = aNetlistComponent->GetProperties().at( wxT( "Sheetname" ) );
600
601 if( aNetlistComponent->GetProperties().count( wxT( "Sheetfile" ) ) > 0 )
602 sheetfile = aNetlistComponent->GetProperties().at( wxT( "Sheetfile" ) );
603
604 if( aNetlistComponent->GetProperties().count( wxT( "ki_fp_filters" ) ) > 0 )
605 fpFilters = aNetlistComponent->GetProperties().at( wxT( "ki_fp_filters" ) );
606
607 if( sheetname != aPcbFootprint->GetSheetname() )
608 {
609 if( m_isDryRun )
610 {
611 msg.Printf( _( "Update %s sheetname to '%s'." ),
612 aPcbFootprint->GetReference(),
613 EscapeHTML( sheetname ) );
614 }
615 else
616 {
617 aPcbFootprint->SetSheetname( sheetname );
618 msg.Printf( _( "Updated %s sheetname to '%s'." ),
619 aPcbFootprint->GetReference(),
620 EscapeHTML( sheetname ) );
621 }
622
624 }
625
626 if( sheetfile != aPcbFootprint->GetSheetfile() )
627 {
628 if( m_isDryRun )
629 {
630 msg.Printf( _( "Update %s sheetfile to '%s'." ),
631 aPcbFootprint->GetReference(),
632 EscapeHTML( sheetfile ) );
633 }
634 else
635 {
636 aPcbFootprint->SetSheetfile( sheetfile );
637 msg.Printf( _( "Updated %s sheetfile to '%s'." ),
638 aPcbFootprint->GetReference(),
639 EscapeHTML( sheetfile ) );
640 }
641
643 }
644
645 if( fpFilters != aPcbFootprint->GetFilters() )
646 {
647 if( m_isDryRun )
648 {
649 msg.Printf( _( "Update %s footprint filters to '%s'." ),
650 aPcbFootprint->GetReference(),
651 EscapeHTML( fpFilters ) );
652 }
653 else
654 {
655 aPcbFootprint->SetFilters( fpFilters );
656 msg.Printf( _( "Updated %s footprint filters to '%s'." ),
657 aPcbFootprint->GetReference(),
658 EscapeHTML( fpFilters ) );
659 }
660
662 }
663
664 if( ( aNetlistComponent->GetProperties().count( wxT( "exclude_from_bom" ) ) > 0 )
665 != ( ( aPcbFootprint->GetAttributes() & FP_EXCLUDE_FROM_BOM ) > 0 ) )
666 {
667 if( m_isDryRun )
668 {
669 if( aNetlistComponent->GetProperties().count( wxT( "exclude_from_bom" ) ) )
670 {
671 msg.Printf( _( "Add %s 'exclude from BOM' fabrication attribute." ),
672 aPcbFootprint->GetReference() );
673 }
674 else
675 {
676 msg.Printf( _( "Remove %s 'exclude from BOM' fabrication attribute." ),
677 aPcbFootprint->GetReference() );
678 }
679 }
680 else
681 {
682 int attributes = aPcbFootprint->GetAttributes();
683
684 if( aNetlistComponent->GetProperties().count( wxT( "exclude_from_bom" ) ) )
685 {
686 attributes |= FP_EXCLUDE_FROM_BOM;
687 msg.Printf( _( "Added %s 'exclude from BOM' fabrication attribute." ),
688 aPcbFootprint->GetReference() );
689 }
690 else
691 {
692 attributes &= ~FP_EXCLUDE_FROM_BOM;
693 msg.Printf( _( "Removed %s 'exclude from BOM' fabrication attribute." ),
694 aPcbFootprint->GetReference() );
695 }
696
697 changed = true;
698 aPcbFootprint->SetAttributes( attributes );
699 }
700
702 }
703
704 if( ( aNetlistComponent->GetProperties().count( wxT( "dnp" ) ) > 0 )
705 != ( ( aPcbFootprint->GetAttributes() & FP_DNP ) > 0 ) )
706 {
707 if( m_isDryRun )
708 {
709 if( aNetlistComponent->GetProperties().count( wxT( "dnp" ) ) )
710 {
711 msg.Printf( _( "Add %s 'Do not place' fabrication attribute." ),
712 aPcbFootprint->GetReference() );
713 }
714 else
715 {
716 msg.Printf( _( "Remove %s 'Do not place' fabrication attribute." ),
717 aPcbFootprint->GetReference() );
718 }
719 }
720 else
721 {
722 int attributes = aPcbFootprint->GetAttributes();
723
724 if( aNetlistComponent->GetProperties().count( wxT( "dnp" ) ) )
725 {
726 attributes |= FP_DNP;
727 msg.Printf( _( "Added %s 'Do not place' fabrication attribute." ),
728 aPcbFootprint->GetReference() );
729 }
730 else
731 {
732 attributes &= ~FP_DNP;
733 msg.Printf( _( "Removed %s 'Do not place' fabrication attribute." ),
734 aPcbFootprint->GetReference() );
735 }
736
737 changed = true;
738 aPcbFootprint->SetAttributes( attributes );
739 }
740
742 }
743
744 if( aNetlistComponent->GetDuplicatePadNumbersAreJumpers()
745 != aPcbFootprint->GetDuplicatePadNumbersAreJumpers() )
746 {
747 bool value = aNetlistComponent->GetDuplicatePadNumbersAreJumpers();
748
749 if( !m_isDryRun )
750 {
751 changed = true;
752 aPcbFootprint->SetDuplicatePadNumbersAreJumpers( value );
753
754 if( value )
755 {
756 msg.Printf( _( "Added %s 'duplicate pad numbers are jumpers' attribute." ),
757 aPcbFootprint->GetReference() );
758 }
759 else
760 {
761 msg.Printf( _( "Removed %s 'duplicate pad numbers are jumpers' attribute." ),
762 aPcbFootprint->GetReference() );
763 }
764 }
765 else
766 {
767 if( value )
768 {
769 msg.Printf( _( "Add %s 'duplicate pad numbers are jumpers' attribute." ),
770 aPcbFootprint->GetReference() );
771 }
772 else
773 {
774 msg.Printf( _( "Remove %s 'duplicate pad numbers are jumpers' attribute." ),
775 aPcbFootprint->GetReference() );
776 }
777 }
778
780 }
781
782 if( aNetlistComponent->JumperPadGroups() != aPcbFootprint->JumperPadGroups() )
783 {
784 if( !m_isDryRun )
785 {
786 changed = true;
787 aPcbFootprint->JumperPadGroups() = aNetlistComponent->JumperPadGroups();
788 msg.Printf( _( "Updated %s jumper pad groups" ), aPcbFootprint->GetReference() );
789 }
790 else
791 {
792 msg.Printf( _( "Update %s jumper pad groups" ), aPcbFootprint->GetReference() );
793 }
794
796 }
797
798 if( changed && copy )
799 m_commit.Modified( aPcbFootprint, copy );
800 else if( copy )
801 delete copy;
802
803 return true;
804}
805
806
808 COMPONENT* aNewComponent )
809{
810 wxString msg;
811
812 // Create a copy only if the footprint has not been added during this update
813 FOOTPRINT* copy = nullptr;
814
815 if( !m_isDryRun && !m_commit.GetStatus( aFootprint ) )
816 {
817 copy = static_cast<FOOTPRINT*>( aFootprint->Clone() );
818 copy->SetParentGroup( nullptr );
819 }
820
821 bool changed = false;
822
823 // At this point, the component footprint is updated. Now update the nets.
824 std::deque<PAD*> pads = aFootprint->Pads();
825 std::set<wxString> padNetnames;
826
827 std::sort( pads.begin(), pads.end(),
828 []( PAD* a, PAD* b )
829 {
830 return a->m_Uuid < b->m_Uuid;
831 } );
832
833 for( PAD* pad : pads )
834 {
835 const COMPONENT_NET& net = aNewComponent->GetNet( pad->GetNumber() );
836
837 wxString pinFunction;
838 wxString pinType;
839
840 if( net.IsValid() ) // i.e. the pad has a name
841 {
842 pinFunction = net.GetPinFunction();
843 pinType = net.GetPinType();
844 }
845
846 if( !m_isDryRun )
847 {
848 if( pad->GetPinFunction() != pinFunction )
849 {
850 changed = true;
851 pad->SetPinFunction( pinFunction );
852 }
853
854 if( pad->GetPinType() != pinType )
855 {
856 changed = true;
857 pad->SetPinType( pinType );
858 }
859 }
860 else
861 {
862 cachePinFunction( pad, pinFunction );
863 }
864
865 // Test if new footprint pad has no net (pads not on copper layers have no net).
866 if( !net.IsValid() || !pad->IsOnCopperLayer() )
867 {
868 if( !pad->GetNetname().IsEmpty() )
869 {
870 if( m_isDryRun )
871 {
872 msg.Printf( _( "Disconnect %s pin %s." ),
873 aFootprint->GetReference(),
874 EscapeHTML( pad->GetNumber() ) );
875 }
876 else
877 {
878 msg.Printf( _( "Disconnected %s pin %s." ),
879 aFootprint->GetReference(),
880 EscapeHTML( pad->GetNumber() ) );
881 }
882
884 }
885 else if( pad->IsOnCopperLayer() && !pad->GetNumber().IsEmpty() )
886 {
887 // pad is connectable but has no net found in netlist
888 msg.Printf( _( "No net found for component %s pad %s (no pin %s in symbol)." ),
889 aFootprint->GetReference(),
890 EscapeHTML( pad->GetNumber() ),
891 EscapeHTML( pad->GetNumber() ) );
894 }
895
896 if( !m_isDryRun )
897 {
898 changed = true;
899 pad->SetNetCode( NETINFO_LIST::UNCONNECTED );
900
901 // If the pad has no net from netlist (i.e. not in netlist
902 // it cannot have a pin function
903 if( pad->GetNetname().IsEmpty() )
904 pad->SetPinFunction( wxEmptyString );
905
906 }
907 else
908 {
909 cacheNetname( pad, wxEmptyString );
910 }
911 }
912 else // New footprint pad has a net.
913 {
914 wxString netName = net.GetNetName();
915
916 if( pad->IsNoConnectPad() )
917 {
918 netName = wxString::Format( wxS( "%s" ),
919 EscapeHTML( net.GetNetName() ) );
920
921 for( int jj = 1; !padNetnames.insert( netName ).second; jj++ )
922 {
923 netName = wxString::Format( wxS( "%s_%d" ),
924 EscapeHTML( net.GetNetName() ), jj );
925 }
926 }
927
928 NETINFO_ITEM* netinfo = m_board->FindNet( netName );
929
930 if( netinfo && !m_isDryRun )
931 netinfo->SetIsCurrent( true );
932
933 if( pad->GetNetname() != netName )
934 {
935
936 if( netinfo == nullptr )
937 {
938 // It might be a new net that has not been added to the board yet
939 if( m_addedNets.count( netName ) )
940 netinfo = m_addedNets[ netName ];
941 }
942
943 if( netinfo == nullptr )
944 {
945 netinfo = new NETINFO_ITEM( m_board, netName );
946
947 // It is a new net, we have to add it
948 if( !m_isDryRun )
949 {
950 changed = true;
951 m_commit.Add( netinfo );
952 }
953
954 m_addedNets[netName] = netinfo;
955 msg.Printf( _( "Add net %s." ),
956 EscapeHTML( UnescapeString( netName ) ) );
958 }
959
960 if( !pad->GetNetname().IsEmpty() )
961 {
962 m_oldToNewNets[ pad->GetNetname() ] = netName;
963
964 if( m_isDryRun )
965 {
966 msg.Printf( _( "Reconnect %s pin %s from %s to %s."),
967 aFootprint->GetReference(),
968 EscapeHTML( pad->GetNumber() ),
969 EscapeHTML( UnescapeString( pad->GetNetname() ) ),
970 EscapeHTML( UnescapeString( netName ) ) );
971 }
972 else
973 {
974 msg.Printf( _( "Reconnected %s pin %s from %s to %s."),
975 aFootprint->GetReference(),
976 EscapeHTML( pad->GetNumber() ),
977 EscapeHTML( UnescapeString( pad->GetNetname() ) ),
978 EscapeHTML( UnescapeString( netName ) ) );
979 }
980 }
981 else
982 {
983 if( m_isDryRun )
984 {
985 msg.Printf( _( "Connect %s pin %s to %s."),
986 aFootprint->GetReference(),
987 EscapeHTML( pad->GetNumber() ),
988 EscapeHTML( UnescapeString( netName ) ) );
989 }
990 else
991 {
992 msg.Printf( _( "Connected %s pin %s to %s."),
993 aFootprint->GetReference(),
994 EscapeHTML( pad->GetNumber() ),
995 EscapeHTML( UnescapeString( netName ) ) );
996 }
997 }
998
1000
1001 if( !m_isDryRun )
1002 {
1003 changed = true;
1004 pad->SetNet( netinfo );
1005 }
1006 else
1007 {
1008 cacheNetname( pad, netName );
1009 }
1010 }
1011 }
1012 }
1013
1014 if( changed && copy )
1015 m_commit.Modified( aFootprint, copy );
1016 else if( copy )
1017 delete copy;
1018
1019 return true;
1020}
1021
1022
1024{
1025 for( ZONE* zone : m_board->Zones() )
1026 {
1027 if( !zone->IsOnCopperLayer() || zone->GetIsRuleArea() )
1028 continue;
1029
1030 m_zoneConnectionsCache[ zone ] = m_board->GetConnectivity()->GetConnectedPads( zone );
1031 }
1032}
1033
1034
1036{
1037 wxString msg;
1038 std::set<wxString> netlistNetnames;
1039
1040 for( int ii = 0; ii < (int) aNetlist.GetCount(); ii++ )
1041 {
1042 const COMPONENT* component = aNetlist.GetComponent( ii );
1043
1044 for( unsigned jj = 0; jj < component->GetNetCount(); jj++ )
1045 {
1046 const COMPONENT_NET& net = component->GetNet( jj );
1047 netlistNetnames.insert( net.GetNetName() );
1048 }
1049 }
1050
1051 for( PCB_TRACK* via : m_board->Tracks() )
1052 {
1053 if( via->Type() != PCB_VIA_T )
1054 continue;
1055
1056 if( netlistNetnames.count( via->GetNetname() ) == 0 )
1057 {
1058 wxString updatedNetname = wxEmptyString;
1059
1060 // Take via name from name change map if it didn't match to a new pad
1061 // (this is useful for stitching vias that don't connect to tracks)
1062 if( m_oldToNewNets.count( via->GetNetname() ) )
1063 {
1064 updatedNetname = m_oldToNewNets[via->GetNetname()];
1065 }
1066
1067 if( !updatedNetname.IsEmpty() )
1068 {
1069 if( m_isDryRun )
1070 {
1071 wxString originalNetname = via->GetNetname();
1072
1073 msg.Printf( _( "Reconnect via from %s to %s." ),
1074 EscapeHTML( UnescapeString( originalNetname ) ),
1075 EscapeHTML( UnescapeString( updatedNetname ) ) );
1076
1078 }
1079 else
1080 {
1081 NETINFO_ITEM* netinfo = m_board->FindNet( updatedNetname );
1082
1083 if( !netinfo )
1084 netinfo = m_addedNets[updatedNetname];
1085
1086 if( netinfo )
1087 {
1088 wxString originalNetname = via->GetNetname();
1089
1090 m_commit.Modify( via );
1091 via->SetNet( netinfo );
1092
1093 msg.Printf( _( "Reconnected via from %s to %s." ),
1094 EscapeHTML( UnescapeString( originalNetname ) ),
1095 EscapeHTML( UnescapeString( updatedNetname ) ) );
1096
1098 }
1099 }
1100 }
1101 else
1102 {
1103 msg.Printf( _( "Via connected to unknown net (%s)." ),
1104 EscapeHTML( UnescapeString( via->GetNetname() ) ) );
1107 }
1108 }
1109 }
1110
1111 // Test copper zones to detect "dead" nets (nets without any pad):
1112 for( ZONE* zone : m_board->Zones() )
1113 {
1114 if( !zone->IsOnCopperLayer() || zone->GetIsRuleArea() )
1115 continue;
1116
1117 if( netlistNetnames.count( zone->GetNetname() ) == 0 )
1118 {
1119 // Look for a pad in the zone's connected-pad-cache which has been updated to
1120 // a new net and use that. While this won't always be the right net, the dead
1121 // net is guaranteed to be wrong.
1122 wxString updatedNetname = wxEmptyString;
1123
1124 for( PAD* pad : m_zoneConnectionsCache[ zone ] )
1125 {
1126 if( getNetname( pad ) != zone->GetNetname() )
1127 {
1128 updatedNetname = getNetname( pad );
1129 break;
1130 }
1131 }
1132
1133 // Take zone name from name change map if it didn't match to a new pad
1134 // (this is useful for zones on internal layers)
1135 if( updatedNetname.IsEmpty() && m_oldToNewNets.count( zone->GetNetname() ) )
1136 {
1137 updatedNetname = m_oldToNewNets[ zone->GetNetname() ];
1138 }
1139
1140 if( !updatedNetname.IsEmpty() )
1141 {
1142 if( m_isDryRun )
1143 {
1144 wxString originalNetname = zone->GetNetname();
1145
1146 if( !zone->GetZoneName().IsEmpty() )
1147 {
1148 msg.Printf( _( "Reconnect copper zone '%s' from %s to %s." ),
1149 zone->GetZoneName(),
1150 EscapeHTML( UnescapeString( originalNetname ) ),
1151 EscapeHTML( UnescapeString( updatedNetname ) ) );
1152 }
1153 else
1154 {
1155 msg.Printf( _( "Reconnect copper zone from %s to %s." ),
1156 EscapeHTML( UnescapeString( originalNetname ) ),
1157 EscapeHTML( UnescapeString( updatedNetname ) ) );
1158 }
1159
1161 }
1162 else
1163 {
1164 NETINFO_ITEM* netinfo = m_board->FindNet( updatedNetname );
1165
1166 if( !netinfo )
1167 netinfo = m_addedNets[ updatedNetname ];
1168
1169 if( netinfo )
1170 {
1171 wxString originalNetname = zone->GetNetname();
1172
1173 m_commit.Modify( zone );
1174 zone->SetNet( netinfo );
1175
1176 if( !zone->GetZoneName().IsEmpty() )
1177 {
1178 msg.Printf( _( "Reconnected copper zone '%s' from %s to %s." ),
1179 EscapeHTML( zone->GetZoneName() ),
1180 EscapeHTML( UnescapeString( originalNetname ) ),
1181 EscapeHTML( UnescapeString( updatedNetname ) ) );
1182 }
1183 else
1184 {
1185 msg.Printf( _( "Reconnected copper zone from %s to %s." ),
1186 EscapeHTML( UnescapeString( originalNetname ) ),
1187 EscapeHTML( UnescapeString( updatedNetname ) ) );
1188 }
1189
1191 }
1192 }
1193 }
1194 else
1195 {
1196 if( !zone->GetZoneName().IsEmpty() )
1197 {
1198 msg.Printf( _( "Copper zone '%s' has no pads connected." ),
1199 EscapeHTML( zone->GetZoneName() ) );
1200 }
1201 else
1202 {
1203 PCB_LAYER_ID layer = zone->GetLayer();
1204 VECTOR2I pos = zone->GetPosition();
1205
1207 {
1209 pos.x *= -1;
1210
1212 pos.y *= -1;
1213 }
1214
1215 msg.Printf( _( "Copper zone on layer %s at (%s, %s) has no pads connected." ),
1216 EscapeHTML( m_board->GetLayerName( layer ) ),
1218 m_frame->MessageTextFromValue( pos.y ) );
1219 }
1220
1223 }
1224 }
1225 }
1226
1227 return true;
1228}
1229
1230
1232 std::map<COMPONENT*, FOOTPRINT*>& aFootprintMap )
1233{
1234 // Verify that board contains all pads in netlist: if it doesn't then footprints are
1235 // wrong or missing.
1236
1237 wxString msg;
1238 wxString padNumber;
1239
1240 for( int i = 0; i < (int) aNetlist.GetCount(); i++ )
1241 {
1242 COMPONENT* component = aNetlist.GetComponent( i );
1243 FOOTPRINT* footprint = aFootprintMap[component];
1244
1245 if( !footprint ) // It can be missing in partial designs
1246 continue;
1247
1248 // Explore all pins/pads in component
1249 for( unsigned jj = 0; jj < component->GetNetCount(); jj++ )
1250 {
1251 padNumber = component->GetNet( jj ).GetPinName();
1252
1253 if( padNumber.IsEmpty() )
1254 {
1255 // bad symbol, report error
1256 msg.Printf( _( "Symbol %s has pins with no number. These pins can not be matched "
1257 "to pads in %s." ),
1258 component->GetReference(),
1259 EscapeHTML( footprint->GetFPID().Format().wx_str() ) );
1261 ++m_errorCount;
1262 }
1263 else if( !footprint->FindPadByNumber( padNumber ) )
1264 {
1265 // not found: bad footprint, report error
1266 msg.Printf( _( "%s pad %s not found in %s." ),
1267 component->GetReference(),
1268 EscapeHTML( padNumber ),
1269 EscapeHTML( footprint->GetFPID().Format().wx_str() ) );
1271 ++m_errorCount;
1272 }
1273 }
1274 }
1275
1276 return true;
1277}
1278
1279
1281{
1282 FOOTPRINT* lastPreexistingFootprint = nullptr;
1283 COMPONENT* component = nullptr;
1284 wxString msg;
1285 std::unordered_set<wxString> sheetPaths;
1286
1287 m_errorCount = 0;
1288 m_warningCount = 0;
1290
1291 std::map<COMPONENT*, FOOTPRINT*> footprintMap;
1292
1293 if( !m_board->Footprints().empty() )
1294 lastPreexistingFootprint = m_board->Footprints().back();
1295
1297
1298 // First mark all nets (except <no net>) as stale; we'll update those which are current
1299 // in the following two loops. Also prepare the component class manager for updates.
1300 //
1301 if( !m_isDryRun )
1302 {
1303 for( NETINFO_ITEM* net : m_board->GetNetInfo() )
1304 net->SetIsCurrent( net->GetNetCode() == 0 );
1305
1307 }
1308
1309 // Next go through the netlist updating all board footprints which have matching component
1310 // entries and adding new footprints for those that don't.
1311 //
1312 for( unsigned i = 0; i < aNetlist.GetCount(); i++ )
1313 {
1314 component = aNetlist.GetComponent( i );
1315
1316 if( component->GetProperties().count( wxT( "exclude_from_board" ) ) )
1317 continue;
1318
1319 msg.Printf( _( "Processing symbol '%s:%s'." ),
1320 component->GetReference(),
1321 EscapeHTML( component->GetFPID().Format().wx_str() ) );
1323
1324 int matchCount = 0;
1325
1326 for( FOOTPRINT* footprint : m_board->Footprints() )
1327 {
1328 bool match = false;
1329
1331 {
1332 for( const KIID& uuid : component->GetKIIDs() )
1333 {
1334 KIID_PATH base = component->GetPath();
1335 base.push_back( uuid );
1336
1337 if( footprint->GetPath() == base )
1338 {
1339 match = true;
1340 break;
1341 }
1342 }
1343 }
1344 else
1345 {
1346 match = footprint->GetReference().CmpNoCase( component->GetReference() ) == 0;
1347 }
1348
1349 if( match )
1350 {
1351 FOOTPRINT* tmp = footprint;
1352
1353 if( m_replaceFootprints && component->GetFPID() != footprint->GetFPID() )
1354 tmp = replaceFootprint( aNetlist, footprint, component );
1355
1356 if( !tmp )
1357 tmp = footprint;
1358
1359 if( tmp )
1360 {
1361 footprintMap[ component ] = tmp;
1362
1363 updateFootprintParameters( tmp, component );
1364 updateComponentPadConnections( tmp, component );
1365 updateComponentClass( tmp, component );
1366
1367 sheetPaths.insert( footprint->GetSheetname() );
1368 }
1369
1370 matchCount++;
1371 }
1372
1373 if( footprint == lastPreexistingFootprint )
1374 {
1375 // No sense going through the newly-created footprints: end of loop
1376 break;
1377 }
1378 }
1379
1380 if( matchCount == 0 )
1381 {
1382 FOOTPRINT* footprint = addNewFootprint( component );
1383
1384 if( footprint )
1385 {
1386 footprintMap[ component ] = footprint;
1387
1388 updateFootprintParameters( footprint, component );
1389 updateComponentPadConnections( footprint, component );
1390 updateComponentClass( footprint, component );
1391
1392 sheetPaths.insert( footprint->GetSheetname() );
1393 }
1394 }
1395 else if( matchCount > 1 )
1396 {
1397 msg.Printf( _( "Multiple footprints found for %s." ),
1398 component->GetReference() );
1400 m_errorCount++;
1401 }
1402 }
1403
1404 updateCopperZoneNets( aNetlist );
1405
1406 // Finally go through the board footprints and update all those that *don't* have matching
1407 // component entries.
1408 //
1409 for( FOOTPRINT* footprint : m_board->Footprints() )
1410 {
1411 bool matched = false;
1412 bool doDelete = m_deleteUnusedFootprints;
1413
1414 if( ( footprint->GetAttributes() & FP_BOARD_ONLY ) > 0 )
1415 doDelete = false;
1416
1418 component = aNetlist.GetComponentByPath( footprint->GetPath() );
1419 else
1420 component = aNetlist.GetComponentByReference( footprint->GetReference() );
1421
1422 if( component && component->GetProperties().count( wxT( "exclude_from_board" ) ) == 0 )
1423 matched = true;
1424
1425 if( doDelete && !matched && footprint->IsLocked() && !m_overrideLocks )
1426 {
1427 if( m_isDryRun )
1428 {
1429 msg.Printf( _( "Cannot remove unused footprint %s (footprint is locked)." ),
1430 footprint->GetReference() );
1431 }
1432 else
1433 {
1434 msg.Printf( _( "Could not remove unused footprint %s (footprint is locked)." ),
1435 footprint->GetReference() );
1436 }
1437
1440 doDelete = false;
1441 }
1442
1443 if( doDelete && !matched )
1444 {
1445 if( m_isDryRun )
1446 {
1447 msg.Printf( _( "Remove unused footprint %s." ),
1448 footprint->GetReference() );
1449 }
1450 else
1451 {
1452 if( footprint->GetParentGroup() )
1453 m_commit.Stage( footprint, CHT_UNGROUP );
1454
1455 m_commit.Remove( footprint );
1456 msg.Printf( _( "Removed unused footprint %s." ),
1457 footprint->GetReference() );
1458 }
1459
1461 }
1462 else if( !m_isDryRun )
1463 {
1464 if( !matched )
1465 footprint->SetPath( KIID_PATH() );
1466
1467 for( PAD* pad : footprint->Pads() )
1468 {
1469 if( pad->GetNet() )
1470 pad->GetNet()->SetIsCurrent( true );
1471 }
1472 }
1473 }
1474
1475 if( !m_isDryRun )
1476 {
1477 // Finalise the component class manager
1479 m_board->SynchronizeComponentClasses( sheetPaths );
1480
1482 testConnectivity( aNetlist, footprintMap );
1483
1484 for( NETINFO_ITEM* net : m_board->GetNetInfo() )
1485 {
1486 if( !net->IsCurrent() )
1487 {
1488 msg.Printf( _( "Removed unused net %s." ),
1489 EscapeHTML( net->GetNetname() ) );
1491 }
1492 }
1493
1495
1496 // When new footprints are added, the automatic zone refill is disabled because:
1497 // * it creates crashes when calculating dynamic ratsnests if auto refill is enabled.
1498 // (the auto refills rebuild the connectivity with incomplete data)
1499 // * it is useless because zones will be refilled after placing new footprints
1500 m_commit.Push( _( "Update Netlist" ), m_newFootprintsCount ? ZONE_FILL_OP : 0 );
1501
1502 // Update net, netcode and netclass data after commiting the netlist
1504 m_board->GetConnectivity()->RefreshNetcodeMap( m_board );
1505
1506 // Although m_commit will probably also set this, it's not guaranteed, and we need to make
1507 // sure any modification to netclasses gets persisted to project settings through a save.
1508 m_frame->OnModify();
1509 }
1510
1511 if( m_isDryRun )
1512 {
1513 for( const std::pair<const wxString, NETINFO_ITEM*>& addedNet : m_addedNets )
1514 delete addedNet.second;
1515
1516 m_addedNets.clear();
1517 }
1518
1519 // Update the ratsnest
1522
1523 msg.Printf( _( "Total warnings: %d, errors: %d." ), m_warningCount, m_errorCount );
1525
1526 return true;
1527}
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:280
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:297
const NETINFO_LIST & GetNetInfo() const
Definition: board.h:897
const BOX2I GetBoardEdgesBoundingBox() const
Return the board bounding box calculated using exclusively the board edges (graphics on Edge....
Definition: board.h:955
const PAGE_INFO & GetPageSettings() const
Definition: board.h:715
NETINFO_ITEM * FindNet(int aNetcode) const
Search for a net with the given netcode.
Definition: board.cpp:2011
const ZONES & Zones() const
Definition: board.h:342
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:185
void SynchronizeNetsAndNetClasses(bool aResetTrackAndViaSizes)
Copy NETCLASS info to each NET, based on NET membership in a NETCLASS.
Definition: board.cpp:2144
void RemoveUnusedNets(BOARD_COMMIT *aCommit)
Definition: board.h:902
const FOOTPRINTS & Footprints() const
Definition: board.h:338
const TRACKS & Tracks() const
Definition: board.h:336
const wxString GetLayerName(PCB_LAYER_ID aLayer) const
Return the name of a aLayer.
Definition: board.cpp:614
bool IsEmpty() const
Definition: board.h:393
COMPONENT_CLASS_MANAGER & GetComponentClassManager()
Gets the component class manager.
Definition: board.h:1305
bool SynchronizeComponentClasses(const std::unordered_set< wxString > &aNewSheetPaths) const
Copy component class / component class generator information from the project settings.
Definition: board.cpp:2174
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 * GetEffectiveStaticComponentClass(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.
A lightweight representation of a component class.
const wxString & GetName() 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:178
const COMPONENT_NET & GetNet(unsigned aIndex) const
Definition: pcb_netlist.h:115
const KIID_PATH & GetPath() const
Definition: pcb_netlist.h:153
const wxString & GetReference() const
Definition: pcb_netlist.h:130
const wxString & GetValue() const
Definition: pcb_netlist.h:133
const nlohmann::ordered_map< wxString, wxString > & GetFields() const
Definition: pcb_netlist.h:139
const std::map< wxString, wxString > & GetProperties() const
Definition: pcb_netlist.h:145
const std::vector< KIID > & GetKIIDs() const
Definition: pcb_netlist.h:155
bool GetDuplicatePadNumbersAreJumpers() const
Definition: pcb_netlist.h:187
const LIB_ID & GetFPID() const
Definition: pcb_netlist.h:148
unsigned GetNetCount() const
Definition: pcb_netlist.h:113
std::unordered_set< wxString > & GetComponentClassNames()
Definition: pcb_netlist.h:185
std::vector< std::set< wxString > > & JumperPadGroups()
Definition: pcb_netlist.h:190
virtual void SetParent(EDA_ITEM *aParent)
Definition: eda_item.h:111
virtual void SetVisible(bool aVisible)
Definition: eda_text.cpp:379
virtual void SetText(const wxString &aText)
Definition: eda_text.cpp:270
bool GetDuplicatePadNumbersAreJumpers() const
Definition: footprint.h:820
void SetPosition(const VECTOR2I &aPos) override
Definition: footprint.cpp:2459
EDA_ANGLE GetOrientation() const
Definition: footprint.h:232
void Remove(BOARD_ITEM *aItem, REMOVE_MODE aMode=REMOVE_MODE::NORMAL) override
Removes an item from the container.
Definition: footprint.cpp:1130
wxString GetSheetname() const
Definition: footprint.h:271
void SetPath(const KIID_PATH &aPath)
Definition: footprint.h:269
void SetFilters(const wxString &aFilters)
Definition: footprint.h:278
void SetStaticComponentClass(const COMPONENT_CLASS *aClass) const
Sets the component class object pointer for this footprint.
Definition: footprint.cpp:4041
void SetAttributes(int aAttributes)
Definition: footprint.h:296
void SetSheetfile(const wxString &aSheetfile)
Definition: footprint.h:275
EDA_ITEM * Clone() const override
Invoke a function on all children.
Definition: footprint.cpp:2196
std::vector< std::set< wxString > > & JumperPadGroups()
Each jumper pad group is a set of pad numbers that should be treated as internally connected.
Definition: footprint.h:827
void SetDuplicatePadNumbersAreJumpers(bool aEnabled)
Definition: footprint.h:821
bool HasField(const wxString &aFieldName) const
Definition: footprint.cpp:609
PCB_FIELD * GetField(FIELD_T aFieldType)
Return a mandatory field in this footprint.
Definition: footprint.cpp:582
std::deque< PAD * > & Pads()
Definition: footprint.h:211
int GetAttributes() const
Definition: footprint.h:295
PCB_LAYER_ID GetLayer() const override
Return the primary layer this item is on.
Definition: footprint.h:241
wxString GetSheetfile() const
Definition: footprint.h:274
const LIB_ID & GetFPID() const
Definition: footprint.h:253
void SetReference(const wxString &aReference)
Definition: footprint.h:627
bool IsLocked() const override
Definition: footprint.h:416
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:1069
wxString GetFilters() const
Definition: footprint.h:277
void SetSheetname(const wxString &aSheetname)
Definition: footprint.h:272
void GetFields(std::vector< PCB_FIELD * > &aVector, bool aVisibleOnly) const
Populate a std::vector with PCB_TEXTs.
Definition: footprint.cpp:627
const wxString & GetValue() const
Definition: footprint.h:643
const COMPONENT_CLASS * GetStaticComponentClass() const
Returns the component class for this footprint.
Definition: footprint.cpp:4047
const wxString & GetReference() const
Definition: footprint.h:621
const KIID_PATH & GetPath() const
Definition: footprint.h:268
VECTOR2I GetPosition() const override
Definition: footprint.h:229
PAD * FindPadByNumber(const wxString &aPadNumber, PAD *aSearchAfterMe=nullptr) const
Return a PAD with a matching number.
Definition: footprint.cpp:1955
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:119
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:255
unsigned GetCount() const
Definition: pcb_netlist.h:276
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:284
static REPORTER & GetInstance()
Definition: reporter.cpp:108
Definition: pad.h:54
const wxString & GetPinFunction() const
Definition: pad.h:147
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:108
void StyleFromSettings(const BOARD_DESIGN_SETTINGS &settings) override
Definition: pcb_text.cpp:307
virtual void SetPosition(const VECTOR2I &aPos) override
Definition: pcb_text.h:89
void Rotate(const VECTOR2I &aRotCentre, const EDA_ANGLE &aAngle) override
Rotate this object.
Definition: pcb_text.cpp:377
virtual REPORTER & Report(const wxString &aText, SEVERITY aSeverity=RPT_SEVERITY_UNDEFINED)
Report a string with a given severity.
Definition: reporter.h:102
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:112
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:88
@ FP_BOARD_ONLY
Definition: footprint.h:84
@ FP_EXCLUDE_FROM_BOM
Definition: footprint.h:83
@ FP_JUST_ADDED
Definition: footprint.h:85
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