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 // { change, update }
44bool g_removeExtraFields[2] = { false, false };
45bool g_resetEmptyFields[2] = { false, false };
46bool g_resetFieldText[2] = { true, true };
47bool g_resetFieldVisibilities[2] = { true, false };
48bool g_resetFieldEffects[2] = { true, false };
49bool g_resetFieldPositions[2] = { true, false };
50bool g_resetAttributes[2] = { true, false };
51bool g_resetPinVisibilities[2] = { true, false };
52bool g_resetCustomPower[2] = { false, false };
53bool g_resetAlternatePins[2] = { true, false };
54
55
57 MODE aMode ) :
59 m_symbol( aSymbol),
60 m_mode( aMode )
61{
62 wxASSERT( aParent );
63
64 if( m_mode == MODE::UPDATE )
65 {
66 m_newIdSizer->Show( false );
67 }
68 else
69 {
70 m_matchAll->SetLabel( _( "Change all symbols in schematic" ) );
71 SetTitle( _( "Change Symbols" ) );
72 m_matchSizer->FindItem( m_matchAll )->Show( false );
73 }
74
75 if( m_symbol )
76 {
77 SCH_SHEET_PATH* currentSheet = &aParent->Schematic().CurrentSheet();
78
79 if( m_mode == MODE::CHANGE )
80 m_matchBySelection->SetLabel( _( "Change selected symbol(s)" ) );
81
82 m_newId->ChangeValue( UnescapeString( m_symbol->GetLibId().Format() ) );
83 m_specifiedReference->ChangeValue( m_symbol->GetRef( currentSheet ) );
84 m_specifiedValue->ChangeValue( UnescapeString( m_symbol->GetField( FIELD_T::VALUE )->GetText() ) );
85 m_specifiedId->ChangeValue( UnescapeString( m_symbol->GetLibId().Format() ) );
86 }
87 else
88 {
89 m_matchSizer->FindItem( m_matchBySelection )->Show( false );
90 }
91
92 m_matchIdBrowserButton->SetBitmap( KiBitmapBundle( BITMAPS::small_library ) );
93 m_newIdBrowserButton->SetBitmap( KiBitmapBundle( BITMAPS::small_library ) );
94
95 if( m_mode == MODE::CHANGE )
96 {
97 m_matchByReference->SetLabel( _( "Change symbols matching reference designator:" ) );
98 m_matchByValue->SetLabel( _( "Change symbols matching value:" ) );
99 m_matchById->SetLabel( _( "Change symbols matching library identifier:" ) );
100 }
101
102 m_matchSizer->SetEmptyCellSize( wxSize( 0, 0 ) );
103 m_matchSizer->Layout();
104
105 for( FIELD_T fieldId : MANDATORY_FIELDS )
106 {
107 int listIdx = m_fieldsBox->GetCount();
108
109 m_fieldsBox->Append( GetDefaultFieldName( fieldId, DO_TRANSLATE ) );
110
111 if( fieldId == FIELD_T::REFERENCE )
112 m_fieldsBox->Check( listIdx, g_selectRefDes );
113 else if( fieldId == FIELD_T::VALUE )
114 m_fieldsBox->Check( listIdx, g_selectValue );
115 else
116 m_fieldsBox->Check( listIdx, true );
117
118 m_mandatoryFieldListIndexes[fieldId] = listIdx;
119 }
120
122 m_messagePanel->SetFileName( Prj().GetProjectPath() + wxT( "report.txt" ) );
123
124 if( aSymbol && aSymbol->IsSelected() )
125 {
126 m_matchBySelection->SetValue( true );
127 }
128 else
129 {
130 if( aMode == MODE::UPDATE )
131 m_matchAll->SetValue( true );
132 else
133 m_matchByReference->SetValue( true );
134 }
135
137
138 if( m_mode == MODE::CHANGE )
139 {
140 m_updateFieldsSizer->GetStaticBox()->SetLabel( _( "Update Fields" ) );
141 m_removeExtraBox->SetLabel( _( "Remove fields if not in new symbol" ) );
142 m_resetEmptyFields->SetLabel( _( "Reset fields if empty in new symbol" ) );
143 m_resetFieldText->SetLabel( _( "Update field text" ) );
144 m_resetFieldVisibilities->SetLabel( _( "Update field visibilities" ) );
145 m_resetFieldEffects->SetLabel( _( "Update field sizes and styles" ) );
146 m_resetFieldPositions->SetLabel( _( "Update field positions" ) );
147 m_resetAttributes->SetLabel( _( "Update symbol attributes" ) );
148 m_resetPinTextVisibility->SetLabel( _( "Update pin name/number visibilities" ) );
149 m_resetAlternatePin->SetLabel( _( "Reset alternate pin functions" ) );
150 m_resetCustomPower->SetLabel( _( "Reset custom power symbols" ) );
151 }
152
153 m_removeExtraBox->SetValue( g_removeExtraFields[ (int) m_mode ] );
154 m_resetEmptyFields->SetValue( g_resetEmptyFields[ (int) m_mode ] );
155 m_resetFieldText->SetValue( g_resetFieldText[ (int) m_mode ] );
157 m_resetFieldEffects->SetValue( g_resetFieldEffects[ (int) m_mode ] );
159 m_resetAttributes->SetValue( g_resetAttributes[ (int) m_mode ] );
161 m_resetCustomPower->SetValue( g_resetCustomPower[ (int) m_mode ] );
162 m_resetAlternatePin->SetValue( g_resetAlternatePins[ (int) m_mode ] );
163
164 // DIALOG_SHIM needs a unique hash_key because classname is not sufficient
165 // because the update and change versions of this dialog have different controls.
166 m_hash_key = TO_UTF8( GetTitle() );
167
168 wxString okLabel = m_mode == MODE::CHANGE ? _( "Change" ) : _( "Update" );
169
170 SetupStandardButtons( { { wxID_OK, okLabel },
171 { wxID_CANCEL, _( "Close" ) } } );
172
173 // Now all widgets have the size fixed, call FinishDialogSettings
175}
176
177
178void DIALOG_CHANGE_SYMBOLS::onMatchByAll( wxCommandEvent& aEvent )
179{
181}
182
183
184void DIALOG_CHANGE_SYMBOLS::onMatchBySelected( wxCommandEvent& aEvent )
185{
187}
188
189
190void DIALOG_CHANGE_SYMBOLS::onMatchByReference( wxCommandEvent& aEvent )
191{
193 m_specifiedReference->SetFocus();
194}
195
196
197void DIALOG_CHANGE_SYMBOLS::onMatchByValue( wxCommandEvent& aEvent )
198{
200 m_specifiedValue->SetFocus();
201}
202
203
204void DIALOG_CHANGE_SYMBOLS::onMatchById( wxCommandEvent& aEvent )
205{
207 m_specifiedId->SetFocus();
208}
209
210
212{
214 event.Skip(); // Mandatory in wxFocusEvent
215}
216
217
219{
221 event.Skip(); // Mandatory in wxFocusEvent
222}
223
224
226{
228 event.Skip(); // Mandatory in wxFocusEvent
229}
230
231
233{
234 g_selectRefDes = m_fieldsBox->IsChecked( m_mandatoryFieldListIndexes[FIELD_T::REFERENCE] );
235 g_selectValue = m_fieldsBox->IsChecked( m_mandatoryFieldListIndexes[FIELD_T::VALUE] );
236
237 g_removeExtraFields[ (int) m_mode ] = m_removeExtraBox->GetValue();
238 g_resetEmptyFields[ (int) m_mode ] = m_resetEmptyFields->GetValue();
239 g_resetFieldText[ (int) m_mode ] = m_resetFieldText->GetValue();
241 g_resetFieldEffects[ (int) m_mode ] = m_resetFieldEffects->GetValue();
243 g_resetAttributes[ (int) m_mode ] = m_resetAttributes->GetValue();
245 g_resetCustomPower[ (int) m_mode ] = m_resetCustomPower->GetValue();
246 g_resetAlternatePins[ (int) m_mode ] = m_resetAlternatePin->GetValue();
247}
248
249
250wxString getLibIdValue( const wxTextCtrl* aCtrl )
251{
252 wxString rawValue = aCtrl->GetValue();
253 wxString itemName;
254 wxString libName = rawValue.BeforeFirst( ':', &itemName );
255
256 return EscapeString( libName, CTX_LIBID ) + ':' + EscapeString( itemName, CTX_LIBID );
257}
258
259
261{
262 wxString newName = getLibIdValue( m_specifiedId );
263
264 if( KIWAY_PLAYER* frame = Kiway().Player( FRAME_SYMBOL_CHOOSER, true, this ) )
265 {
266 if( frame->ShowModal( &newName, this ) )
267 {
268 m_specifiedId->SetValue( UnescapeString( newName ) );
270 }
271
272 frame->Destroy();
273 }
274}
275
276
278{
279 wxString newName = getLibIdValue( m_newId );
280
281 if( KIWAY_PLAYER* frame = Kiway().Player( FRAME_SYMBOL_CHOOSER, true, this ) )
282 {
283 if( frame->ShowModal( &newName, this ) )
284 {
285 m_newId->SetValue( UnescapeString( newName ) );
287 }
288
289 frame->Destroy();
290 }
291}
292
293
295{
296 SCH_EDIT_FRAME* frame = dynamic_cast<SCH_EDIT_FRAME*>( GetParent() );
297
298 wxCHECK( frame, /* void */ );
299
300 // Load non-mandatory fields from all matching symbols and their library symbols
301 std::set<wxString> fieldNames;
302
303 for( SCH_SHEET_PATH& instance : frame->Schematic().Hierarchy() )
304 {
305 SCH_SCREEN* screen = instance.LastScreen();
306
307 wxCHECK2( screen, continue );
308
309 for( SCH_ITEM* item : screen->Items().OfType( SCH_SYMBOL_T ) )
310 {
311 SCH_SYMBOL* symbol = dynamic_cast<SCH_SYMBOL*>( item );
312
313 wxCHECK2( symbol, continue );
314
315 if( !isMatch( symbol, &instance ) )
316 continue;
317
318 for( SCH_FIELD& field : symbol->GetFields() )
319 {
320 if( !field.IsMandatory() && !field.IsPrivate() )
321 fieldNames.insert( field.GetName() );
322 }
323
324 if( m_mode == MODE::UPDATE && symbol->GetLibId().IsValid() )
325 {
326 LIB_SYMBOL* libSymbol = frame->GetLibSymbol( symbol->GetLibId() );
327
328 if( libSymbol )
329 {
330 std::unique_ptr<LIB_SYMBOL> flattenedSymbol = libSymbol->Flatten();
331 std::vector<SCH_FIELD*> orderedLibFields;
332
333 flattenedSymbol->GetFields( orderedLibFields );
334
335 for( SCH_FIELD* libField : orderedLibFields )
336 {
337 if( !libField->IsMandatory() && !libField->IsPrivate() )
338 fieldNames.insert( libField->GetName() );
339 }
340 }
341 }
342 }
343 }
344
345 // Load non-mandatory fields from the change-to library symbol
346 if( m_mode == MODE::CHANGE )
347 {
348 LIB_ID newId;
349
350 newId.Parse( getLibIdValue( m_newId ) );
351
352 if( newId.IsValid() )
353 {
354 LIB_SYMBOL* libSymbol = frame->GetLibSymbol( newId );
355
356 if( libSymbol )
357 {
358 std::unique_ptr<LIB_SYMBOL> flattenedSymbol = libSymbol->Flatten();
359 std::vector<SCH_FIELD*> orderedLibFields;
360
361 flattenedSymbol->GetFields( orderedLibFields );
362
363 for( SCH_FIELD* libField : orderedLibFields )
364 {
365 if( !libField->IsMandatory() && !libField->IsPrivate() )
366 fieldNames.insert( libField->GetName() );
367 }
368 }
369 }
370 }
371
372 // Update the listbox widget
373 wxArrayInt checkedItems;
374 wxArrayString checkedNames;
375
376 m_fieldsBox->GetCheckedItems( checkedItems );
377
378 for( int ii : checkedItems )
379 checkedNames.push_back( m_fieldsBox->GetString( ii ) );
380
381 bool allChecked = true;
382
383 for( int ii = 0; ii < (int) m_fieldsBox->GetCount(); ++ii )
384 {
385 if( !m_fieldsBox->IsChecked( ii )
386 && ii != m_mandatoryFieldListIndexes[FIELD_T::REFERENCE]
387 && ii != m_mandatoryFieldListIndexes[FIELD_T::VALUE] )
388 {
389 allChecked = false;
390 }
391 }
392
393 auto isMandatoryField =
394 [&]( int listbox_idx )
395 {
396 for( FIELD_T fieldId : MANDATORY_FIELDS )
397 {
398 if( m_mandatoryFieldListIndexes[fieldId] == listbox_idx )
399 return true;
400 }
401
402 return false;
403 };
404
405 for( int ii = (int) m_fieldsBox->GetCount() - 1; ii >= 0; --ii )
406 {
407 if( isMandatoryField( ii ) )
408 continue;
409
410 m_fieldsBox->Delete( ii );
411 }
412
413 for( const wxString& fieldName : fieldNames )
414 {
415 m_fieldsBox->Append( fieldName );
416
417 if( allChecked || alg::contains( checkedNames, fieldName ) )
418 m_fieldsBox->Check( m_fieldsBox->GetCount() - 1, true );
419 }
420}
421
422
424{
425 for( unsigned i = 0; i < m_fieldsBox->GetCount(); ++i )
426 m_fieldsBox->Check( i, aSelect );
427}
428
429
431{
432 m_removeExtraBox->SetValue( aCheck );
433 m_resetEmptyFields->SetValue( aCheck );
434 m_resetFieldText->SetValue( aCheck );
435 m_resetFieldVisibilities->SetValue( aCheck );
436 m_resetFieldEffects->SetValue( aCheck );
437 m_resetFieldPositions->SetValue( aCheck );
438 m_resetPinTextVisibility->SetValue( aCheck );
439 m_resetAlternatePin->SetValue( aCheck );
440 m_resetAttributes->SetValue( aCheck );
441 m_resetCustomPower->SetValue( aCheck );
442}
443
444
445void DIALOG_CHANGE_SYMBOLS::onOkButtonClicked( wxCommandEvent& aEvent )
446{
447 SCH_EDIT_FRAME* parent = dynamic_cast<SCH_EDIT_FRAME*>( GetParent() );
448
449 wxCHECK( parent, /* void */ );
450
451 wxBusyCursor dummy;
452 SCH_COMMIT commit( parent );
453
455 m_messagePanel->Flush( false );
456
457 // Create the set of fields to be updated. Use non translated (canonical) names
458 // for mandatory fields
459 m_updateFields.clear();
460
461 for( unsigned ii = 0; ii < m_fieldsBox->GetCount(); ++ii )
462 {
463 if( m_fieldsBox->IsChecked( ii ) )
464 m_updateFields.insert( m_fieldsBox->GetString( ii ) );
465 }
466
467 for( FIELD_T fieldId : MANDATORY_FIELDS )
468 {
469 if( m_fieldsBox->IsChecked( m_mandatoryFieldListIndexes[fieldId] ) )
470 m_updateFields.insert( GetCanonicalFieldName( fieldId ) );
471 }
472
473 if( processMatchingSymbols( &commit) )
474 commit.Push( m_mode == MODE::CHANGE ? _( "Change Symbols" ) : _( "Update Symbols" ) );
475
476 m_messagePanel->Flush( false );
477}
478
479
481{
482 SCH_EDIT_FRAME* frame = dynamic_cast<SCH_EDIT_FRAME*>( GetParent() );
483
484 wxCHECK( frame, false );
485
486 if( !aSymbol )
487 return false;
488
489 if( m_matchAll->GetValue() )
490 {
491 return true;
492 }
493 else if( m_matchBySelection->GetValue() )
494 {
495 return aSymbol == m_symbol || aSymbol->IsSelected();
496 }
497 else if( m_matchByReference->GetValue() )
498 {
499 return WildCompareString( m_specifiedReference->GetValue(),
500 UnescapeString( aSymbol->GetRef( aInstance, false ) ),
501 false );
502 }
503 else if( m_matchByValue->GetValue() )
504 {
505 return WildCompareString( m_specifiedValue->GetValue(),
506 UnescapeString( aSymbol->GetField( FIELD_T::VALUE )->GetText() ),
507 false );
508 }
509 else if( m_matchById )
510 {
511 LIB_ID id;
512
514 return aSymbol->GetLibId() == id;
515 }
516
517 return false;
518}
519
520
522{
523 SCH_EDIT_FRAME* frame = dynamic_cast<SCH_EDIT_FRAME*>( GetParent() );
524
525 wxCHECK( frame, false );
526
527 LIB_ID newId;
528 int matchesProcessed = 0;
529 SCH_SYMBOL* symbol = nullptr;
530
531 if( m_mode == MODE::CHANGE )
532 {
533 newId.Parse( getLibIdValue( m_newId ) );
534
535 if( !newId.IsValid() )
536 return false;
537 }
538
539 std::map<SCH_SYMBOL*, SYMBOL_CHANGE_INFO> symbols;
540
541 for( SCH_SHEET_PATH& instance : frame->Schematic().Hierarchy() )
542 {
543 SCH_SCREEN* screen = instance.LastScreen();
544
545 wxCHECK2( screen, continue );
546
547 // Fetch all the symbols that meet the change criteria.
548 for( SCH_ITEM* item : screen->Items().OfType( SCH_SYMBOL_T ) )
549 {
550 symbol = static_cast<SCH_SYMBOL*>( item );
551
552 wxCHECK2( symbol, continue );
553
554 if( !isMatch( symbol, &instance ) )
555 continue;
556
557 if( m_mode == MODE::UPDATE )
558 newId = symbol->GetLibId();
559
560 auto it = symbols.find( symbol );
561
562 if( it == symbols.end() )
563 {
565
566 info.m_Instances.emplace_back( instance );
567 info.m_LibId = newId;
568 symbols.insert( { symbol, info } );
569 }
570 else
571 {
572 it->second.m_Instances.emplace_back( instance );
573 }
574 }
575 }
576
577 if( symbols.size() > 0 )
578 matchesProcessed += processSymbols( aCommit, symbols );
579 else
580 m_messagePanel->Report( _( "*** No symbols matching criteria found ***" ),
582
584
585 return matchesProcessed;
586}
587
588
590 const std::map<SCH_SYMBOL*,
591 SYMBOL_CHANGE_INFO>& aSymbols )
592{
593 wxCHECK( !aSymbols.empty(), 0 );
594
595 int matchesProcessed = 0;
596 SCH_EDIT_FRAME* frame = dynamic_cast<SCH_EDIT_FRAME*>( GetParent() );
597 wxString msg;
598
599 wxCHECK( frame, 0 );
600
601 std::map<SCH_SYMBOL*, SYMBOL_CHANGE_INFO> symbols = aSymbols;
602 std::map<SCH_SYMBOL*, SYMBOL_CHANGE_INFO>::iterator it = symbols.begin();
603
604 // Remove all symbols that don't have a valid library symbol link or enough units to
605 // satisfy the library symbol update.
606 while( it != symbols.end() )
607 {
608 SCH_SYMBOL* symbol = it->first;
609
610 wxCHECK2( symbol && it->second.m_LibId.IsValid(), continue );
611
612 LIB_SYMBOL* libSymbol = frame->GetLibSymbol( it->second.m_LibId );
613
614 if( !libSymbol )
615 {
616 msg = getSymbolReferences( *symbol, it->second.m_LibId );
617 msg << wxT( ": " ) << _( "*** symbol not found ***" );
619 it = symbols.erase( it );
620 continue;
621 }
622
623 std::unique_ptr<LIB_SYMBOL> flattenedSymbol = libSymbol->Flatten();
624
625 if( flattenedSymbol->GetUnitCount() < symbol->GetUnit() )
626 {
627 msg = getSymbolReferences( *symbol, it->second.m_LibId );
628 msg << wxT( ": " ) << _( "*** new symbol has too few units ***" );
630 it = symbols.erase( it );
631 }
632 else
633 {
634 ++it;
635 }
636 }
637
638 // Removing the symbol needs to be done before the LIB_SYMBOL is changed to prevent stale
639 // library symbols in the schematic file.
640 for( const auto& [ symbol, symbol_change_info ] : symbols )
641 {
642 wxCHECK( symbol && !symbol_change_info.m_Instances.empty(), 0 );
643
644 SCH_SCREEN* screen = symbol_change_info.m_Instances[0].LastScreen();
645
646 wxCHECK( screen, 0 );
647
648 screen->Remove( symbol );
649 SCH_SYMBOL* symbol_copy = static_cast<SCH_SYMBOL*>( symbol->Clone() );
650 aCommit->Modified( symbol, symbol_copy, screen );
651
652 CONNECTION_GRAPH* connectionGraph = screen->Schematic()->ConnectionGraph();
653
654 // When we replace the lib symbol below, we free the associated pins if the new symbol has
655 // fewer than the original. This will cause the connection graph to be out of date unless
656 // we replace references in the graph to the old symbol/pins with references to the ones
657 // stored in the undo stack.
658 if( connectionGraph )
659 connectionGraph->ExchangeItem( symbol, symbol_copy );
660 }
661
662 for( const auto& [ symbol, symbol_change_info ] : symbols )
663 {
664 // Remember initial link before changing for diags purpose
665 wxString initialLibLinkName = UnescapeString( symbol->GetLibId().Format() );
666
667 if( symbol_change_info.m_LibId != symbol->GetLibId() )
668 symbol->SetLibId( symbol_change_info.m_LibId );
669
670 LIB_SYMBOL* libSymbol = frame->GetLibSymbol( symbol_change_info.m_LibId );
671 std::unique_ptr<LIB_SYMBOL> flattenedSymbol = libSymbol->Flatten();
672 SCH_SCREEN* screen = symbol_change_info.m_Instances[0].LastScreen();
673
674 symbol->SetLibSymbol( flattenedSymbol.release() );
675
676 if( m_resetAttributes->GetValue() )
677 {
678 // Fetch the attributes from the *flattened* library symbol. They are not supported
679 // in derived symbols.
680 symbol->SetExcludedFromSim( symbol->GetLibSymbolRef()->GetExcludedFromSim() );
681 symbol->SetExcludedFromBOM( symbol->GetLibSymbolRef()->GetExcludedFromBOM() );
682 symbol->SetExcludedFromBoard( symbol->GetLibSymbolRef()->GetExcludedFromBoard() );
683 }
684
685 if( m_resetPinTextVisibility->GetValue() )
686 {
687 symbol->SetShowPinNames( symbol->GetLibSymbolRef()->GetShowPinNames() );
688 symbol->SetShowPinNumbers( symbol->GetLibSymbolRef()->GetShowPinNumbers() );
689 }
690
691 bool removeExtras = m_removeExtraBox->GetValue();
692 bool resetVis = m_resetFieldVisibilities->GetValue();
693 bool resetEffects = m_resetFieldEffects->GetValue();
694 bool resetPositions = m_resetFieldPositions->GetValue();
695
696 for( int ii = (int) symbol->GetFields().size() - 1; ii >= 0; ii-- )
697 {
698 SCH_FIELD& field = symbol->GetFields()[ii];
699 SCH_FIELD* libField = nullptr;
700 bool doUpdate = field.IsPrivate();
701
702 // Mandatory fields always exist in m_updateFields, but these names can be translated.
703 // so use GetCanonicalName().
704 doUpdate |= alg::contains( m_updateFields, field.GetCanonicalName() );
705
706 if( !doUpdate )
707 continue;
708
709 if( field.IsMandatory() )
710 libField = symbol->GetLibSymbolRef()->GetField( field.GetId() );
711 else
712 libField = symbol->GetLibSymbolRef()->GetField( field.GetName() );
713
714 if( libField )
715 {
716 field.SetPrivate( libField->IsPrivate() );
717
718 bool resetText = libField->GetText().IsEmpty() ? m_resetEmptyFields->GetValue()
719 : m_resetFieldText->GetValue();
720
721 if( resetText )
722 {
723 if( field.GetId() == FIELD_T::REFERENCE )
724 {
725 wxString prefix = UTIL::GetRefDesPrefix( libField->GetText() );
726
727 for( const SCH_SHEET_PATH& instance : symbol_change_info.m_Instances )
728 {
729 wxString ref = symbol->GetRef( &instance );
730 int number = UTIL::GetRefDesNumber( ref );
731
732 if( number >= 0 )
733 ref.Printf( wxS( "%s%d" ), prefix, number );
734 else
735 ref = UTIL::GetRefDesUnannotated( prefix );
736
737 symbol->SetRef( &instance, ref );
738 }
739 }
740 else if( field.GetId() == FIELD_T::VALUE )
741 {
742 if( !symbol->IsPower() || m_resetCustomPower->IsChecked() )
743 symbol->SetValueFieldText( UnescapeString( libField->GetText() ) );
744 }
745 else
746 {
747 field.SetText( libField->GetText() );
748 }
749 }
750
751 if( resetVis )
752 field.SetVisible( libField->IsVisible() );
753
754 if( resetEffects )
755 {
756 // Careful: the visible bit and position are also set by SetAttributes()
757 bool visible = field.IsVisible();
758 VECTOR2I pos = field.GetPosition();
759
760 field.SetAttributes( *libField );
761
762 field.SetVisible( visible );
763 field.SetPosition( pos );
764 field.SetNameShown( libField->IsNameShown() );
765 field.SetCanAutoplace( libField->CanAutoplace() );
766 }
767
768 if( resetPositions )
769 field.SetTextPos( symbol->GetPosition() + libField->GetTextPos() );
770 }
771 else if( !field.IsMandatory() && removeExtras )
772 {
773 symbol->RemoveField( field.GetName() );
774 }
775 }
776
777 std::vector<SCH_FIELD*> libFields;
778 symbol->GetLibSymbolRef()->GetFields( libFields );
779
780 for( SCH_FIELD* libField : libFields )
781 {
782 if( libField->IsMandatory() )
783 continue;
784
785 if( !alg::contains( m_updateFields, libField->GetCanonicalName() ) )
786 continue;
787
788 if( !symbol->GetField( libField->GetName() ) )
789 {
790 SCH_FIELD* schField = symbol->AddField( SCH_FIELD( symbol, FIELD_T::USER, libField->GetName() ) );
791
792 // SetAttributes() also covers text angle, size, italic and bold
793 schField->SetAttributes( *libField );
794 schField->SetVisible( libField->IsVisible() );
795 schField->SetText( libField->GetText() );
796 schField->SetTextPos( symbol->GetPosition() + libField->GetTextPos() );
797 schField->SetPrivate( libField->IsPrivate() );
798 }
799
800 if( resetPositions && frame->eeconfig()->m_AutoplaceFields.enable )
801 {
802 AUTOPLACE_ALGO fieldsAutoplaced = symbol->GetFieldsAutoplaced();
803
804 if( fieldsAutoplaced == AUTOPLACE_AUTO || fieldsAutoplaced == AUTOPLACE_MANUAL )
805 symbol->AutoplaceFields( screen, fieldsAutoplaced );
806 }
807 }
808
809 symbol->SetSchSymbolLibraryName( wxEmptyString );
810 screen->Append( symbol );
811
812 if( resetPositions )
813 {
814 AUTOPLACE_ALGO fieldsAutoplaced = symbol->GetFieldsAutoplaced();
815
816 if( fieldsAutoplaced == AUTOPLACE_AUTO || fieldsAutoplaced == AUTOPLACE_MANUAL )
817 symbol->AutoplaceFields( screen, fieldsAutoplaced );
818 }
819
820 // Clear alternate pins as required.
821 for( const SCH_SHEET_PATH& instance : symbol_change_info.m_Instances )
822 {
823 for( SCH_PIN* pin : symbol->GetPins( &instance ) )
824 {
825 if( !pin->GetAlt().IsEmpty() )
826 {
827 // There is a bug that allows the alternate pin name to be set to the default pin
828 // name which causes library symbol comparison errors. Clear the alternate pin
829 // name in this case even if the reset option is not checked. Also clear the
830 // alternate pin name if it no longer exists in the alternate pin map.
831 if( m_resetAlternatePin->IsChecked() || ( pin->GetAlt() == pin->GetName() )
832 || ( pin->GetAlternates().count( pin->GetAlt() ) == 0 ) )
833 pin->SetAlt( wxEmptyString );
834 }
835 }
836 }
837
838 frame->GetCanvas()->GetView()->Update( symbol );
839
840 msg = getSymbolReferences( *symbol, symbol_change_info.m_LibId, &initialLibLinkName );
841 msg += wxS( ": OK" );
843 matchesProcessed +=1;
844 }
845
846 return matchesProcessed;
847}
848
849
851 const LIB_ID& aNewId,
852 const wxString* aOldLibLinkName )
853{
854 wxString msg;
855 wxString references;
856 const LIB_ID& oldId = aSymbol.GetLibId();
857
858 wxString oldLibLinkName; // For report
859
860 if( aOldLibLinkName )
861 oldLibLinkName = *aOldLibLinkName;
862 else
863 oldLibLinkName = UnescapeString( oldId.Format() );
864
865 SCH_EDIT_FRAME* parent = dynamic_cast< SCH_EDIT_FRAME* >( GetParent() );
866
867 wxCHECK( parent, msg );
868
869 SCH_SHEET_LIST sheets = parent->Schematic().Hierarchy();
870
871 for( const SCH_SYMBOL_INSTANCE& instance : aSymbol.GetInstances() )
872 {
873 // Only include the symbol instances for the current project.
874 if( !sheets.HasPath( instance.m_Path ) )
875 continue;
876
877 if( references.IsEmpty() )
878 references = instance.m_Reference;
879 else
880 references += wxT( " " ) + instance.m_Reference;
881 }
882
883 if( m_mode == MODE::UPDATE )
884 {
885 if( aSymbol.GetInstances().size() == 1 )
886 {
887 msg.Printf( _( "Update symbol %s from '%s' to '%s'" ),
888 references,
889 oldLibLinkName,
890 UnescapeString( aNewId.Format() ) );
891 }
892 else
893 {
894 msg.Printf( _( "Update symbols %s from '%s' to '%s'" ),
895 references,
896 oldLibLinkName,
897 UnescapeString( aNewId.Format() ) );
898 }
899 }
900 else // mode is MODE::CHANGE
901 {
902 if( aSymbol.GetInstances().size() == 1 )
903 {
904 msg.Printf( _( "Change symbol %s from '%s' to '%s'" ),
905 references,
906 oldLibLinkName,
907 UnescapeString( aNewId.Format() ) );
908 }
909 else
910 {
911 msg.Printf( _( "Change symbols %s from '%s' to '%s'" ),
912 references,
913 oldLibLinkName,
914 UnescapeString( aNewId.Format() ) );
915 }
916 }
917
918 return msg;
919}
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
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:194
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:126
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:345
SCH_SHEET_LIST Hierarchy() const
Return the full schematic flattened hierarchical sheet list.
Definition: schematic.cpp:219
CONNECTION_GRAPH * ConnectionGraph() const
Definition: schematic.h:182
SCH_SHEET_PATH & CurrentSheet() const
Definition: schematic.h:170
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:201
FIELD_T GetId() const
Definition: sch_field.h:115
void SetCanAutoplace(bool aCanPlace)
Definition: sch_field.h:213
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:212
void SetText(const wxString &aText) override
Definition: sch_field.cpp:1089
void SetNameShown(bool aShown=true)
Definition: sch_field.h:202
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:249
int GetUnit() const
Definition: sch_item.h:242
bool IsPrivate() const
Definition: sch_item.h:250
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:112
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:780
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:550
SCH_FIELD * GetField(FIELD_T aFieldType)
Return a mandatory field in this symbol.
Definition: sch_symbol.cpp:752
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_resetAlternatePins[2]
bool g_resetFieldEffects[2]
bool g_selectRefDes
bool g_resetFieldPositions[2]
bool g_resetAttributes[2]
bool g_removeExtraFields[2]
bool g_resetFieldVisibilities[2]
bool g_resetEmptyFields[2]
wxString getLibIdValue(const wxTextCtrl *aCtrl)
bool g_resetFieldText[2]
bool g_selectValue
bool g_resetCustomPower[2]
bool g_resetPinVisibilities[2]
#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