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