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 (C) 2021-2023 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 <string_utils.h> // WildCompareString
27#include <kiway.h>
28#include <refdes_utils.h>
29#include <core/kicad_algo.h>
31#include <sch_symbol.h>
32#include <sch_edit_frame.h>
33#include <sch_screen.h>
34#include <schematic.h>
35#include <template_fieldnames.h>
38#include <sch_commit.h>
39
40bool g_selectRefDes = false;
41bool g_selectValue = false;
42 // { change, update }
43bool g_removeExtraFields[2] = { false, false };
44bool g_resetEmptyFields[2] = { false, false };
45bool g_resetFieldText[2] = { true, true };
46bool g_resetFieldVisibilities[2] = { true, false };
47bool g_resetFieldEffects[2] = { true, false };
48bool g_resetFieldPositions[2] = { true, false };
49bool g_resetAttributes[2] = { true, false };
50
51
53 MODE aMode ) :
55 m_symbol( aSymbol),
56 m_mode( aMode )
57{
58 wxASSERT( aParent );
59
60 if( m_mode == MODE::UPDATE )
61 {
62 m_newIdSizer->Show( false );
63 }
64 else
65 {
66 m_matchAll->SetLabel( _( "Change all symbols in schematic" ) );
67 SetTitle( _( "Change Symbols" ) );
68 m_matchSizer->FindItem( m_matchAll )->Show( false );
69 }
70
71 if( m_symbol )
72 {
73 SCH_SHEET_PATH* currentSheet = &aParent->Schematic().CurrentSheet();
74
75 if( m_mode == MODE::CHANGE )
76 m_matchBySelection->SetLabel( _( "Change selected symbol(s)" ) );
77
78 m_newId->ChangeValue( UnescapeString( m_symbol->GetLibId().Format() ) );
79 m_specifiedReference->ChangeValue( m_symbol->GetRef( currentSheet ) );
81 m_specifiedId->ChangeValue( UnescapeString( m_symbol->GetLibId().Format() ) );
82 }
83 else
84 {
85 m_matchSizer->FindItem( m_matchBySelection )->Show( false );
86 }
87
88 m_matchIdBrowserButton->SetBitmap( KiBitmapBundle( BITMAPS::small_library ) );
89 m_newIdBrowserButton->SetBitmap( KiBitmapBundle( BITMAPS::small_library ) );
90
91 if( m_mode == MODE::CHANGE )
92 {
93 m_matchByReference->SetLabel( _( "Change symbols matching reference designator:" ) );
94 m_matchByValue->SetLabel( _( "Change symbols matching value:" ) );
95 m_matchById->SetLabel( _( "Change symbols matching library identifier:" ) );
96 }
97
98 m_matchSizer->SetEmptyCellSize( wxSize( 0, 0 ) );
99 m_matchSizer->Layout();
100
101 for( int i = 0; i < MANDATORY_FIELDS; ++i )
102 {
104
105 if( i == REFERENCE_FIELD )
106 m_fieldsBox->Check( i, g_selectRefDes );
107 else if( i == VALUE_FIELD )
108 m_fieldsBox->Check( i, g_selectValue );
109 else
110 m_fieldsBox->Check( i, true );
111 }
112
114 m_messagePanel->SetFileName( Prj().GetProjectPath() + wxT( "report.txt" ) );
115
116 if( aSymbol && aSymbol->IsSelected() )
117 {
118 m_matchBySelection->SetValue( true );
119 }
120 else
121 {
122 if( aMode == MODE::UPDATE )
123 m_matchAll->SetValue( true );
124 else
125 m_matchByReference->SetValue( true );
126 }
127
129
130 if( m_mode == MODE::CHANGE )
131 {
132 m_updateFieldsSizer->GetStaticBox()->SetLabel( _( "Update Fields" ) );
133 m_removeExtraBox->SetLabel( _( "Remove fields if not in new symbol" ) );
134 m_resetEmptyFields->SetLabel( _( "Reset fields if empty in new symbol" ) );
135 m_resetFieldText->SetLabel( _( "Update field text" ) );
136 m_resetFieldVisibilities->SetLabel( _( "Update field visibilities" ) );
137 m_resetFieldEffects->SetLabel( _( "Update field sizes and styles" ) );
138 m_resetFieldPositions->SetLabel( _( "Update field positions" ) );
139 m_resetAttributes->SetLabel( _( "Update symbol attributes" ) );
140 }
141
142 m_removeExtraBox->SetValue( g_removeExtraFields[ (int) m_mode ] );
143 m_resetEmptyFields->SetValue( g_resetEmptyFields[ (int) m_mode ] );
144 m_resetFieldText->SetValue( g_resetFieldText[ (int) m_mode ] );
146 m_resetFieldEffects->SetValue( g_resetFieldEffects[ (int) m_mode ] );
148 m_resetAttributes->SetValue( g_resetAttributes[ (int) m_mode ] );
149
150 // DIALOG_SHIM needs a unique hash_key because classname is not sufficient
151 // because the update and change versions of this dialog have different controls.
152 m_hash_key = TO_UTF8( GetTitle() );
153
154 wxString okLabel = m_mode == MODE::CHANGE ? _( "Change" ) : _( "Update" );
155
156 SetupStandardButtons( { { wxID_OK, okLabel },
157 { wxID_CANCEL, _( "Close" ) } } );
158
159 // Now all widgets have the size fixed, call FinishDialogSettings
161}
162
163
164void DIALOG_CHANGE_SYMBOLS::onMatchByAll( wxCommandEvent& aEvent )
165{
167}
168
169
170void DIALOG_CHANGE_SYMBOLS::onMatchBySelected( wxCommandEvent& aEvent )
171{
173}
174
175
176void DIALOG_CHANGE_SYMBOLS::onMatchByReference( wxCommandEvent& aEvent )
177{
179 m_specifiedReference->SetFocus();
180}
181
182
183void DIALOG_CHANGE_SYMBOLS::onMatchByValue( wxCommandEvent& aEvent )
184{
186 m_specifiedValue->SetFocus();
187}
188
189
190void DIALOG_CHANGE_SYMBOLS::onMatchById( wxCommandEvent& aEvent )
191{
193 m_specifiedId->SetFocus();
194}
195
196
198{
200 event.Skip(); // Mandatory in wxFocusEvent
201}
202
203
205{
207 event.Skip(); // Mandatory in wxFocusEvent
208}
209
210
212{
214 event.Skip(); // Mandatory in wxFocusEvent
215}
216
217
219{
221 g_selectValue = m_fieldsBox->IsChecked( VALUE_FIELD );
222
223 g_removeExtraFields[ (int) m_mode ] = m_removeExtraBox->GetValue();
224 g_resetEmptyFields[ (int) m_mode ] = m_resetEmptyFields->GetValue();
225 g_resetFieldText[ (int) m_mode ] = m_resetFieldText->GetValue();
227 g_resetFieldEffects[ (int) m_mode ] = m_resetFieldEffects->GetValue();
229 g_resetAttributes[ (int) m_mode ] = m_resetAttributes->GetValue();
230}
231
232
233wxString getLibIdValue( const wxTextCtrl* aCtrl )
234{
235 wxString rawValue = aCtrl->GetValue();
236 wxString itemName;
237 wxString libName = rawValue.BeforeFirst( ':', &itemName );
238
239 return EscapeString( libName, CTX_LIBID ) + ':' + EscapeString( itemName, CTX_LIBID );
240}
241
242
244{
245 wxString newName = getLibIdValue( m_specifiedId );
246
247 KIWAY_PLAYER* frame = Kiway().Player( FRAME_SYMBOL_CHOOSER, true, this );
248
249 if( frame->ShowModal( &newName, this ) )
250 {
251 m_specifiedId->SetValue( UnescapeString( newName ) );
253 }
254
255 frame->Destroy();
256}
257
258
260{
261 wxString newName = getLibIdValue( m_newId );
262
263 KIWAY_PLAYER* frame = Kiway().Player( FRAME_SYMBOL_CHOOSER, true, this );
264
265 if( frame->ShowModal( &newName, this ) )
266 {
267 m_newId->SetValue( UnescapeString( newName ) );
269 }
270
271 frame->Destroy();
272}
273
274
276{
277 SCH_EDIT_FRAME* frame = dynamic_cast<SCH_EDIT_FRAME*>( GetParent() );
278
279 wxCHECK( frame, /* void */ );
280
281 SCH_SHEET_LIST hierarchy = frame->Schematic().GetSheets();
282
283 // Load non-mandatory fields from all matching symbols and their library symbols
284 std::vector<SCH_FIELD*> fields;
285 std::vector<LIB_FIELD*> libFields;
286 std::set<wxString> fieldNames;
287
288 for( SCH_SHEET_PATH& instance : 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 fields.clear();
304 symbol->GetFields( fields, false );
305
306 for( unsigned i = MANDATORY_FIELDS; i < fields.size(); ++i )
307 fieldNames.insert( fields[i]->GetName() );
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
317 flattenedSymbol->GetFields( libFields );
318
319 for( unsigned i = MANDATORY_FIELDS; i < libFields.size(); ++i )
320 fieldNames.insert( libFields[i]->GetName() );
321
322 libFields.clear(); // flattenedSymbol is about to go out of scope...
323 }
324 }
325 }
326 }
327
328 // Load non-mandatory fields from the change-to library symbol
329 if( m_mode == MODE::CHANGE )
330 {
331 LIB_ID newId;
332
333 newId.Parse( getLibIdValue( m_newId ) );
334
335 if( newId.IsValid() )
336 {
337 LIB_SYMBOL* libSymbol = frame->GetLibSymbol( newId );
338
339 if( libSymbol )
340 {
341 std::unique_ptr<LIB_SYMBOL> flattenedSymbol = libSymbol->Flatten();
342
343 flattenedSymbol->GetFields( libFields );
344
345 for( unsigned i = MANDATORY_FIELDS; i < libFields.size(); ++i )
346 fieldNames.insert( libFields[i]->GetName() );
347
348 libFields.clear(); // flattenedSymbol is about to go out of scope...
349 }
350 }
351 }
352
353 // Update the listbox widget
354 wxArrayInt checkedItems;
355 wxArrayString checkedNames;
356
357 m_fieldsBox->GetCheckedItems( checkedItems );
358
359 for( int ii : checkedItems )
360 checkedNames.push_back( m_fieldsBox->GetString( ii ) );
361
362 bool allChecked = true;
363
364 for( unsigned ii = 0; ii < m_fieldsBox->GetCount(); ++ii )
365 {
366 if( ii == REFERENCE_FIELD || ii == VALUE_FIELD )
367 continue;
368
369 if( !m_fieldsBox->IsChecked( ii ) )
370 allChecked = false;
371 }
372
373 for( unsigned ii = m_fieldsBox->GetCount() - 1; ii >= MANDATORY_FIELDS; --ii )
374 m_fieldsBox->Delete( ii );
375
376 for( const wxString& fieldName : fieldNames )
377 {
378 m_fieldsBox->Append( fieldName );
379
380 if( allChecked || alg::contains( checkedNames, fieldName ) )
381 m_fieldsBox->Check( m_fieldsBox->GetCount() - 1, true );
382 }
383}
384
385
387{
388 for( unsigned i = 0; i < m_fieldsBox->GetCount(); ++i )
389 m_fieldsBox->Check( i, aCheck );
390}
391
392
393void DIALOG_CHANGE_SYMBOLS::onOkButtonClicked( wxCommandEvent& aEvent )
394{
395 SCH_EDIT_FRAME* parent = dynamic_cast<SCH_EDIT_FRAME*>( GetParent() );
396
397 wxCHECK( parent, /* void */ );
398
399 wxBusyCursor dummy;
400 SCH_COMMIT commit( parent );
401
403 m_messagePanel->Flush( false );
404
405 // Create the set of fields to be updated. Use non translated (canonical) names
406 // for mandatory fields
407 m_updateFields.clear();
408
409 for( unsigned i = 0; i < m_fieldsBox->GetCount(); ++i )
410 {
411 if( m_fieldsBox->IsChecked( i ) )
412 {
413 if( i < MANDATORY_FIELDS )
414 {
415 LIB_FIELD dummy_field( i );
416 m_updateFields.insert( dummy_field.GetCanonicalName() );
417 }
418 else
419 {
420 m_updateFields.insert( m_fieldsBox->GetString( i ) );
421 }
422 }
423 }
424
425 if( processMatchingSymbols( &commit) )
426 commit.Push( m_mode == MODE::CHANGE ? _( "Change Symbols" ) : _( "Update Symbols" ) );
427
428 m_messagePanel->Flush( false );
429}
430
431
433{
434 LIB_ID id;
435
436 wxCHECK( aSymbol, false );
437
438 SCH_EDIT_FRAME* frame = dynamic_cast<SCH_EDIT_FRAME*>( GetParent() );
439
440 wxCHECK( frame, false );
441
442 if( m_matchAll->GetValue() )
443 {
444 return true;
445 }
446 else if( m_matchBySelection->GetValue() )
447 {
448 return aSymbol == m_symbol || aSymbol->IsSelected();
449 }
450 else if( m_matchByReference->GetValue() )
451 {
452 return WildCompareString( m_specifiedReference->GetValue(),
453 UnescapeString( aSymbol->GetRef( aInstance, false ) ),
454 false );
455 }
456 else if( m_matchByValue->GetValue() )
457 {
458 return WildCompareString( m_specifiedValue->GetValue(),
459 UnescapeString( aSymbol->GetField( VALUE_FIELD )->GetText() ),
460 false );
461 }
462 else if( m_matchById )
463 {
464 id.Parse( getLibIdValue( m_specifiedId ) );
465 return aSymbol->GetLibId() == id;
466 }
467
468 return false;
469}
470
471
473{
474 SCH_EDIT_FRAME* frame = dynamic_cast<SCH_EDIT_FRAME*>( GetParent() );
475
476 wxCHECK( frame, false );
477
478 LIB_ID newId;
479 wxString msg;
480 int matchesProcessed = 0;
481 SCH_SYMBOL* symbol = nullptr;
482 SCH_SHEET_LIST hierarchy = frame->Schematic().GetSheets();
483
484 if( m_mode == MODE::CHANGE )
485 {
486 newId.Parse( getLibIdValue( m_newId ) );
487
488 if( !newId.IsValid() )
489 return false;
490 }
491
492 std::map<SCH_SYMBOL*, SYMBOL_CHANGE_INFO> symbols;
493
494 for( SCH_SHEET_PATH& instance : hierarchy )
495 {
496 SCH_SCREEN* screen = instance.LastScreen();
497
498 wxCHECK2( screen, continue );
499
500 // Fetch all the symbols that meet the change criteria.
501 for( SCH_ITEM* item : screen->Items().OfType( SCH_SYMBOL_T ) )
502 {
503 symbol = static_cast<SCH_SYMBOL*>( item );
504
505 wxCHECK2( symbol, continue );
506
507 if( !isMatch( symbol, &instance ) )
508 continue;
509
510 if( m_mode == MODE::UPDATE )
511 newId = symbol->GetLibId();
512
513 auto it = symbols.find( symbol );
514
515 if( it == symbols.end() )
516 {
518
519 info.m_Instances.emplace_back( instance );
520 info.m_LibId = newId;
521 symbols.insert( { symbol, info } );
522 }
523 else
524 {
525 it->second.m_Instances.emplace_back( instance );
526 }
527 }
528 }
529
530 if( symbols.size() > 0 )
531 matchesProcessed += processSymbols( aCommit, symbols );
532 else
533 m_messagePanel->Report( _( "*** No symbols matching criteria found ***" ),
535
537
538 return matchesProcessed;
539}
540
541
543 const std::map<SCH_SYMBOL*, SYMBOL_CHANGE_INFO>& aSymbols )
544{
545 wxCHECK( !aSymbols.empty(), 0 );
546
547 int matchesProcessed = 0;
548 SCH_EDIT_FRAME* frame = dynamic_cast<SCH_EDIT_FRAME*>( GetParent() );
549 wxString msg;
550
551 wxCHECK( frame, 0 );
552
553 std::map<SCH_SYMBOL*, SYMBOL_CHANGE_INFO> symbols = aSymbols;
554 std::map<SCH_SYMBOL*, SYMBOL_CHANGE_INFO>::iterator it = symbols.begin();
555
556 // Remove all symbols that don't have a valid library symbol link or enough units to
557 // satify the library symbol update.
558 while( it != symbols.end() )
559 {
560 SCH_SYMBOL* symbol = it->first;
561
562 wxCHECK2( symbol && it->second.m_LibId.IsValid(), continue );
563
564 LIB_SYMBOL* libSymbol = frame->GetLibSymbol( it->second.m_LibId );
565
566 if( !libSymbol )
567 {
568 msg = getSymbolReferences( *symbol, it->second.m_LibId );
569 msg << wxT( ": " ) << _( "*** symbol not found ***" );
571 it = symbols.erase( it );
572 continue;
573 }
574
575 std::unique_ptr<LIB_SYMBOL> flattenedSymbol = libSymbol->Flatten();
576
577 if( flattenedSymbol->GetUnitCount() < symbol->GetUnit() )
578 {
579 msg = getSymbolReferences( *symbol, it->second.m_LibId );
580 msg << wxT( ": " ) << _( "*** new symbol has too few units ***" );
582 it = symbols.erase( it );
583 }
584 else
585 {
586 ++it;
587 }
588 }
589
590 // Removing the symbol needs to be done before the LIB_SYMBOL is changed to prevent stale
591 // library symbols in the schematic file.
592 for( const auto& [ symbol, symbol_change_info ] : symbols )
593 {
594 wxCHECK( symbol && !symbol_change_info.m_Instances.empty(), 0 );
595
596 SCH_SCREEN* screen = symbol_change_info.m_Instances[0].LastScreen();
597
598 wxCHECK( screen, 0 );
599
600 screen->Remove( symbol );
601 aCommit->Modify( symbol, screen );
602 }
603
604 for( const auto& [ symbol, symbol_change_info ] : symbols )
605 {
606 if( symbol_change_info.m_LibId != symbol->GetLibId() )
607 symbol->SetLibId( symbol_change_info.m_LibId );
608
609 LIB_SYMBOL* libSymbol = frame->GetLibSymbol( symbol_change_info.m_LibId );
610 std::unique_ptr<LIB_SYMBOL> flattenedSymbol = libSymbol->Flatten();
611 SCH_SCREEN* screen = symbol_change_info.m_Instances[0].LastScreen();
612
613 symbol->SetLibSymbol( flattenedSymbol.release() );
614
615 if( m_resetAttributes->GetValue() )
616 {
617 // Fetch the attributes from the *flattened* library symbol. They are not supported
618 // in derived symbols.
619 symbol->SetExcludedFromSim( symbol->GetLibSymbolRef()->GetExcludedFromSim() );
620 symbol->SetExcludedFromBOM( symbol->GetLibSymbolRef()->GetExcludedFromBOM() );
621 symbol->SetExcludedFromBoard( symbol->GetLibSymbolRef()->GetExcludedFromBoard() );
622 }
623
624 bool removeExtras = m_removeExtraBox->GetValue();
625 bool resetVis = m_resetFieldVisibilities->GetValue();
626 bool resetEffects = m_resetFieldEffects->GetValue();
627 bool resetPositions = m_resetFieldPositions->GetValue();
628
629 for( unsigned i = 0; i < symbol->GetFields().size(); ++i )
630 {
631 SCH_FIELD& field = symbol->GetFields()[i];
632 LIB_FIELD* libField = nullptr;
633
634 // Mandatory fields always exist in m_updateFields, but these names can be translated.
635 // so use GetCanonicalName().
637 continue;
638
639 if( i < MANDATORY_FIELDS )
640 libField = symbol->GetLibSymbolRef()->GetFieldById( (int) i );
641 else
642 libField = symbol->GetLibSymbolRef()->FindField( field.GetName() );
643
644 if( libField )
645 {
646 bool resetText = libField->GetText().IsEmpty() ? m_resetEmptyFields->GetValue()
647 : m_resetFieldText->GetValue();
648
649 if( resetText )
650 {
651 if( i == REFERENCE_FIELD )
652 {
653 for( const SCH_SHEET_PATH& instance : symbol_change_info.m_Instances )
654 {
655 symbol->SetRef( &instance,
656 UTIL::GetRefDesUnannotated( libField->GetText() ) );
657 }
658 }
659 else if( i == VALUE_FIELD )
660 {
661 symbol->SetValueFieldText( UnescapeString( libField->GetText() ) );
662 }
663 else if( i == FOOTPRINT_FIELD )
664 {
665 symbol->SetFootprintFieldText( libField->GetText() );
666 }
667 else
668 {
669 field.SetText( libField->GetText() );
670 }
671 }
672
673 if( resetVis )
674 field.SetVisible( libField->IsVisible() );
675
676 if( resetEffects )
677 {
678 // Careful: the visible bit and position are also set by SetAttributes()
679 bool visible = field.IsVisible();
680 VECTOR2I pos = field.GetPosition();
681
682 field.SetAttributes( *libField );
683
684 field.SetVisible( visible );
685 field.SetPosition( pos );
686 field.SetNameShown( libField->IsNameShown() );
687 field.SetCanAutoplace( libField->CanAutoplace() );
688 }
689
690 if( resetPositions )
691 field.SetTextPos( symbol->GetPosition() + libField->GetTextPos() );
692 }
693 else if( i >= MANDATORY_FIELDS && removeExtras )
694 {
695 symbol->RemoveField( field.GetName() );
696 i--;
697 }
698 }
699
700 std::vector<LIB_FIELD*> libFields;
701 symbol->GetLibSymbolRef()->GetFields( libFields );
702
703 for( unsigned i = MANDATORY_FIELDS; i < libFields.size(); ++i )
704 {
705 const LIB_FIELD& libField = *libFields[i];
706
707 if( !alg::contains( m_updateFields, libField.GetCanonicalName() ) )
708 continue;
709
710 if( !symbol->FindField( libField.GetName(), false ) )
711 {
712 wxString fieldName = libField.GetCanonicalName();
713 SCH_FIELD newField( VECTOR2I( 0, 0 ), symbol->GetFieldCount(), symbol,
714 fieldName );
715 SCH_FIELD* schField = symbol->AddField( newField );
716
717 // Careful: the visible bit and position are also set by SetAttributes()
718 schField->SetAttributes( libField );
719 schField->SetText( libField.GetText() );
720 schField->SetTextPos( symbol->GetPosition() + libField.GetTextPos() );
721 }
722
723 if( resetPositions && frame->eeconfig()->m_AutoplaceFields.enable )
724 symbol->AutoAutoplaceFields( screen );
725 }
726
727 symbol->SetSchSymbolLibraryName( wxEmptyString );
728 screen->Append( symbol );
729
730 if( resetPositions )
731 symbol->AutoAutoplaceFields( screen );
732
733 frame->GetCanvas()->GetView()->Update( symbol );
734
735 msg = getSymbolReferences( *symbol, symbol_change_info.m_LibId );
736 msg += wxS( ": OK" );
738 matchesProcessed +=1;
739 }
740
741 return matchesProcessed;
742}
743
744
746{
747 wxString msg;
748 wxString references;
749 LIB_ID oldId = aSymbol.GetLibId();
750
751 SCH_EDIT_FRAME* parent = dynamic_cast< SCH_EDIT_FRAME* >( GetParent() );
752
753 wxCHECK( parent, msg );
754
755 SCH_SHEET_LIST sheets = parent->Schematic().GetSheets();
756
757 for( const SCH_SYMBOL_INSTANCE& instance : aSymbol.GetInstances() )
758 {
759 // Only include the symbol instances for the current project.
760 if( !sheets.HasPath( instance.m_Path ) )
761 continue;
762
763 if( references.IsEmpty() )
764 references = instance.m_Reference;
765 else
766 references += wxT( " " ) + instance.m_Reference;
767 }
768
769 if( m_mode == MODE::UPDATE )
770 {
771 if( aSymbol.GetInstances().size() == 1 )
772 {
773 msg.Printf( _( "Update symbol %s from '%s' to '%s'" ),
774 references,
775 UnescapeString( oldId.Format() ),
776 UnescapeString( aNewId.Format() ) );
777 }
778 else
779 {
780 msg.Printf( _( "Update symbols %s from '%s' to '%s'" ),
781 references,
782 UnescapeString( oldId.Format() ),
783 UnescapeString( aNewId.Format() ) );
784 }
785 }
786 else
787 {
788 if( aSymbol.GetInstances().size() == 1 )
789 {
790 msg.Printf( _( "Change symbol %s from '%s' to '%s'" ),
791 references,
792 UnescapeString( oldId.Format() ),
793 UnescapeString( aNewId.Format() ) );
794 }
795 else
796 {
797 msg.Printf( _( "Change symbols %s from '%s' to '%s'" ),
798 references,
799 UnescapeString( oldId.Format() ),
800 UnescapeString( aNewId.Format() ) );
801 }
802 }
803
804 return msg;
805}
wxBitmapBundle KiBitmapBundle(BITMAPS aBitmap)
Definition: bitmap.cpp:110
COMMIT & Modify(EDA_ITEM *aItem, BASE_SCREEN *aScreen=nullptr)
Create an undo entry for an item that has been already modified.
Definition: commit.h:105
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
MODE m_mode
Set of field names that should have values updated.
wxString getSymbolReferences(SCH_SYMBOL &aSymbol, const LIB_ID &aNewId)
bool isMatch(SCH_SYMBOL *aSymbol, SCH_SHEET_PATH *aInstance)
void onOkButtonClicked(wxCommandEvent &aEvent) override
std::set< wxString > m_updateFields
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
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:205
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:106
const VECTOR2I & GetTextPos() const
Definition: eda_text.h:230
virtual const wxString & GetText() const
Return the string associated with the text object.
Definition: eda_text.h:95
virtual bool IsVisible() const
Definition: eda_text.h:147
void SetTextPos(const VECTOR2I &aPoint)
Definition: eda_text.cpp:403
void SetAttributes(const EDA_TEXT &aSrc, bool aSetPosition=true)
Set the text attributes from another instance.
Definition: eda_text.cpp:276
virtual void SetVisible(bool aVisible)
Definition: eda_text.cpp:229
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:1619
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:53
A wxFrame capable of the OpenProjectFiles function, meaning it can load a portion of a KiCad project.
Definition: kiway_player.h:67
virtual bool ShowModal(wxString *aResult=nullptr, wxWindow *aResultantFocusWindow=nullptr)
Show this wxFrame as if it were a modal dialog, with all other instantiated wxFrames disabled until t...
bool Destroy() override
Our version of Destroy() which is virtual from wxWidgets.
virtual KIWAY_PLAYER * Player(FRAME_T aFrameType, bool doCreate=true, wxTopLevelWindow *aParent=nullptr)
Return the KIWAY_PLAYER* given a FRAME_T.
Definition: kiway.cpp:432
Field object used in symbol libraries.
Definition: lib_field.h:62
bool CanAutoplace() const
Definition: lib_field.h:195
wxString GetName(bool aUseDefaultName=true) const
Return the field name (not translated).
Definition: lib_field.cpp:485
bool IsNameShown() const
Definition: lib_field.h:192
wxString GetCanonicalName() const
Get a non-language-specific name for a field which can be used for storage, variable look-up,...
Definition: lib_field.cpp:494
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:99
std::unique_ptr< LIB_SYMBOL > Flatten() const
Return a flattened symbol inheritance to the caller.
Definition: lib_symbol.cpp:605
SCH_SHEET_PATH & CurrentSheet() const override
Definition: schematic.h:136
SCH_SHEET_LIST GetSheets() const override
Builds and returns an updated schematic hierarchy TODO: can this be cached?
Definition: schematic.h:100
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
Revert the commit by restoring the modified items state.
Definition: sch_commit.cpp:367
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:52
VECTOR2I GetPosition() const override
Definition: sch_field.cpp:1267
void SetCanAutoplace(bool aCanPlace)
Definition: sch_field.h:196
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:1032
wxString GetName(bool aUseDefaultName=true) const
Return the field name (not translated).
Definition: sch_field.cpp:1000
void SetPosition(const VECTOR2I &aPosition) override
Definition: sch_field.cpp:1247
void SetText(const wxString &aText) override
Definition: sch_field.cpp:989
void SetNameShown(bool aShown=true)
Definition: sch_field.h:185
Base class for any item which can be embedded within the SCHEMATIC container class,...
Definition: sch_item.h:151
void Append(SCH_ITEM *aItem, bool aUpdateLibSymbol=true)
Definition: sch_screen.cpp:150
EE_RTREE & Items()
Gets the full RTree, usually for iterating.
Definition: sch_screen.h:109
bool Remove(SCH_ITEM *aItem, bool aUpdateLibSymbol=true)
Remove aItem from the schematic associated with this screen.
Definition: sch_screen.cpp:320
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:109
const std::vector< SCH_SYMBOL_INSTANCE > & GetInstances() const
Definition: sch_symbol.h:168
int GetUnit() const
Definition: sch_symbol.h:258
const wxString GetRef(const SCH_SHEET_PATH *aSheet, bool aIncludeUnit=false) const
Return the reference for the given sheet path.
Definition: sch_symbol.cpp:748
SCH_FIELD * GetField(MANDATORY_FIELD_T aFieldType)
Return a mandatory field in this symbol.
Definition: sch_symbol.cpp:950
const LIB_ID & GetLibId() const
Definition: sch_symbol.h:203
void GetFields(std::vector< SCH_FIELD * > &aVector, bool aVisibleOnly)
Populate a std::vector with SCH_FIELDs.
Definition: sch_symbol.cpp:998
void SetBitmap(const wxBitmapBundle &aBmp)
void Clear()
return the number of messages matching the given severity mask.
void SetLazyUpdate(bool aLazyUpdate)
Forces updating the HTML page, after the report is built in lazy mode If aSort = true,...
void SetFileName(const wxString &aReportFileName)
void Report(const wxString &aText, SEVERITY aSeverity, REPORTER::LOCATION aLocation=REPORTER::LOC_BODY)
Reports the string.
void Flush(bool aSort=false)
Set the visible severity filter.
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
#define _(s)
@ FRAME_SYMBOL_CHOOSER
Definition: frame_type.h:37
wxString GetRefDesUnannotated(const wxString &aSource)
Return an unannotated refdes from either a prefix or an existing refdes.
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
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:391
@ 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:156
VECTOR2< int > VECTOR2I
Definition: vector2d.h:588