2020-08-13 13:51:26 -04:00
|
|
|
/*
|
|
|
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
|
|
|
*
|
2021-02-24 08:48:02 -05:00
|
|
|
* Copyright (C) 2020-2021 CERN
|
2025-01-01 13:30:11 -08:00
|
|
|
* Copyright The KiCad Developers, see AUTHORS.txt for contributors.
|
2020-08-13 13:51:26 -04:00
|
|
|
*
|
|
|
|
* @author Wayne Stambaugh <stambaughw@gmail.com>
|
|
|
|
*
|
|
|
|
* This program is free software: you can redistribute it and/or modify it
|
|
|
|
* under the terms of the GNU General Public License as published by the
|
|
|
|
* Free Software Foundation, either version 3 of the License, or (at your
|
|
|
|
* option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful, but
|
|
|
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
* General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License along
|
|
|
|
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <algorithm>
|
|
|
|
|
|
|
|
#include <bitmaps.h>
|
2024-04-24 12:44:32 -07:00
|
|
|
#include <connection_graph.h>
|
2021-07-29 10:56:22 +01:00
|
|
|
#include <string_utils.h> // WildCompareString
|
2020-08-13 13:51:26 -04:00
|
|
|
#include <kiway.h>
|
2021-04-18 16:23:15 +01:00
|
|
|
#include <refdes_utils.h>
|
2020-10-24 08:53:11 -04:00
|
|
|
#include <core/kicad_algo.h>
|
2020-08-13 13:51:26 -04:00
|
|
|
#include <dialog_change_symbols.h>
|
2021-02-24 08:48:02 -05:00
|
|
|
#include <sch_symbol.h>
|
2020-08-13 13:51:26 -04:00
|
|
|
#include <sch_edit_frame.h>
|
|
|
|
#include <sch_screen.h>
|
|
|
|
#include <schematic.h>
|
|
|
|
#include <template_fieldnames.h>
|
2022-09-03 19:29:02 +01:00
|
|
|
#include <widgets/wx_html_report_panel.h>
|
2023-09-01 00:04:12 +01:00
|
|
|
#include <widgets/std_bitmap_button.h>
|
2023-06-09 22:41:33 +01:00
|
|
|
#include <sch_commit.h>
|
2020-08-13 13:51:26 -04:00
|
|
|
|
2020-12-18 13:00:22 +00:00
|
|
|
bool g_selectRefDes = false;
|
|
|
|
bool g_selectValue = false;
|
2021-01-15 22:18:51 +00:00
|
|
|
// { change, update }
|
|
|
|
bool g_removeExtraFields[2] = { false, false };
|
|
|
|
bool g_resetEmptyFields[2] = { false, false };
|
2021-02-22 00:35:37 +00:00
|
|
|
bool g_resetFieldText[2] = { true, true };
|
2021-01-15 22:18:51 +00:00
|
|
|
bool g_resetFieldVisibilities[2] = { true, false };
|
|
|
|
bool g_resetFieldEffects[2] = { true, false };
|
|
|
|
bool g_resetFieldPositions[2] = { true, false };
|
|
|
|
bool g_resetAttributes[2] = { true, false };
|
2024-03-10 18:32:00 +00:00
|
|
|
bool g_resetCustomPower[2] = { false, false };
|
2020-09-02 14:11:51 +01:00
|
|
|
|
|
|
|
|
2021-06-10 10:10:55 -04:00
|
|
|
DIALOG_CHANGE_SYMBOLS::DIALOG_CHANGE_SYMBOLS( SCH_EDIT_FRAME* aParent, SCH_SYMBOL* aSymbol,
|
2020-09-27 14:07:48 +01:00
|
|
|
MODE aMode ) :
|
2020-08-13 13:51:26 -04:00
|
|
|
DIALOG_CHANGE_SYMBOLS_BASE( aParent ),
|
|
|
|
m_symbol( aSymbol),
|
|
|
|
m_mode( aMode )
|
|
|
|
{
|
|
|
|
wxASSERT( aParent );
|
|
|
|
|
|
|
|
if( m_mode == MODE::UPDATE )
|
|
|
|
{
|
|
|
|
m_newIdSizer->Show( false );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2020-10-16 19:57:07 -07:00
|
|
|
m_matchAll->SetLabel( _( "Change all symbols in schematic" ) );
|
|
|
|
SetTitle( _( "Change Symbols" ) );
|
2020-08-13 13:51:26 -04:00
|
|
|
m_matchSizer->FindItem( m_matchAll )->Show( false );
|
|
|
|
}
|
|
|
|
|
|
|
|
if( m_symbol )
|
|
|
|
{
|
2020-09-06 13:05:07 +01:00
|
|
|
SCH_SHEET_PATH* currentSheet = &aParent->Schematic().CurrentSheet();
|
|
|
|
|
2020-10-16 19:57:07 -07:00
|
|
|
if( m_mode == MODE::CHANGE )
|
2021-06-17 23:34:19 +01:00
|
|
|
m_matchBySelection->SetLabel( _( "Change selected symbol(s)" ) );
|
2020-10-16 19:57:07 -07:00
|
|
|
|
2021-07-28 16:39:40 +01:00
|
|
|
m_newId->ChangeValue( UnescapeString( m_symbol->GetLibId().Format() ) );
|
2020-09-06 13:05:07 +01:00
|
|
|
m_specifiedReference->ChangeValue( m_symbol->GetRef( currentSheet ) );
|
2025-02-08 13:45:57 +00:00
|
|
|
m_specifiedValue->ChangeValue( UnescapeString( m_symbol->GetField( FIELD_T::VALUE )->GetText() ) );
|
2021-07-28 16:39:40 +01:00
|
|
|
m_specifiedId->ChangeValue( UnescapeString( m_symbol->GetLibId().Format() ) );
|
2020-08-13 13:51:26 -04:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
m_matchSizer->FindItem( m_matchBySelection )->Show( false );
|
|
|
|
}
|
|
|
|
|
2023-10-21 14:56:19 -04:00
|
|
|
m_matchIdBrowserButton->SetBitmap( KiBitmapBundle( BITMAPS::small_library ) );
|
|
|
|
m_newIdBrowserButton->SetBitmap( KiBitmapBundle( BITMAPS::small_library ) );
|
2020-08-13 13:51:26 -04:00
|
|
|
|
2020-10-16 19:57:07 -07:00
|
|
|
if( m_mode == MODE::CHANGE )
|
|
|
|
{
|
|
|
|
m_matchByReference->SetLabel( _( "Change symbols matching reference designator:" ) );
|
|
|
|
m_matchByValue->SetLabel( _( "Change symbols matching value:" ) );
|
|
|
|
m_matchById->SetLabel( _( "Change symbols matching library identifier:" ) );
|
|
|
|
}
|
2020-08-13 13:51:26 -04:00
|
|
|
|
|
|
|
m_matchSizer->SetEmptyCellSize( wxSize( 0, 0 ) );
|
|
|
|
m_matchSizer->Layout();
|
|
|
|
|
2025-02-08 13:45:57 +00:00
|
|
|
for( FIELD_T fieldId : MANDATORY_FIELDS )
|
2020-09-27 14:07:48 +01:00
|
|
|
{
|
2025-02-08 13:45:57 +00:00
|
|
|
int listIdx = m_fieldsBox->GetCount();
|
2020-09-27 14:07:48 +01:00
|
|
|
|
2025-02-08 13:45:57 +00:00
|
|
|
m_fieldsBox->Append( GetDefaultFieldName( fieldId, DO_TRANSLATE ) );
|
|
|
|
|
|
|
|
if( fieldId == FIELD_T::REFERENCE )
|
|
|
|
m_fieldsBox->Check( listIdx, g_selectRefDes );
|
|
|
|
else if( fieldId == FIELD_T::VALUE )
|
|
|
|
m_fieldsBox->Check( listIdx, g_selectValue );
|
2020-12-18 13:00:22 +00:00
|
|
|
else
|
2025-02-08 13:45:57 +00:00
|
|
|
m_fieldsBox->Check( listIdx, true );
|
|
|
|
|
|
|
|
m_mandatoryFieldListIndexes[fieldId] = listIdx;
|
2020-09-27 14:07:48 +01:00
|
|
|
}
|
|
|
|
|
2020-08-13 13:51:26 -04:00
|
|
|
m_messagePanel->SetLazyUpdate( true );
|
2021-02-25 15:05:26 +00:00
|
|
|
m_messagePanel->SetFileName( Prj().GetProjectPath() + wxT( "report.txt" ) );
|
2020-08-13 13:51:26 -04:00
|
|
|
|
|
|
|
if( aSymbol && aSymbol->IsSelected() )
|
|
|
|
{
|
|
|
|
m_matchBySelection->SetValue( true );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if( aMode == MODE::UPDATE )
|
|
|
|
m_matchAll->SetValue( true );
|
|
|
|
else
|
|
|
|
m_matchByReference->SetValue( true );
|
|
|
|
}
|
|
|
|
|
2020-12-02 14:17:59 +00:00
|
|
|
updateFieldsList();
|
|
|
|
|
2020-10-16 19:57:07 -07:00
|
|
|
if( m_mode == MODE::CHANGE )
|
|
|
|
{
|
2020-12-02 14:23:03 +00:00
|
|
|
m_updateFieldsSizer->GetStaticBox()->SetLabel( _( "Update Fields" ) );
|
2020-10-16 19:57:07 -07:00
|
|
|
m_removeExtraBox->SetLabel( _( "Remove fields if not in new symbol" ) );
|
|
|
|
m_resetEmptyFields->SetLabel( _( "Reset fields if empty in new symbol" ) );
|
2021-02-22 00:35:37 +00:00
|
|
|
m_resetFieldText->SetLabel( _( "Update field text" ) );
|
2020-10-16 19:57:07 -07:00
|
|
|
m_resetFieldVisibilities->SetLabel( _( "Update field visibilities" ) );
|
|
|
|
m_resetFieldEffects->SetLabel( _( "Update field sizes and styles" ) );
|
|
|
|
m_resetFieldPositions->SetLabel( _( "Update field positions" ) );
|
2021-02-22 00:35:37 +00:00
|
|
|
m_resetAttributes->SetLabel( _( "Update symbol attributes" ) );
|
2020-10-16 19:57:07 -07:00
|
|
|
}
|
2020-09-15 23:52:53 +01:00
|
|
|
|
2021-01-15 22:18:51 +00:00
|
|
|
m_removeExtraBox->SetValue( g_removeExtraFields[ (int) m_mode ] );
|
|
|
|
m_resetEmptyFields->SetValue( g_resetEmptyFields[ (int) m_mode ] );
|
2021-02-22 00:35:37 +00:00
|
|
|
m_resetFieldText->SetValue( g_resetFieldText[ (int) m_mode ] );
|
2021-01-15 22:18:51 +00:00
|
|
|
m_resetFieldVisibilities->SetValue( g_resetFieldVisibilities[ (int) m_mode ] );
|
|
|
|
m_resetFieldEffects->SetValue( g_resetFieldEffects[ (int) m_mode ] );
|
|
|
|
m_resetFieldPositions->SetValue( g_resetFieldPositions[ (int) m_mode ] );
|
|
|
|
m_resetAttributes->SetValue( g_resetAttributes[ (int) m_mode ] );
|
2024-03-10 18:32:00 +00:00
|
|
|
m_resetCustomPower->SetValue( g_resetCustomPower[ (int) m_mode ] );
|
2020-09-02 14:11:51 +01:00
|
|
|
|
2020-08-13 13:51:26 -04:00
|
|
|
// DIALOG_SHIM needs a unique hash_key because classname is not sufficient
|
|
|
|
// because the update and change versions of this dialog have different controls.
|
|
|
|
m_hash_key = TO_UTF8( GetTitle() );
|
|
|
|
|
2021-11-16 19:39:58 +00:00
|
|
|
wxString okLabel = m_mode == MODE::CHANGE ? _( "Change" ) : _( "Update" );
|
2020-10-16 19:57:07 -07:00
|
|
|
|
2021-11-16 19:39:58 +00:00
|
|
|
SetupStandardButtons( { { wxID_OK, okLabel },
|
|
|
|
{ wxID_CANCEL, _( "Close" ) } } );
|
2020-08-13 13:51:26 -04:00
|
|
|
|
|
|
|
// Now all widgets have the size fixed, call FinishDialogSettings
|
2020-11-16 11:16:44 +00:00
|
|
|
finishDialogSettings();
|
2020-08-13 13:51:26 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2020-09-27 14:07:48 +01:00
|
|
|
void DIALOG_CHANGE_SYMBOLS::onMatchByAll( wxCommandEvent& aEvent )
|
|
|
|
{
|
|
|
|
updateFieldsList();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void DIALOG_CHANGE_SYMBOLS::onMatchBySelected( wxCommandEvent& aEvent )
|
|
|
|
{
|
|
|
|
updateFieldsList();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2020-08-13 13:51:26 -04:00
|
|
|
void DIALOG_CHANGE_SYMBOLS::onMatchByReference( wxCommandEvent& aEvent )
|
|
|
|
{
|
2020-09-27 14:07:48 +01:00
|
|
|
updateFieldsList();
|
2020-08-13 13:51:26 -04:00
|
|
|
m_specifiedReference->SetFocus();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void DIALOG_CHANGE_SYMBOLS::onMatchByValue( wxCommandEvent& aEvent )
|
|
|
|
{
|
2020-09-27 14:07:48 +01:00
|
|
|
updateFieldsList();
|
2020-08-13 13:51:26 -04:00
|
|
|
m_specifiedValue->SetFocus();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void DIALOG_CHANGE_SYMBOLS::onMatchById( wxCommandEvent& aEvent )
|
|
|
|
{
|
2020-09-27 14:07:48 +01:00
|
|
|
updateFieldsList();
|
2020-08-13 13:51:26 -04:00
|
|
|
m_specifiedId->SetFocus();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2020-09-27 14:07:48 +01:00
|
|
|
void DIALOG_CHANGE_SYMBOLS::onMatchTextKillFocus( wxFocusEvent& event )
|
|
|
|
{
|
|
|
|
updateFieldsList();
|
2021-10-27 17:17:17 +02:00
|
|
|
event.Skip(); // Mandatory in wxFocusEvent
|
2020-09-27 14:07:48 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-06-28 20:37:51 +01:00
|
|
|
void DIALOG_CHANGE_SYMBOLS::onMatchIDKillFocus( wxFocusEvent& event )
|
|
|
|
{
|
|
|
|
updateFieldsList();
|
2021-10-27 17:17:17 +02:00
|
|
|
event.Skip(); // Mandatory in wxFocusEvent
|
2021-06-28 20:37:51 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void DIALOG_CHANGE_SYMBOLS::onNewLibIDKillFocus( wxFocusEvent& event )
|
|
|
|
{
|
|
|
|
updateFieldsList();
|
2021-10-27 17:17:17 +02:00
|
|
|
event.Skip(); // Mandatory in wxFocusEvent
|
2021-06-28 20:37:51 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2020-08-13 13:51:26 -04:00
|
|
|
DIALOG_CHANGE_SYMBOLS::~DIALOG_CHANGE_SYMBOLS()
|
|
|
|
{
|
2025-02-08 13:45:57 +00:00
|
|
|
g_selectRefDes = m_fieldsBox->IsChecked( m_mandatoryFieldListIndexes[FIELD_T::REFERENCE] );
|
|
|
|
g_selectValue = m_fieldsBox->IsChecked( m_mandatoryFieldListIndexes[FIELD_T::VALUE] );
|
2020-12-18 13:00:22 +00:00
|
|
|
|
2021-01-15 22:18:51 +00:00
|
|
|
g_removeExtraFields[ (int) m_mode ] = m_removeExtraBox->GetValue();
|
|
|
|
g_resetEmptyFields[ (int) m_mode ] = m_resetEmptyFields->GetValue();
|
2021-02-22 00:35:37 +00:00
|
|
|
g_resetFieldText[ (int) m_mode ] = m_resetFieldText->GetValue();
|
2021-01-15 22:18:51 +00:00
|
|
|
g_resetFieldVisibilities[ (int) m_mode ] = m_resetFieldVisibilities->GetValue();
|
|
|
|
g_resetFieldEffects[ (int) m_mode ] = m_resetFieldEffects->GetValue();
|
|
|
|
g_resetFieldPositions[ (int) m_mode ] = m_resetFieldPositions->GetValue();
|
|
|
|
g_resetAttributes[ (int) m_mode ] = m_resetAttributes->GetValue();
|
2024-03-10 18:32:00 +00:00
|
|
|
g_resetCustomPower[ (int) m_mode ] = m_resetCustomPower->GetValue();
|
2020-08-13 13:51:26 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-07-28 16:39:40 +01:00
|
|
|
wxString getLibIdValue( const wxTextCtrl* aCtrl )
|
|
|
|
{
|
|
|
|
wxString rawValue = aCtrl->GetValue();
|
|
|
|
wxString itemName;
|
|
|
|
wxString libName = rawValue.BeforeFirst( ':', &itemName );
|
|
|
|
|
|
|
|
return EscapeString( libName, CTX_LIBID ) + ':' + EscapeString( itemName, CTX_LIBID );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2020-08-13 13:51:26 -04:00
|
|
|
void DIALOG_CHANGE_SYMBOLS::launchMatchIdSymbolBrowser( wxCommandEvent& aEvent )
|
|
|
|
{
|
2021-07-28 16:39:40 +01:00
|
|
|
wxString newName = getLibIdValue( m_specifiedId );
|
2020-08-13 13:51:26 -04:00
|
|
|
|
2024-05-08 18:19:24 +01:00
|
|
|
if( KIWAY_PLAYER* frame = Kiway().Player( FRAME_SYMBOL_CHOOSER, true, this ) )
|
2020-09-27 14:07:48 +01:00
|
|
|
{
|
2024-05-08 18:19:24 +01:00
|
|
|
if( frame->ShowModal( &newName, this ) )
|
|
|
|
{
|
|
|
|
m_specifiedId->SetValue( UnescapeString( newName ) );
|
|
|
|
updateFieldsList();
|
|
|
|
}
|
2020-08-13 13:51:26 -04:00
|
|
|
|
2024-05-08 18:19:24 +01:00
|
|
|
frame->Destroy();
|
|
|
|
}
|
2020-08-13 13:51:26 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void DIALOG_CHANGE_SYMBOLS::launchNewIdSymbolBrowser( wxCommandEvent& aEvent )
|
|
|
|
{
|
2021-07-28 16:39:40 +01:00
|
|
|
wxString newName = getLibIdValue( m_newId );
|
2020-08-13 13:51:26 -04:00
|
|
|
|
2024-05-08 18:19:24 +01:00
|
|
|
if( KIWAY_PLAYER* frame = Kiway().Player( FRAME_SYMBOL_CHOOSER, true, this ) )
|
2020-09-27 14:07:48 +01:00
|
|
|
{
|
2024-05-08 18:19:24 +01:00
|
|
|
if( frame->ShowModal( &newName, this ) )
|
|
|
|
{
|
|
|
|
m_newId->SetValue( UnescapeString( newName ) );
|
|
|
|
updateFieldsList();
|
|
|
|
}
|
2020-08-13 13:51:26 -04:00
|
|
|
|
2024-05-08 18:19:24 +01:00
|
|
|
frame->Destroy();
|
|
|
|
}
|
2020-08-13 13:51:26 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2020-09-27 14:07:48 +01:00
|
|
|
void DIALOG_CHANGE_SYMBOLS::updateFieldsList()
|
|
|
|
{
|
|
|
|
SCH_EDIT_FRAME* frame = dynamic_cast<SCH_EDIT_FRAME*>( GetParent() );
|
2020-12-16 23:54:53 +00:00
|
|
|
|
|
|
|
wxCHECK( frame, /* void */ );
|
|
|
|
|
2021-06-10 14:51:46 -04:00
|
|
|
// Load non-mandatory fields from all matching symbols and their library symbols
|
2025-02-08 13:45:57 +00:00
|
|
|
std::set<wxString> fieldNames;
|
2020-09-27 14:07:48 +01:00
|
|
|
|
2024-10-08 13:51:09 -04:00
|
|
|
for( SCH_SHEET_PATH& instance : frame->Schematic().Hierarchy() )
|
2020-09-27 14:07:48 +01:00
|
|
|
{
|
|
|
|
SCH_SCREEN* screen = instance.LastScreen();
|
|
|
|
|
|
|
|
wxCHECK2( screen, continue );
|
|
|
|
|
2021-06-10 10:10:55 -04:00
|
|
|
for( SCH_ITEM* item : screen->Items().OfType( SCH_SYMBOL_T ) )
|
2020-09-27 14:07:48 +01:00
|
|
|
{
|
2021-06-10 10:10:55 -04:00
|
|
|
SCH_SYMBOL* symbol = dynamic_cast<SCH_SYMBOL*>( item );
|
2020-09-27 14:07:48 +01:00
|
|
|
|
|
|
|
wxCHECK2( symbol, continue );
|
|
|
|
|
|
|
|
if( !isMatch( symbol, &instance ) )
|
|
|
|
continue;
|
|
|
|
|
2025-02-08 13:45:57 +00:00
|
|
|
for( SCH_FIELD& field : symbol->GetFields() )
|
2025-01-05 14:35:49 +00:00
|
|
|
{
|
2025-02-08 13:45:57 +00:00
|
|
|
if( !field.IsMandatory() && !field.IsPrivate() )
|
|
|
|
fieldNames.insert( field.GetName() );
|
2025-01-05 14:35:49 +00:00
|
|
|
}
|
2020-12-15 15:06:19 +00:00
|
|
|
|
2021-02-22 00:35:37 +00:00
|
|
|
if( m_mode == MODE::UPDATE && symbol->GetLibId().IsValid() )
|
2020-12-15 15:06:19 +00:00
|
|
|
{
|
2021-06-17 22:22:10 +01:00
|
|
|
LIB_SYMBOL* libSymbol = frame->GetLibSymbol( symbol->GetLibId() );
|
2020-12-16 17:58:55 +00:00
|
|
|
|
2021-02-22 00:35:37 +00:00
|
|
|
if( libSymbol )
|
|
|
|
{
|
2021-06-10 14:51:46 -04:00
|
|
|
std::unique_ptr<LIB_SYMBOL> flattenedSymbol = libSymbol->Flatten();
|
2025-02-08 13:45:57 +00:00
|
|
|
std::vector<SCH_FIELD*> orderedLibFields;
|
2020-12-15 15:06:19 +00:00
|
|
|
|
2025-02-08 13:45:57 +00:00
|
|
|
flattenedSymbol->GetFields( orderedLibFields );
|
2020-12-16 17:58:55 +00:00
|
|
|
|
2025-02-08 13:45:57 +00:00
|
|
|
for( SCH_FIELD* libField : orderedLibFields )
|
2025-01-05 14:35:49 +00:00
|
|
|
{
|
2025-01-22 14:26:57 +00:00
|
|
|
if( !libField->IsMandatory() && !libField->IsPrivate() )
|
|
|
|
fieldNames.insert( libField->GetName() );
|
2025-01-05 14:35:49 +00:00
|
|
|
}
|
2021-02-22 00:35:37 +00:00
|
|
|
}
|
2020-12-15 15:06:19 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-06-10 14:51:46 -04:00
|
|
|
// Load non-mandatory fields from the change-to library symbol
|
2020-12-15 15:06:19 +00:00
|
|
|
if( m_mode == MODE::CHANGE )
|
|
|
|
{
|
|
|
|
LIB_ID newId;
|
|
|
|
|
2021-07-28 16:39:40 +01:00
|
|
|
newId.Parse( getLibIdValue( m_newId ) );
|
2020-12-15 15:06:19 +00:00
|
|
|
|
|
|
|
if( newId.IsValid() )
|
|
|
|
{
|
2021-06-17 22:22:10 +01:00
|
|
|
LIB_SYMBOL* libSymbol = frame->GetLibSymbol( newId );
|
2020-12-15 15:06:19 +00:00
|
|
|
|
|
|
|
if( libSymbol )
|
|
|
|
{
|
2021-06-10 14:51:46 -04:00
|
|
|
std::unique_ptr<LIB_SYMBOL> flattenedSymbol = libSymbol->Flatten();
|
2025-02-08 13:45:57 +00:00
|
|
|
std::vector<SCH_FIELD*> orderedLibFields;
|
2020-12-15 15:06:19 +00:00
|
|
|
|
2025-02-08 13:45:57 +00:00
|
|
|
flattenedSymbol->GetFields( orderedLibFields );
|
2020-12-15 15:06:19 +00:00
|
|
|
|
2025-02-08 13:45:57 +00:00
|
|
|
for( SCH_FIELD* libField : orderedLibFields )
|
2025-01-05 14:35:49 +00:00
|
|
|
{
|
2025-01-22 14:26:57 +00:00
|
|
|
if( !libField->IsMandatory() && !libField->IsPrivate() )
|
|
|
|
fieldNames.insert( libField->GetName() );
|
2025-01-05 14:35:49 +00:00
|
|
|
}
|
2020-12-15 15:06:19 +00:00
|
|
|
}
|
2020-09-27 14:07:48 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Update the listbox widget
|
2023-12-20 13:06:32 +00:00
|
|
|
wxArrayInt checkedItems;
|
|
|
|
wxArrayString checkedNames;
|
|
|
|
|
|
|
|
m_fieldsBox->GetCheckedItems( checkedItems );
|
|
|
|
|
2023-12-22 13:57:43 +00:00
|
|
|
for( int ii : checkedItems )
|
|
|
|
checkedNames.push_back( m_fieldsBox->GetString( ii ) );
|
2023-12-20 13:06:32 +00:00
|
|
|
|
2023-12-22 13:57:43 +00:00
|
|
|
bool allChecked = true;
|
2023-12-20 13:06:32 +00:00
|
|
|
|
2025-02-08 13:45:57 +00:00
|
|
|
for( int ii = 0; ii < (int) m_fieldsBox->GetCount(); ++ii )
|
2023-12-22 13:57:43 +00:00
|
|
|
{
|
2025-02-08 13:45:57 +00:00
|
|
|
if( !m_fieldsBox->IsChecked( ii )
|
|
|
|
&& ii != m_mandatoryFieldListIndexes[FIELD_T::REFERENCE]
|
|
|
|
&& ii != m_mandatoryFieldListIndexes[FIELD_T::VALUE] )
|
|
|
|
{
|
2023-12-22 13:57:43 +00:00
|
|
|
allChecked = false;
|
2025-02-08 13:45:57 +00:00
|
|
|
}
|
2023-12-22 13:57:43 +00:00
|
|
|
}
|
|
|
|
|
2025-02-08 13:45:57 +00:00
|
|
|
auto isMandatoryField =
|
|
|
|
[&]( int listbox_idx )
|
|
|
|
{
|
|
|
|
for( FIELD_T fieldId : MANDATORY_FIELDS )
|
|
|
|
{
|
|
|
|
if( m_mandatoryFieldListIndexes[fieldId] == listbox_idx )
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
};
|
|
|
|
|
|
|
|
for( int ii = (int) m_fieldsBox->GetCount() - 1; ii >= 0; --ii )
|
|
|
|
{
|
|
|
|
if( isMandatoryField( ii ) )
|
|
|
|
continue;
|
|
|
|
|
2023-12-22 13:57:43 +00:00
|
|
|
m_fieldsBox->Delete( ii );
|
2025-02-08 13:45:57 +00:00
|
|
|
}
|
2020-09-27 14:07:48 +01:00
|
|
|
|
|
|
|
for( const wxString& fieldName : fieldNames )
|
2023-12-20 13:06:32 +00:00
|
|
|
{
|
2020-09-27 14:07:48 +01:00
|
|
|
m_fieldsBox->Append( fieldName );
|
|
|
|
|
2023-12-20 13:06:32 +00:00
|
|
|
if( allChecked || alg::contains( checkedNames, fieldName ) )
|
|
|
|
m_fieldsBox->Check( m_fieldsBox->GetCount() - 1, true );
|
|
|
|
}
|
2020-09-27 14:07:48 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void DIALOG_CHANGE_SYMBOLS::checkAll( bool aCheck )
|
|
|
|
{
|
|
|
|
for( unsigned i = 0; i < m_fieldsBox->GetCount(); ++i )
|
|
|
|
m_fieldsBox->Check( i, aCheck );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2020-08-13 13:51:26 -04:00
|
|
|
void DIALOG_CHANGE_SYMBOLS::onOkButtonClicked( wxCommandEvent& aEvent )
|
|
|
|
{
|
2023-06-09 22:41:33 +01:00
|
|
|
SCH_EDIT_FRAME* parent = dynamic_cast<SCH_EDIT_FRAME*>( GetParent() );
|
2020-08-13 13:51:26 -04:00
|
|
|
|
|
|
|
wxCHECK( parent, /* void */ );
|
|
|
|
|
2023-08-17 10:06:02 +02:00
|
|
|
wxBusyCursor dummy;
|
|
|
|
SCH_COMMIT commit( parent );
|
|
|
|
|
2020-08-13 13:51:26 -04:00
|
|
|
m_messagePanel->Clear();
|
|
|
|
m_messagePanel->Flush( false );
|
|
|
|
|
2021-11-13 13:46:54 +01:00
|
|
|
// Create the set of fields to be updated. Use non translated (canonical) names
|
|
|
|
// for mandatory fields
|
2020-09-27 14:07:48 +01:00
|
|
|
m_updateFields.clear();
|
|
|
|
|
2025-02-08 13:45:57 +00:00
|
|
|
for( unsigned ii = 0; ii < m_fieldsBox->GetCount(); ++ii )
|
2020-09-27 14:07:48 +01:00
|
|
|
{
|
2025-02-08 13:45:57 +00:00
|
|
|
if( m_fieldsBox->IsChecked( ii ) )
|
|
|
|
m_updateFields.insert( m_fieldsBox->GetString( ii ) );
|
|
|
|
}
|
|
|
|
|
|
|
|
for( FIELD_T fieldId : MANDATORY_FIELDS )
|
|
|
|
{
|
|
|
|
if( m_fieldsBox->IsChecked( m_mandatoryFieldListIndexes[fieldId] ) )
|
|
|
|
m_updateFields.insert( GetCanonicalFieldName( fieldId ) );
|
2020-09-27 14:07:48 +01:00
|
|
|
}
|
|
|
|
|
2023-06-07 23:45:06 +01:00
|
|
|
if( processMatchingSymbols( &commit) )
|
|
|
|
commit.Push( m_mode == MODE::CHANGE ? _( "Change Symbols" ) : _( "Update Symbols" ) );
|
2020-08-13 13:51:26 -04:00
|
|
|
|
|
|
|
m_messagePanel->Flush( false );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-06-10 10:10:55 -04:00
|
|
|
bool DIALOG_CHANGE_SYMBOLS::isMatch( SCH_SYMBOL* aSymbol, SCH_SHEET_PATH* aInstance )
|
2020-08-13 13:51:26 -04:00
|
|
|
{
|
|
|
|
SCH_EDIT_FRAME* frame = dynamic_cast<SCH_EDIT_FRAME*>( GetParent() );
|
|
|
|
|
|
|
|
wxCHECK( frame, false );
|
|
|
|
|
2024-07-18 18:01:05 +01:00
|
|
|
if( !aSymbol )
|
|
|
|
return false;
|
|
|
|
|
2020-08-13 13:51:26 -04:00
|
|
|
if( m_matchAll->GetValue() )
|
2020-09-06 13:05:07 +01:00
|
|
|
{
|
2020-08-13 13:51:26 -04:00
|
|
|
return true;
|
2020-09-06 13:05:07 +01:00
|
|
|
}
|
2020-08-13 13:51:26 -04:00
|
|
|
else if( m_matchBySelection->GetValue() )
|
2020-09-06 13:05:07 +01:00
|
|
|
{
|
2021-06-17 23:34:19 +01:00
|
|
|
return aSymbol == m_symbol || aSymbol->IsSelected();
|
2020-09-06 13:05:07 +01:00
|
|
|
}
|
2020-08-13 13:51:26 -04:00
|
|
|
else if( m_matchByReference->GetValue() )
|
2020-09-06 13:05:07 +01:00
|
|
|
{
|
2020-11-17 21:36:17 +00:00
|
|
|
return WildCompareString( m_specifiedReference->GetValue(),
|
2023-05-05 14:21:56 +01:00
|
|
|
UnescapeString( aSymbol->GetRef( aInstance, false ) ),
|
|
|
|
false );
|
2020-09-06 13:05:07 +01:00
|
|
|
}
|
2020-08-13 13:51:26 -04:00
|
|
|
else if( m_matchByValue->GetValue() )
|
2020-09-06 13:05:07 +01:00
|
|
|
{
|
2020-11-17 21:36:17 +00:00
|
|
|
return WildCompareString( m_specifiedValue->GetValue(),
|
2025-02-08 13:45:57 +00:00
|
|
|
UnescapeString( aSymbol->GetField( FIELD_T::VALUE )->GetText() ),
|
2023-05-05 14:21:56 +01:00
|
|
|
false );
|
2020-09-06 13:05:07 +01:00
|
|
|
}
|
2020-08-13 13:51:26 -04:00
|
|
|
else if( m_matchById )
|
|
|
|
{
|
2024-07-18 18:01:05 +01:00
|
|
|
LIB_ID id;
|
|
|
|
|
2021-07-28 16:39:40 +01:00
|
|
|
id.Parse( getLibIdValue( m_specifiedId ) );
|
2020-08-13 13:51:26 -04:00
|
|
|
return aSymbol->GetLibId() == id;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2023-06-09 22:41:33 +01:00
|
|
|
int DIALOG_CHANGE_SYMBOLS::processMatchingSymbols( SCH_COMMIT* aCommit )
|
2020-08-13 13:51:26 -04:00
|
|
|
{
|
|
|
|
SCH_EDIT_FRAME* frame = dynamic_cast<SCH_EDIT_FRAME*>( GetParent() );
|
|
|
|
|
|
|
|
wxCHECK( frame, false );
|
|
|
|
|
2024-06-06 17:58:48 +01:00
|
|
|
LIB_ID newId;
|
|
|
|
wxString msg;
|
|
|
|
int matchesProcessed = 0;
|
2023-02-02 15:53:57 -05:00
|
|
|
SCH_SYMBOL* symbol = nullptr;
|
2020-08-13 13:51:26 -04:00
|
|
|
|
|
|
|
if( m_mode == MODE::CHANGE )
|
|
|
|
{
|
2021-07-28 16:39:40 +01:00
|
|
|
newId.Parse( getLibIdValue( m_newId ) );
|
2020-08-13 13:51:26 -04:00
|
|
|
|
|
|
|
if( !newId.IsValid() )
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2023-02-05 10:36:18 -05:00
|
|
|
std::map<SCH_SYMBOL*, SYMBOL_CHANGE_INFO> symbols;
|
2023-02-02 15:53:57 -05:00
|
|
|
|
2024-10-08 13:51:09 -04:00
|
|
|
for( SCH_SHEET_PATH& instance : frame->Schematic().Hierarchy() )
|
2020-08-13 13:51:26 -04:00
|
|
|
{
|
|
|
|
SCH_SCREEN* screen = instance.LastScreen();
|
|
|
|
|
|
|
|
wxCHECK2( screen, continue );
|
|
|
|
|
2023-02-02 15:53:57 -05:00
|
|
|
// Fetch all the symbols that meet the change criteria.
|
2021-06-10 10:10:55 -04:00
|
|
|
for( SCH_ITEM* item : screen->Items().OfType( SCH_SYMBOL_T ) )
|
2020-12-02 12:32:59 -05:00
|
|
|
{
|
2023-02-02 15:53:57 -05:00
|
|
|
symbol = static_cast<SCH_SYMBOL*>( item );
|
|
|
|
|
|
|
|
wxCHECK2( symbol, continue );
|
|
|
|
|
2020-08-13 13:51:26 -04:00
|
|
|
if( !isMatch( symbol, &instance ) )
|
|
|
|
continue;
|
|
|
|
|
2023-02-05 10:36:18 -05:00
|
|
|
if( m_mode == MODE::UPDATE )
|
2023-02-02 15:53:57 -05:00
|
|
|
newId = symbol->GetLibId();
|
|
|
|
|
|
|
|
auto it = symbols.find( symbol );
|
2020-08-18 20:13:16 +02:00
|
|
|
|
2023-02-02 15:53:57 -05:00
|
|
|
if( it == symbols.end() )
|
2023-02-05 10:36:18 -05:00
|
|
|
{
|
|
|
|
SYMBOL_CHANGE_INFO info;
|
|
|
|
|
|
|
|
info.m_Instances.emplace_back( instance );
|
|
|
|
info.m_LibId = newId;
|
|
|
|
symbols.insert( { symbol, info } );
|
|
|
|
}
|
2023-02-02 15:53:57 -05:00
|
|
|
else
|
2023-02-05 10:36:18 -05:00
|
|
|
{
|
|
|
|
it->second.m_Instances.emplace_back( instance );
|
|
|
|
}
|
2020-08-13 13:51:26 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-06-29 22:37:25 +01:00
|
|
|
if( symbols.size() > 0 )
|
|
|
|
matchesProcessed += processSymbols( aCommit, symbols );
|
|
|
|
else
|
2023-12-28 18:25:47 -05:00
|
|
|
m_messagePanel->Report( _( "*** No symbols matching criteria found ***" ),
|
|
|
|
RPT_SEVERITY_ERROR );
|
2023-02-02 15:53:57 -05:00
|
|
|
|
2020-11-23 21:23:40 +00:00
|
|
|
frame->GetCurrentSheet().UpdateAllScreenReferences();
|
|
|
|
|
2023-02-02 15:53:57 -05:00
|
|
|
return matchesProcessed;
|
2020-08-13 13:51:26 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2023-06-09 22:41:33 +01:00
|
|
|
int DIALOG_CHANGE_SYMBOLS::processSymbols( SCH_COMMIT* aCommit,
|
2024-02-28 11:21:17 +01:00
|
|
|
const std::map<SCH_SYMBOL*,
|
|
|
|
SYMBOL_CHANGE_INFO>& aSymbols )
|
2020-08-13 13:51:26 -04:00
|
|
|
{
|
2023-02-05 10:36:18 -05:00
|
|
|
wxCHECK( !aSymbols.empty(), 0 );
|
2020-08-13 13:51:26 -04:00
|
|
|
|
2023-02-02 15:53:57 -05:00
|
|
|
int matchesProcessed = 0;
|
2020-08-13 13:51:26 -04:00
|
|
|
SCH_EDIT_FRAME* frame = dynamic_cast<SCH_EDIT_FRAME*>( GetParent() );
|
2023-02-24 22:41:04 +00:00
|
|
|
wxString msg;
|
2020-08-13 13:51:26 -04:00
|
|
|
|
2023-02-02 15:53:57 -05:00
|
|
|
wxCHECK( frame, 0 );
|
2020-08-13 13:51:26 -04:00
|
|
|
|
2023-02-24 22:41:04 +00:00
|
|
|
std::map<SCH_SYMBOL*, SYMBOL_CHANGE_INFO> symbols = aSymbols;
|
|
|
|
std::map<SCH_SYMBOL*, SYMBOL_CHANGE_INFO>::iterator it = symbols.begin();
|
2020-08-13 13:51:26 -04:00
|
|
|
|
2023-02-02 15:53:57 -05:00
|
|
|
// Remove all symbols that don't have a valid library symbol link or enough units to
|
2025-01-18 10:32:42 -05:00
|
|
|
// satisfy the library symbol update.
|
2023-02-02 15:53:57 -05:00
|
|
|
while( it != symbols.end() )
|
2020-11-23 21:23:40 +00:00
|
|
|
{
|
2023-02-03 15:08:12 +00:00
|
|
|
SCH_SYMBOL* symbol = it->first;
|
2023-02-02 15:53:57 -05:00
|
|
|
|
2023-02-05 10:36:18 -05:00
|
|
|
wxCHECK2( symbol && it->second.m_LibId.IsValid(), continue );
|
2023-02-02 15:53:57 -05:00
|
|
|
|
2023-02-24 22:41:04 +00:00
|
|
|
LIB_SYMBOL* libSymbol = frame->GetLibSymbol( it->second.m_LibId );
|
2023-02-02 15:53:57 -05:00
|
|
|
|
|
|
|
if( !libSymbol )
|
2020-11-23 21:23:40 +00:00
|
|
|
{
|
2023-02-05 10:36:18 -05:00
|
|
|
msg = getSymbolReferences( *symbol, it->second.m_LibId );
|
2023-02-02 15:53:57 -05:00
|
|
|
msg << wxT( ": " ) << _( "*** symbol not found ***" );
|
|
|
|
m_messagePanel->Report( msg, RPT_SEVERITY_ERROR );
|
|
|
|
it = symbols.erase( it );
|
|
|
|
continue;
|
2020-11-23 21:23:40 +00:00
|
|
|
}
|
2023-02-02 15:53:57 -05:00
|
|
|
|
|
|
|
std::unique_ptr<LIB_SYMBOL> flattenedSymbol = libSymbol->Flatten();
|
|
|
|
|
|
|
|
if( flattenedSymbol->GetUnitCount() < symbol->GetUnit() )
|
2020-11-23 21:23:40 +00:00
|
|
|
{
|
2023-02-05 10:36:18 -05:00
|
|
|
msg = getSymbolReferences( *symbol, it->second.m_LibId );
|
2023-02-02 15:53:57 -05:00
|
|
|
msg << wxT( ": " ) << _( "*** new symbol has too few units ***" );
|
|
|
|
m_messagePanel->Report( msg, RPT_SEVERITY_ERROR );
|
|
|
|
it = symbols.erase( it );
|
2020-11-23 21:23:40 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2023-02-02 15:53:57 -05:00
|
|
|
++it;
|
2020-11-23 21:23:40 +00:00
|
|
|
}
|
|
|
|
}
|
2020-08-13 13:51:26 -04:00
|
|
|
|
2023-02-02 15:53:57 -05:00
|
|
|
// Removing the symbol needs to be done before the LIB_SYMBOL is changed to prevent stale
|
|
|
|
// library symbols in the schematic file.
|
2023-02-05 10:36:18 -05:00
|
|
|
for( const auto& [ symbol, symbol_change_info ] : symbols )
|
2020-08-13 13:51:26 -04:00
|
|
|
{
|
2023-02-05 10:36:18 -05:00
|
|
|
wxCHECK( symbol && !symbol_change_info.m_Instances.empty(), 0 );
|
2020-08-13 13:51:26 -04:00
|
|
|
|
2023-02-24 22:41:04 +00:00
|
|
|
SCH_SCREEN* screen = symbol_change_info.m_Instances[0].LastScreen();
|
2020-08-13 13:51:26 -04:00
|
|
|
|
2023-02-02 15:53:57 -05:00
|
|
|
wxCHECK( screen, 0 );
|
2020-08-13 13:51:26 -04:00
|
|
|
|
2023-02-02 15:53:57 -05:00
|
|
|
screen->Remove( symbol );
|
2024-04-24 12:44:32 -07:00
|
|
|
SCH_SYMBOL* symbol_copy = static_cast<SCH_SYMBOL*>( symbol->Clone() );
|
|
|
|
aCommit->Modified( symbol, symbol_copy, screen );
|
|
|
|
|
|
|
|
CONNECTION_GRAPH* connectionGraph = screen->Schematic()->ConnectionGraph();
|
|
|
|
|
|
|
|
// When we replace the lib symbol below, we free the associated pins if the new symbol has
|
|
|
|
// fewer than the original. This will cause the connection graph to be out of date unless
|
2025-01-18 10:32:42 -05:00
|
|
|
// we replace references in the graph to the old symbol/pins with references to the ones
|
|
|
|
// stored in the undo stack.
|
2024-04-24 12:44:32 -07:00
|
|
|
if( connectionGraph )
|
|
|
|
connectionGraph->ExchangeItem( symbol, symbol_copy );
|
2023-02-02 15:53:57 -05:00
|
|
|
}
|
2020-09-02 14:11:51 +01:00
|
|
|
|
2023-02-05 10:36:18 -05:00
|
|
|
for( const auto& [ symbol, symbol_change_info ] : symbols )
|
2021-01-15 22:18:51 +00:00
|
|
|
{
|
2024-02-28 11:21:17 +01:00
|
|
|
// Remember initial link before changing for diags purpose
|
|
|
|
wxString initialLibLinkName = UnescapeString( symbol->GetLibId().Format() );
|
|
|
|
|
2023-02-05 10:36:18 -05:00
|
|
|
if( symbol_change_info.m_LibId != symbol->GetLibId() )
|
|
|
|
symbol->SetLibId( symbol_change_info.m_LibId );
|
2020-09-02 14:11:51 +01:00
|
|
|
|
2024-06-12 13:27:17 -04:00
|
|
|
LIB_SYMBOL* libSymbol = frame->GetLibSymbol( symbol_change_info.m_LibId );
|
|
|
|
std::unique_ptr<LIB_SYMBOL> flattenedSymbol = libSymbol->Flatten();
|
|
|
|
SCH_SCREEN* screen = symbol_change_info.m_Instances[0].LastScreen();
|
2020-09-02 14:11:51 +01:00
|
|
|
|
2024-06-12 13:27:17 -04:00
|
|
|
symbol->SetLibSymbol( flattenedSymbol.release() );
|
2020-09-27 14:07:48 +01:00
|
|
|
|
2023-02-02 15:53:57 -05:00
|
|
|
if( m_resetAttributes->GetValue() )
|
|
|
|
{
|
2023-04-15 16:51:10 +01:00
|
|
|
// Fetch the attributes from the *flattened* library symbol. They are not supported
|
|
|
|
// in derived symbols.
|
2024-06-12 13:27:17 -04:00
|
|
|
symbol->SetExcludedFromSim( symbol->GetLibSymbolRef()->GetExcludedFromSim() );
|
|
|
|
symbol->SetExcludedFromBOM( symbol->GetLibSymbolRef()->GetExcludedFromBOM() );
|
|
|
|
symbol->SetExcludedFromBoard( symbol->GetLibSymbolRef()->GetExcludedFromBoard() );
|
2023-02-02 15:53:57 -05:00
|
|
|
}
|
2020-09-02 14:11:51 +01:00
|
|
|
|
2024-04-27 12:09:27 +01:00
|
|
|
if( m_resetPinTextVisibility->GetValue() )
|
|
|
|
{
|
2024-06-12 13:27:17 -04:00
|
|
|
symbol->SetShowPinNames( symbol->GetLibSymbolRef()->GetShowPinNames() );
|
|
|
|
symbol->SetShowPinNumbers( symbol->GetLibSymbolRef()->GetShowPinNumbers() );
|
2024-04-27 12:09:27 +01:00
|
|
|
}
|
|
|
|
|
2023-02-02 15:53:57 -05:00
|
|
|
bool removeExtras = m_removeExtraBox->GetValue();
|
|
|
|
bool resetVis = m_resetFieldVisibilities->GetValue();
|
|
|
|
bool resetEffects = m_resetFieldEffects->GetValue();
|
|
|
|
bool resetPositions = m_resetFieldPositions->GetValue();
|
|
|
|
|
2025-02-08 13:45:57 +00:00
|
|
|
for( int ii = (int) symbol->GetFields().size() - 1; ii >= 0; ii-- )
|
2020-09-02 14:11:51 +01:00
|
|
|
{
|
2025-02-08 13:45:57 +00:00
|
|
|
SCH_FIELD& field = symbol->GetFields()[ii];
|
2024-04-12 22:00:41 +01:00
|
|
|
SCH_FIELD* libField = nullptr;
|
2025-01-05 14:35:49 +00:00
|
|
|
bool doUpdate = field.IsPrivate();
|
2021-02-22 00:35:37 +00:00
|
|
|
|
2023-02-02 15:53:57 -05:00
|
|
|
// Mandatory fields always exist in m_updateFields, but these names can be translated.
|
|
|
|
// so use GetCanonicalName().
|
2025-01-05 14:35:49 +00:00
|
|
|
doUpdate |= alg::contains( m_updateFields, field.GetCanonicalName() );
|
|
|
|
|
|
|
|
if( !doUpdate )
|
2023-02-02 15:53:57 -05:00
|
|
|
continue;
|
2020-09-02 14:11:51 +01:00
|
|
|
|
2025-02-08 13:45:57 +00:00
|
|
|
if( field.IsMandatory() )
|
|
|
|
libField = symbol->GetLibSymbolRef()->GetField( field.GetId() );
|
2023-02-02 15:53:57 -05:00
|
|
|
else
|
2025-02-08 13:45:57 +00:00
|
|
|
libField = symbol->GetLibSymbolRef()->GetField( field.GetName() );
|
2020-09-02 14:11:51 +01:00
|
|
|
|
2023-02-02 15:53:57 -05:00
|
|
|
if( libField )
|
2020-09-02 14:11:51 +01:00
|
|
|
{
|
2024-12-09 20:30:01 +00:00
|
|
|
field.SetPrivate( libField->IsPrivate() );
|
|
|
|
|
2023-02-02 15:53:57 -05:00
|
|
|
bool resetText = libField->GetText().IsEmpty() ? m_resetEmptyFields->GetValue()
|
|
|
|
: m_resetFieldText->GetValue();
|
2021-02-14 18:29:27 +00:00
|
|
|
|
2023-02-02 15:53:57 -05:00
|
|
|
if( resetText )
|
|
|
|
{
|
2025-02-08 13:45:57 +00:00
|
|
|
if( field.GetId() == FIELD_T::REFERENCE )
|
2023-02-02 15:53:57 -05:00
|
|
|
{
|
2024-02-18 21:43:27 +00:00
|
|
|
wxString prefix = UTIL::GetRefDesPrefix( libField->GetText() );
|
|
|
|
|
2023-02-05 10:36:18 -05:00
|
|
|
for( const SCH_SHEET_PATH& instance : symbol_change_info.m_Instances )
|
2023-02-02 15:53:57 -05:00
|
|
|
{
|
2024-02-27 17:15:59 +00:00
|
|
|
wxString ref = symbol->GetRef( &instance );
|
2024-02-18 21:43:27 +00:00
|
|
|
int number = UTIL::GetRefDesNumber( ref );
|
|
|
|
|
|
|
|
if( number >= 0 )
|
|
|
|
ref.Printf( wxS( "%s%d" ), prefix, number );
|
|
|
|
else
|
|
|
|
ref = UTIL::GetRefDesUnannotated( prefix );
|
|
|
|
|
|
|
|
symbol->SetRef( &instance, ref );
|
2023-02-02 15:53:57 -05:00
|
|
|
}
|
|
|
|
}
|
2025-02-08 13:45:57 +00:00
|
|
|
else if( field.GetId() == FIELD_T::VALUE )
|
2023-02-02 15:53:57 -05:00
|
|
|
{
|
2025-02-08 13:45:57 +00:00
|
|
|
if( !symbol->IsPower() || m_resetCustomPower->IsChecked() )
|
2024-03-10 18:32:00 +00:00
|
|
|
symbol->SetValueFieldText( UnescapeString( libField->GetText() ) );
|
2023-02-02 15:53:57 -05:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
field.SetText( libField->GetText() );
|
|
|
|
}
|
|
|
|
}
|
2021-02-14 18:29:27 +00:00
|
|
|
|
2023-02-02 15:53:57 -05:00
|
|
|
if( resetVis )
|
|
|
|
field.SetVisible( libField->IsVisible() );
|
|
|
|
|
|
|
|
if( resetEffects )
|
|
|
|
{
|
|
|
|
// Careful: the visible bit and position are also set by SetAttributes()
|
|
|
|
bool visible = field.IsVisible();
|
|
|
|
VECTOR2I pos = field.GetPosition();
|
|
|
|
|
|
|
|
field.SetAttributes( *libField );
|
2020-09-02 14:11:51 +01:00
|
|
|
|
2023-02-02 15:53:57 -05:00
|
|
|
field.SetVisible( visible );
|
|
|
|
field.SetPosition( pos );
|
|
|
|
field.SetNameShown( libField->IsNameShown() );
|
|
|
|
field.SetCanAutoplace( libField->CanAutoplace() );
|
|
|
|
}
|
|
|
|
|
|
|
|
if( resetPositions )
|
|
|
|
field.SetTextPos( symbol->GetPosition() + libField->GetTextPos() );
|
|
|
|
}
|
2025-02-08 13:45:57 +00:00
|
|
|
else if( !field.IsMandatory() && removeExtras )
|
2023-02-02 15:53:57 -05:00
|
|
|
{
|
|
|
|
symbol->RemoveField( field.GetName() );
|
|
|
|
}
|
2020-09-02 14:11:51 +01:00
|
|
|
}
|
2023-02-02 15:53:57 -05:00
|
|
|
|
2024-04-12 22:00:41 +01:00
|
|
|
std::vector<SCH_FIELD*> libFields;
|
2024-06-12 13:27:17 -04:00
|
|
|
symbol->GetLibSymbolRef()->GetFields( libFields );
|
2023-02-02 15:53:57 -05:00
|
|
|
|
2025-01-22 14:26:57 +00:00
|
|
|
for( SCH_FIELD* libField : libFields )
|
2020-09-02 14:11:51 +01:00
|
|
|
{
|
2025-01-22 14:26:57 +00:00
|
|
|
if( libField->IsMandatory() )
|
|
|
|
continue;
|
2020-09-02 14:11:51 +01:00
|
|
|
|
2025-01-22 14:26:57 +00:00
|
|
|
if( !alg::contains( m_updateFields, libField->GetCanonicalName() ) )
|
2023-02-02 15:53:57 -05:00
|
|
|
continue;
|
2020-09-02 14:11:51 +01:00
|
|
|
|
2025-02-08 13:45:57 +00:00
|
|
|
if( !symbol->GetField( libField->GetName() ) )
|
2023-02-02 15:53:57 -05:00
|
|
|
{
|
2025-02-08 13:45:57 +00:00
|
|
|
SCH_FIELD* schField = symbol->AddField( SCH_FIELD( { 0, 0 }, FIELD_T::USER, symbol,
|
|
|
|
libField->GetName() ) );
|
2020-09-02 14:11:51 +01:00
|
|
|
|
2023-02-02 15:53:57 -05:00
|
|
|
// Careful: the visible bit and position are also set by SetAttributes()
|
2025-01-22 14:26:57 +00:00
|
|
|
schField->SetAttributes( *libField );
|
|
|
|
schField->SetText( libField->GetText() );
|
|
|
|
schField->SetTextPos( symbol->GetPosition() + libField->GetTextPos() );
|
|
|
|
schField->SetPrivate( libField->IsPrivate() );
|
2023-02-02 15:53:57 -05:00
|
|
|
}
|
2020-09-27 14:07:48 +01:00
|
|
|
|
2023-02-02 15:53:57 -05:00
|
|
|
if( resetPositions && frame->eeconfig()->m_AutoplaceFields.enable )
|
2024-12-23 14:19:43 +00:00
|
|
|
{
|
|
|
|
AUTOPLACE_ALGO fieldsAutoplaced = symbol->GetFieldsAutoplaced();
|
|
|
|
|
|
|
|
if( fieldsAutoplaced == AUTOPLACE_AUTO || fieldsAutoplaced == AUTOPLACE_MANUAL )
|
|
|
|
symbol->AutoplaceFields( screen, fieldsAutoplaced );
|
|
|
|
}
|
2020-09-02 14:11:51 +01:00
|
|
|
}
|
2023-02-02 15:53:57 -05:00
|
|
|
|
|
|
|
symbol->SetSchSymbolLibraryName( wxEmptyString );
|
|
|
|
screen->Append( symbol );
|
2023-08-31 23:28:02 +01:00
|
|
|
|
|
|
|
if( resetPositions )
|
2024-12-23 14:19:43 +00:00
|
|
|
{
|
|
|
|
AUTOPLACE_ALGO fieldsAutoplaced = symbol->GetFieldsAutoplaced();
|
|
|
|
|
|
|
|
if( fieldsAutoplaced == AUTOPLACE_AUTO || fieldsAutoplaced == AUTOPLACE_MANUAL )
|
|
|
|
symbol->AutoplaceFields( screen, fieldsAutoplaced );
|
|
|
|
}
|
2023-08-31 23:28:02 +01:00
|
|
|
|
2023-02-02 15:53:57 -05:00
|
|
|
frame->GetCanvas()->GetView()->Update( symbol );
|
|
|
|
|
2024-02-28 11:21:17 +01:00
|
|
|
msg = getSymbolReferences( *symbol, symbol_change_info.m_LibId, &initialLibLinkName );
|
2023-02-02 15:53:57 -05:00
|
|
|
msg += wxS( ": OK" );
|
|
|
|
m_messagePanel->Report( msg, RPT_SEVERITY_ACTION );
|
|
|
|
matchesProcessed +=1;
|
2020-09-02 14:11:51 +01:00
|
|
|
}
|
|
|
|
|
2023-02-02 15:53:57 -05:00
|
|
|
return matchesProcessed;
|
|
|
|
}
|
2022-09-11 10:11:13 -04:00
|
|
|
|
2020-08-13 13:51:26 -04:00
|
|
|
|
2024-02-28 11:21:17 +01:00
|
|
|
wxString DIALOG_CHANGE_SYMBOLS::getSymbolReferences( SCH_SYMBOL& aSymbol,
|
|
|
|
const LIB_ID& aNewId,
|
|
|
|
const wxString* aOldLibLinkName )
|
2023-02-02 15:53:57 -05:00
|
|
|
{
|
|
|
|
wxString msg;
|
|
|
|
wxString references;
|
|
|
|
LIB_ID oldId = aSymbol.GetLibId();
|
2020-08-13 13:51:26 -04:00
|
|
|
|
2024-02-28 11:21:17 +01:00
|
|
|
wxString oldLibLinkName; // For report
|
|
|
|
|
|
|
|
if( aOldLibLinkName )
|
|
|
|
oldLibLinkName = *aOldLibLinkName;
|
|
|
|
else
|
|
|
|
oldLibLinkName = UnescapeString( oldId.Format() );
|
|
|
|
|
2023-08-25 08:51:59 -04:00
|
|
|
SCH_EDIT_FRAME* parent = dynamic_cast< SCH_EDIT_FRAME* >( GetParent() );
|
|
|
|
|
|
|
|
wxCHECK( parent, msg );
|
|
|
|
|
2024-10-08 13:51:09 -04:00
|
|
|
SCH_SHEET_LIST sheets = parent->Schematic().Hierarchy();
|
2023-08-25 08:51:59 -04:00
|
|
|
|
2023-12-28 18:25:47 -05:00
|
|
|
for( const SCH_SYMBOL_INSTANCE& instance : aSymbol.GetInstances() )
|
2023-02-02 15:53:57 -05:00
|
|
|
{
|
2023-08-25 08:51:59 -04:00
|
|
|
// Only include the symbol instances for the current project.
|
|
|
|
if( !sheets.HasPath( instance.m_Path ) )
|
|
|
|
continue;
|
|
|
|
|
2023-02-02 15:53:57 -05:00
|
|
|
if( references.IsEmpty() )
|
|
|
|
references = instance.m_Reference;
|
|
|
|
else
|
|
|
|
references += wxT( " " ) + instance.m_Reference;
|
|
|
|
}
|
|
|
|
|
|
|
|
if( m_mode == MODE::UPDATE )
|
|
|
|
{
|
2023-12-28 18:25:47 -05:00
|
|
|
if( aSymbol.GetInstances().size() == 1 )
|
2023-02-02 15:53:57 -05:00
|
|
|
{
|
|
|
|
msg.Printf( _( "Update symbol %s from '%s' to '%s'" ),
|
|
|
|
references,
|
2024-02-28 11:21:17 +01:00
|
|
|
oldLibLinkName,
|
2023-02-02 15:53:57 -05:00
|
|
|
UnescapeString( aNewId.Format() ) );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
msg.Printf( _( "Update symbols %s from '%s' to '%s'" ),
|
|
|
|
references,
|
2024-02-28 11:21:17 +01:00
|
|
|
oldLibLinkName,
|
2023-02-02 15:53:57 -05:00
|
|
|
UnescapeString( aNewId.Format() ) );
|
|
|
|
}
|
|
|
|
}
|
2024-02-28 11:21:17 +01:00
|
|
|
else // mode is MODE::CHANGE
|
2023-02-02 15:53:57 -05:00
|
|
|
{
|
2023-12-28 18:25:47 -05:00
|
|
|
if( aSymbol.GetInstances().size() == 1 )
|
2023-02-02 15:53:57 -05:00
|
|
|
{
|
|
|
|
msg.Printf( _( "Change symbol %s from '%s' to '%s'" ),
|
|
|
|
references,
|
2024-02-28 11:21:17 +01:00
|
|
|
oldLibLinkName,
|
2023-02-02 15:53:57 -05:00
|
|
|
UnescapeString( aNewId.Format() ) );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
msg.Printf( _( "Change symbols %s from '%s' to '%s'" ),
|
|
|
|
references,
|
2024-02-28 11:21:17 +01:00
|
|
|
oldLibLinkName,
|
2023-02-02 15:53:57 -05:00
|
|
|
UnescapeString( aNewId.Format() ) );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return msg;
|
|
|
|
}
|