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_resetCustomPower[2] = { false, false };
52
53
55 MODE aMode ) :
57 m_symbol( aSymbol),
58 m_mode( aMode )
59{
60 wxASSERT( aParent );
61
62 if( m_mode == MODE::UPDATE )
63 {
64 m_newIdSizer->Show( false );
65 }
66 else
67 {
68 m_matchAll->SetLabel( _( "Change all symbols in schematic" ) );
69 SetTitle( _( "Change Symbols" ) );
70 m_matchSizer->FindItem( m_matchAll )->Show( false );
71 }
72
73 if( m_symbol )
74 {
75 SCH_SHEET_PATH* currentSheet = &aParent->Schematic().CurrentSheet();
76
77 if( m_mode == MODE::CHANGE )
78 m_matchBySelection->SetLabel( _( "Change selected symbol(s)" ) );
79
80 m_newId->ChangeValue( UnescapeString( m_symbol->GetLibId().Format() ) );
81 m_specifiedReference->ChangeValue( m_symbol->GetRef( currentSheet ) );
82 m_specifiedValue->ChangeValue(
84 m_specifiedId->ChangeValue( UnescapeString( m_symbol->GetLibId().Format() ) );
85 }
86 else
87 {
88 m_matchSizer->FindItem( m_matchBySelection )->Show( false );
89 }
90
91 m_matchIdBrowserButton->SetBitmap( KiBitmapBundle( BITMAPS::small_library ) );
92 m_newIdBrowserButton->SetBitmap( KiBitmapBundle( BITMAPS::small_library ) );
93
94 if( m_mode == MODE::CHANGE )
95 {
96 m_matchByReference->SetLabel( _( "Change symbols matching reference designator:" ) );
97 m_matchByValue->SetLabel( _( "Change symbols matching value:" ) );
98 m_matchById->SetLabel( _( "Change symbols matching library identifier:" ) );
99 }
100
101 m_matchSizer->SetEmptyCellSize( wxSize( 0, 0 ) );
102 m_matchSizer->Layout();
103
104 for( int i = 0; i < MANDATORY_FIELDS; ++i )
105 {
107
108 if( i == REFERENCE_FIELD )
109 m_fieldsBox->Check( i, g_selectRefDes );
110 else if( i == VALUE_FIELD )
111 m_fieldsBox->Check( i, g_selectValue );
112 else
113 m_fieldsBox->Check( i, true );
114 }
115
117 m_messagePanel->SetFileName( Prj().GetProjectPath() + wxT( "report.txt" ) );
118
119 if( aSymbol && aSymbol->IsSelected() )
120 {
121 m_matchBySelection->SetValue( true );
122 }
123 else
124 {
125 if( aMode == MODE::UPDATE )
126 m_matchAll->SetValue( true );
127 else
128 m_matchByReference->SetValue( true );
129 }
130
132
133 if( m_mode == MODE::CHANGE )
134 {
135 m_updateFieldsSizer->GetStaticBox()->SetLabel( _( "Update Fields" ) );
136 m_removeExtraBox->SetLabel( _( "Remove fields if not in new symbol" ) );
137 m_resetEmptyFields->SetLabel( _( "Reset fields if empty in new symbol" ) );
138 m_resetFieldText->SetLabel( _( "Update field text" ) );
139 m_resetFieldVisibilities->SetLabel( _( "Update field visibilities" ) );
140 m_resetFieldEffects->SetLabel( _( "Update field sizes and styles" ) );
141 m_resetFieldPositions->SetLabel( _( "Update field positions" ) );
142 m_resetAttributes->SetLabel( _( "Update symbol attributes" ) );
143 }
144
145 m_removeExtraBox->SetValue( g_removeExtraFields[ (int) m_mode ] );
146 m_resetEmptyFields->SetValue( g_resetEmptyFields[ (int) m_mode ] );
147 m_resetFieldText->SetValue( g_resetFieldText[ (int) m_mode ] );
149 m_resetFieldEffects->SetValue( g_resetFieldEffects[ (int) m_mode ] );
151 m_resetAttributes->SetValue( g_resetAttributes[ (int) m_mode ] );
152 m_resetCustomPower->SetValue( g_resetCustomPower[ (int) m_mode ] );
153
154 // DIALOG_SHIM needs a unique hash_key because classname is not sufficient
155 // because the update and change versions of this dialog have different controls.
156 m_hash_key = TO_UTF8( GetTitle() );
157
158 wxString okLabel = m_mode == MODE::CHANGE ? _( "Change" ) : _( "Update" );
159
160 SetupStandardButtons( { { wxID_OK, okLabel },
161 { wxID_CANCEL, _( "Close" ) } } );
162
163 // Now all widgets have the size fixed, call FinishDialogSettings
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{
225 g_selectValue = m_fieldsBox->IsChecked( VALUE_FIELD );
226
227 g_removeExtraFields[ (int) m_mode ] = m_removeExtraBox->GetValue();
228 g_resetEmptyFields[ (int) m_mode ] = m_resetEmptyFields->GetValue();
229 g_resetFieldText[ (int) m_mode ] = m_resetFieldText->GetValue();
231 g_resetFieldEffects[ (int) m_mode ] = m_resetFieldEffects->GetValue();
233 g_resetAttributes[ (int) m_mode ] = m_resetAttributes->GetValue();
234 g_resetCustomPower[ (int) m_mode ] = m_resetCustomPower->GetValue();
235}
236
237
238wxString getLibIdValue( const wxTextCtrl* aCtrl )
239{
240 wxString rawValue = aCtrl->GetValue();
241 wxString itemName;
242 wxString libName = rawValue.BeforeFirst( ':', &itemName );
243
244 return EscapeString( libName, CTX_LIBID ) + ':' + EscapeString( itemName, CTX_LIBID );
245}
246
247
249{
250 wxString newName = getLibIdValue( m_specifiedId );
251
252 if( KIWAY_PLAYER* frame = Kiway().Player( FRAME_SYMBOL_CHOOSER, true, this ) )
253 {
254 if( frame->ShowModal( &newName, this ) )
255 {
256 m_specifiedId->SetValue( UnescapeString( newName ) );
258 }
259
260 frame->Destroy();
261 }
262}
263
264
266{
267 wxString newName = getLibIdValue( m_newId );
268
269 if( KIWAY_PLAYER* frame = Kiway().Player( FRAME_SYMBOL_CHOOSER, true, this ) )
270 {
271 if( frame->ShowModal( &newName, this ) )
272 {
273 m_newId->SetValue( UnescapeString( newName ) );
275 }
276
277 frame->Destroy();
278 }
279}
280
281
283{
284 SCH_EDIT_FRAME* frame = dynamic_cast<SCH_EDIT_FRAME*>( GetParent() );
285
286 wxCHECK( frame, /* void */ );
287
288 // Load non-mandatory fields from all matching symbols and their library symbols
289 std::vector<SCH_FIELD*> fields;
290 std::vector<SCH_FIELD*> libFields;
291 std::set<wxString> fieldNames;
292
293 for( SCH_SHEET_PATH& instance : frame->Schematic().Hierarchy() )
294 {
295 SCH_SCREEN* screen = instance.LastScreen();
296
297 wxCHECK2( screen, continue );
298
299 for( SCH_ITEM* item : screen->Items().OfType( SCH_SYMBOL_T ) )
300 {
301 SCH_SYMBOL* symbol = dynamic_cast<SCH_SYMBOL*>( item );
302
303 wxCHECK2( symbol, continue );
304
305 if( !isMatch( symbol, &instance ) )
306 continue;
307
308 fields.clear();
309 symbol->GetFields( fields, false );
310
311 for( unsigned i = MANDATORY_FIELDS; i < fields.size(); ++i )
312 {
313 if( !fields[i]->IsPrivate() )
314 fieldNames.insert( fields[i]->GetName() );
315 }
316
317 if( m_mode == MODE::UPDATE && symbol->GetLibId().IsValid() )
318 {
319 LIB_SYMBOL* libSymbol = frame->GetLibSymbol( symbol->GetLibId() );
320
321 if( libSymbol )
322 {
323 std::unique_ptr<LIB_SYMBOL> flattenedSymbol = libSymbol->Flatten();
324
325 flattenedSymbol->GetFields( libFields );
326
327 for( unsigned i = MANDATORY_FIELDS; i < libFields.size(); ++i )
328 {
329 if( !libFields[i]->IsPrivate() )
330 fieldNames.insert( libFields[i]->GetName() );
331 }
332
333 libFields.clear(); // flattenedSymbol is about to go out of scope...
334 }
335 }
336 }
337 }
338
339 // Load non-mandatory fields from the change-to library symbol
340 if( m_mode == MODE::CHANGE )
341 {
342 LIB_ID newId;
343
344 newId.Parse( getLibIdValue( m_newId ) );
345
346 if( newId.IsValid() )
347 {
348 LIB_SYMBOL* libSymbol = frame->GetLibSymbol( newId );
349
350 if( libSymbol )
351 {
352 std::unique_ptr<LIB_SYMBOL> flattenedSymbol = libSymbol->Flatten();
353
354 flattenedSymbol->GetFields( libFields );
355
356 for( unsigned i = MANDATORY_FIELDS; i < libFields.size(); ++i )
357 {
358 if( !libFields[i]->IsPrivate() )
359 fieldNames.insert( libFields[i]->GetName() );
360 }
361
362 libFields.clear(); // flattenedSymbol is about to go out of scope...
363 }
364 }
365 }
366
367 // Update the listbox widget
368 wxArrayInt checkedItems;
369 wxArrayString checkedNames;
370
371 m_fieldsBox->GetCheckedItems( checkedItems );
372
373 for( int ii : checkedItems )
374 checkedNames.push_back( m_fieldsBox->GetString( ii ) );
375
376 bool allChecked = true;
377
378 for( unsigned ii = 0; ii < m_fieldsBox->GetCount(); ++ii )
379 {
380 if( ii == REFERENCE_FIELD || ii == VALUE_FIELD )
381 continue;
382
383 if( !m_fieldsBox->IsChecked( ii ) )
384 allChecked = false;
385 }
386
387 for( unsigned ii = m_fieldsBox->GetCount() - 1; ii >= MANDATORY_FIELDS; --ii )
388 m_fieldsBox->Delete( ii );
389
390 for( const wxString& fieldName : fieldNames )
391 {
392 m_fieldsBox->Append( fieldName );
393
394 if( allChecked || alg::contains( checkedNames, fieldName ) )
395 m_fieldsBox->Check( m_fieldsBox->GetCount() - 1, true );
396 }
397}
398
399
401{
402 for( unsigned i = 0; i < m_fieldsBox->GetCount(); ++i )
403 m_fieldsBox->Check( i, aCheck );
404}
405
406
407void DIALOG_CHANGE_SYMBOLS::onOkButtonClicked( wxCommandEvent& aEvent )
408{
409 SCH_EDIT_FRAME* parent = dynamic_cast<SCH_EDIT_FRAME*>( GetParent() );
410
411 wxCHECK( parent, /* void */ );
412
413 wxBusyCursor dummy;
414 SCH_COMMIT commit( parent );
415
417 m_messagePanel->Flush( false );
418
419 // Create the set of fields to be updated. Use non translated (canonical) names
420 // for mandatory fields
421 m_updateFields.clear();
422
423 for( unsigned i = 0; i < m_fieldsBox->GetCount(); ++i )
424 {
425 if( m_fieldsBox->IsChecked( i ) )
426 {
427 if( i < MANDATORY_FIELDS )
428 {
429 SCH_FIELD dummy_field( nullptr, i );
430 m_updateFields.insert( dummy_field.GetCanonicalName() );
431 }
432 else
433 {
434 m_updateFields.insert( m_fieldsBox->GetString( i ) );
435 }
436 }
437 }
438
439 if( processMatchingSymbols( &commit) )
440 commit.Push( m_mode == MODE::CHANGE ? _( "Change Symbols" ) : _( "Update Symbols" ) );
441
442 m_messagePanel->Flush( false );
443}
444
445
447{
448 SCH_EDIT_FRAME* frame = dynamic_cast<SCH_EDIT_FRAME*>( GetParent() );
449
450 wxCHECK( frame, false );
451
452 if( !aSymbol )
453 return false;
454
455 if( m_matchAll->GetValue() )
456 {
457 return true;
458 }
459 else if( m_matchBySelection->GetValue() )
460 {
461 return aSymbol == m_symbol || aSymbol->IsSelected();
462 }
463 else if( m_matchByReference->GetValue() )
464 {
465 return WildCompareString( m_specifiedReference->GetValue(),
466 UnescapeString( aSymbol->GetRef( aInstance, false ) ),
467 false );
468 }
469 else if( m_matchByValue->GetValue() )
470 {
471 return WildCompareString( m_specifiedValue->GetValue(),
472 UnescapeString( aSymbol->GetField( VALUE_FIELD )->GetText() ),
473 false );
474 }
475 else if( m_matchById )
476 {
477 LIB_ID id;
478
480 return aSymbol->GetLibId() == id;
481 }
482
483 return false;
484}
485
486
488{
489 SCH_EDIT_FRAME* frame = dynamic_cast<SCH_EDIT_FRAME*>( GetParent() );
490
491 wxCHECK( frame, false );
492
493 LIB_ID newId;
494 wxString msg;
495 int matchesProcessed = 0;
496 SCH_SYMBOL* symbol = nullptr;
497
498 if( m_mode == MODE::CHANGE )
499 {
500 newId.Parse( getLibIdValue( m_newId ) );
501
502 if( !newId.IsValid() )
503 return false;
504 }
505
506 std::map<SCH_SYMBOL*, SYMBOL_CHANGE_INFO> symbols;
507
508 for( SCH_SHEET_PATH& instance : frame->Schematic().Hierarchy() )
509 {
510 SCH_SCREEN* screen = instance.LastScreen();
511
512 wxCHECK2( screen, continue );
513
514 // Fetch all the symbols that meet the change criteria.
515 for( SCH_ITEM* item : screen->Items().OfType( SCH_SYMBOL_T ) )
516 {
517 symbol = static_cast<SCH_SYMBOL*>( item );
518
519 wxCHECK2( symbol, continue );
520
521 if( !isMatch( symbol, &instance ) )
522 continue;
523
524 if( m_mode == MODE::UPDATE )
525 newId = symbol->GetLibId();
526
527 auto it = symbols.find( symbol );
528
529 if( it == symbols.end() )
530 {
532
533 info.m_Instances.emplace_back( instance );
534 info.m_LibId = newId;
535 symbols.insert( { symbol, info } );
536 }
537 else
538 {
539 it->second.m_Instances.emplace_back( instance );
540 }
541 }
542 }
543
544 if( symbols.size() > 0 )
545 matchesProcessed += processSymbols( aCommit, symbols );
546 else
547 m_messagePanel->Report( _( "*** No symbols matching criteria found ***" ),
549
551
552 return matchesProcessed;
553}
554
555
557 const std::map<SCH_SYMBOL*,
558 SYMBOL_CHANGE_INFO>& aSymbols )
559{
560 wxCHECK( !aSymbols.empty(), 0 );
561
562 int matchesProcessed = 0;
563 SCH_EDIT_FRAME* frame = dynamic_cast<SCH_EDIT_FRAME*>( GetParent() );
564 wxString msg;
565
566 wxCHECK( frame, 0 );
567
568 std::map<SCH_SYMBOL*, SYMBOL_CHANGE_INFO> symbols = aSymbols;
569 std::map<SCH_SYMBOL*, SYMBOL_CHANGE_INFO>::iterator it = symbols.begin();
570
571 // Remove all symbols that don't have a valid library symbol link or enough units to
572 // satisfy the library symbol update.
573 while( it != symbols.end() )
574 {
575 SCH_SYMBOL* symbol = it->first;
576
577 wxCHECK2( symbol && it->second.m_LibId.IsValid(), continue );
578
579 LIB_SYMBOL* libSymbol = frame->GetLibSymbol( it->second.m_LibId );
580
581 if( !libSymbol )
582 {
583 msg = getSymbolReferences( *symbol, it->second.m_LibId );
584 msg << wxT( ": " ) << _( "*** symbol not found ***" );
586 it = symbols.erase( it );
587 continue;
588 }
589
590 std::unique_ptr<LIB_SYMBOL> flattenedSymbol = libSymbol->Flatten();
591
592 if( flattenedSymbol->GetUnitCount() < symbol->GetUnit() )
593 {
594 msg = getSymbolReferences( *symbol, it->second.m_LibId );
595 msg << wxT( ": " ) << _( "*** new symbol has too few units ***" );
597 it = symbols.erase( it );
598 }
599 else
600 {
601 ++it;
602 }
603 }
604
605 // Removing the symbol needs to be done before the LIB_SYMBOL is changed to prevent stale
606 // library symbols in the schematic file.
607 for( const auto& [ symbol, symbol_change_info ] : symbols )
608 {
609 wxCHECK( symbol && !symbol_change_info.m_Instances.empty(), 0 );
610
611 SCH_SCREEN* screen = symbol_change_info.m_Instances[0].LastScreen();
612
613 wxCHECK( screen, 0 );
614
615 screen->Remove( symbol );
616 SCH_SYMBOL* symbol_copy = static_cast<SCH_SYMBOL*>( symbol->Clone() );
617 aCommit->Modified( symbol, symbol_copy, screen );
618
619 CONNECTION_GRAPH* connectionGraph = screen->Schematic()->ConnectionGraph();
620
621 // When we replace the lib symbol below, we free the associated pins if the new symbol has
622 // fewer than the original. This will cause the connection graph to be out of date unless
623 // we replace references in the graph to the old symbol/pins with references to the ones
624 // stored in the undo stack.
625 if( connectionGraph )
626 connectionGraph->ExchangeItem( symbol, symbol_copy );
627 }
628
629 for( const auto& [ symbol, symbol_change_info ] : symbols )
630 {
631 // Remember initial link before changing for diags purpose
632 wxString initialLibLinkName = UnescapeString( symbol->GetLibId().Format() );
633
634 if( symbol_change_info.m_LibId != symbol->GetLibId() )
635 symbol->SetLibId( symbol_change_info.m_LibId );
636
637 LIB_SYMBOL* libSymbol = frame->GetLibSymbol( symbol_change_info.m_LibId );
638 std::unique_ptr<LIB_SYMBOL> flattenedSymbol = libSymbol->Flatten();
639 SCH_SCREEN* screen = symbol_change_info.m_Instances[0].LastScreen();
640
641 symbol->SetLibSymbol( flattenedSymbol.release() );
642
643 if( m_resetAttributes->GetValue() )
644 {
645 // Fetch the attributes from the *flattened* library symbol. They are not supported
646 // in derived symbols.
647 symbol->SetExcludedFromSim( symbol->GetLibSymbolRef()->GetExcludedFromSim() );
648 symbol->SetExcludedFromBOM( symbol->GetLibSymbolRef()->GetExcludedFromBOM() );
649 symbol->SetExcludedFromBoard( symbol->GetLibSymbolRef()->GetExcludedFromBoard() );
650 }
651
652 if( m_resetPinTextVisibility->GetValue() )
653 {
654 symbol->SetShowPinNames( symbol->GetLibSymbolRef()->GetShowPinNames() );
655 symbol->SetShowPinNumbers( symbol->GetLibSymbolRef()->GetShowPinNumbers() );
656 }
657
658 bool removeExtras = m_removeExtraBox->GetValue();
659 bool resetVis = m_resetFieldVisibilities->GetValue();
660 bool resetEffects = m_resetFieldEffects->GetValue();
661 bool resetPositions = m_resetFieldPositions->GetValue();
662
663 for( unsigned i = 0; i < symbol->GetFields().size(); ++i )
664 {
665 SCH_FIELD& field = symbol->GetFields()[i];
666 SCH_FIELD* libField = nullptr;
667 bool doUpdate = field.IsPrivate();
668
669 // Mandatory fields always exist in m_updateFields, but these names can be translated.
670 // so use GetCanonicalName().
671 doUpdate |= alg::contains( m_updateFields, field.GetCanonicalName() );
672
673 if( !doUpdate )
674 continue;
675
676 if( i < MANDATORY_FIELDS )
677 libField = symbol->GetLibSymbolRef()->GetFieldById( (int) i );
678 else
679 libField = symbol->GetLibSymbolRef()->FindField( field.GetName() );
680
681 if( libField )
682 {
683 field.SetPrivate( libField->IsPrivate() );
684
685 bool resetText = libField->GetText().IsEmpty() ? m_resetEmptyFields->GetValue()
686 : m_resetFieldText->GetValue();
687
688 if( resetText )
689 {
690 if( i == REFERENCE_FIELD )
691 {
692 wxString prefix = UTIL::GetRefDesPrefix( libField->GetText() );
693
694 for( const SCH_SHEET_PATH& instance : symbol_change_info.m_Instances )
695 {
696 wxString ref = symbol->GetRef( &instance );
697 int number = UTIL::GetRefDesNumber( ref );
698
699 if( number >= 0 )
700 ref.Printf( wxS( "%s%d" ), prefix, number );
701 else
702 ref = UTIL::GetRefDesUnannotated( prefix );
703
704 symbol->SetRef( &instance, ref );
705 }
706 }
707 else if( i == VALUE_FIELD )
708 {
709 if( ( symbol->IsPower() && m_resetCustomPower->IsChecked() )
710 || !symbol->IsPower() )
711 symbol->SetValueFieldText( UnescapeString( libField->GetText() ) );
712 }
713 else if( i == FOOTPRINT_FIELD )
714 {
715 symbol->SetFootprintFieldText( libField->GetText() );
716 }
717 else
718 {
719 field.SetText( libField->GetText() );
720 }
721 }
722
723 if( resetVis )
724 field.SetVisible( libField->IsVisible() );
725
726 if( resetEffects )
727 {
728 // Careful: the visible bit and position are also set by SetAttributes()
729 bool visible = field.IsVisible();
730 VECTOR2I pos = field.GetPosition();
731
732 field.SetAttributes( *libField );
733
734 field.SetVisible( visible );
735 field.SetPosition( pos );
736 field.SetNameShown( libField->IsNameShown() );
737 field.SetCanAutoplace( libField->CanAutoplace() );
738 }
739
740 if( resetPositions )
741 field.SetTextPos( symbol->GetPosition() + libField->GetTextPos() );
742 }
743 else if( i >= MANDATORY_FIELDS && removeExtras )
744 {
745 symbol->RemoveField( field.GetName() );
746 i--;
747 }
748 }
749
750 std::vector<SCH_FIELD*> libFields;
751 symbol->GetLibSymbolRef()->GetFields( libFields );
752
753 for( unsigned i = MANDATORY_FIELDS; i < libFields.size(); ++i )
754 {
755 const SCH_FIELD& libField = *libFields[i];
756
757 if( !alg::contains( m_updateFields, libField.GetCanonicalName() ) )
758 continue;
759
760 if( !symbol->FindField( libField.GetName(), false ) )
761 {
762 wxString fieldName = libField.GetCanonicalName();
763 SCH_FIELD newField( VECTOR2I( 0, 0 ), symbol->GetFieldCount(), symbol,
764 fieldName );
765 SCH_FIELD* schField = symbol->AddField( newField );
766
767 // Careful: the visible bit and position are also set by SetAttributes()
768 schField->SetAttributes( libField );
769 schField->SetText( libField.GetText() );
770 schField->SetTextPos( symbol->GetPosition() + libField.GetTextPos() );
771 schField->SetPrivate( libField.IsPrivate() );
772 }
773
774 if( resetPositions && frame->eeconfig()->m_AutoplaceFields.enable )
775 {
776 AUTOPLACE_ALGO fieldsAutoplaced = symbol->GetFieldsAutoplaced();
777
778 if( fieldsAutoplaced == AUTOPLACE_AUTO || fieldsAutoplaced == AUTOPLACE_MANUAL )
779 symbol->AutoplaceFields( screen, fieldsAutoplaced );
780 }
781 }
782
783 symbol->SetSchSymbolLibraryName( wxEmptyString );
784 screen->Append( symbol );
785
786 if( resetPositions )
787 {
788 AUTOPLACE_ALGO fieldsAutoplaced = symbol->GetFieldsAutoplaced();
789
790 if( fieldsAutoplaced == AUTOPLACE_AUTO || fieldsAutoplaced == AUTOPLACE_MANUAL )
791 symbol->AutoplaceFields( screen, fieldsAutoplaced );
792 }
793
794 frame->GetCanvas()->GetView()->Update( symbol );
795
796 msg = getSymbolReferences( *symbol, symbol_change_info.m_LibId, &initialLibLinkName );
797 msg += wxS( ": OK" );
799 matchesProcessed +=1;
800 }
801
802 return matchesProcessed;
803}
804
805
807 const LIB_ID& aNewId,
808 const wxString* aOldLibLinkName )
809{
810 wxString msg;
811 wxString references;
812 LIB_ID oldId = aSymbol.GetLibId();
813
814 wxString oldLibLinkName; // For report
815
816 if( aOldLibLinkName )
817 oldLibLinkName = *aOldLibLinkName;
818 else
819 oldLibLinkName = UnescapeString( oldId.Format() );
820
821 SCH_EDIT_FRAME* parent = dynamic_cast< SCH_EDIT_FRAME* >( GetParent() );
822
823 wxCHECK( parent, msg );
824
825 SCH_SHEET_LIST sheets = parent->Schematic().Hierarchy();
826
827 for( const SCH_SYMBOL_INSTANCE& instance : aSymbol.GetInstances() )
828 {
829 // Only include the symbol instances for the current project.
830 if( !sheets.HasPath( instance.m_Path ) )
831 continue;
832
833 if( references.IsEmpty() )
834 references = instance.m_Reference;
835 else
836 references += wxT( " " ) + instance.m_Reference;
837 }
838
839 if( m_mode == MODE::UPDATE )
840 {
841 if( aSymbol.GetInstances().size() == 1 )
842 {
843 msg.Printf( _( "Update symbol %s from '%s' to '%s'" ),
844 references,
845 oldLibLinkName,
846 UnescapeString( aNewId.Format() ) );
847 }
848 else
849 {
850 msg.Printf( _( "Update symbols %s from '%s' to '%s'" ),
851 references,
852 oldLibLinkName,
853 UnescapeString( aNewId.Format() ) );
854 }
855 }
856 else // mode is MODE::CHANGE
857 {
858 if( aSymbol.GetInstances().size() == 1 )
859 {
860 msg.Printf( _( "Change symbol %s from '%s' to '%s'" ),
861 references,
862 oldLibLinkName,
863 UnescapeString( aNewId.Format() ) );
864 }
865 else
866 {
867 msg.Printf( _( "Change symbols %s from '%s' to '%s'" ),
868 references,
869 oldLibLinkName,
870 UnescapeString( aNewId.Format() ) );
871 }
872 }
873
874 return msg;
875}
wxBitmapBundle KiBitmapBundle(BITMAPS aBitmap)
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)
void onOkButtonClicked(wxCommandEvent &aEvent) override
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 checkAll(bool aCheck)
Select or deselect all fields in the listbox widget.
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:230
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:110
const VECTOR2I & GetTextPos() const
Definition: eda_text.h:260
virtual const wxString & GetText() const
Return the string associated with the text object.
Definition: eda_text.h:98
virtual bool IsVisible() const
Definition: eda_text.h:174
void SetTextPos(const VECTOR2I &aPoint)
Definition: eda_text.cpp:569
void SetAttributes(const EDA_TEXT &aSrc, bool aSetPosition=true)
Set the text attributes from another instance.
Definition: eda_text.cpp:424
virtual void SetVisible(bool aVisible)
Definition: eda_text.cpp:377
AUTOPLACE_FIELDS m_AutoplaceFields
EE_TYPE OfType(KICAD_T aType) const
Definition: sch_rtree.h:238
virtual void Update(const VIEW_ITEM *aItem, int aUpdateFlags) const
For dynamic VIEWs, inform the associated VIEW that the graphical representation of this item has chan...
Definition: view.cpp:1673
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:51
bool IsValid() const
Check if this LID_ID is valid.
Definition: lib_id.h:172
UTF8 Format() const
Definition: lib_id.cpp:118
Define a library symbol object.
Definition: lib_symbol.h:84
std::unique_ptr< LIB_SYMBOL > Flatten() const
Return a flattened symbol inheritance to the caller.
Definition: lib_symbol.cpp:333
SCH_SHEET_PATH & CurrentSheet() const override
Definition: schematic.h:161
CONNECTION_GRAPH * ConnectionGraph() const override
Definition: schematic.h:171
SCH_SHEET_LIST Hierarchy() const override
Return the full schematic flattened hierarchical sheet list.
Definition: schematic.cpp:214
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:432
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
Instances are attached to a symbol or sheet and provide a place for the symbol's value,...
Definition: sch_field.h:51
VECTOR2I GetPosition() const override
Definition: sch_field.cpp:1485
bool IsNameShown() const
Definition: sch_field.h:208
void SetCanAutoplace(bool aCanPlace)
Definition: sch_field.h:220
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:1252
wxString GetName(bool aUseDefaultName=true) const
Return the field name (not translated).
Definition: sch_field.cpp:1227
void SetPosition(const VECTOR2I &aPosition) override
Definition: sch_field.cpp:1465
bool CanAutoplace() const
Definition: sch_field.h:219
void SetText(const wxString &aText) override
Definition: sch_field.cpp:1212
void SetNameShown(bool aShown=true)
Definition: sch_field.h:209
Base class for any item which can be embedded within the SCHEMATIC container class,...
Definition: sch_item.h:167
void SetPrivate(bool aPrivate)
Definition: sch_item.h:235
int GetUnit() const
Definition: sch_item.h:230
bool IsPrivate() const
Definition: sch_item.h:236
void Append(SCH_ITEM *aItem, bool aUpdateLibSymbol=true)
Definition: sch_screen.cpp:153
EE_RTREE & Items()
Gets the full RTree, usually for iterating.
Definition: sch_screen.h:108
bool Remove(SCH_ITEM *aItem, bool aUpdateLibSymbol=true)
Remove aItem from the schematic associated with this screen.
Definition: sch_screen.cpp:323
SCHEMATIC * Schematic() const
Definition: sch_screen.cpp:100
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:77
const std::vector< SCH_SYMBOL_INSTANCE > & GetInstances() const
Definition: sch_symbol.h:136
void GetFields(std::vector< SCH_FIELD * > &aVector, bool aVisibleOnly) override
Populate a std::vector with SCH_FIELDs.
Definition: sch_symbol.cpp:953
SCH_FIELD * GetField(MANDATORY_FIELD_T aFieldType)
Return a mandatory field in this symbol.
Definition: sch_symbol.cpp:905
const LIB_ID & GetLibId() const override
Definition: sch_symbol.h:166
const wxString GetRef(const SCH_SHEET_PATH *aSheet, bool aIncludeUnit=false) const override
Definition: sch_symbol.cpp:703
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_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]
#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:68
@ AUTOPLACE_MANUAL
Definition: sch_item.h:71
@ AUTOPLACE_AUTO
Definition: sch_item.h:70
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:398
@ CTX_LIBID
Definition: string_utils.h:54
A simple container for schematic symbol instance information.
static const wxString GetDefaultFieldName(int aFieldNdx, bool aTranslateForHI=false)
Return a default symbol field name for field aFieldNdx for all components.
#define DO_TRANSLATE
@ FOOTPRINT_FIELD
Field Name Module PCB, i.e. "16DIP300".
@ VALUE_FIELD
Field Value of part, i.e. "3.3K".
@ MANDATORY_FIELDS
The first 5 are mandatory, and must be instantiated in SCH_COMPONENT and LIB_PART constructors.
@ REFERENCE_FIELD
Field Reference of part, i.e. "IC21".
@ SCH_SYMBOL_T
Definition: typeinfo.h:172
VECTOR2< int32_t > VECTOR2I
Definition: vector2d.h:695