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 };
50bool g_resetCustomPower[2] = { false, false };
51
52
54 MODE aMode ) :
56 m_symbol( aSymbol),
57 m_mode( aMode )
58{
59 wxASSERT( aParent );
60
61 if( m_mode == MODE::UPDATE )
62 {
63 m_newIdSizer->Show( false );
64 }
65 else
66 {
67 m_matchAll->SetLabel( _( "Change all symbols in schematic" ) );
68 SetTitle( _( "Change Symbols" ) );
69 m_matchSizer->FindItem( m_matchAll )->Show( false );
70 }
71
72 if( m_symbol )
73 {
74 SCH_SHEET_PATH* currentSheet = &aParent->Schematic().CurrentSheet();
75
76 if( m_mode == MODE::CHANGE )
77 m_matchBySelection->SetLabel( _( "Change selected symbol(s)" ) );
78
79 m_newId->ChangeValue( UnescapeString( m_symbol->GetLibId().Format() ) );
80 m_specifiedReference->ChangeValue( m_symbol->GetRef( currentSheet ) );
82 m_specifiedId->ChangeValue( UnescapeString( m_symbol->GetLibId().Format() ) );
83 }
84 else
85 {
86 m_matchSizer->FindItem( m_matchBySelection )->Show( false );
87 }
88
89 m_matchIdBrowserButton->SetBitmap( KiBitmapBundle( BITMAPS::small_library ) );
90 m_newIdBrowserButton->SetBitmap( KiBitmapBundle( BITMAPS::small_library ) );
91
92 if( m_mode == MODE::CHANGE )
93 {
94 m_matchByReference->SetLabel( _( "Change symbols matching reference designator:" ) );
95 m_matchByValue->SetLabel( _( "Change symbols matching value:" ) );
96 m_matchById->SetLabel( _( "Change symbols matching library identifier:" ) );
97 }
98
99 m_matchSizer->SetEmptyCellSize( wxSize( 0, 0 ) );
100 m_matchSizer->Layout();
101
102 for( int i = 0; i < MANDATORY_FIELDS; ++i )
103 {
105
106 if( i == REFERENCE_FIELD )
107 m_fieldsBox->Check( i, g_selectRefDes );
108 else if( i == VALUE_FIELD )
109 m_fieldsBox->Check( i, g_selectValue );
110 else
111 m_fieldsBox->Check( i, true );
112 }
113
115 m_messagePanel->SetFileName( Prj().GetProjectPath() + wxT( "report.txt" ) );
116
117 if( aSymbol && aSymbol->IsSelected() )
118 {
119 m_matchBySelection->SetValue( true );
120 }
121 else
122 {
123 if( aMode == MODE::UPDATE )
124 m_matchAll->SetValue( true );
125 else
126 m_matchByReference->SetValue( true );
127 }
128
130
131 if( m_mode == MODE::CHANGE )
132 {
133 m_updateFieldsSizer->GetStaticBox()->SetLabel( _( "Update Fields" ) );
134 m_removeExtraBox->SetLabel( _( "Remove fields if not in new symbol" ) );
135 m_resetEmptyFields->SetLabel( _( "Reset fields if empty in new symbol" ) );
136 m_resetFieldText->SetLabel( _( "Update field text" ) );
137 m_resetFieldVisibilities->SetLabel( _( "Update field visibilities" ) );
138 m_resetFieldEffects->SetLabel( _( "Update field sizes and styles" ) );
139 m_resetFieldPositions->SetLabel( _( "Update field positions" ) );
140 m_resetAttributes->SetLabel( _( "Update symbol attributes" ) );
141 }
142
143 m_removeExtraBox->SetValue( g_removeExtraFields[ (int) m_mode ] );
144 m_resetEmptyFields->SetValue( g_resetEmptyFields[ (int) m_mode ] );
145 m_resetFieldText->SetValue( g_resetFieldText[ (int) m_mode ] );
147 m_resetFieldEffects->SetValue( g_resetFieldEffects[ (int) m_mode ] );
149 m_resetAttributes->SetValue( g_resetAttributes[ (int) m_mode ] );
150 m_resetCustomPower->SetValue( g_resetCustomPower[ (int) m_mode ] );
151
152 // DIALOG_SHIM needs a unique hash_key because classname is not sufficient
153 // because the update and change versions of this dialog have different controls.
154 m_hash_key = TO_UTF8( GetTitle() );
155
156 wxString okLabel = m_mode == MODE::CHANGE ? _( "Change" ) : _( "Update" );
157
158 SetupStandardButtons( { { wxID_OK, okLabel },
159 { wxID_CANCEL, _( "Close" ) } } );
160
161 // Now all widgets have the size fixed, call FinishDialogSettings
163}
164
165
166void DIALOG_CHANGE_SYMBOLS::onMatchByAll( wxCommandEvent& aEvent )
167{
169}
170
171
172void DIALOG_CHANGE_SYMBOLS::onMatchBySelected( wxCommandEvent& aEvent )
173{
175}
176
177
178void DIALOG_CHANGE_SYMBOLS::onMatchByReference( wxCommandEvent& aEvent )
179{
181 m_specifiedReference->SetFocus();
182}
183
184
185void DIALOG_CHANGE_SYMBOLS::onMatchByValue( wxCommandEvent& aEvent )
186{
188 m_specifiedValue->SetFocus();
189}
190
191
192void DIALOG_CHANGE_SYMBOLS::onMatchById( wxCommandEvent& aEvent )
193{
195 m_specifiedId->SetFocus();
196}
197
198
200{
202 event.Skip(); // Mandatory in wxFocusEvent
203}
204
205
207{
209 event.Skip(); // Mandatory in wxFocusEvent
210}
211
212
214{
216 event.Skip(); // Mandatory in wxFocusEvent
217}
218
219
221{
223 g_selectValue = m_fieldsBox->IsChecked( VALUE_FIELD );
224
225 g_removeExtraFields[ (int) m_mode ] = m_removeExtraBox->GetValue();
226 g_resetEmptyFields[ (int) m_mode ] = m_resetEmptyFields->GetValue();
227 g_resetFieldText[ (int) m_mode ] = m_resetFieldText->GetValue();
229 g_resetFieldEffects[ (int) m_mode ] = m_resetFieldEffects->GetValue();
231 g_resetAttributes[ (int) m_mode ] = m_resetAttributes->GetValue();
232 g_resetCustomPower[ (int) m_mode ] = m_resetCustomPower->GetValue();
233}
234
235
236wxString getLibIdValue( const wxTextCtrl* aCtrl )
237{
238 wxString rawValue = aCtrl->GetValue();
239 wxString itemName;
240 wxString libName = rawValue.BeforeFirst( ':', &itemName );
241
242 return EscapeString( libName, CTX_LIBID ) + ':' + EscapeString( itemName, CTX_LIBID );
243}
244
245
247{
248 wxString newName = getLibIdValue( m_specifiedId );
249
250 KIWAY_PLAYER* frame = Kiway().Player( FRAME_SYMBOL_CHOOSER, true, this );
251
252 if( frame->ShowModal( &newName, this ) )
253 {
254 m_specifiedId->SetValue( UnescapeString( newName ) );
256 }
257
258 frame->Destroy();
259}
260
261
263{
264 wxString newName = getLibIdValue( m_newId );
265
266 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
279{
280 SCH_EDIT_FRAME* frame = dynamic_cast<SCH_EDIT_FRAME*>( GetParent() );
281
282 wxCHECK( frame, /* void */ );
283
284 SCH_SHEET_LIST hierarchy = frame->Schematic().GetSheets();
285
286 // Load non-mandatory fields from all matching symbols and their library symbols
287 std::vector<SCH_FIELD*> fields;
288 std::vector<LIB_FIELD*> libFields;
289 std::set<wxString> fieldNames;
290
291 for( SCH_SHEET_PATH& instance : hierarchy )
292 {
293 SCH_SCREEN* screen = instance.LastScreen();
294
295 wxCHECK2( screen, continue );
296
297 for( SCH_ITEM* item : screen->Items().OfType( SCH_SYMBOL_T ) )
298 {
299 SCH_SYMBOL* symbol = dynamic_cast<SCH_SYMBOL*>( item );
300
301 wxCHECK2( symbol, continue );
302
303 if( !isMatch( symbol, &instance ) )
304 continue;
305
306 fields.clear();
307 symbol->GetFields( fields, false );
308
309 for( unsigned i = MANDATORY_FIELDS; i < fields.size(); ++i )
310 fieldNames.insert( fields[i]->GetName() );
311
312 if( m_mode == MODE::UPDATE && symbol->GetLibId().IsValid() )
313 {
314 LIB_SYMBOL* libSymbol = frame->GetLibSymbol( symbol->GetLibId() );
315
316 if( libSymbol )
317 {
318 std::unique_ptr<LIB_SYMBOL> flattenedSymbol = libSymbol->Flatten();
319
320 flattenedSymbol->GetFields( libFields );
321
322 for( unsigned i = MANDATORY_FIELDS; i < libFields.size(); ++i )
323 fieldNames.insert( libFields[i]->GetName() );
324
325 libFields.clear(); // flattenedSymbol is about to go out of scope...
326 }
327 }
328 }
329 }
330
331 // Load non-mandatory fields from the change-to library symbol
332 if( m_mode == MODE::CHANGE )
333 {
334 LIB_ID newId;
335
336 newId.Parse( getLibIdValue( m_newId ) );
337
338 if( newId.IsValid() )
339 {
340 LIB_SYMBOL* libSymbol = frame->GetLibSymbol( newId );
341
342 if( libSymbol )
343 {
344 std::unique_ptr<LIB_SYMBOL> flattenedSymbol = libSymbol->Flatten();
345
346 flattenedSymbol->GetFields( libFields );
347
348 for( unsigned i = MANDATORY_FIELDS; i < libFields.size(); ++i )
349 fieldNames.insert( libFields[i]->GetName() );
350
351 libFields.clear(); // flattenedSymbol is about to go out of scope...
352 }
353 }
354 }
355
356 // Update the listbox widget
357 wxArrayInt checkedItems;
358 wxArrayString checkedNames;
359
360 m_fieldsBox->GetCheckedItems( checkedItems );
361
362 for( int ii : checkedItems )
363 checkedNames.push_back( m_fieldsBox->GetString( ii ) );
364
365 bool allChecked = true;
366
367 for( unsigned ii = 0; ii < m_fieldsBox->GetCount(); ++ii )
368 {
369 if( ii == REFERENCE_FIELD || ii == VALUE_FIELD )
370 continue;
371
372 if( !m_fieldsBox->IsChecked( ii ) )
373 allChecked = false;
374 }
375
376 for( unsigned ii = m_fieldsBox->GetCount() - 1; ii >= MANDATORY_FIELDS; --ii )
377 m_fieldsBox->Delete( ii );
378
379 for( const wxString& fieldName : fieldNames )
380 {
381 m_fieldsBox->Append( fieldName );
382
383 if( allChecked || alg::contains( checkedNames, fieldName ) )
384 m_fieldsBox->Check( m_fieldsBox->GetCount() - 1, true );
385 }
386}
387
388
390{
391 for( unsigned i = 0; i < m_fieldsBox->GetCount(); ++i )
392 m_fieldsBox->Check( i, aCheck );
393}
394
395
396void DIALOG_CHANGE_SYMBOLS::onOkButtonClicked( wxCommandEvent& aEvent )
397{
398 SCH_EDIT_FRAME* parent = dynamic_cast<SCH_EDIT_FRAME*>( GetParent() );
399
400 wxCHECK( parent, /* void */ );
401
402 wxBusyCursor dummy;
403 SCH_COMMIT commit( parent );
404
406 m_messagePanel->Flush( false );
407
408 // Create the set of fields to be updated. Use non translated (canonical) names
409 // for mandatory fields
410 m_updateFields.clear();
411
412 for( unsigned i = 0; i < m_fieldsBox->GetCount(); ++i )
413 {
414 if( m_fieldsBox->IsChecked( i ) )
415 {
416 if( i < MANDATORY_FIELDS )
417 {
418 LIB_FIELD dummy_field( i );
419 m_updateFields.insert( dummy_field.GetCanonicalName() );
420 }
421 else
422 {
423 m_updateFields.insert( m_fieldsBox->GetString( i ) );
424 }
425 }
426 }
427
428 if( processMatchingSymbols( &commit) )
429 commit.Push( m_mode == MODE::CHANGE ? _( "Change Symbols" ) : _( "Update Symbols" ) );
430
431 m_messagePanel->Flush( false );
432}
433
434
436{
437 LIB_ID id;
438
439 wxCHECK( aSymbol, false );
440
441 SCH_EDIT_FRAME* frame = dynamic_cast<SCH_EDIT_FRAME*>( GetParent() );
442
443 wxCHECK( frame, false );
444
445 if( m_matchAll->GetValue() )
446 {
447 return true;
448 }
449 else if( m_matchBySelection->GetValue() )
450 {
451 return aSymbol == m_symbol || aSymbol->IsSelected();
452 }
453 else if( m_matchByReference->GetValue() )
454 {
455 return WildCompareString( m_specifiedReference->GetValue(),
456 UnescapeString( aSymbol->GetRef( aInstance, false ) ),
457 false );
458 }
459 else if( m_matchByValue->GetValue() )
460 {
461 return WildCompareString( m_specifiedValue->GetValue(),
462 UnescapeString( aSymbol->GetField( VALUE_FIELD )->GetText() ),
463 false );
464 }
465 else if( m_matchById )
466 {
467 id.Parse( getLibIdValue( m_specifiedId ) );
468 return aSymbol->GetLibId() == id;
469 }
470
471 return false;
472}
473
474
476{
477 SCH_EDIT_FRAME* frame = dynamic_cast<SCH_EDIT_FRAME*>( GetParent() );
478
479 wxCHECK( frame, false );
480
481 LIB_ID newId;
482 wxString msg;
483 int matchesProcessed = 0;
484 SCH_SYMBOL* symbol = nullptr;
485 SCH_SHEET_LIST hierarchy = frame->Schematic().GetSheets();
486
487 if( m_mode == MODE::CHANGE )
488 {
489 newId.Parse( getLibIdValue( m_newId ) );
490
491 if( !newId.IsValid() )
492 return false;
493 }
494
495 std::map<SCH_SYMBOL*, SYMBOL_CHANGE_INFO> symbols;
496
497 for( SCH_SHEET_PATH& instance : hierarchy )
498 {
499 SCH_SCREEN* screen = instance.LastScreen();
500
501 wxCHECK2( screen, continue );
502
503 // Fetch all the symbols that meet the change criteria.
504 for( SCH_ITEM* item : screen->Items().OfType( SCH_SYMBOL_T ) )
505 {
506 symbol = static_cast<SCH_SYMBOL*>( item );
507
508 wxCHECK2( symbol, continue );
509
510 if( !isMatch( symbol, &instance ) )
511 continue;
512
513 if( m_mode == MODE::UPDATE )
514 newId = symbol->GetLibId();
515
516 auto it = symbols.find( symbol );
517
518 if( it == symbols.end() )
519 {
521
522 info.m_Instances.emplace_back( instance );
523 info.m_LibId = newId;
524 symbols.insert( { symbol, info } );
525 }
526 else
527 {
528 it->second.m_Instances.emplace_back( instance );
529 }
530 }
531 }
532
533 if( symbols.size() > 0 )
534 matchesProcessed += processSymbols( aCommit, symbols );
535 else
536 m_messagePanel->Report( _( "*** No symbols matching criteria found ***" ),
538
540
541 return matchesProcessed;
542}
543
544
546 const std::map<SCH_SYMBOL*,
547 SYMBOL_CHANGE_INFO>& aSymbols )
548{
549 wxCHECK( !aSymbols.empty(), 0 );
550
551 int matchesProcessed = 0;
552 SCH_EDIT_FRAME* frame = dynamic_cast<SCH_EDIT_FRAME*>( GetParent() );
553 wxString msg;
554
555 wxCHECK( frame, 0 );
556
557 std::map<SCH_SYMBOL*, SYMBOL_CHANGE_INFO> symbols = aSymbols;
558 std::map<SCH_SYMBOL*, SYMBOL_CHANGE_INFO>::iterator it = symbols.begin();
559
560 // Remove all symbols that don't have a valid library symbol link or enough units to
561 // satify the library symbol update.
562 while( it != symbols.end() )
563 {
564 SCH_SYMBOL* symbol = it->first;
565
566 wxCHECK2( symbol && it->second.m_LibId.IsValid(), continue );
567
568 LIB_SYMBOL* libSymbol = frame->GetLibSymbol( it->second.m_LibId );
569
570 if( !libSymbol )
571 {
572 msg = getSymbolReferences( *symbol, it->second.m_LibId );
573 msg << wxT( ": " ) << _( "*** symbol not found ***" );
575 it = symbols.erase( it );
576 continue;
577 }
578
579 std::unique_ptr<LIB_SYMBOL> flattenedSymbol = libSymbol->Flatten();
580
581 if( flattenedSymbol->GetUnitCount() < symbol->GetUnit() )
582 {
583 msg = getSymbolReferences( *symbol, it->second.m_LibId );
584 msg << wxT( ": " ) << _( "*** new symbol has too few units ***" );
586 it = symbols.erase( it );
587 }
588 else
589 {
590 ++it;
591 }
592 }
593
594 // Removing the symbol needs to be done before the LIB_SYMBOL is changed to prevent stale
595 // library symbols in the schematic file.
596 for( const auto& [ symbol, symbol_change_info ] : symbols )
597 {
598 wxCHECK( symbol && !symbol_change_info.m_Instances.empty(), 0 );
599
600 SCH_SCREEN* screen = symbol_change_info.m_Instances[0].LastScreen();
601
602 wxCHECK( screen, 0 );
603
604 screen->Remove( symbol );
605 aCommit->Modify( symbol, screen );
606 }
607
608 for( const auto& [ symbol, symbol_change_info ] : symbols )
609 {
610 // Remember initial link before changing for diags purpose
611 wxString initialLibLinkName = UnescapeString( symbol->GetLibId().Format() );
612
613 if( symbol_change_info.m_LibId != symbol->GetLibId() )
614 symbol->SetLibId( symbol_change_info.m_LibId );
615
616 LIB_SYMBOL* libSymbol = frame->GetLibSymbol( symbol_change_info.m_LibId );
617 std::unique_ptr<LIB_SYMBOL> flattenedSymbol = libSymbol->Flatten();
618 SCH_SCREEN* screen = symbol_change_info.m_Instances[0].LastScreen();
619
620 symbol->SetLibSymbol( flattenedSymbol.release() );
621
622 if( m_resetAttributes->GetValue() )
623 {
624 // Fetch the attributes from the *flattened* library symbol. They are not supported
625 // in derived symbols.
626 symbol->SetExcludedFromSim( symbol->GetLibSymbolRef()->GetExcludedFromSim() );
627 symbol->SetExcludedFromBOM( symbol->GetLibSymbolRef()->GetExcludedFromBOM() );
628 symbol->SetExcludedFromBoard( symbol->GetLibSymbolRef()->GetExcludedFromBoard() );
629 }
630
631 bool removeExtras = m_removeExtraBox->GetValue();
632 bool resetVis = m_resetFieldVisibilities->GetValue();
633 bool resetEffects = m_resetFieldEffects->GetValue();
634 bool resetPositions = m_resetFieldPositions->GetValue();
635
636 for( unsigned i = 0; i < symbol->GetFields().size(); ++i )
637 {
638 SCH_FIELD& field = symbol->GetFields()[i];
639 LIB_FIELD* libField = nullptr;
640
641 // Mandatory fields always exist in m_updateFields, but these names can be translated.
642 // so use GetCanonicalName().
644 continue;
645
646 if( i < MANDATORY_FIELDS )
647 libField = symbol->GetLibSymbolRef()->GetFieldById( (int) i );
648 else
649 libField = symbol->GetLibSymbolRef()->FindField( field.GetName() );
650
651 if( libField )
652 {
653 bool resetText = libField->GetText().IsEmpty() ? m_resetEmptyFields->GetValue()
654 : m_resetFieldText->GetValue();
655
656 if( resetText )
657 {
658 if( i == REFERENCE_FIELD )
659 {
660 wxString prefix = UTIL::GetRefDesPrefix( libField->GetText() );
661
662 for( const SCH_SHEET_PATH& instance : symbol_change_info.m_Instances )
663 {
664 wxString ref = symbol->GetRef( &instance );
665 int number = UTIL::GetRefDesNumber( ref );
666
667 if( number >= 0 )
668 ref.Printf( wxS( "%s%d" ), prefix, number );
669 else
670 ref = UTIL::GetRefDesUnannotated( prefix );
671
672 symbol->SetRef( &instance, ref );
673 }
674 }
675 else if( i == VALUE_FIELD )
676 {
677 if( ( symbol->IsPower() && m_resetCustomPower->IsChecked() )
678 || !symbol->IsPower() )
679 symbol->SetValueFieldText( UnescapeString( libField->GetText() ) );
680 }
681 else if( i == FOOTPRINT_FIELD )
682 {
683 symbol->SetFootprintFieldText( libField->GetText() );
684 }
685 else
686 {
687 field.SetText( libField->GetText() );
688 }
689 }
690
691 if( resetVis )
692 field.SetVisible( libField->IsVisible() );
693
694 if( resetEffects )
695 {
696 // Careful: the visible bit and position are also set by SetAttributes()
697 bool visible = field.IsVisible();
698 VECTOR2I pos = field.GetPosition();
699
700 field.SetAttributes( *libField );
701
702 field.SetVisible( visible );
703 field.SetPosition( pos );
704 field.SetNameShown( libField->IsNameShown() );
705 field.SetCanAutoplace( libField->CanAutoplace() );
706 }
707
708 if( resetPositions )
709 field.SetTextPos( symbol->GetPosition() + libField->GetTextPos() );
710 }
711 else if( i >= MANDATORY_FIELDS && removeExtras )
712 {
713 symbol->RemoveField( field.GetName() );
714 i--;
715 }
716 }
717
718 std::vector<LIB_FIELD*> libFields;
719 symbol->GetLibSymbolRef()->GetFields( libFields );
720
721 for( unsigned i = MANDATORY_FIELDS; i < libFields.size(); ++i )
722 {
723 const LIB_FIELD& libField = *libFields[i];
724
725 if( !alg::contains( m_updateFields, libField.GetCanonicalName() ) )
726 continue;
727
728 if( !symbol->FindField( libField.GetName(), false ) )
729 {
730 wxString fieldName = libField.GetCanonicalName();
731 SCH_FIELD newField( VECTOR2I( 0, 0 ), symbol->GetFieldCount(), symbol,
732 fieldName );
733 SCH_FIELD* schField = symbol->AddField( newField );
734
735 // Careful: the visible bit and position are also set by SetAttributes()
736 schField->SetAttributes( libField );
737 schField->SetText( libField.GetText() );
738 schField->SetTextPos( symbol->GetPosition() + libField.GetTextPos() );
739 }
740
741 if( resetPositions && frame->eeconfig()->m_AutoplaceFields.enable )
742 symbol->AutoAutoplaceFields( screen );
743 }
744
745 symbol->SetSchSymbolLibraryName( wxEmptyString );
746 screen->Append( symbol );
747
748 if( resetPositions )
749 symbol->AutoAutoplaceFields( screen );
750
751 frame->GetCanvas()->GetView()->Update( symbol );
752
753 msg = getSymbolReferences( *symbol, symbol_change_info.m_LibId, &initialLibLinkName );
754 msg += wxS( ": OK" );
756 matchesProcessed +=1;
757 }
758
759 return matchesProcessed;
760}
761
762
764 const LIB_ID& aNewId,
765 const wxString* aOldLibLinkName )
766{
767 wxString msg;
768 wxString references;
769 LIB_ID oldId = aSymbol.GetLibId();
770
771 wxString oldLibLinkName; // For report
772
773 if( aOldLibLinkName )
774 oldLibLinkName = *aOldLibLinkName;
775 else
776 oldLibLinkName = UnescapeString( oldId.Format() );
777
778 SCH_EDIT_FRAME* parent = dynamic_cast< SCH_EDIT_FRAME* >( GetParent() );
779
780 wxCHECK( parent, msg );
781
782 SCH_SHEET_LIST sheets = parent->Schematic().GetSheets();
783
784 for( const SCH_SYMBOL_INSTANCE& instance : aSymbol.GetInstances() )
785 {
786 // Only include the symbol instances for the current project.
787 if( !sheets.HasPath( instance.m_Path ) )
788 continue;
789
790 if( references.IsEmpty() )
791 references = instance.m_Reference;
792 else
793 references += wxT( " " ) + instance.m_Reference;
794 }
795
796 if( m_mode == MODE::UPDATE )
797 {
798 if( aSymbol.GetInstances().size() == 1 )
799 {
800 msg.Printf( _( "Update symbol %s from '%s' to '%s'" ),
801 references,
802 oldLibLinkName,
803 UnescapeString( aNewId.Format() ) );
804 }
805 else
806 {
807 msg.Printf( _( "Update symbols %s from '%s' to '%s'" ),
808 references,
809 oldLibLinkName,
810 UnescapeString( aNewId.Format() ) );
811 }
812 }
813 else // mode is MODE::CHANGE
814 {
815 if( aSymbol.GetInstances().size() == 1 )
816 {
817 msg.Printf( _( "Change symbol %s from '%s' to '%s'" ),
818 references,
819 oldLibLinkName,
820 UnescapeString( aNewId.Format() ) );
821 }
822 else
823 {
824 msg.Printf( _( "Change symbols %s from '%s' to '%s'" ),
825 references,
826 oldLibLinkName,
827 UnescapeString( aNewId.Format() ) );
828 }
829 }
830
831 return msg;
832}
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.
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
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: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:231
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:148
void SetTextPos(const VECTOR2I &aPoint)
Definition: eda_text.cpp:419
void SetAttributes(const EDA_TEXT &aSrc, bool aSetPosition=true)
Set the text attributes from another instance.
Definition: eda_text.cpp:292
virtual void SetVisible(bool aVisible)
Definition: eda_text.cpp:245
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:1636
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:393
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:1274
void SetCanAutoplace(bool aCanPlace)
Definition: sch_field.h:199
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:1039
wxString GetName(bool aUseDefaultName=true) const
Return the field name (not translated).
Definition: sch_field.cpp:1007
void SetPosition(const VECTOR2I &aPosition) override
Definition: sch_field.cpp:1254
void SetText(const wxString &aText) override
Definition: sch_field.cpp:996
void SetNameShown(bool aShown=true)
Definition: sch_field.h:188
Base class for any item which can be embedded within the SCHEMATIC container class,...
Definition: sch_item.h:165
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:751
SCH_FIELD * GetField(MANDATORY_FIELD_T aFieldType)
Return a mandatory field in this symbol.
Definition: sch_symbol.cpp:953
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.
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
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
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:160
VECTOR2< int > VECTOR2I
Definition: vector2d.h:588