Templatize MigrateSimModel() so it can be used on LIB_SYMBOLs as well.

Fixes https://gitlab.com/kicad/code/kicad/issues/13080
This commit is contained in:
Jeff Young 2022-12-08 23:56:55 +00:00
parent cfbf14ebfd
commit 8931e55dd2
14 changed files with 285 additions and 219 deletions

View File

@ -2,6 +2,7 @@
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2018 Jean-Pierre Charras, jp.charras at wanadoo.fr
* Copyright (C) 2022 CERN
* Copyright (C) 2004-2022 KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software; you can redistribute it and/or
@ -39,11 +40,12 @@
#include <settings/color_settings.h>
LIB_FIELD::LIB_FIELD( LIB_SYMBOL* aParent, int aId ) :
LIB_FIELD::LIB_FIELD( LIB_SYMBOL* aParent, int aId, const wxString& aName ) :
LIB_ITEM( LIB_FIELD_T, aParent ),
EDA_TEXT( schIUScale )
{
Init( aId );
m_name = aName;
}

View File

@ -2,7 +2,8 @@
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2019 Jean-Pierre Charras, jp.charras at wanadoo.fr
* Copyright (C) 2004-2021 KiCad Developers, see AUTHORS.txt for contributors.
* Copyright (C) 2022 CERN
* Copyright (C) 2004-2022 KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -63,7 +64,7 @@ public:
LIB_FIELD( int aId, const wxString& aName );
LIB_FIELD( LIB_SYMBOL* aParent, int aId = 2 );
LIB_FIELD( LIB_SYMBOL* aParent, int aId = 2, const wxString& aName = wxEmptyString );
// Do not create a copy constructor. The one generated by the compiler is adequate.

View File

@ -3,6 +3,7 @@
*
* Copyright (C) 2004-2015 Jean-Pierre Charras, jp.charras at wanadoo.fr
* Copyright (C) 2008 Wayne Stambaugh <stambaughw@gmail.com>
* Copyright (C) 2022 CERN
* Copyright (C) 2004-2022 KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software; you can redistribute it and/or
@ -1181,6 +1182,32 @@ LIB_FIELD& LIB_SYMBOL::GetDatasheetField()
}
wxString LIB_SYMBOL::GetPrefix()
{
wxString refDesignator = GetFieldById( REFERENCE_FIELD )->GetText();
refDesignator.Replace( "~", " " );
wxString prefix = refDesignator;
while( prefix.Length() )
{
wxUniCharRef last = prefix.Last();
if( ( last >= '0' && last <= '9' ) || last == '?' || last == '*' )
prefix.RemoveLast();
else
break;
}
// Avoid a prefix containing trailing/leading spaces
prefix.Trim( true );
prefix.Trim( false );
return prefix;
}
int LIB_SYMBOL::UpdateFieldOrdinals()
{
int retv = 0;

View File

@ -3,6 +3,7 @@
*
* Copyright (C) 2004-2015 Jean-Pierre Charras, jp.charras at wanadoo.fr
* Copyright (C) 2008 Wayne Stambaugh <stambaughw@gmail.com>
* Copyright (C) 2022 CERN
* Copyright (C) 2004-2022 KiCad Developers, see change_log.txt for contributors.
*
* This program is free software; you can redistribute it and/or
@ -276,6 +277,8 @@ public:
*/
void AddField( LIB_FIELD* aField );
void AddField( LIB_FIELD& aField ) { AddField( new LIB_FIELD( aField ) ); }
/**
* Find a field within this symbol matching \a aFieldName and returns it
* or NULL if not found.
@ -304,6 +307,8 @@ public:
/** Return reference to the datasheet field. */
LIB_FIELD& GetDatasheetField();
wxString GetPrefix();
/**
* Order optional field indices.
*
@ -385,6 +390,8 @@ public:
*/
void RemoveDrawItem( LIB_ITEM* aItem );
void RemoveField( LIB_FIELD* aField ) { RemoveDrawItem( aField ); }
/**
* Return the next draw object pointer.
*

View File

@ -73,6 +73,12 @@ SCH_FIELD::SCH_FIELD( const VECTOR2I& aPos, int aFieldId, SCH_ITEM* aParent,
}
SCH_FIELD::SCH_FIELD( SCH_ITEM* aParent, int aFieldId, const wxString& aName ) :
SCH_FIELD( VECTOR2I(), aFieldId, aParent, aName )
{
}
SCH_FIELD::SCH_FIELD( const SCH_FIELD& aField ) :
SCH_ITEM( aField ),
EDA_TEXT( aField )

View File

@ -2,7 +2,8 @@
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2015 Jean-Pierre Charras, jp.charras at wanadoo.fr
* Copyright (C) 2004-2021 KiCad Developers, see AUTHORS.txt for contributors.
* Copyright (C) 2022 CERN
* Copyright (C) 2004-2022 KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -52,6 +53,8 @@ public:
SCH_FIELD( const VECTOR2I& aPos, int aFieldId, SCH_ITEM* aParent,
const wxString& aName = wxEmptyString );
SCH_FIELD( SCH_ITEM* aParent, int aFieldId, const wxString& aName = wxEmptyString );
SCH_FIELD( const SCH_FIELD& aText );
~SCH_FIELD()

View File

@ -83,7 +83,7 @@ void SCH_PLUGIN::EnumerateSymbolLib( std::vector<LIB_SYMBOL*>& aSymbolList,
LIB_SYMBOL* SCH_PLUGIN::LoadSymbol( const wxString& aLibraryPath, const wxString& aSymbolName,
const STRING_UTF8_MAP* aProperties )
const STRING_UTF8_MAP* aProperties )
{
// not pure virtual so that plugins only have to implement subset of the SCH_PLUGIN interface.
not_implemented( this, __FUNCTION__ );

View File

@ -1856,188 +1856,6 @@ void SCH_SCREEN::MigrateSimModels()
for( SCH_ITEM* item : Items().OfType( SCH_SYMBOL_T ) )
{
SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
migrateSimModel( *symbol );
}
}
void SCH_SCREEN::migrateSimModel( SCH_SYMBOL& aSymbol )
{
if( aSymbol.FindField( SIM_MODEL::DEVICE_TYPE_FIELD )
|| aSymbol.FindField( SIM_MODEL::TYPE_FIELD )
|| aSymbol.FindField( SIM_MODEL::PINS_FIELD )
|| aSymbol.FindField( SIM_MODEL::PARAMS_FIELD ) )
{
// Has a V7 model field -- skip.
return;
}
wxString prefix = aSymbol.GetPrefix();
wxString value = aSymbol.GetValueFieldText( true );
wxString spiceType;
wxString spiceModel;
wxString spiceLib;
wxString pinMap;
if( aSymbol.FindField( wxT( "Spice_Primitive" ) )
|| aSymbol.FindField( wxT( "Spice_Node_Sequence" ) )
|| aSymbol.FindField( wxT( "Spice_Model" ) )
|| aSymbol.FindField( wxT( "Spice_Netlist_Enabled" ) )
|| aSymbol.FindField( wxT( "Spice_Lib_File" ) ) )
{
if( SCH_FIELD* primitiveField = aSymbol.FindField( wxT( "Spice_Primitive" ) ) )
{
spiceType = primitiveField->GetText();
aSymbol.RemoveField( wxT( "Spice_Primitive" ) );
}
if( SCH_FIELD* nodeSequenceField = aSymbol.FindField( wxT( "Spice_Node_Sequence" ) ) )
{
const wxString delimiters( "{:,; }" );
const wxString& nodeSequence = nodeSequenceField->GetText();
if( nodeSequence != "" )
{
wxStringTokenizer tkz( nodeSequence, delimiters );
for( long modelPinNumber = 1; tkz.HasMoreTokens(); ++modelPinNumber )
{
long symbolPinNumber = 1;
tkz.GetNextToken().ToLong( &symbolPinNumber );
if( modelPinNumber != 1 )
pinMap.Append( " " );
pinMap.Append( wxString::Format( "%ld=%ld", symbolPinNumber, modelPinNumber ) );
}
}
aSymbol.RemoveField( wxT( "Spice_Node_Sequence" ) );
}
if( SCH_FIELD* modelField = aSymbol.FindField( wxT( "Spice_Model" ) ) )
{
spiceModel = modelField->GetText();
aSymbol.RemoveField( wxT( "Spice_Model" ) );
}
else
{
spiceModel = aSymbol.GetValueFieldText( true );
}
if( SCH_FIELD* netlistEnabledField = aSymbol.FindField( wxT( "Spice_Netlist_Enabled" ) ) )
{
wxString netlistEnabled = netlistEnabledField->GetText().Lower();
if( netlistEnabled.StartsWith( wxT( "0" ) )
|| netlistEnabled.StartsWith( wxT( "n" ) )
|| netlistEnabled.StartsWith( wxT( "f" ) ) )
{
SCH_FIELD enableField( VECTOR2I( 0, 0 ), aSymbol.GetFieldCount(), &aSymbol,
SIM_MODEL::ENABLE_FIELD );
}
}
if( SCH_FIELD* libFileField = aSymbol.FindField( wxT( "Spice_Lib_File" ) ) )
{
spiceLib = libFileField->GetText();
aSymbol.RemoveField( wxT( "Spice_Lib_File" ) );
}
}
else if( prefix == wxT( "V" ) || prefix == wxT( "I" ) )
{
spiceModel = value;
}
else
{
// Auto convert some legacy fields used in the middle of 7.0 development...
if( SCH_FIELD* legacyDevice = aSymbol.FindField( wxT( "Sim_Type" ) ) )
{
legacyDevice->SetName( SIM_MODEL::TYPE_FIELD );
}
if( SCH_FIELD* legacyDevice = aSymbol.FindField( wxT( "Sim_Device" ) ) )
{
legacyDevice->SetName( SIM_MODEL::DEVICE_TYPE_FIELD );
}
if( SCH_FIELD* legacyPins = aSymbol.FindField( wxT( "Sim_Pins" ) ) )
{
// Migrate pins from array of indexes to name-value-pairs
wxArrayString pinIndexes;
wxString pins;
wxStringSplit( legacyPins->GetText(), pinIndexes, ' ' );
if( SIM_MODEL_IDEAL::InferSimParams( prefix, value ).length() )
{
if( pinIndexes[0] == wxT( "2" ) )
pins = "1=- 2=+";
else
pins = "1=+ 2=-";
}
else
{
for( unsigned ii = 0; ii < pinIndexes.size(); ++ii )
{
if( ii > 0 )
pins.Append( wxS( " " ) );
pins.Append( wxString::Format( wxT( "%u=%s" ), ii + 1, pinIndexes[ ii ] ) );
}
}
legacyPins->SetName( SIM_MODEL::PINS_FIELD );
legacyPins->SetText( pins );
}
if( SCH_FIELD* legacyPins = aSymbol.FindField( wxT( "Sim_Params" ) ) )
{
legacyPins->SetName( SIM_MODEL::PARAMS_FIELD );
}
return;
}
// Insert a plaintext model as a substitute.
SCH_FIELD deviceTypeField( VECTOR2I( 0, 0 ), aSymbol.GetFieldCount(), &aSymbol,
SIM_MODEL::DEVICE_TYPE_FIELD );
deviceTypeField.SetText( SIM_MODEL::DeviceInfo( SIM_MODEL::DEVICE_T::SPICE ).fieldValue );
aSymbol.AddField( deviceTypeField );
SCH_FIELD paramsField( VECTOR2I( 0, 0 ), aSymbol.GetFieldCount(), &aSymbol,
SIM_MODEL::PARAMS_FIELD );
paramsField.SetText( wxString::Format( "type=\"%s\" model=\"%s\" lib=\"%s\"",
spiceType, spiceModel, spiceLib ) );
aSymbol.AddField( paramsField );
// Legacy models by default get linear pin mapping.
if( pinMap != "" )
{
SCH_FIELD pinsField( VECTOR2I( 0, 0 ), aSymbol.GetFieldCount(), &aSymbol,
SIM_MODEL::PINS_FIELD );
pinsField.SetText( pinMap );
aSymbol.AddField( pinsField );
}
else
{
wxString pins;
for( unsigned ii = 0; ii < aSymbol.GetLibPins().size(); ++ii )
{
if( ii > 0 )
pins.Append( wxS( " " ) );
pins.Append( wxString::Format( wxT( "%u=%u" ), ii + 1, ii + 1 ) );
}
SCH_FIELD pinsField( VECTOR2I( 0, 0 ), aSymbol.GetFieldCount(), &aSymbol,
SIM_MODEL::PINS_FIELD );
pinsField.SetText( pins );
aSymbol.AddField( pinsField );
SIM_MODEL::MigrateSimModel<SCH_SYMBOL, SCH_FIELD>( *symbol );
}
}

View File

@ -723,10 +723,12 @@ void SCH_SYMBOL::UpdatePrefix()
while( prefix.Length() )
{
if( ( prefix.Last() < '0' || prefix.Last() > '9' ) && prefix.Last() != '?' )
break;
wxUniCharRef last = prefix.Last();
prefix.RemoveLast();
if( ( last >= '0' && last <= '9' ) || last == '?' || last == '*' )
prefix.RemoveLast();
else
break;
}
// Avoid a prefix containing trailing/leading spaces

View File

@ -4,6 +4,7 @@
* Copyright (C) 2015 Jean-Pierre Charras, jp.charras at wanadoo.fr
* Copyright (C) 2014 Dick Hollenbeck, dick@softplc.com
* Copyright (C) 2015 Wayne Stambaugh <stambaughw@gmail.com>
* Copyright (C) 2022 CERN
* Copyright (C) 1992-2022 KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software; you can redistribute it and/or
@ -438,6 +439,8 @@ public:
*/
void RemoveField( const wxString& aFieldName );
void RemoveField( SCH_FIELD* aField ) { RemoveField( aField->GetName() ); }
/**
* Search for a #SCH_FIELD with \a aFieldName
*
@ -521,6 +524,8 @@ public:
*/
std::vector<LIB_PIN*> GetLibPins() const;
size_t GetPinCount() { return GetLibPins().size(); }
SCH_PIN* GetPin( LIB_PIN* aLibPin ) const;
/**

View File

@ -2,6 +2,7 @@
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2022 Mikolaj Wielgus
* Copyright (C) 2022 CERN
* Copyright (C) 2022 KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software; you can redistribute it and/or
@ -22,7 +23,9 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <lib_symbol.h>
#include <sch_symbol.h>
#include <confirm.h>
#include <string_utils.h>
#include <sim/sim_model.h>
#include <sim/sim_model_behavioral.h>
@ -628,6 +631,7 @@ void SIM_MODEL::AddPin( const PIN& aPin )
m_pins.push_back( aPin );
}
void SIM_MODEL::ClearPins()
{
m_pins.clear();
@ -916,23 +920,19 @@ std::unique_ptr<SIM_MODEL> SIM_MODEL::Create( TYPE aType )
SIM_MODEL::SIM_MODEL( TYPE aType ) :
SIM_MODEL( aType,
std::make_unique<SPICE_GENERATOR>( *this ),
std::make_unique<SIM_SERDE>( *this ) )
{
}
SIM_MODEL::SIM_MODEL( TYPE aType,
std::unique_ptr<SPICE_GENERATOR> aSpiceGenerator ) :
SIM_MODEL( aType,
std::move( aSpiceGenerator ),
SIM_MODEL( aType, std::make_unique<SPICE_GENERATOR>( *this ),
std::make_unique<SIM_SERDE>( *this ) )
{
}
SIM_MODEL::SIM_MODEL( TYPE aType,
std::unique_ptr<SPICE_GENERATOR> aSpiceGenerator,
SIM_MODEL::SIM_MODEL( TYPE aType, std::unique_ptr<SPICE_GENERATOR> aSpiceGenerator ) :
SIM_MODEL( aType, std::move( aSpiceGenerator ), std::make_unique<SIM_SERDE>( *this ) )
{
}
SIM_MODEL::SIM_MODEL( TYPE aType, std::unique_ptr<SPICE_GENERATOR> aSpiceGenerator,
std::unique_ptr<SIM_SERDE> aSerde ) :
m_baseModel( nullptr ),
m_serde( std::move( aSerde ) ),
@ -1004,3 +1004,189 @@ bool SIM_MODEL::requiresSpiceModelLine() const
return false;
}
template <typename T_symbol, typename T_field>
void SIM_MODEL::MigrateSimModel( T_symbol& aSymbol )
{
if( aSymbol.FindField( SIM_MODEL::DEVICE_TYPE_FIELD )
|| aSymbol.FindField( SIM_MODEL::TYPE_FIELD )
|| aSymbol.FindField( SIM_MODEL::PINS_FIELD )
|| aSymbol.FindField( SIM_MODEL::PARAMS_FIELD ) )
{
// Has a V7 model field -- skip.
return;
}
wxString prefix = aSymbol.GetPrefix();
wxString value;
// Yes, the Value field is always present, but Coverity doesn't know that...
if( T_field* valueField = aSymbol.FindField( wxT( "Value" ) ) )
value = valueField->GetText();
wxString spiceType;
wxString spiceModel;
wxString spiceLib;
wxString pinMap;
if( aSymbol.FindField( wxT( "Spice_Primitive" ) )
|| aSymbol.FindField( wxT( "Spice_Node_Sequence" ) )
|| aSymbol.FindField( wxT( "Spice_Model" ) )
|| aSymbol.FindField( wxT( "Spice_Netlist_Enabled" ) )
|| aSymbol.FindField( wxT( "Spice_Lib_File" ) ) )
{
if( T_field* primitiveField = aSymbol.FindField( wxT( "Spice_Primitive" ) ) )
{
spiceType = primitiveField->GetText();
aSymbol.RemoveField( primitiveField );
}
if( T_field* nodeSequenceField = aSymbol.FindField( wxT( "Spice_Node_Sequence" ) ) )
{
const wxString delimiters( "{:,; }" );
const wxString& nodeSequence = nodeSequenceField->GetText();
if( nodeSequence != "" )
{
wxStringTokenizer tkz( nodeSequence, delimiters );
for( long modelPinNumber = 1; tkz.HasMoreTokens(); ++modelPinNumber )
{
long symbolPinNumber = 1;
tkz.GetNextToken().ToLong( &symbolPinNumber );
if( modelPinNumber != 1 )
pinMap.Append( " " );
pinMap.Append( wxString::Format( "%ld=%ld", symbolPinNumber, modelPinNumber ) );
}
}
aSymbol.RemoveField( nodeSequenceField );
}
if( T_field* modelField = aSymbol.FindField( wxT( "Spice_Model" ) ) )
{
spiceModel = modelField->GetText();
aSymbol.RemoveField( modelField );
}
else
{
spiceModel = value;
}
if( T_field* netlistEnabledField = aSymbol.FindField( wxT( "Spice_Netlist_Enabled" ) ) )
{
wxString netlistEnabled = netlistEnabledField->GetText().Lower();
if( netlistEnabled.StartsWith( wxT( "0" ) )
|| netlistEnabled.StartsWith( wxT( "n" ) )
|| netlistEnabled.StartsWith( wxT( "f" ) ) )
{
T_field enableField( &aSymbol, aSymbol.GetFieldCount(), SIM_MODEL::ENABLE_FIELD );
}
}
if( T_field* libFileField = aSymbol.FindField( wxT( "Spice_Lib_File" ) ) )
{
spiceLib = libFileField->GetText();
aSymbol.RemoveField( libFileField );
}
}
else if( prefix == wxT( "V" ) || prefix == wxT( "I" ) )
{
spiceModel = value;
}
else
{
// Auto convert some legacy fields used in the middle of 7.0 development...
if( T_field* legacyDevice = aSymbol.FindField( wxT( "Sim_Type" ) ) )
{
legacyDevice->SetName( SIM_MODEL::TYPE_FIELD );
}
if( T_field* legacyDevice = aSymbol.FindField( wxT( "Sim_Device" ) ) )
{
legacyDevice->SetName( SIM_MODEL::DEVICE_TYPE_FIELD );
}
if( T_field* legacyPins = aSymbol.FindField( wxT( "Sim_Pins" ) ) )
{
// Migrate pins from array of indexes to name-value-pairs
wxArrayString pinIndexes;
wxString pins;
wxStringSplit( legacyPins->GetText(), pinIndexes, ' ' );
if( SIM_MODEL_IDEAL::InferSimParams( prefix, value ).length() )
{
if( pinIndexes[0] == wxT( "2" ) )
pins = "1=- 2=+";
else
pins = "1=+ 2=-";
}
else
{
for( unsigned ii = 0; ii < pinIndexes.size(); ++ii )
{
if( ii > 0 )
pins.Append( wxS( " " ) );
pins.Append( wxString::Format( wxT( "%u=%s" ), ii + 1, pinIndexes[ ii ] ) );
}
}
legacyPins->SetName( SIM_MODEL::PINS_FIELD );
legacyPins->SetText( pins );
}
if( T_field* legacyPins = aSymbol.FindField( wxT( "Sim_Params" ) ) )
{
legacyPins->SetName( SIM_MODEL::PARAMS_FIELD );
}
return;
}
// Insert a plaintext model as a substitute.
T_field deviceTypeField( &aSymbol, aSymbol.GetFieldCount(), SIM_MODEL::DEVICE_TYPE_FIELD );
deviceTypeField.SetText( SIM_MODEL::DeviceInfo( SIM_MODEL::DEVICE_T::SPICE ).fieldValue );
aSymbol.AddField( deviceTypeField );
T_field paramsField( &aSymbol, aSymbol.GetFieldCount(), SIM_MODEL::PARAMS_FIELD );
paramsField.SetText( wxString::Format( "type=\"%s\" model=\"%s\" lib=\"%s\"",
spiceType, spiceModel, spiceLib ) );
aSymbol.AddField( paramsField );
// Legacy models by default get linear pin mapping.
if( pinMap != "" )
{
T_field pinsField( &aSymbol, aSymbol.GetFieldCount(), SIM_MODEL::PINS_FIELD );
pinsField.SetText( pinMap );
aSymbol.AddField( pinsField );
}
else
{
wxString pins;
for( unsigned ii = 0; ii < aSymbol.GetPinCount(); ++ii )
{
if( ii > 0 )
pins.Append( wxS( " " ) );
pins.Append( wxString::Format( wxT( "%u=%u" ), ii + 1, ii + 1 ) );
}
T_field pinsField( &aSymbol, aSymbol.GetFieldCount(), SIM_MODEL::PINS_FIELD );
pinsField.SetText( pins );
aSymbol.AddField( pinsField );
}
}
template void SIM_MODEL::MigrateSimModel<SCH_SYMBOL, SCH_FIELD>( SCH_SYMBOL& aSymbol );
template void SIM_MODEL::MigrateSimModel<LIB_SYMBOL, LIB_FIELD>( LIB_SYMBOL& aSymbol );

View File

@ -2,6 +2,7 @@
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2022 Mikolaj Wielgus
* Copyright (C) 2022 CERN
* Copyright (C) 2022 KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software; you can redistribute it and/or
@ -518,6 +519,9 @@ public:
}
bool IsStoredInValue() const { return m_isStoredInValue; }
template <class T_symbol, class T_field>
static void MigrateSimModel( T_symbol& aSymbol );
protected:
static std::unique_ptr<SIM_MODEL> Create( TYPE aType );
@ -535,11 +539,6 @@ protected:
std::unique_ptr<SIM_SERDE> m_serde;
private:
static TYPE readTypeFromSpiceStrings( const std::string& aTypeString,
const std::string& aLevel = "",
const std::string& aVersion = "",
bool aSkipDefaultLevel = true );
template <typename T>
void doReadDataFields( unsigned aSymbolPinCount, const std::vector<T>* aFields );

View File

@ -2,7 +2,8 @@
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2016 Wayne Stambaugh <stambaughw@gmail.com>
* Copyright (C) 2016-2021 KiCad Developers, see AUTHORS.txt for contributors.
* Copyright (C) 2022 CERN
* Copyright (C) 2016-2022 KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -34,7 +35,7 @@
#include <lib_symbol.h>
#include <wx/dir.h>
#include "sim/sim_model.h"
#define OPT_SEP '|' ///< options separator character
@ -393,16 +394,18 @@ LIB_SYMBOL* SYMBOL_LIB_TABLE::LoadSymbol( const wxString& aNickname, const wxStr
LIB_SYMBOL* symbol = row->plugin->LoadSymbol( row->GetFullURI( true ), aSymbolName,
row->GetProperties() );
// The library cannot know its own name, because it might have been renamed or moved.
// Therefore footprints cannot know their own library nickname when residing in
// a symbol library.
// Only at this API layer can we tell the symbol about its actual library nickname.
if( symbol )
{
// The library cannot know its own name, because it might have been renamed or moved.
// Therefore footprints cannot know their own library nickname when residing in
// a symbol library.
// Only at this API layer can we tell the symbol about its actual library nickname.
LIB_ID id = symbol->GetLibId();
id.SetLibNickname( row->GetNickName() );
symbol->SetLibId( id );
SIM_MODEL::MigrateSimModel<LIB_SYMBOL, LIB_FIELD>( *symbol );
}
return symbol;

View File

@ -3,6 +3,7 @@
*
* Copyright (C) 2004-2016 Jean-Pierre Charras, jp.charras at wanadoo.fr
* Copyright (C) 2008 Wayne Stambaugh <stambaughw@gmail.com>
* Copyright (C) 2022 CERN
* Copyright (C) 2004-2022 KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software; you can redistribute it and/or
@ -43,6 +44,7 @@
#include <wx/log.h>
#include <wx/progdlg.h>
#include <wx/tokenzr.h>
#include "sim/sim_model.h"
SYMBOL_LIB::SYMBOL_LIB( SCH_LIB_TYPE aType, const wxString& aFileName,
SCH_IO_MGR::SCH_FILE_T aPluginType ) :
@ -159,11 +161,16 @@ LIB_SYMBOL* SYMBOL_LIB::FindSymbol( const wxString& aName ) const
{
LIB_SYMBOL* symbol = m_plugin->LoadSymbol( fileName.GetFullPath(), aName, m_properties.get() );
// Set the library to this even though technically the legacy cache plugin owns the
// symbols. This allows the symbol library table conversion tool to determine the
// correct library where the symbol was found.
if( symbol && !symbol->GetLib() )
symbol->SetLib( const_cast<SYMBOL_LIB*>( this ) );
if( symbol )
{
// Set the library to this even though technically the legacy cache plugin owns the
// symbols. This allows the symbol library table conversion tool to determine the
// correct library where the symbol was found.
if( !symbol->GetLib() )
symbol->SetLib( const_cast<SYMBOL_LIB*>( this ) );
SIM_MODEL::MigrateSimModel<LIB_SYMBOL, LIB_FIELD>( *symbol );
}
return symbol;
}