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