Fix schematic symbol initial default instance data bug.

The commit bumps the schematic file format version in order to fix the
initial symbol default instance data to the first instance of each symbol.
It also sets the initial instance data to undefined in the SCH_SYMBOL
ctor so on the first schematic save, the default instance will be set
to the first instance of the symbol.

Fixes https://gitlab.com/kicad/code/kicad/-/issues/12190
This commit is contained in:
Wayne Stambaugh 2022-08-20 13:47:43 -04:00
parent b2a2d66005
commit 10123d164f
6 changed files with 85 additions and 13 deletions

View File

@ -450,6 +450,15 @@ bool SCH_EDIT_FRAME::OpenProjectFiles( const std::vector<wxString>& aFileSet, in
// Restore all of the loaded symbol and sheet instances from the root sheet.
sheetList.UpdateSymbolInstances( Schematic().RootScreen()->GetSymbolInstances() );
sheetList.UpdateSheetInstances( Schematic().RootScreen()->GetSheetInstances() );
for( SCH_SCREEN* screen = schematic.GetFirst(); screen; screen = schematic.GetNext() )
{
if( screen->GetFileFormatVersionAtLoad() <= 20220622 )
{
if( screen->AllSymbolDefaultInstancesNotSet() )
screen->SetAllSymbolDefaultInstances();
}
}
}
Schematic().ConnectionGraph()->Reset();

View File

@ -81,4 +81,5 @@
//#define SEXPR_SCHEMATIC_FILE_VERSION 20220328 // Text box start/end -> at/size
//#define SEXPR_SCHEMATIC_FILE_VERSION 20220331 // Text colors
//#define SEXPR_SCHEMATIC_FILE_VERSION 20220404 // Default schematic symbol instance data.
#define SEXPR_SCHEMATIC_FILE_VERSION 20220622 // New simulation model format.
//#define SEXPR_SCHEMATIC_FILE_VERSION 20220622 // New simulation model format.
#define SEXPR_SCHEMATIC_FILE_VERSION 20220820 // Fix broken default symbol instance data.

View File

@ -682,9 +682,11 @@ void SCH_SEXPR_PLUGIN::saveSymbol( SCH_SYMBOL* aSymbol, SCH_SHEET_PATH* aSheetPa
m_out->Print( 0, ")" );
}
// The symbol unit is always set to the default instance regardless of the sheet instance
// to prevent file churn.
int unit = aSymbol->GetDefaultInstance().m_Unit;
// The symbol unit is always set to the first instance regardless of the current sheet
// instance to prevent file churn.
int unit = ( aSymbol->GetInstanceReferences().size() == 0 ) ?
aSymbol->GetUnit() :
aSymbol->GetInstanceReferences()[0].m_Unit;
m_out->Print( 0, " (unit %d)", unit );
@ -703,6 +705,17 @@ void SCH_SEXPR_PLUGIN::saveSymbol( SCH_SYMBOL* aSymbol, SCH_SHEET_PATH* aSheetPa
m_out->Print( aNestLevel + 1, "(uuid %s)\n", TO_UTF8( aSymbol->m_Uuid.AsString() ) );
// On the first save, if the default instance is not set, use the first instance data as
// the default.
if( aSymbol->GetDefaultInstance().m_Reference == wxEmptyString &&
aSymbol->GetDefaultInstance().m_Unit == -1 &&
aSymbol->GetDefaultInstance().m_Value == wxEmptyString &&
aSymbol->GetDefaultInstance().m_Footprint == wxEmptyString )
{
if( !aSymbol->GetInstanceReferences().empty() )
aSymbol->SetDefaultInstance( aSymbol->GetInstanceReferences()[0] );
}
m_out->Print( aNestLevel + 1,
"(default_instance (reference %s) (unit %d) (value %s) (footprint %s))\n",
m_out->Quotew( aSymbol->GetDefaultInstance().m_Reference ).c_str(),

View File

@ -1437,6 +1437,46 @@ void SCH_SCREEN::SetLegacySymbolInstanceData()
}
bool SCH_SCREEN::AllSymbolDefaultInstancesNotSet()
{
for( SCH_ITEM* item : Items().OfType( SCH_SYMBOL_T ) )
{
SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
wxCHECK2( symbol, continue );
SYMBOL_INSTANCE_REFERENCE symbolDefaultReference = symbol->GetDefaultInstance();
const std::unique_ptr<LIB_SYMBOL>& libSymbol = symbol->GetLibSymbolRef();
if( !libSymbol )
continue;
if( symbolDefaultReference.m_Unit != 1 ||
symbolDefaultReference.m_Reference != symbol->GetPrefix() ||
symbolDefaultReference.m_Value != libSymbol->GetValueField().GetText() ||
symbolDefaultReference.m_Footprint != libSymbol->GetFootprintField().GetText() )
return false;
}
return true;
}
void SCH_SCREEN::SetAllSymbolDefaultInstances()
{
for( SCH_ITEM* item : Items().OfType( SCH_SYMBOL_T ) )
{
SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
wxCHECK2( symbol, continue );
if( !symbol->GetInstanceReferences().empty() )
symbol->SetDefaultInstance( symbol->GetInstanceReferences()[0] );
}
}
#if defined(DEBUG)
void SCH_SCREEN::Show( int nestLevel, std::ostream& os ) const
{

View File

@ -100,8 +100,9 @@ public:
* Gets the full RTree, usually for iterating.
* N.B. The iteration order of the RTree is not readily apparent and will change
* if/when you add or move items and the RTree is re-balanced. Any exposure of the
* RTree contents to the user MUST be sorted before being presented. See SCH_SEXPR_PLUGIN::Format
* or SCH_EDITOR_CONTROL::nextMatch for examples.
* RTree contents to the user MUST be sorted before being presented. See
* SCH_SEXPR_PLUGIN::Format() or SCH_EDITOR_CONTROL::nextMatch() for examples.
*
* @return Complete RTree of the screen's items
*/
EE_RTREE& Items() { return m_rtree; }
@ -503,6 +504,18 @@ public:
*/
void SetLegacySymbolInstanceData();
/**
* Check all symbol default instance to see if they are not set yet.
*/
bool AllSymbolDefaultInstancesNotSet();
/**
* Set symbol default instances to the first instance in the instance list.
*
* @warning The schematic symbol instance data must be loaded before this method is called.
*/
void SetAllSymbolDefaultInstances();
#if defined(DEBUG)
void Show( int nestLevel, std::ostream& os ) const override;
#endif

View File

@ -131,10 +131,7 @@ SCH_SYMBOL::SCH_SYMBOL( const LIB_SYMBOL& aSymbol, const LIB_ID& aLibId,
m_prefix = UTIL::GetRefDesPrefix( m_part->GetReferenceField().GetText() );
// Set initial default symbol instance data from library symbol and initial unit.
m_defaultInstance.m_Reference = m_prefix;
m_defaultInstance.m_Unit = aUnit;
m_defaultInstance.m_Value = m_part->GetValueField().GetText();
m_defaultInstance.m_Footprint = m_part->GetFootprintField().GetText();
m_defaultInstance.m_Unit = -1;
if( aSheet )
{
@ -224,7 +221,6 @@ void SCH_SYMBOL::Init( const VECTOR2I& pos )
}
m_prefix = wxString( wxT( "U" ) );
m_defaultInstance.m_Reference = m_prefix;
m_isInNetlist = true;
m_inBom = true;
m_onBoard = true;
@ -240,8 +236,8 @@ EDA_ITEM* SCH_SYMBOL::Clone() const
void SCH_SYMBOL::ViewGetLayers( int aLayers[], int& aCount ) const
{
aCount = 7;
aLayers[0] = LAYER_DANGLING; // Pins are drawn by their parent symbol, so the parent
// symbol needs to draw to LAYER_DANGLING
aLayers[0] = LAYER_DANGLING; // Pins are drawn by their parent symbol, so the parent
// symbol needs to draw to LAYER_DANGLING
aLayers[1] = LAYER_DEVICE;
aLayers[2] = LAYER_REFERENCEPART;
aLayers[3] = LAYER_VALUEPART;