KiCad PCB EDA Suite
Loading...
Searching...
No Matches
dialog_change_symbols.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) 2020-2021 CERN
5 * Copyright The KiCad Developers, see AUTHORS.txt for contributors.
6 *
7 * @author Wayne Stambaugh <[email protected]>
8 *
9 * This program is free software: you can redistribute it and/or modify it
10 * under the terms of the GNU General Public License as published by the
11 * Free Software Foundation, either version 3 of the License, or (at your
12 * option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License along
20 * with this program. If not, see <http://www.gnu.org/licenses/>.
21 */
22
23#include <algorithm>
24
25#include <bitmaps.h>
26#include <connection_graph.h>
27#include <string_utils.h> // WildCompareString
28#include <kiway.h>
29#include <refdes_utils.h>
30#include <core/kicad_algo.h>
32#include <sch_symbol.h>
33#include <sch_edit_frame.h>
34#include <sch_screen.h>
35#include <schematic.h>
36#include <template_fieldnames.h>
39#include <sch_commit.h>
40
41bool g_selectRefDes = false;
42bool g_selectValue = false;
43
44
47 m_symbol( aSymbol),
48 m_mode( aMode )
49{
50 wxASSERT( aParent );
51
52 if( m_mode == MODE::UPDATE )
53 {
54 m_newIdSizer->Show( false );
55 }
56 else
57 {
58 m_matchAll->SetLabel( _( "Change all symbols in schematic" ) );
59 SetTitle( _( "Change Symbols" ) );
60 m_matchSizer->FindItem( m_matchAll )->Show( false );
61
62 m_matchByReference->SetLabel( _( "Change symbols matching reference designator:" ) );
63 m_matchByValue->SetLabel( _( "Change symbols matching value:" ) );
64 m_matchById->SetLabel( _( "Change symbols matching library identifier:" ) );
65
66 m_updateFieldsSizer->GetStaticBox()->SetLabel( _( "Update Fields" ) );
67 m_removeExtraBox->SetLabel( _( "Remove fields if not in new symbol" ) );
68 m_resetEmptyFields->SetLabel( _( "Reset fields if empty in new symbol" ) );
69 m_resetFieldText->SetLabel( _( "Update field text" ) );
70 m_resetFieldVisibilities->SetLabel( _( "Update field visibilities" ) );
71 m_resetFieldEffects->SetLabel( _( "Update field sizes and styles" ) );
72 m_resetFieldPositions->SetLabel( _( "Update field positions" ) );
73 m_resetAttributes->SetLabel( _( "Update symbol attributes" ) );
74 m_resetPinTextVisibility->SetLabel( _( "Update pin name/number visibilities" ) );
75 m_resetAlternatePin->SetLabel( _( "Reset alternate pin functions" ) );
76 m_resetCustomPower->SetLabel( _( "Reset custom power symbols" ) );
77
78 if( m_symbol )
79 m_matchBySelection->SetLabel( _( "Change selected symbol(s)" ) );
80 }
81
82 if( !m_symbol )
83 m_matchSizer->FindItem( m_matchBySelection )->Show( false );
84
85 m_matchIdBrowserButton->SetBitmap( KiBitmapBundle( BITMAPS::small_library ) );
86 m_newIdBrowserButton->SetBitmap( KiBitmapBundle( BITMAPS::small_library ) );
87
88 m_matchSizer->SetEmptyCellSize( wxSize( 0, 0 ) );
89 m_matchSizer->Layout();
90
91 for( FIELD_T fieldId : MANDATORY_FIELDS )
92 {
93 int listIdx = (int) m_fieldsBox->GetCount();
94
95 m_fieldsBox->Append( GetDefaultFieldName( fieldId, DO_TRANSLATE ) );
96
97 // List boxes aren't currently handled in DIALOG_SHIM's control-state-save/restore
98 if( fieldId == FIELD_T::REFERENCE )
99 m_fieldsBox->Check( listIdx, g_selectRefDes );
100 else if( fieldId == FIELD_T::VALUE )
101 m_fieldsBox->Check( listIdx, g_selectValue );
102 else
103 m_fieldsBox->Check( listIdx, true );
104
105 m_mandatoryFieldListIndexes[fieldId] = listIdx;
106 }
107
109
110 // initialize controls based on m_mode in case there is no saved state yet
111 m_removeExtraBox->SetValue( m_mode == MODE::CHANGE ? false : false );
112 m_resetEmptyFields->SetValue( m_mode == MODE::CHANGE ? false : false );
113 m_resetFieldText->SetValue( m_mode == MODE::CHANGE ? true : true );
114 m_resetFieldVisibilities->SetValue( m_mode == MODE::CHANGE ? true : false );
115 m_resetFieldEffects->SetValue( m_mode == MODE::CHANGE ? true : false );
116 m_resetFieldPositions->SetValue( m_mode == MODE::CHANGE ? true : false );
117 m_resetAttributes->SetValue( m_mode == MODE::CHANGE ? true : false );
118 m_resetPinTextVisibility->SetValue( m_mode == MODE::CHANGE ? true : false );
119 m_resetCustomPower->SetValue( m_mode == MODE::CHANGE ? false : false );
120 m_resetAlternatePin->SetValue( m_mode == MODE::CHANGE ? true : false );
121
123 m_messagePanel->SetFileName( Prj().GetProjectPath() + wxT( "report.txt" ) );
124
125 // DIALOG_SHIM needs a unique hash_key because classname is not sufficient
126 // because the update and change versions of this dialog have different controls.
127 m_hash_key = TO_UTF8( GetTitle() );
128
129 wxString okLabel = m_mode == MODE::CHANGE ? _( "Change" ) : _( "Update" );
130
131 SetupStandardButtons( { { wxID_OK, okLabel },
132 { wxID_CANCEL, _( "Close" ) } } );
133
134 // Now all widgets have the size fixed, call FinishDialogSettings
136}
137
138
140{
141 if( m_symbol )
142 {
143 SCH_SHEET_PATH* currentSheet = &m_symbol->Schematic()->CurrentSheet();
144
145 m_specifiedReference->ChangeValue( m_symbol->GetRef( currentSheet ) );
146 m_specifiedValue->ChangeValue( UnescapeString( m_symbol->GetField( FIELD_T::VALUE )->GetText() ) );
147 m_specifiedId->ChangeValue( UnescapeString( m_symbol->GetLibId().Format() ) );
148 }
149
150 if( m_symbol && m_symbol->IsSelected() )
151 m_matchBySelection->SetValue( true );
152 else if( m_mode == MODE::UPDATE )
153 m_matchAll->SetValue( true );
154 else
155 m_matchByReference->SetValue( true );
156
157 return true;
158}
159
160
161void DIALOG_CHANGE_SYMBOLS::onMatchByAll( wxCommandEvent& aEvent )
162{
164}
165
166
167void DIALOG_CHANGE_SYMBOLS::onMatchBySelected( wxCommandEvent& aEvent )
168{
170}
171
172
173void DIALOG_CHANGE_SYMBOLS::onMatchByReference( wxCommandEvent& aEvent )
174{
176 m_specifiedReference->SetFocus();
177}
178
179
180void DIALOG_CHANGE_SYMBOLS::onMatchByValue( wxCommandEvent& aEvent )
181{
183 m_specifiedValue->SetFocus();
184}
185
186
187void DIALOG_CHANGE_SYMBOLS::onMatchById( wxCommandEvent& aEvent )
188{
190 m_specifiedId->SetFocus();
191}
192
193
195{
197 event.Skip(); // Mandatory in wxFocusEvent
198}
199
200
202{
204 event.Skip(); // Mandatory in wxFocusEvent
205}
206
207
209{
211 event.Skip(); // Mandatory in wxFocusEvent
212}
213
214
216{
217 // List boxes aren't currently handled in DIALOG_SHIM's control-state-save/restore
218 g_selectRefDes = m_fieldsBox->IsChecked( m_mandatoryFieldListIndexes[FIELD_T::REFERENCE] );
219 g_selectValue = m_fieldsBox->IsChecked( m_mandatoryFieldListIndexes[FIELD_T::VALUE] );
220}
221
222
223wxString getLibIdValue( const wxTextCtrl* aCtrl )
224{
225 wxString rawValue = aCtrl->GetValue();
226 wxString itemName;
227 wxString libName = rawValue.BeforeFirst( ':', &itemName );
228
229 return EscapeString( libName, CTX_LIBID ) + ':' + EscapeString( itemName, CTX_LIBID );
230}
231
232
234{
235 wxString newName = getLibIdValue( m_specifiedId );
236
237 if( KIWAY_PLAYER* frame = Kiway().Player( FRAME_SYMBOL_CHOOSER, true, this ) )
238 {
239 if( frame->ShowModal( &newName, this ) )
240 {
241 m_specifiedId->SetValue( UnescapeString( newName ) );
243 }
244
245 frame->Destroy();
246 }
247}
248
249
251{
252 wxString newName = getLibIdValue( m_newId );
253
254 if( KIWAY_PLAYER* frame = Kiway().Player( FRAME_SYMBOL_CHOOSER, true, this ) )
255 {
256 if( frame->ShowModal( &newName, this ) )
257 {
258 m_newId->SetValue( UnescapeString( newName ) );
260 }
261
262 frame->Destroy();
263 }
264}
265
266
268{
269 SCH_EDIT_FRAME* frame = dynamic_cast<SCH_EDIT_FRAME*>( GetParent() );
270
271 wxCHECK( frame, /* void */ );
272
273 // Load non-mandatory fields from all matching symbols and their library symbols
274 std::set<wxString> fieldNames;
275
276 for( SCH_SHEET_PATH& instance : frame->Schematic().Hierarchy() )
277 {
278 SCH_SCREEN* screen = instance.LastScreen();
279
280 wxCHECK2( screen, continue );
281
282 for( SCH_ITEM* item : screen->Items().OfType( SCH_SYMBOL_T ) )
283 {
284 SCH_SYMBOL* symbol = dynamic_cast<SCH_SYMBOL*>( item );
285
286 wxCHECK2( symbol, continue );
287
288 if( !isMatch( symbol, &instance ) )
289 continue;
290
291 for( SCH_FIELD& field : symbol->GetFields() )
292 {
293 if( !field.IsMandatory() && !field.IsPrivate() )
294 fieldNames.insert( field.GetName() );
295 }
296
297 if( m_mode == MODE::UPDATE && symbol->GetLibId().IsValid() )
298 {
299 LIB_SYMBOL* libSymbol = frame->GetLibSymbol( symbol->GetLibId() );
300
301 if( libSymbol )
302 {
303 std::unique_ptr<LIB_SYMBOL> flattenedSymbol = libSymbol->Flatten();
304 std::vector<SCH_FIELD*> orderedLibFields;
305
306 flattenedSymbol->GetFields( orderedLibFields );
307
308 for( SCH_FIELD* libField : orderedLibFields )
309 {
310 if( !libField->IsMandatory() && !libField->IsPrivate() )
311 fieldNames.insert( libField->GetName() );
312 }
313 }
314 }
315 }
316 }
317
318 // Load non-mandatory fields from the change-to library symbol
319 if( m_mode == MODE::CHANGE )
320 {
321 LIB_ID newId;
322
323 newId.Parse( getLibIdValue( m_newId ) );
324
325 if( newId.IsValid() )
326 {
327 LIB_SYMBOL* libSymbol = frame->GetLibSymbol( newId );
328
329 if( libSymbol )
330 {
331 std::unique_ptr<LIB_SYMBOL> flattenedSymbol = libSymbol->Flatten();
332 std::vector<SCH_FIELD*> orderedLibFields;
333
334 flattenedSymbol->GetFields( orderedLibFields );
335
336 for( SCH_FIELD* libField : orderedLibFields )
337 {
338 if( !libField->IsMandatory() && !libField->IsPrivate() )
339 fieldNames.insert( libField->GetName() );
340 }
341 }
342 }
343 }
344
345 // Update the listbox widget
346 wxArrayInt checkedItems;
347 wxArrayString checkedNames;
348
349 m_fieldsBox->GetCheckedItems( checkedItems );
350
351 for( int ii : checkedItems )
352 checkedNames.push_back( m_fieldsBox->GetString( ii ) );
353
354 bool allChecked = true;
355
356 for( int ii = 0; ii < (int) m_fieldsBox->GetCount(); ++ii )
357 {
358 if( !m_fieldsBox->IsChecked( ii )
359 && ii != m_mandatoryFieldListIndexes[FIELD_T::REFERENCE]
360 && ii != m_mandatoryFieldListIndexes[FIELD_T::VALUE] )
361 {
362 allChecked = false;
363 }
364 }
365
366 auto isMandatoryField =
367 [&]( int listbox_idx )
368 {
369 for( FIELD_T fieldId : MANDATORY_FIELDS )
370 {
371 if( m_mandatoryFieldListIndexes[fieldId] == listbox_idx )
372 return true;
373 }
374
375 return false;
376 };
377
378 for( int ii = (int) m_fieldsBox->GetCount() - 1; ii >= 0; --ii )
379 {
380 if( isMandatoryField( ii ) )
381 continue;
382
383 m_fieldsBox->Delete( ii );
384 }
385
386 for( const wxString& fieldName : fieldNames )
387 {
388 m_fieldsBox->Append( fieldName );
389
390 if( allChecked || alg::contains( checkedNames, fieldName ) )
391 m_fieldsBox->Check( m_fieldsBox->GetCount() - 1, true );
392 }
393}
394
395
397{
398 for( unsigned i = 0; i < m_fieldsBox->GetCount(); ++i )
399 m_fieldsBox->Check( i, aSelect );
400}
401
402
404{
405 m_removeExtraBox->SetValue( aCheck );
406 m_resetEmptyFields->SetValue( aCheck );
407 m_resetFieldText->SetValue( aCheck );
408 m_resetFieldVisibilities->SetValue( aCheck );
409 m_resetFieldEffects->SetValue( aCheck );
410 m_resetFieldPositions->SetValue( aCheck );
411 m_resetPinTextVisibility->SetValue( aCheck );
412 m_resetAlternatePin->SetValue( aCheck );
413 m_resetAttributes->SetValue( aCheck );
414 m_resetCustomPower->SetValue( aCheck );
415}
416
417
418void DIALOG_CHANGE_SYMBOLS::onOkButtonClicked( wxCommandEvent& aEvent )
419{
420 SCH_EDIT_FRAME* parent = dynamic_cast<SCH_EDIT_FRAME*>( GetParent() );
421
422 wxCHECK( parent, /* void */ );
423
424 wxBusyCursor dummy;
425 SCH_COMMIT commit( parent );
426
428 m_messagePanel->Flush( false );
429
430 // Create the set of fields to be updated. Use non translated (canonical) names
431 // for mandatory fields
432 m_updateFields.clear();
433
434 for( unsigned ii = 0; ii < m_fieldsBox->GetCount(); ++ii )
435 {
436 if( m_fieldsBox->IsChecked( ii ) )
437 m_updateFields.insert( m_fieldsBox->GetString( ii ) );
438 }
439
440 for( FIELD_T fieldId : MANDATORY_FIELDS )
441 {
442 if( m_fieldsBox->IsChecked( m_mandatoryFieldListIndexes[fieldId] ) )
443 m_updateFields.insert( GetCanonicalFieldName( fieldId ) );
444 }
445
446 if( processMatchingSymbols( &commit) )
447 commit.Push( m_mode == MODE::CHANGE ? _( "Change Symbols" ) : _( "Update Symbols" ) );
448
449 m_messagePanel->Flush( false );
450}
451
452
454{
455 SCH_EDIT_FRAME* frame = dynamic_cast<SCH_EDIT_FRAME*>( GetParent() );
456
457 wxCHECK( frame, false );
458
459 if( !aSymbol )
460 return false;
461
462 if( m_matchAll->GetValue() )
463 {
464 return true;
465 }
466 else if( m_matchBySelection->GetValue() )
467 {
468 return aSymbol == m_symbol || aSymbol->IsSelected();
469 }
470 else if( m_matchByReference->GetValue() )
471 {
472 return WildCompareString( m_specifiedReference->GetValue(),
473 UnescapeString( aSymbol->GetRef( aInstance, false ) ),
474 false );
475 }
476 else if( m_matchByValue->GetValue() )
477 {
478 return WildCompareString( m_specifiedValue->GetValue(),
479 UnescapeString( aSymbol->GetField( FIELD_T::VALUE )->GetText() ),
480 false );
481 }
482 else if( m_matchById )
483 {
484 LIB_ID id;
485
487 return aSymbol->GetLibId() == id;
488 }
489
490 return false;
491}
492
493
495{
496 SCH_EDIT_FRAME* frame = dynamic_cast<SCH_EDIT_FRAME*>( GetParent() );
497
498 wxCHECK( frame, false );
499
500 LIB_ID newId;
501 int matchesProcessed = 0;
502 SCH_SYMBOL* symbol = nullptr;
503
504 if( m_mode == MODE::CHANGE )
505 {
506 newId.Parse( getLibIdValue( m_newId ) );
507
508 if( !newId.IsValid() )
509 return false;
510 }
511
512 std::map<SCH_SYMBOL*, SYMBOL_CHANGE_INFO> symbols;
513
514 for( SCH_SHEET_PATH& instance : frame->Schematic().Hierarchy() )
515 {
516 SCH_SCREEN* screen = instance.LastScreen();
517
518 wxCHECK2( screen, continue );
519
520 // Fetch all the symbols that meet the change criteria.
521 for( SCH_ITEM* item : screen->Items().OfType( SCH_SYMBOL_T ) )
522 {
523 symbol = static_cast<SCH_SYMBOL*>( item );
524
525 wxCHECK2( symbol, continue );
526
527 if( !isMatch( symbol, &instance ) )
528 continue;
529
530 if( m_mode == MODE::UPDATE )
531 newId = symbol->GetLibId();
532
533 auto it = symbols.find( symbol );
534
535 if( it == symbols.end() )
536 {
538
539 info.m_Instances.emplace_back( instance );
540 info.m_LibId = newId;
541 symbols.insert( { symbol, info } );
542 }
543 else
544 {
545 it->second.m_Instances.emplace_back( instance );
546 }
547 }
548 }
549
550 if( symbols.size() > 0 )
551 matchesProcessed += processSymbols( aCommit, symbols );
552 else
553 m_messagePanel->Report( _( "*** No symbols matching criteria found ***" ), RPT_SEVERITY_ERROR );
554
556
557 return matchesProcessed;
558}
559
560
562 SYMBOL_CHANGE_INFO>& aSymbols )
563{
564 wxCHECK( !aSymbols.empty(), 0 );
565
566 int matchesProcessed = 0;
567 SCH_EDIT_FRAME* frame = dynamic_cast<SCH_EDIT_FRAME*>( GetParent() );
568 wxString msg;
569
570 wxCHECK( frame, 0 );
571
572 std::map<SCH_SYMBOL*, SYMBOL_CHANGE_INFO> symbols = aSymbols;
573 std::map<SCH_SYMBOL*, SYMBOL_CHANGE_INFO>::iterator it = symbols.begin();
574
575 // Remove all symbols that don't have a valid library symbol link or enough units to
576 // satisfy the library symbol update.
577 while( it != symbols.end() )
578 {
579 SCH_SYMBOL* symbol = it->first;
580
581 wxCHECK2( symbol && it->second.m_LibId.IsValid(), continue );
582
583 LIB_SYMBOL* libSymbol = frame->GetLibSymbol( it->second.m_LibId );
584
585 if( !libSymbol )
586 {
587 msg = getSymbolReferences( *symbol, it->second.m_LibId );
588 msg << wxT( ": " ) << _( "*** symbol not found ***" );
590 it = symbols.erase( it );
591 continue;
592 }
593
594 std::unique_ptr<LIB_SYMBOL> flattenedSymbol = libSymbol->Flatten();
595
596 if( flattenedSymbol->GetUnitCount() < symbol->GetUnit() )
597 {
598 msg = getSymbolReferences( *symbol, it->second.m_LibId );
599 msg << wxT( ": " ) << _( "*** new symbol has too few units ***" );
601 it = symbols.erase( it );
602 }
603 else
604 {
605 ++it;
606 }
607 }
608
609 // Removing the symbol needs to be done before the LIB_SYMBOL is changed to prevent stale
610 // library symbols in the schematic file.
611 for( const auto& [ symbol, symbol_change_info ] : symbols )
612 {
613 wxCHECK( symbol && !symbol_change_info.m_Instances.empty(), 0 );
614
615 SCH_SCREEN* screen = symbol_change_info.m_Instances[0].LastScreen();
616
617 wxCHECK( screen, 0 );
618
619 screen->Remove( symbol );
620 SCH_SYMBOL* symbol_copy = static_cast<SCH_SYMBOL*>( symbol->Clone() );
621 aCommit->Modified( symbol, symbol_copy, screen );
622
623 CONNECTION_GRAPH* connectionGraph = screen->Schematic()->ConnectionGraph();
624
625 // When we replace the lib symbol below, we free the associated pins if the new symbol has
626 // fewer than the original. This will cause the connection graph to be out of date unless
627 // we replace references in the graph to the old symbol/pins with references to the ones
628 // stored in the undo stack.
629 if( connectionGraph )
630 connectionGraph->ExchangeItem( symbol, symbol_copy );
631 }
632
633 for( const auto& [ symbol, symbol_change_info ] : symbols )
634 {
635 // Remember initial link before changing for diags purpose
636 wxString initialLibLinkName = UnescapeString( symbol->GetLibId().Format() );
637
638 if( symbol_change_info.m_LibId != symbol->GetLibId() )
639 symbol->SetLibId( symbol_change_info.m_LibId );
640
641 LIB_SYMBOL* libSymbol = frame->GetLibSymbol( symbol_change_info.m_LibId );
642 std::unique_ptr<LIB_SYMBOL> flattenedSymbol = libSymbol->Flatten();
643 SCH_SCREEN* screen = symbol_change_info.m_Instances[0].LastScreen();
644
645 symbol->SetLibSymbol( flattenedSymbol.release() );
646
647 if( m_resetAttributes->GetValue() )
648 {
649 // Fetch the attributes from the *flattened* library symbol. They are not supported
650 // in derived symbols.
651 symbol->SetExcludedFromSim( symbol->GetLibSymbolRef()->GetExcludedFromSim() );
652 symbol->SetExcludedFromBOM( symbol->GetLibSymbolRef()->GetExcludedFromBOM() );
653 symbol->SetExcludedFromBoard( symbol->GetLibSymbolRef()->GetExcludedFromBoard() );
654 }
655
656 if( m_resetPinTextVisibility->GetValue() )
657 {
658 symbol->SetShowPinNames( symbol->GetLibSymbolRef()->GetShowPinNames() );
659 symbol->SetShowPinNumbers( symbol->GetLibSymbolRef()->GetShowPinNumbers() );
660 }
661
662 bool removeExtras = m_removeExtraBox->GetValue();
663 bool resetVis = m_resetFieldVisibilities->GetValue();
664 bool resetEffects = m_resetFieldEffects->GetValue();
665 bool resetPositions = m_resetFieldPositions->GetValue();
666
667 for( int ii = (int) symbol->GetFields().size() - 1; ii >= 0; ii-- )
668 {
669 SCH_FIELD& field = symbol->GetFields()[ii];
670 SCH_FIELD* libField = nullptr;
671 bool doUpdate = field.IsPrivate();
672
673 // Mandatory fields always exist in m_updateFields, but these names can be translated.
674 // so use GetCanonicalName().
675 doUpdate |= alg::contains( m_updateFields, field.GetCanonicalName() );
676
677 if( !doUpdate )
678 continue;
679
680 if( field.IsMandatory() )
681 libField = symbol->GetLibSymbolRef()->GetField( field.GetId() );
682 else
683 libField = symbol->GetLibSymbolRef()->GetField( field.GetName() );
684
685 if( libField )
686 {
687 field.SetPrivate( libField->IsPrivate() );
688
689 bool resetText = libField->GetText().IsEmpty() ? m_resetEmptyFields->GetValue()
690 : m_resetFieldText->GetValue();
691
692 if( resetText )
693 {
694 if( field.GetId() == FIELD_T::REFERENCE )
695 {
696 wxString prefix = UTIL::GetRefDesPrefix( libField->GetText() );
697
698 for( const SCH_SHEET_PATH& instance : symbol_change_info.m_Instances )
699 {
700 wxString ref = symbol->GetRef( &instance );
701 int number = UTIL::GetRefDesNumber( ref );
702
703 if( number >= 0 )
704 ref.Printf( wxS( "%s%d" ), prefix, number );
705 else
706 ref = UTIL::GetRefDesUnannotated( prefix );
707
708 symbol->SetRef( &instance, ref );
709 }
710 }
711 else if( field.GetId() == FIELD_T::VALUE )
712 {
713 if( !symbol->IsPower() || m_resetCustomPower->IsChecked() )
714 symbol->SetValueFieldText( UnescapeString( libField->GetText() ) );
715 }
716 else
717 {
718 field.SetText( libField->GetText() );
719 }
720 }
721
722 if( resetVis )
723 field.SetVisible( libField->IsVisible() );
724
725 if( resetEffects )
726 {
727 // Careful: the visible bit and position are also set by SetAttributes()
728 bool visible = field.IsVisible();
729 VECTOR2I pos = field.GetPosition();
730
731 field.SetAttributes( *libField );
732
733 field.SetVisible( visible );
734 field.SetPosition( pos );
735 field.SetNameShown( libField->IsNameShown() );
736 field.SetCanAutoplace( libField->CanAutoplace() );
737 }
738
739 if( resetPositions )
740 field.SetTextPos( symbol->GetPosition() + libField->GetTextPos() );
741 }
742 else if( !field.IsMandatory() && removeExtras )
743 {
744 symbol->RemoveField( field.GetName() );
745 }
746 }
747
748 std::vector<SCH_FIELD*> libFields;
749 symbol->GetLibSymbolRef()->GetFields( libFields );
750
751 for( SCH_FIELD* libField : libFields )
752 {
753 if( libField->IsMandatory() )
754 continue;
755
756 if( !alg::contains( m_updateFields, libField->GetCanonicalName() ) )
757 continue;
758
759 if( !symbol->GetField( libField->GetName() ) )
760 {
761 SCH_FIELD* schField = symbol->AddField( SCH_FIELD( symbol, FIELD_T::USER, libField->GetName() ) );
762
763 // SetAttributes() also covers text angle, size, italic and bold
764 schField->SetAttributes( *libField );
765 schField->SetVisible( libField->IsVisible() );
766 schField->SetText( libField->GetText() );
767 schField->SetTextPos( symbol->GetPosition() + libField->GetTextPos() );
768 schField->SetPrivate( libField->IsPrivate() );
769 }
770
771 if( resetPositions && frame->eeconfig()->m_AutoplaceFields.enable )
772 {
773 AUTOPLACE_ALGO fieldsAutoplaced = symbol->GetFieldsAutoplaced();
774
775 if( fieldsAutoplaced == AUTOPLACE_AUTO || fieldsAutoplaced == AUTOPLACE_MANUAL )
776 symbol->AutoplaceFields( screen, fieldsAutoplaced );
777 }
778 }
779
780 symbol->SetSchSymbolLibraryName( wxEmptyString );
781 screen->Append( symbol );
782
783 if( resetPositions )
784 {
785 AUTOPLACE_ALGO fieldsAutoplaced = symbol->GetFieldsAutoplaced();
786
787 if( fieldsAutoplaced == AUTOPLACE_AUTO || fieldsAutoplaced == AUTOPLACE_MANUAL )
788 symbol->AutoplaceFields( screen, fieldsAutoplaced );
789 }
790
791 // Clear alternate pins as required.
792 for( const SCH_SHEET_PATH& instance : symbol_change_info.m_Instances )
793 {
794 for( SCH_PIN* pin : symbol->GetPins( &instance ) )
795 {
796 if( !pin->GetAlt().IsEmpty() )
797 {
798 // There is a bug that allows the alternate pin name to be set to the default pin
799 // name which causes library symbol comparison errors. Clear the alternate pin
800 // name in this case even if the reset option is not checked. Also clear the
801 // alternate pin name if it no longer exists in the alternate pin map.
802 if( m_resetAlternatePin->IsChecked()
803 || ( pin->GetAlt() == pin->GetBaseName() )
804 || ( pin->GetAlternates().count( pin->GetAlt() ) == 0 ) )
805 {
806 pin->SetAlt( wxEmptyString );
807 }
808 }
809 }
810 }
811
812 frame->GetCanvas()->GetView()->Update( symbol );
813
814 msg = getSymbolReferences( *symbol, symbol_change_info.m_LibId, &initialLibLinkName );
815 msg += wxS( ": OK" );
817 matchesProcessed +=1;
818 }
819
820 return matchesProcessed;
821}
822
823
825 const wxString* aOldLibLinkName )
826{
827 wxString msg;
828 wxString references;
829 const LIB_ID& oldId = aSymbol.GetLibId();
830 wxString oldLibLinkName; // For report
831
832 if( aOldLibLinkName )
833 oldLibLinkName = *aOldLibLinkName;
834 else
835 oldLibLinkName = UnescapeString( oldId.Format() );
836
837 SCH_EDIT_FRAME* parent = dynamic_cast< SCH_EDIT_FRAME* >( GetParent() );
838
839 wxCHECK( parent, msg );
840
841 SCH_SHEET_LIST sheets = parent->Schematic().Hierarchy();
842
843 for( const SCH_SYMBOL_INSTANCE& instance : aSymbol.GetInstances() )
844 {
845 // Only include the symbol instances for the current project.
846 if( !sheets.HasPath( instance.m_Path ) )
847 continue;
848
849 if( references.IsEmpty() )
850 references = instance.m_Reference;
851 else
852 references += wxT( " " ) + instance.m_Reference;
853 }
854
855 if( m_mode == MODE::UPDATE )
856 {
857 if( aSymbol.GetInstances().size() == 1 )
858 {
859 msg.Printf( _( "Update symbol %s from '%s' to '%s'" ),
860 references,
861 oldLibLinkName,
862 UnescapeString( aNewId.Format() ) );
863 }
864 else
865 {
866 msg.Printf( _( "Update symbols %s from '%s' to '%s'" ),
867 references,
868 oldLibLinkName,
869 UnescapeString( aNewId.Format() ) );
870 }
871 }
872 else // mode is MODE::CHANGE
873 {
874 if( aSymbol.GetInstances().size() == 1 )
875 {
876 msg.Printf( _( "Change symbol %s from '%s' to '%s'" ),
877 references,
878 oldLibLinkName,
879 UnescapeString( aNewId.Format() ) );
880 }
881 else
882 {
883 msg.Printf( _( "Change symbols %s from '%s' to '%s'" ),
884 references,
885 oldLibLinkName,
886 UnescapeString( aNewId.Format() ) );
887 }
888 }
889
890 return msg;
891}
wxBitmapBundle KiBitmapBundle(BITMAPS aBitmap, int aMinHeight)
Definition: bitmap.cpp:110
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
Calculate the connectivity of a schematic and generates netlists.
void ExchangeItem(SCH_ITEM *aOldItem, SCH_ITEM *aNewItem)
Replace all references to #aOldItem with #aNewItem in the graph.
Class DIALOG_CHANGE_SYMBOLS_BASE.
WX_HTML_REPORT_PANEL * m_messagePanel
STD_BITMAP_BUTTON * m_matchIdBrowserButton
void onNewLibIDKillFocus(wxFocusEvent &event) override
void onMatchBySelected(wxCommandEvent &aEvent) override
bool isMatch(SCH_SYMBOL *aSymbol, SCH_SHEET_PATH *aInstance)
std::map< FIELD_T, int > m_mandatoryFieldListIndexes
Index in the list control for each mandatory FIELD_T type.
void onOkButtonClicked(wxCommandEvent &aEvent) override
void selectAll(bool aSelect)
Select or deselect all fields in the listbox widget.
std::set< wxString > m_updateFields
Set of field names that should have values updated.
void onMatchById(wxCommandEvent &aEvent) override
bool TransferDataToWindow() override
void launchMatchIdSymbolBrowser(wxCommandEvent &aEvent) override
void onMatchByReference(wxCommandEvent &aEvent) override
void onMatchByValue(wxCommandEvent &aEvent) override
int processMatchingSymbols(SCH_COMMIT *aCommit)
DIALOG_CHANGE_SYMBOLS(SCH_EDIT_FRAME *aParent, SCH_SYMBOL *aSymbol, MODE aMode=MODE::UPDATE)
void onMatchTextKillFocus(wxFocusEvent &event) override
void onMatchIDKillFocus(wxFocusEvent &event) override
wxString getSymbolReferences(SCH_SYMBOL &aSymbol, const LIB_ID &aNewId, const wxString *aOldLibLinkName=nullptr)
void launchNewIdSymbolBrowser(wxCommandEvent &aEvent) override
void onMatchByAll(wxCommandEvent &aEvent) override
int processSymbols(SCH_COMMIT *aCommit, const std::map< SCH_SYMBOL *, SYMBOL_CHANGE_INFO > &aSymbols)
void SetupStandardButtons(std::map< int, wxString > aLabels={})
std::string m_hash_key
Definition: dialog_shim.h:236
void finishDialogSettings()
In all dialogs, we must call the same functions to fix minimal dlg size, the default position and per...
bool IsSelected() const
Definition: eda_item.h:127
const VECTOR2I & GetTextPos() const
Definition: eda_text.h:270
virtual const wxString & GetText() const
Return the string associated with the text object.
Definition: eda_text.h:97
virtual bool IsVisible() const
Definition: eda_text.h:184
void SetTextPos(const VECTOR2I &aPoint)
Definition: eda_text.cpp:578
void SetAttributes(const EDA_TEXT &aSrc, bool aSetPosition=true)
Set the text attributes from another instance.
Definition: eda_text.cpp:433
virtual void SetVisible(bool aVisible)
Definition: eda_text.cpp:386
AUTOPLACE_FIELDS m_AutoplaceFields
EE_TYPE OfType(KICAD_T aType) const
Definition: sch_rtree.h:241
void Update(const KIGFX::VIEW_ITEM *aItem, int aUpdateFlags) const override
For dynamic VIEWs, inform the associated VIEW that the graphical representation of this item has chan...
Definition: sch_view.cpp:60
PROJECT & Prj() const
Return a reference to the PROJECT associated with this KIWAY.
KIWAY & Kiway() const
Return a reference to the KIWAY that this object has an opportunity to participate in.
Definition: kiway_holder.h:55
A wxFrame capable of the OpenProjectFiles function, meaning it can load a portion of a KiCad project.
Definition: kiway_player.h:65
A logical library item identifier and consists of various portions much like a URI.
Definition: lib_id.h:49
int Parse(const UTF8 &aId, bool aFix=false)
Parse LIB_ID with the information from aId.
Definition: lib_id.cpp:52
bool IsValid() const
Check if this LID_ID is valid.
Definition: lib_id.h:172
UTF8 Format() const
Definition: lib_id.cpp:119
Define a library symbol object.
Definition: lib_symbol.h:85
std::unique_ptr< LIB_SYMBOL > Flatten() const
Return a flattened symbol inheritance to the caller.
Definition: lib_symbol.cpp:344
SCH_SHEET_LIST Hierarchy() const
Return the full schematic flattened hierarchical sheet list.
Definition: schematic.cpp:258
CONNECTION_GRAPH * ConnectionGraph() const
Definition: schematic.h:183
SCH_SHEET_PATH & CurrentSheet() const
Definition: schematic.h:171
SCH_DRAW_PANEL * GetCanvas() const override
Return a pointer to GAL-based canvas of given EDA draw frame.
EESCHEMA_SETTINGS * eeconfig() const
LIB_SYMBOL * GetLibSymbol(const LIB_ID &aLibId, bool aUseCacheLib=false, bool aShowErrorMsg=false)
Load symbol from symbol library table.
virtual void Push(const wxString &aMessage=wxT("A commit"), int aCommitFlags=0) override
Execute the changes.
Definition: sch_commit.cpp:489
KIGFX::SCH_VIEW * GetView() const override
Return a pointer to the #VIEW instance used in the panel.
Schematic editor (Eeschema) main window.
SCH_SHEET_PATH & GetCurrentSheet() const
SCHEMATIC & Schematic() const
bool IsMandatory() const
Definition: sch_field.cpp:1359
VECTOR2I GetPosition() const override
Definition: sch_field.cpp:1337
bool IsNameShown() const
Definition: sch_field.h:202
FIELD_T GetId() const
Definition: sch_field.h:116
void SetCanAutoplace(bool aCanPlace)
Definition: sch_field.h:214
wxString GetCanonicalName() const
Get a non-language-specific name for a field which can be used for storage, variable look-up,...
Definition: sch_field.cpp:1117
wxString GetName(bool aUseDefaultName=true) const
Return the field name (not translated).
Definition: sch_field.cpp:1103
void SetPosition(const VECTOR2I &aPosition) override
Definition: sch_field.cpp:1317
bool CanAutoplace() const
Definition: sch_field.h:213
void SetText(const wxString &aText) override
Definition: sch_field.cpp:1089
void SetNameShown(bool aShown=true)
Definition: sch_field.h:203
Base class for any item which can be embedded within the SCHEMATIC container class,...
Definition: sch_item.h:168
void SetPrivate(bool aPrivate)
Definition: sch_item.h:253
SCHEMATIC * Schematic() const
Search the item hierarchy to find a SCHEMATIC.
Definition: sch_item.cpp:246
int GetUnit() const
Definition: sch_item.h:239
bool IsPrivate() const
Definition: sch_item.h:254
void Append(SCH_ITEM *aItem, bool aUpdateLibSymbol=true)
Definition: sch_screen.cpp:160
EE_RTREE & Items()
Get the full RTree, usually for iterating.
Definition: sch_screen.h:117
bool Remove(SCH_ITEM *aItem, bool aUpdateLibSymbol=true)
Remove aItem from the schematic associated with this screen.
Definition: sch_screen.cpp:330
SCHEMATIC * Schematic() const
Definition: sch_screen.cpp:105
A container for handling SCH_SHEET_PATH objects in a flattened hierarchy.
bool HasPath(const KIID_PATH &aPath) const
Handle access to a stack of flattened SCH_SHEET objects by way of a path for creating a flattened sch...
void UpdateAllScreenReferences() const
Update all the symbol references for this sheet path.
Schematic symbol object.
Definition: sch_symbol.h:75
const std::vector< SCH_SYMBOL_INSTANCE > & GetInstances() const
Definition: sch_symbol.h:134
void GetFields(std::vector< SCH_FIELD * > &aVector, bool aVisibleOnly) const override
Populate a std::vector with SCH_FIELDs, sorted in ordinal order.
Definition: sch_symbol.cpp:788
const LIB_ID & GetLibId() const override
Definition: sch_symbol.h:164
const wxString GetRef(const SCH_SHEET_PATH *aSheet, bool aIncludeUnit=false) const override
Definition: sch_symbol.cpp:558
SCH_FIELD * GetField(FIELD_T aFieldType)
Return a mandatory field in this symbol.
Definition: sch_symbol.cpp:760
void SetBitmap(const wxBitmapBundle &aBmp)
void Clear()
Clears the report panel.
void SetLazyUpdate(bool aLazyUpdate)
Set the lazy update.
void SetFileName(const wxString &aReportFileName)
Set the report full file name to the string.
void Report(const wxString &aText, SEVERITY aSeverity, REPORTER::LOCATION aLocation=REPORTER::LOC_BODY)
Report the string.
void Flush(bool aSort=false)
Force updating the HTML page, after the report is built in lazy mode If aSort = true,...
bool g_selectRefDes
wxString getLibIdValue(const wxTextCtrl *aCtrl)
bool g_selectValue
#define _(s)
@ FRAME_SYMBOL_CHOOSER
Definition: frame_type.h:37
wxString GetRefDesPrefix(const wxString &aRefDes)
Get the (non-numeric) prefix from a refdes - e.g.
wxString GetRefDesUnannotated(const wxString &aSource)
Return an unannotated refdes from either a prefix or an existing refdes.
int GetRefDesNumber(const wxString &aRefDes)
Get the numeric suffix from a refdes - e.g.
bool contains(const _Container &__container, _Value __value)
Returns true if the container contains the given value.
Definition: kicad_algo.h:100
Collection of utility functions for component reference designators (refdes)
@ RPT_SEVERITY_ERROR
@ RPT_SEVERITY_ACTION
AUTOPLACE_ALGO
Definition: sch_item.h:69
@ AUTOPLACE_MANUAL
Definition: sch_item.h:72
@ AUTOPLACE_AUTO
Definition: sch_item.h:71
std::vector< FAB_LAYER_COLOR > dummy
bool WildCompareString(const wxString &pattern, const wxString &string_to_tst, bool case_sensitive)
Compare a string against wild card (* and ?) pattern using the usual rules.
wxString UnescapeString(const wxString &aSource)
wxString EscapeString(const wxString &aSource, ESCAPE_CONTEXT aContext)
The Escape/Unescape routines use HTML-entity-reference-style encoding to handle characters which are:...
#define TO_UTF8(wxstring)
Convert a wxString to a UTF8 encoded C string for all wxWidgets build modes.
Definition: string_utils.h:429
@ CTX_LIBID
Definition: string_utils.h:54
A simple container for schematic symbol instance information.
wxString GetDefaultFieldName(FIELD_T aFieldId, bool aTranslateForHI)
Return a default symbol field name for a mandatory field type.
#define DO_TRANSLATE
#define MANDATORY_FIELDS
FIELD_T
The set of all field indices assuming an array like sequence that a SCH_COMPONENT or LIB_PART can hol...
wxString GetCanonicalFieldName(FIELD_T aFieldType)
@ SCH_SYMBOL_T
Definition: typeinfo.h:173