Fix schematic update library symbols issues.
Rather than update library symbols one at a time, queue them up by schematic symbol to prevent multiple updates to the same symbol in complex hierarchies. This also removes all of the library symbols first which will clear out all of the library symbol variants that were created by modifying library symbols in place and/or changes to the symbol in the library. Don't add new variant library symbol if an equivalent variant already exists in the schematic local cache. This prevents duplicate library symbols from being added to the local cache when the first variant in the cache does not match that of the symbol being added.
This commit is contained in:
parent
e60152e351
commit
c88c4e1200
|
@ -445,15 +445,18 @@ bool DIALOG_CHANGE_SYMBOLS::isMatch( SCH_SYMBOL* aSymbol, SCH_SHEET_PATH* aInsta
|
|||
}
|
||||
|
||||
|
||||
bool DIALOG_CHANGE_SYMBOLS::processMatchingSymbols()
|
||||
|
||||
|
||||
int DIALOG_CHANGE_SYMBOLS::processMatchingSymbols()
|
||||
{
|
||||
SCH_EDIT_FRAME* frame = dynamic_cast<SCH_EDIT_FRAME*>( GetParent() );
|
||||
|
||||
wxCHECK( frame, false );
|
||||
|
||||
LIB_ID newId;
|
||||
bool appendToUndo = false;
|
||||
bool changed = false;
|
||||
wxString msg;
|
||||
int matchesProcessed = 0;
|
||||
SCH_SYMBOL* symbol = nullptr;
|
||||
SCH_SHEET_LIST hierarchy = frame->Schematic().GetSheets();
|
||||
|
||||
if( m_mode == MODE::CHANGE )
|
||||
|
@ -464,70 +467,271 @@ bool DIALOG_CHANGE_SYMBOLS::processMatchingSymbols()
|
|||
return false;
|
||||
}
|
||||
|
||||
std::map<SCH_SYMBOL*, std::vector<SCH_SHEET_PATH>> symbols;
|
||||
|
||||
for( SCH_SHEET_PATH& instance : hierarchy )
|
||||
{
|
||||
SCH_SCREEN* screen = instance.LastScreen();
|
||||
|
||||
wxCHECK2( screen, continue );
|
||||
|
||||
std::vector<SCH_SYMBOL*> symbols;
|
||||
|
||||
// Fetch all the symbols that meet the change criteria.
|
||||
for( SCH_ITEM* item : screen->Items().OfType( SCH_SYMBOL_T ) )
|
||||
symbols.push_back( static_cast<SCH_SYMBOL*>( item ) );
|
||||
|
||||
for( SCH_SYMBOL* symbol : symbols )
|
||||
{
|
||||
symbol = static_cast<SCH_SYMBOL*>( item );
|
||||
|
||||
wxCHECK2( symbol, continue );
|
||||
|
||||
if( !isMatch( symbol, &instance ) )
|
||||
continue;
|
||||
|
||||
if( m_mode == MODE::UPDATE )
|
||||
{
|
||||
if( processSymbol( symbol, &instance, symbol->GetLibId(), appendToUndo ) )
|
||||
changed = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( processSymbol( symbol, &instance, newId, appendToUndo ) )
|
||||
changed = true;
|
||||
}
|
||||
if( ( m_mode == MODE::UPDATE ) && !newId.IsValid() )
|
||||
newId = symbol->GetLibId();
|
||||
|
||||
if( changed )
|
||||
appendToUndo = true;
|
||||
auto it = symbols.find( symbol );
|
||||
|
||||
if( it == symbols.end() )
|
||||
symbols.insert( { symbol, { instance } } );
|
||||
else
|
||||
it->second.emplace_back( instance );
|
||||
}
|
||||
}
|
||||
|
||||
matchesProcessed += processSymbols( symbols, newId );
|
||||
|
||||
frame->GetCurrentSheet().UpdateAllScreenReferences();
|
||||
|
||||
return changed;
|
||||
return matchesProcessed;
|
||||
}
|
||||
|
||||
|
||||
bool DIALOG_CHANGE_SYMBOLS::processSymbol( SCH_SYMBOL* aSymbol, const SCH_SHEET_PATH* aInstance,
|
||||
const LIB_ID& aNewId, bool aAppendToUndo )
|
||||
int DIALOG_CHANGE_SYMBOLS::processSymbols( const std::map<SCH_SYMBOL*,
|
||||
std::vector<SCH_SHEET_PATH>>& aSymbols,
|
||||
const LIB_ID& aNewId )
|
||||
{
|
||||
wxCHECK( aSymbol, false );
|
||||
wxCHECK( aNewId.IsValid(), false );
|
||||
wxCHECK( !aSymbols.empty() && aNewId.IsValid(), 0 );
|
||||
|
||||
std::vector<SCH_SHEET_PATH> instances;
|
||||
int matchesProcessed = 0;
|
||||
SCH_EDIT_FRAME* frame = dynamic_cast<SCH_EDIT_FRAME*>( GetParent() );
|
||||
SCH_SCREEN* screen = aInstance->LastScreen();
|
||||
SCH_SCREEN* screen = nullptr;
|
||||
SCH_SYMBOL* symbol = nullptr;
|
||||
LIB_SYMBOL* libSymbol = nullptr;
|
||||
std::map<SCH_SYMBOL*, std::vector<SCH_SHEET_PATH>> symbols = aSymbols;
|
||||
|
||||
wxCHECK( frame, false );
|
||||
wxCHECK( frame, 0 );
|
||||
|
||||
LIB_ID oldId = aSymbol->GetLibId();
|
||||
wxString msg;
|
||||
wxString references;
|
||||
|
||||
for( SCH_SYMBOL_INSTANCE instance : aSymbol->GetInstanceReferences() )
|
||||
auto it = symbols.begin();
|
||||
|
||||
// Remove all symbols that don't have a valid library symbol link or enough units to
|
||||
// satify the library symbol update.
|
||||
while( it != symbols.end() )
|
||||
{
|
||||
symbol = it->first;
|
||||
|
||||
wxCHECK2( symbol, continue );
|
||||
|
||||
libSymbol = frame->GetLibSymbol( aNewId );
|
||||
|
||||
if( !libSymbol )
|
||||
{
|
||||
msg = getSymbolReferences( *symbol, aNewId );
|
||||
msg << wxT( ": " ) << _( "*** symbol not found ***" );
|
||||
m_messagePanel->Report( msg, RPT_SEVERITY_ERROR );
|
||||
it = symbols.erase( it );
|
||||
continue;
|
||||
}
|
||||
|
||||
std::unique_ptr<LIB_SYMBOL> flattenedSymbol = libSymbol->Flatten();
|
||||
|
||||
if( flattenedSymbol->GetUnitCount() < symbol->GetUnit() )
|
||||
{
|
||||
msg = getSymbolReferences( *symbol, aNewId );
|
||||
msg << wxT( ": " ) << _( "*** new symbol has too few units ***" );
|
||||
m_messagePanel->Report( msg, RPT_SEVERITY_ERROR );
|
||||
it = symbols.erase( it );
|
||||
}
|
||||
else
|
||||
{
|
||||
++it;
|
||||
}
|
||||
}
|
||||
|
||||
// Removing the symbol needs to be done before the LIB_SYMBOL is changed to prevent stale
|
||||
// library symbols in the schematic file.
|
||||
for( auto pair : symbols )
|
||||
{
|
||||
symbol = pair.first;
|
||||
instances = pair.second;
|
||||
|
||||
wxCHECK( symbol && !instances.empty(), 0 );
|
||||
|
||||
screen = instances[0].LastScreen();
|
||||
|
||||
wxCHECK( screen, 0 );
|
||||
|
||||
screen->Remove( symbol );
|
||||
frame->SaveCopyInUndoList( screen, symbol, UNDO_REDO::CHANGED, true );
|
||||
}
|
||||
|
||||
for( auto pair : symbols )
|
||||
{
|
||||
symbol = pair.first;
|
||||
|
||||
if( aNewId != symbol->GetLibId() )
|
||||
symbol->SetLibId( aNewId );
|
||||
|
||||
libSymbol = frame->GetLibSymbol( aNewId );
|
||||
std::unique_ptr<LIB_SYMBOL> flattenedSymbol = libSymbol->Flatten();
|
||||
|
||||
symbol->SetLibSymbol( flattenedSymbol.release() );
|
||||
|
||||
if( m_resetAttributes->GetValue() )
|
||||
{
|
||||
symbol->SetIncludeInBom( libSymbol->GetIncludeInBom() );
|
||||
symbol->SetIncludeOnBoard( libSymbol->GetIncludeOnBoard() );
|
||||
}
|
||||
|
||||
bool removeExtras = m_removeExtraBox->GetValue();
|
||||
bool resetVis = m_resetFieldVisibilities->GetValue();
|
||||
bool resetEffects = m_resetFieldEffects->GetValue();
|
||||
bool resetPositions = m_resetFieldPositions->GetValue();
|
||||
|
||||
for( unsigned i = 0; i < symbol->GetFields().size(); ++i )
|
||||
{
|
||||
SCH_FIELD& field = symbol->GetFields()[i];
|
||||
LIB_FIELD* libField = nullptr;
|
||||
|
||||
// Mandatory fields always exist in m_updateFields, but these names can be translated.
|
||||
// so use GetCanonicalName().
|
||||
if( !alg::contains( m_updateFields, field.GetCanonicalName() ) )
|
||||
continue;
|
||||
|
||||
if( i < MANDATORY_FIELDS )
|
||||
libField = libSymbol->GetFieldById( (int) i );
|
||||
else
|
||||
libField = libSymbol->FindField( field.GetName() );
|
||||
|
||||
if( libField )
|
||||
{
|
||||
bool resetText = libField->GetText().IsEmpty() ? m_resetEmptyFields->GetValue()
|
||||
: m_resetFieldText->GetValue();
|
||||
|
||||
if( resetText )
|
||||
{
|
||||
if( i == REFERENCE_FIELD )
|
||||
{
|
||||
for( const SCH_SHEET_PATH& instance : pair.second )
|
||||
{
|
||||
symbol->SetRef( &instance,
|
||||
UTIL::GetRefDesUnannotated( libField->GetText() ) );
|
||||
}
|
||||
}
|
||||
else if( i == VALUE_FIELD )
|
||||
{
|
||||
symbol->SetValueFieldText( UnescapeString( libField->GetText() ) );
|
||||
}
|
||||
else if( i == FOOTPRINT_FIELD )
|
||||
{
|
||||
symbol->SetFootprintFieldText( libField->GetText() );
|
||||
}
|
||||
else
|
||||
{
|
||||
field.SetText( libField->GetText() );
|
||||
}
|
||||
}
|
||||
|
||||
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 );
|
||||
|
||||
field.SetVisible( visible );
|
||||
field.SetPosition( pos );
|
||||
field.SetNameShown( libField->IsNameShown() );
|
||||
field.SetCanAutoplace( libField->CanAutoplace() );
|
||||
}
|
||||
|
||||
if( resetPositions )
|
||||
field.SetTextPos( symbol->GetPosition() + libField->GetTextPos() );
|
||||
}
|
||||
else if( i >= MANDATORY_FIELDS && removeExtras )
|
||||
{
|
||||
symbol->RemoveField( field.GetName() );
|
||||
i--;
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<LIB_FIELD*> libFields;
|
||||
libSymbol->GetFields( libFields );
|
||||
|
||||
for( unsigned i = MANDATORY_FIELDS; i < libFields.size(); ++i )
|
||||
{
|
||||
const LIB_FIELD& libField = *libFields[i];
|
||||
|
||||
if( !alg::contains( m_updateFields, libField.GetCanonicalName() ) )
|
||||
continue;
|
||||
|
||||
if( !symbol->FindField( libField.GetName(), false ) )
|
||||
{
|
||||
wxString fieldName = libField.GetCanonicalName();
|
||||
SCH_FIELD newField( VECTOR2I( 0, 0 ), symbol->GetFieldCount(), symbol,
|
||||
fieldName );
|
||||
SCH_FIELD* schField = symbol->AddField( newField );
|
||||
|
||||
// Careful: the visible bit and position are also set by SetAttributes()
|
||||
schField->SetAttributes( libField );
|
||||
schField->SetText( libField.GetText() );
|
||||
schField->SetTextPos( symbol->GetPosition() + libField.GetTextPos() );
|
||||
}
|
||||
|
||||
if( resetPositions && frame->eeconfig()->m_AutoplaceFields.enable )
|
||||
symbol->AutoAutoplaceFields( screen );
|
||||
}
|
||||
|
||||
symbol->SetSchSymbolLibraryName( wxEmptyString );
|
||||
instances = pair.second;
|
||||
screen = instances[0].LastScreen();
|
||||
screen->Append( symbol );
|
||||
frame->GetCanvas()->GetView()->Update( symbol );
|
||||
|
||||
msg = getSymbolReferences( *symbol, aNewId );
|
||||
msg += wxS( ": OK" );
|
||||
m_messagePanel->Report( msg, RPT_SEVERITY_ACTION );
|
||||
matchesProcessed +=1;
|
||||
}
|
||||
|
||||
return matchesProcessed;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
wxString DIALOG_CHANGE_SYMBOLS::getSymbolReferences( SCH_SYMBOL& aSymbol, const LIB_ID& aNewId )
|
||||
{
|
||||
wxString msg;
|
||||
wxString references;
|
||||
LIB_ID oldId = aSymbol.GetLibId();
|
||||
|
||||
for( const SCH_SYMBOL_INSTANCE& instance : aSymbol.GetInstanceReferences() )
|
||||
{
|
||||
if( references.IsEmpty() )
|
||||
references = instance.m_Reference;
|
||||
else
|
||||
references += " " + instance.m_Reference;
|
||||
references += wxT( " " ) + instance.m_Reference;
|
||||
}
|
||||
|
||||
if( m_mode == MODE::UPDATE )
|
||||
{
|
||||
if( aSymbol->GetInstanceReferences().size() == 1 )
|
||||
if( aSymbol.GetInstanceReferences().size() == 1 )
|
||||
{
|
||||
msg.Printf( _( "Update symbol %s from '%s' to '%s'" ),
|
||||
references,
|
||||
|
@ -544,7 +748,7 @@ bool DIALOG_CHANGE_SYMBOLS::processSymbol( SCH_SYMBOL* aSymbol, const SCH_SHEET_
|
|||
}
|
||||
else
|
||||
{
|
||||
if( aSymbol->GetInstanceReferences().size() == 1 )
|
||||
if( aSymbol.GetInstanceReferences().size() == 1 )
|
||||
{
|
||||
msg.Printf( _( "Change symbol %s from '%s' to '%s'" ),
|
||||
references,
|
||||
|
@ -560,138 +764,5 @@ bool DIALOG_CHANGE_SYMBOLS::processSymbol( SCH_SYMBOL* aSymbol, const SCH_SHEET_
|
|||
}
|
||||
}
|
||||
|
||||
LIB_SYMBOL* libSymbol = frame->GetLibSymbol( aNewId );
|
||||
|
||||
if( !libSymbol )
|
||||
{
|
||||
msg << wxS( ": " ) << _( "*** symbol not found ***" );
|
||||
m_messagePanel->Report( msg, RPT_SEVERITY_ERROR );
|
||||
return false;
|
||||
}
|
||||
|
||||
std::unique_ptr<LIB_SYMBOL> flattenedSymbol = libSymbol->Flatten();
|
||||
|
||||
if( flattenedSymbol->GetUnitCount() < aSymbol->GetUnit() )
|
||||
{
|
||||
msg << wxS( ": " ) << _( "*** new symbol has too few units ***" );
|
||||
m_messagePanel->Report( msg, RPT_SEVERITY_ERROR );
|
||||
return false;
|
||||
}
|
||||
|
||||
// Removing the symbol needs to be done before the LIB_SYMBOL is changed to prevent stale
|
||||
// library symbols in the schematic file.
|
||||
screen->Remove( aSymbol );
|
||||
frame->SaveCopyInUndoList( screen, aSymbol, UNDO_REDO::CHANGED, aAppendToUndo );
|
||||
|
||||
if( aNewId != aSymbol->GetLibId() )
|
||||
aSymbol->SetLibId( aNewId );
|
||||
|
||||
aSymbol->SetLibSymbol( flattenedSymbol.release() );
|
||||
|
||||
if( m_resetAttributes->GetValue() )
|
||||
{
|
||||
aSymbol->SetIncludeInBom( libSymbol->GetIncludeInBom() );
|
||||
aSymbol->SetIncludeOnBoard( libSymbol->GetIncludeOnBoard() );
|
||||
}
|
||||
|
||||
bool removeExtras = m_removeExtraBox->GetValue();
|
||||
bool resetVis = m_resetFieldVisibilities->GetValue();
|
||||
bool resetEffects = m_resetFieldEffects->GetValue();
|
||||
bool resetPositions = m_resetFieldPositions->GetValue();
|
||||
|
||||
for( unsigned i = 0; i < aSymbol->GetFields().size(); ++i )
|
||||
{
|
||||
SCH_FIELD& field = aSymbol->GetFields()[i];
|
||||
LIB_FIELD* libField = nullptr;
|
||||
|
||||
// Mandatory fields always exist in m_updateFields, but these names can be translated.
|
||||
// so use GetCanonicalName().
|
||||
if( !alg::contains( m_updateFields, field.GetCanonicalName() ) )
|
||||
continue;
|
||||
|
||||
if( i < MANDATORY_FIELDS )
|
||||
libField = libSymbol->GetFieldById( (int) i );
|
||||
else
|
||||
libField = libSymbol->FindField( field.GetName() );
|
||||
|
||||
if( libField )
|
||||
{
|
||||
bool resetText = libField->GetText().IsEmpty() ? m_resetEmptyFields->GetValue()
|
||||
: m_resetFieldText->GetValue();
|
||||
|
||||
if( resetText )
|
||||
{
|
||||
if( i == REFERENCE_FIELD )
|
||||
aSymbol->SetRef( aInstance, UTIL::GetRefDesUnannotated( libField->GetText() ) );
|
||||
else if( i == VALUE_FIELD )
|
||||
aSymbol->SetValueFieldText( UnescapeString( libField->GetText() ) );
|
||||
else if( i == FOOTPRINT_FIELD )
|
||||
aSymbol->SetFootprintFieldText( libField->GetText() );
|
||||
else
|
||||
field.SetText( libField->GetText() );
|
||||
}
|
||||
|
||||
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 );
|
||||
|
||||
field.SetVisible( visible );
|
||||
field.SetPosition( pos );
|
||||
field.SetNameShown( libField->IsNameShown() );
|
||||
field.SetCanAutoplace( libField->CanAutoplace() );
|
||||
}
|
||||
|
||||
if( resetPositions )
|
||||
field.SetTextPos( aSymbol->GetPosition() + libField->GetTextPos() );
|
||||
}
|
||||
else if( i >= MANDATORY_FIELDS && removeExtras )
|
||||
{
|
||||
aSymbol->RemoveField( field.GetName() );
|
||||
i--;
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<LIB_FIELD*> libFields;
|
||||
libSymbol->GetFields( libFields );
|
||||
|
||||
for( unsigned i = MANDATORY_FIELDS; i < libFields.size(); ++i )
|
||||
{
|
||||
const LIB_FIELD& libField = *libFields[i];
|
||||
|
||||
if( !alg::contains( m_updateFields, libField.GetCanonicalName() ) )
|
||||
continue;
|
||||
|
||||
if( !aSymbol->FindField( libField.GetName(), false ) )
|
||||
{
|
||||
wxString fieldName = libField.GetCanonicalName();
|
||||
SCH_FIELD newField( VECTOR2I( 0, 0 ), aSymbol->GetFieldCount(), aSymbol, fieldName );
|
||||
SCH_FIELD* schField = aSymbol->AddField( newField );
|
||||
|
||||
// Careful: the visible bit and position are also set by SetAttributes()
|
||||
schField->SetAttributes( libField );
|
||||
schField->SetText( libField.GetText() );
|
||||
schField->SetTextPos( aSymbol->GetPosition() + libField.GetTextPos() );
|
||||
}
|
||||
}
|
||||
|
||||
if( resetPositions && frame->eeconfig()->m_AutoplaceFields.enable )
|
||||
aSymbol->AutoAutoplaceFields( screen );
|
||||
|
||||
aSymbol->SetSchSymbolLibraryName( wxEmptyString );
|
||||
screen->Append( aSymbol );
|
||||
frame->GetCanvas()->GetView()->Update( aSymbol );
|
||||
|
||||
msg += ": OK";
|
||||
m_messagePanel->Report( msg, RPT_SEVERITY_ACTION );
|
||||
|
||||
return true;
|
||||
return msg;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2020 CERN
|
||||
* Copyright (C) 2021 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 2021-2023 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* @author Wayne Stambaugh <stambaughw@gmail.com>
|
||||
*
|
||||
|
@ -73,9 +73,10 @@ private:
|
|||
void updateFieldsList();
|
||||
|
||||
bool isMatch( SCH_SYMBOL* aSymbol, SCH_SHEET_PATH* aInstance );
|
||||
bool processMatchingSymbols();
|
||||
bool processSymbol( SCH_SYMBOL* aSymbol, const SCH_SHEET_PATH* aInstance,
|
||||
const LIB_ID& aNewId, bool aAppendToUndo );
|
||||
int processMatchingSymbols();
|
||||
int processSymbols( const std::map<SCH_SYMBOL*, std::vector<SCH_SHEET_PATH>>& aSymbols,
|
||||
const LIB_ID& aNewId );
|
||||
wxString getSymbolReferences( SCH_SYMBOL& aSymbol, const LIB_ID& aNewId );
|
||||
|
||||
SCH_SYMBOL* m_symbol;
|
||||
MODE m_mode;
|
||||
|
|
|
@ -142,14 +142,14 @@ bool SCH_SCREEN::ClassOf( const EDA_ITEM* aItem )
|
|||
}
|
||||
|
||||
|
||||
void SCH_SCREEN::Append( SCH_ITEM* aItem )
|
||||
void SCH_SCREEN::Append( SCH_ITEM* aItem, bool aUpdateLibSymbol )
|
||||
{
|
||||
if( aItem->Type() != SCH_SHEET_PIN_T && aItem->Type() != SCH_FIELD_T )
|
||||
{
|
||||
// Ensure the item can reach the SCHEMATIC through this screen
|
||||
aItem->SetParent( this );
|
||||
|
||||
if( aItem->Type() == SCH_SYMBOL_T )
|
||||
if( aItem->Type() == SCH_SYMBOL_T && aUpdateLibSymbol )
|
||||
{
|
||||
SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( aItem );
|
||||
|
||||
|
@ -176,30 +176,65 @@ void SCH_SCREEN::Append( SCH_ITEM* aItem )
|
|||
|
||||
if( *foundSymbol != *symbol->GetLibSymbolRef() )
|
||||
{
|
||||
int cnt = 1;
|
||||
wxString newName;
|
||||
std::vector<wxString> matches;
|
||||
|
||||
newName.Printf( "%s_%d", symbol->GetLibId().GetUniStringLibItemName(),
|
||||
cnt );
|
||||
getLibSymbolNameMatches( *symbol, matches );
|
||||
foundSymbol = nullptr;
|
||||
|
||||
while( m_libSymbols.find( newName ) != m_libSymbols.end() )
|
||||
for( const wxString& libSymbolName : matches )
|
||||
{
|
||||
cnt += 1;
|
||||
newName.Printf( "%s_%d", symbol->GetLibId().GetUniStringLibItemName(),
|
||||
it = m_libSymbols.find( libSymbolName );
|
||||
|
||||
if( it == m_libSymbols.end() )
|
||||
continue;
|
||||
|
||||
foundSymbol = it->second;
|
||||
|
||||
wxCHECK2( foundSymbol, continue );
|
||||
|
||||
if( *foundSymbol == *symbol->GetLibSymbolRef() )
|
||||
{
|
||||
newName = libSymbolName;
|
||||
break;
|
||||
}
|
||||
|
||||
foundSymbol = nullptr;
|
||||
}
|
||||
|
||||
if( !foundSymbol )
|
||||
{
|
||||
int cnt = 1;
|
||||
|
||||
newName.Printf( wxT( "%s_%d" ),
|
||||
symbol->GetLibId().GetUniStringLibItemName(),
|
||||
cnt );
|
||||
|
||||
while( m_libSymbols.find( newName ) != m_libSymbols.end() )
|
||||
{
|
||||
cnt += 1;
|
||||
newName.Printf( wxT( "%s_%d" ),
|
||||
symbol->GetLibId().GetUniStringLibItemName(),
|
||||
cnt );
|
||||
}
|
||||
}
|
||||
|
||||
// Update the schematic symbol library link as this symbol only exists
|
||||
// in the schematic.
|
||||
symbol->SetSchSymbolLibraryName( newName );
|
||||
|
||||
LIB_SYMBOL* newLibSymbol = new LIB_SYMBOL( *symbol->GetLibSymbolRef() );
|
||||
LIB_ID newLibId( wxEmptyString, newName );
|
||||
if( !foundSymbol )
|
||||
{
|
||||
// Update the schematic symbol library link as this symbol does not
|
||||
// exist in any symbol library.
|
||||
LIB_ID newLibId( wxEmptyString, newName );
|
||||
LIB_SYMBOL* newLibSymbol = new LIB_SYMBOL( *symbol->GetLibSymbolRef() );
|
||||
|
||||
newLibSymbol->SetLibId( newLibId );
|
||||
newLibSymbol->SetName( newName );
|
||||
symbol->SetLibSymbol( newLibSymbol->Flatten().release() );
|
||||
m_libSymbols[newName] = newLibSymbol;
|
||||
newLibSymbol->SetLibId( newLibId );
|
||||
newLibSymbol->SetName( newName );
|
||||
symbol->SetLibSymbol( newLibSymbol->Flatten().release() );
|
||||
m_libSymbols[newName] = newLibSymbol;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -262,19 +297,19 @@ void SCH_SCREEN::FreeDrawList()
|
|||
}
|
||||
|
||||
|
||||
void SCH_SCREEN::Update( SCH_ITEM* aItem )
|
||||
void SCH_SCREEN::Update( SCH_ITEM* aItem, bool aUpdateLibSymbol )
|
||||
{
|
||||
if( Remove( aItem ) )
|
||||
Append( aItem );
|
||||
if( Remove( aItem, aUpdateLibSymbol ) )
|
||||
Append( aItem, aUpdateLibSymbol );
|
||||
}
|
||||
|
||||
|
||||
bool SCH_SCREEN::Remove( SCH_ITEM* aItem )
|
||||
bool SCH_SCREEN::Remove( SCH_ITEM* aItem, bool aUpdateLibSymbol )
|
||||
{
|
||||
bool retv = m_rtree.remove( aItem );
|
||||
|
||||
// Check if the library symbol for the removed schematic symbol is still required.
|
||||
if( retv && aItem->Type() == SCH_SYMBOL_T )
|
||||
if( retv && aItem->Type() == SCH_SYMBOL_T && aUpdateLibSymbol )
|
||||
{
|
||||
SCH_SYMBOL* removedSymbol = static_cast<SCH_SYMBOL*>( aItem );
|
||||
|
||||
|
@ -1541,6 +1576,29 @@ void SCH_SCREEN::SetLegacySymbolInstanceData()
|
|||
}
|
||||
|
||||
|
||||
size_t SCH_SCREEN::getLibSymbolNameMatches( const SCH_SYMBOL& aSymbol,
|
||||
std::vector<wxString>& aMatches )
|
||||
{
|
||||
wxString searchName = aSymbol.GetLibId().GetUniStringLibId();
|
||||
|
||||
if( m_libSymbols.find( searchName ) != m_libSymbols.end() )
|
||||
aMatches.emplace_back( searchName );
|
||||
|
||||
searchName = aSymbol.GetLibId().GetUniStringLibItemName() + wxS( "_" );
|
||||
|
||||
int tmp;
|
||||
wxString suffix;
|
||||
|
||||
for( auto pair : m_libSymbols )
|
||||
{
|
||||
if( pair.first.StartsWith( searchName, &suffix ) && suffix.ToInt( &tmp ) )
|
||||
aMatches.emplace_back( pair.first );
|
||||
}
|
||||
|
||||
return aMatches.size();
|
||||
}
|
||||
|
||||
|
||||
#if defined(DEBUG)
|
||||
void SCH_SCREEN::Show( int nestLevel, std::ostream& os ) const
|
||||
{
|
||||
|
|
|
@ -180,7 +180,7 @@ public:
|
|||
return m_clientSheetPathList;
|
||||
}
|
||||
|
||||
void Append( SCH_ITEM* aItem );
|
||||
void Append( SCH_ITEM* aItem, bool aUpdateLibSymbol = true );
|
||||
|
||||
/**
|
||||
* Copy the contents of \a aScreen into this #SCH_SCREEN object.
|
||||
|
@ -263,16 +263,18 @@ public:
|
|||
*
|
||||
* @note The removed item is not deleted. It is only unlinked from the item list.
|
||||
* @param[in] aItem Item to be removed from schematic.
|
||||
* @param aUpdateLibSymbol removes the library symbol as required when true.
|
||||
* @return True if we successfully removed the item
|
||||
*/
|
||||
bool Remove( SCH_ITEM* aItem );
|
||||
bool Remove( SCH_ITEM* aItem, bool aUpdateLibSymbol = true );
|
||||
|
||||
/**
|
||||
* Update \a aItem's bounding box in the tree
|
||||
*
|
||||
* @param[in] aItem Item that needs to be updated.
|
||||
* @param aUpdateLibSymbol removes the library symbol as required when true.
|
||||
*/
|
||||
void Update( SCH_ITEM* aItem );
|
||||
void Update( SCH_ITEM* aItem, bool aUpdateLibSymbol = true );
|
||||
|
||||
/**
|
||||
* Removes \a aItem from the linked list and deletes the object.
|
||||
|
@ -443,7 +445,8 @@ public:
|
|||
* @param aIgnoreEndpoints If true, ignore wires/buses with end points matching aPosition
|
||||
* @return Buses and wires
|
||||
*/
|
||||
std::vector<SCH_LINE*> GetBusesAndWires( const VECTOR2I& aPosition, bool aIgnoreEndpoints = false ) const;
|
||||
std::vector<SCH_LINE*> GetBusesAndWires( const VECTOR2I& aPosition,
|
||||
bool aIgnoreEndpoints = false ) const;
|
||||
|
||||
/**
|
||||
* Collect a unique list of all possible connection points in the schematic.
|
||||
|
@ -554,6 +557,21 @@ private:
|
|||
|
||||
void clearLibSymbols();
|
||||
|
||||
/**
|
||||
* Return a list of potential library symbol matches for \a aSymbol.
|
||||
*
|
||||
* When and existing library symbol named with the full #LIB_ID object is found, there may
|
||||
* be more potential matches if the #SCH_SCREEN::Append() method need to create an alternate
|
||||
* symbol due to differences from the original symbol. This process creates a new library
|
||||
* symbol name by adding a "_#" suffix to the existing #LIB_ID item name.
|
||||
*
|
||||
* @param[in] aSymbol is the schematic symbol to search for potential library symbol matches.
|
||||
* @param[out] aMatches contains library cache names of all of the potential matches.
|
||||
*
|
||||
* @return the number of potential matches found for \a aSymbol.
|
||||
*/
|
||||
size_t getLibSymbolNameMatches( const SCH_SYMBOL& aSymbol, std::vector<wxString>& aMatches );
|
||||
|
||||
public:
|
||||
/**
|
||||
* last value for the zoom level, useful in Eeschema when changing the current displayed
|
||||
|
|
|
@ -339,7 +339,7 @@ void SCH_SHEET_PATH::UpdateAllScreenReferences() const
|
|||
|
||||
symbol->GetField( REFERENCE_FIELD )->SetText( symbol->GetRef( this ) );
|
||||
symbol->UpdateUnit( symbol->GetUnitSelection( this ) );
|
||||
LastScreen()->Update( item );
|
||||
LastScreen()->Update( item, false );
|
||||
}
|
||||
else if( item->Type() == SCH_GLOBAL_LABEL_T )
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue