Revert "Move schematic symbol instance data back into symbol definition."

This reverts commit 7984e114db.
This commit is contained in:
Wayne Stambaugh 2022-09-29 15:24:56 -04:00
parent a60ed99510
commit 979b4a4eb7
18 changed files with 151 additions and 542 deletions

View File

@ -448,9 +448,7 @@ bool SCH_EDIT_FRAME::OpenProjectFiles( const std::vector<wxString>& aFileSet, in
screen->UpdateLocalLibSymbolLinks();
// Restore all of the loaded symbol and sheet instances from the root sheet.
if( Schematic().RootScreen()->GetFileFormatVersionAtLoad() <= 20220919 )
sheetList.UpdateSymbolInstances( Schematic().RootScreen()->GetSymbolInstances() );
sheetList.UpdateSymbolInstances( Schematic().RootScreen()->GetSymbolInstances() );
sheetList.UpdateSheetInstances( Schematic().RootScreen()->GetSheetInstances() );
for( SCH_SCREEN* screen = schematic.GetFirst(); screen; screen = schematic.GetNext() )

View File

@ -87,5 +87,4 @@
//#define SEXPR_SCHEMATIC_FILE_VERSION 20220822 // Hyperlinks in text objects
//#define SEXPR_SCHEMATIC_FILE_VERSION 20220903 // Field name visibility
//#define SEXPR_SCHEMATIC_FILE_VERSION 20220904 // Do not autoplace field option
//#define SEXPR_SCHEMATIC_FILE_VERSION 20220914 // Add support for DNP
#define SEXPR_SCHEMATIC_FILE_VERSION 20220919 // Move instance data back into symbol definition.
#define SEXPR_SCHEMATIC_FILE_VERSION 20220914 // Add support for DNP

View File

@ -1375,9 +1375,10 @@ void SCH_EAGLE_PLUGIN::loadInstance( wxXmlNode* aInstanceNode )
SCH_SHEET_PATH sheetpath;
m_rootSheet->LocatePathOfScreen( screen, &sheetpath );
wxString current_sheetpath = sheetpath.PathAsString() + symbol->m_Uuid.AsString();
symbol->GetField( REFERENCE_FIELD )->SetText( reference );
symbol->AddHierarchicalReference( sheetpath.Path(), reference, unit );
symbol->AddHierarchicalReference( current_sheetpath, reference, unit );
if( epart->value )
symbol->GetField( VALUE_FIELD )->SetText( *epart->value );

View File

@ -65,19 +65,16 @@ using namespace TSCHEMATIC_T;
SCH_SEXPR_PARSER::SCH_SEXPR_PARSER( LINE_READER* aLineReader, PROGRESS_REPORTER* aProgressReporter,
unsigned aLineCount, SCH_SHEET* aRootSheet,
bool aIsAppending ) :
unsigned aLineCount ) :
SCHEMATIC_LEXER( aLineReader ),
m_requiredVersion( 0 ),
m_fieldId( 0 ),
m_unit( 1 ),
m_convert( 1 ),
m_appending( aIsAppending ),
m_progressReporter( aProgressReporter ),
m_lineReader( aLineReader ),
m_lastProgressLine( 0 ),
m_lineCount( aLineCount ),
m_rootSheet( aRootSheet )
m_lineCount( aLineCount )
{
}
@ -2052,9 +2049,6 @@ void SCH_SEXPR_PARSER::parseSchSheetInstances( SCH_SHEET* aRootSheet, SCH_SCREEN
instance.m_Path = KIID_PATH( FromUTF8() );
if( !m_appending && instance.m_Path.empty() )
instance.m_Path.insert( instance.m_Path.begin(), m_rootUuid );
for( token = NextTok(); token != T_RIGHT; token = NextTok() )
{
if( token != T_LEFT )
@ -2114,7 +2108,6 @@ void SCH_SEXPR_PARSER::parseSchSymbolInstances( SCH_SCREEN* aScreen )
wxCHECK_RET( CurTok() == T_symbol_instances,
"Cannot parse " + GetTokenString( CurTok() ) + " as an instances token." );
wxCHECK( aScreen, /* void */ );
wxCHECK( m_rootUuid != NilUuid(), /* void */ );
T token;
@ -2135,9 +2128,6 @@ void SCH_SEXPR_PARSER::parseSchSymbolInstances( SCH_SCREEN* aScreen )
instance.m_Path = KIID_PATH( FromUTF8() );
if( !m_appending )
instance.m_Path.insert( instance.m_Path.begin(), m_rootUuid );
for( token = NextTok(); token != T_RIGHT; token = NextTok() )
{
if( token != T_LEFT )
@ -2208,11 +2198,6 @@ void SCH_SEXPR_PARSER::ParseSchematic( SCH_SHEET* aSheet, bool aIsCopyableOnly,
Expecting( "kicad_sch" );
parseHeader( T_kicad_sch, SEXPR_SCHEMATIC_FILE_VERSION );
// Prior to schematic file version 20210406, schematics did not have UUIDs so we need
// to generate one for the root schematic for instance paths.
if( m_requiredVersion < 20210406 )
m_rootUuid = screen->GetUuid();
}
screen->SetFileFormatVersionAtLoad( m_requiredVersion );
@ -2237,16 +2222,6 @@ void SCH_SEXPR_PARSER::ParseSchematic( SCH_SHEET* aSheet, bool aIsCopyableOnly,
case T_uuid:
NeedSYMBOL();
screen->m_uuid = parseKIID();
// Set the root sheet UUID with the schematic file UUID. Root sheets are virtual
// and always get a new UUID so this prevents file churn now that the root UUID
// is saved in the symbol instance path.
if( aSheet == m_rootSheet )
{
const_cast<KIID&>( aSheet->m_Uuid ) = screen->GetUuid();
m_rootUuid = screen->GetUuid();
}
NeedRIGHT();
break;
@ -2624,7 +2599,7 @@ SCH_SYMBOL* SCH_SEXPR_PARSER::parseSchematicSymbol()
break;
default:
Expecting( "reference, unit, value or footprint" );
Expecting( "path, unit, value or footprint" );
}
}
@ -2632,66 +2607,6 @@ SCH_SYMBOL* SCH_SEXPR_PARSER::parseSchematicSymbol()
break;
}
case T_instances:
{
for( token = NextTok(); token != T_RIGHT; token = NextTok() )
{
if( token != T_LEFT )
Expecting( T_LEFT );
token = NextTok();
if( token != T_path )
Expecting( "path" );
SYMBOL_INSTANCE_REFERENCE instance;
NeedSYMBOL();
instance.m_Path = KIID_PATH( FromUTF8() );
for( token = NextTok(); token != T_RIGHT; token = NextTok() )
{
if( token != T_LEFT )
Expecting( T_LEFT );
token = NextTok();
switch( token )
{
case T_reference:
NeedSYMBOL();
instance.m_Reference = FromUTF8();
NeedRIGHT();
break;
case T_unit:
instance.m_Unit = parseInt( "symbol unit" );
NeedRIGHT();
break;
case T_value:
NeedSYMBOL();
instance.m_Value = FromUTF8();
NeedRIGHT();
break;
case T_footprint:
NeedSYMBOL();
instance.m_Footprint = FromUTF8();
NeedRIGHT();
break;
default:
Expecting( "reference, unit, value or footprint" );
}
symbol->AddHierarchicalReference( instance );
}
}
break;
}
case T_property:
// The field parent symbol must be set and its orientation must be set before
// the field positions are set.
@ -2793,8 +2708,7 @@ SCH_SYMBOL* SCH_SEXPR_PARSER::parseSchematicSymbol()
break;
default:
Expecting( "lib_id, lib_name, at, mirror, uuid, on_board, in_bom, dnp, "
"default_instance, property, pin, or instances" );
Expecting( "lib_id, lib_name, at, mirror, uuid, property, pin, or instances" );
}
}

View File

@ -76,6 +76,22 @@ public:
*/
class SCH_SEXPR_PARSER : public SCHEMATIC_LEXER
{
int m_requiredVersion; ///< Set to the symbol library file version required.
int m_fieldId; ///< The current field ID.
int m_unit; ///< The current unit being parsed.
int m_convert; ///< The current body style being parsed.
wxString m_symbolName; ///< The current symbol name.
/// Field IDs that have been read so far for the current symbol.
std::set<int> m_fieldIDsRead;
std::set<KIID> m_uuids;
PROGRESS_REPORTER* m_progressReporter; // optional; may be nullptr
const LINE_READER* m_lineReader; // for progress reporting
unsigned m_lastProgressLine;
unsigned m_lineCount; // for progress reporting
void checkpoint();
KIID parseKIID();
@ -168,8 +184,7 @@ class SCH_SEXPR_PARSER : public SCHEMATIC_LEXER
public:
SCH_SEXPR_PARSER( LINE_READER* aLineReader = nullptr,
PROGRESS_REPORTER* aProgressReporter = nullptr, unsigned aLineCount = 0,
SCH_SHEET* aRootSheet = nullptr, bool aIsAppending = false );
PROGRESS_REPORTER* aProgressReporter = nullptr, unsigned aLineCount = 0 );
void ParseLib( LIB_SYMBOL_MAP& aSymbolLibMap );
@ -197,28 +212,6 @@ public:
*/
void ParseSchematic( SCH_SHEET* aSheet, bool aIsCopyablyOnly = false,
int aFileVersion = SEXPR_SCHEMATIC_FILE_VERSION );
private:
int m_requiredVersion; ///< Set to the symbol library file version required.
int m_fieldId; ///< The current field ID.
int m_unit; ///< The current unit being parsed.
int m_convert; ///< The current body style being parsed.
wxString m_symbolName; ///< The current symbol name.
bool m_appending; ///< Appending load status.
/// Field IDs that have been read so far for the current symbol.
std::set<int> m_fieldIDsRead;
std::set<KIID> m_uuids;
PROGRESS_REPORTER* m_progressReporter; // optional; may be nullptr
const LINE_READER* m_lineReader; // for progress reporting
unsigned m_lastProgressLine;
unsigned m_lineCount; // for progress reporting
KIID m_rootUuid; // The UUID of the root schematic.
/// The rootsheet for full project loads or null for importing a schematic.
SCH_SHEET* m_rootSheet;
};
#endif // __SCH_SEXPR_PARSER_H__

View File

@ -88,7 +88,6 @@ SCH_SEXPR_PLUGIN::~SCH_SEXPR_PLUGIN()
void SCH_SEXPR_PLUGIN::init( SCHEMATIC* aSchematic, const PROPERTIES* aProperties )
{
m_version = 0;
m_appending = false;
m_rootSheet = nullptr;
m_schematic = aSchematic;
m_cache = nullptr;
@ -114,7 +113,6 @@ SCH_SHEET* SCH_SEXPR_PLUGIN::Load( const wxString& aFileName, SCHEMATIC* aSchema
if( aAppendToMe )
{
m_appending = true;
wxLogTrace( traceSchLegacyPlugin, "Append \"%s\" to sheet \"%s\".",
aFileName, aAppendToMe->GetFileName() );
@ -301,7 +299,7 @@ void SCH_SEXPR_PLUGIN::loadFile( const wxString& aFileName, SCH_SHEET* aSheet )
reader.Rewind();
}
SCH_SEXPR_PARSER parser( &reader, m_progressReporter, lineCount, m_rootSheet, m_appending );
SCH_SEXPR_PARSER parser( &reader, m_progressReporter, lineCount );
parser.ParseSchematic( aSheet );
}
@ -484,14 +482,14 @@ void SCH_SEXPR_PLUGIN::Format( SCH_SHEET* aSheet )
symbolInstances.SortByReferenceOnly();
saveInstances( sheetPaths.GetSheetInstances(), 1 );
saveInstances( sheetPaths.GetSheetInstances(), symbolInstances.GetSymbolInstances(), 1 );
}
else
{
// Schematic files (SCH_SCREEN objects) can be shared so we have to save and restore
// symbol and sheet instance data even if the file being saved is not the root sheet
// because it is possible that the file is the root sheet of another project.
saveInstances( screen->m_sheetInstances, 1 );
saveInstances( screen->m_sheetInstances, screen->m_symbolInstances, 1 );
}
m_out->Print( 0, ")\n" );
@ -623,7 +621,7 @@ void SCH_SEXPR_PLUGIN::Format( EE_SELECTION* aSelection, SCH_SHEET_PATH* aSelect
}
// Make all instance information relative to the selection path
KIID_PATH selectionPath = aSelectionPath->Path();
KIID_PATH selectionPath = aSelectionPath->PathWithoutRootUuid();
selectedSheets.SortByPageNumbers();
std::vector<SCH_SHEET_INSTANCE> sheetinstances = selectedSheets.GetSheetInstances();
@ -644,7 +642,7 @@ void SCH_SEXPR_PLUGIN::Format( EE_SELECTION* aSelection, SCH_SHEET_PATH* aSelect
"Symbol is not inside the selection path?" );
}
saveInstances( sheetinstances, 0 );
saveInstances( sheetinstances, symbolInstances, 0 );
}
@ -809,24 +807,7 @@ void SCH_SEXPR_PLUGIN::saveSymbol( SCH_SYMBOL* aSymbol, SCH_SHEET_PATH* aSheetPa
}
}
m_out->Print( aNestLevel + 1, "(instances\n" );
for( const SYMBOL_INSTANCE_REFERENCE& instance : aSymbol->GetInstanceReferences() )
{
wxString path = instance.m_Path.AsString();
m_out->Print( aNestLevel + 2, "(path %s\n",
m_out->Quotew( path ).c_str() );
m_out->Print( aNestLevel + 3, "(reference %s) (unit %d) (value %s) (footprint %s)\n",
m_out->Quotew( instance.m_Reference ).c_str(),
instance.m_Unit,
m_out->Quotew( instance.m_Value ).c_str(),
m_out->Quotew( instance.m_Footprint ).c_str() );
m_out->Print( aNestLevel + 2, ")\n" );
}
m_out->Print( aNestLevel + 1, ")\n" ); // Closes `instances`.
m_out->Print( aNestLevel, ")\n" ); // Closes `symbol`.
m_out->Print( aNestLevel, ")\n" );
}
@ -1229,6 +1210,7 @@ void SCH_SEXPR_PLUGIN::saveBusAlias( std::shared_ptr<BUS_ALIAS> aAlias, int aNes
void SCH_SEXPR_PLUGIN::saveInstances( const std::vector<SCH_SHEET_INSTANCE>& aSheets,
const std::vector<SYMBOL_INSTANCE_REFERENCE>& aSymbols,
int aNestLevel )
{
if( aSheets.size() )
@ -1250,6 +1232,26 @@ void SCH_SEXPR_PLUGIN::saveInstances( const std::vector<SCH_SHEET_INSTANCE>& aSh
m_out->Print( aNestLevel, ")\n" ); // Close sheet instances token.
}
if( aSymbols.size() )
{
m_out->Print( 0, "\n" );
m_out->Print( aNestLevel, "(symbol_instances\n" );
for( const SYMBOL_INSTANCE_REFERENCE& instance : aSymbols )
{
m_out->Print( aNestLevel + 1, "(path %s\n",
m_out->Quotew( instance.m_Path.AsString() ).c_str() );
m_out->Print( aNestLevel + 2, "(reference %s) (unit %d) (value %s) (footprint %s)\n",
m_out->Quotew( instance.m_Reference ).c_str(),
instance.m_Unit,
m_out->Quotew( instance.m_Value ).c_str(),
m_out->Quotew( instance.m_Footprint ).c_str() );
m_out->Print( aNestLevel + 1, ")\n" );
}
m_out->Print( aNestLevel, ")\n" ); // Close symbol instances token.
}
}

View File

@ -159,7 +159,8 @@ private:
void saveText( SCH_TEXT* aText, int aNestLevel );
void saveTextBox( SCH_TEXTBOX* aText, int aNestLevel );
void saveBusAlias( std::shared_ptr<BUS_ALIAS> aAlias, int aNestLevel );
void saveInstances( const std::vector<SCH_SHEET_INSTANCE>& aSheets, int aNestLevel );
void saveInstances( const std::vector<SCH_SHEET_INSTANCE>& aSheets,
const std::vector<SYMBOL_INSTANCE_REFERENCE>& aSymbols, int aNestLevel );
void cacheLib( const wxString& aLibraryFileName, const PROPERTIES* aProperties );
bool isBuffering( const PROPERTIES* aProperties );
@ -167,7 +168,7 @@ private:
protected:
int m_version; ///< Version of file being loaded.
int m_nextFreeFieldId;
bool m_appending; ///< Schematic load append status.
wxString m_error; ///< For throwing exceptions or errors on partial
///< loads.
PROGRESS_REPORTER* m_progressReporter;

View File

@ -72,7 +72,6 @@
SCH_LEGACY_PLUGIN::SCH_LEGACY_PLUGIN() :
m_appending( false ),
m_progressReporter( nullptr ),
m_lineReader( nullptr ),
m_lastProgressLine( 0 ),
@ -175,7 +174,6 @@ SCH_SHEET* SCH_LEGACY_PLUGIN::Load( const wxString& aFileName, SCHEMATIC* aSchem
}
else
{
m_appending = true;
wxCHECK_MSG( aSchematic->IsValid(), nullptr, "Can't append to a schematic with no root!" );
m_rootSheet = &aSchematic->Root();
sheet = aAppendToMe;
@ -1184,18 +1182,19 @@ SCH_SYMBOL* SCH_LEGACY_PLUGIN::loadSymbol( LINE_READER& aReader )
parseQuotedString( pathStr, aReader, line, &line );
// Note: AR path excludes root sheet, but includes symbol. Drop the symbol ID
// since it's already defined in the symbol itself.
// Note: AR path excludes root sheet, but includes symbol. Normalize to
// internal format by shifting everything down one and adding the root sheet.
KIID_PATH path( pathStr );
if( path.size() > 0 )
path.pop_back();
{
for( size_t i = path.size() - 1; i > 0; --i )
path[i] = path[i-1];
// In the new file format, the root schematic UUID is used as the virtual SCH_SHEET
// UUID so we need to prefix it to the symbol path so the symbol instance paths
// get saved with the root schematic UUID.
if( !m_appending )
path.insert( path.begin(), m_rootSheet->GetScreen()->m_Uuid );
path[0] = m_rootSheet->m_Uuid;
}
else
path.push_back( m_rootSheet->m_Uuid );
strCompare = "Ref=";
len = strlen( strCompare );

View File

@ -178,9 +178,6 @@ private:
protected:
int m_version; ///< Version of file being loaded.
///< Indicate if we are appending the loaded schemitic or loading a full project.
bool m_appending;
wxString m_error; ///< For throwing exceptions or errors on partial
///< schematic loads.
PROGRESS_REPORTER* m_progressReporter; ///< optional; may be nullptr

View File

@ -1645,10 +1645,6 @@ int SCH_SCREENS::ReplaceDuplicateTimeStamps()
// side-effects.
const_cast<KIID&>( item->m_Uuid ) = KIID();
count++;
// @todo If the item is a sheet, we need to decend the heirarchy from the sheet
// and repace all instances of the changed UUID in sheet paths. Otherwise,
// all instance paths with the sheet's UUID will get clobbered.
}
}
@ -1878,16 +1874,3 @@ void SCH_SCREENS::SetLegacySymbolInstanceData()
for( SCH_SCREEN* screen = GetFirst(); screen; screen = GetNext() )
screen->SetLegacySymbolInstanceData();
}
void SCH_SCREENS::SetAllSymbolDefaultInstances()
{
for( SCH_SCREEN* screen = GetFirst(); screen; screen = GetNext() )
{
if( screen->GetFileFormatVersionAtLoad() <= 20220622 )
{
if( screen->AllSymbolDefaultInstancesNotSet() )
screen->SetAllSymbolDefaultInstances();
}
}
}

View File

@ -739,13 +739,6 @@ public:
*/
void SetLegacySymbolInstanceData();
/**
* 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();
private:
void addScreenToList( SCH_SCREEN* aScreen, SCH_SHEET* aSheet );
void buildScreenList( SCH_SHEET* aSheet);

View File

@ -1208,17 +1208,17 @@ bool SCH_SHEET::AddInstance( const SCH_SHEET_PATH& aSheetPath )
for( const SCH_SHEET_INSTANCE& instance : m_instances )
{
// if aSheetPath is found, nothing to do:
if( instance.m_Path == aSheetPath.Path() )
if( instance.m_Path == aSheetPath.PathWithoutRootUuid() )
return false;
}
wxLogTrace( traceSchSheetPaths, wxT( "Adding instance `%s` to sheet `%s`." ),
aSheetPath.Path().AsString(),
aSheetPath.PathWithoutRootUuid().AsString(),
( GetName().IsEmpty() ) ? wxT( "root" ) : GetName() );
SCH_SHEET_INSTANCE instance;
instance.m_Path = aSheetPath.Path();
instance.m_Path = aSheetPath.PathWithoutRootUuid();
// This entry does not exist: add it with an empty page number.
m_instances.emplace_back( instance );
@ -1231,7 +1231,7 @@ wxString SCH_SHEET::GetPageNumber( const SCH_SHEET_PATH& aSheetPath ) const
wxCHECK( aSheetPath.IsFullPath(), wxEmptyString );
wxString pageNumber;
KIID_PATH path = aSheetPath.Path();
KIID_PATH path = aSheetPath.PathWithoutRootUuid();
for( const SCH_SHEET_INSTANCE& instance : m_instances )
{
@ -1250,7 +1250,7 @@ void SCH_SHEET::SetPageNumber( const SCH_SHEET_PATH& aSheetPath, const wxString&
{
wxCHECK( aSheetPath.IsFullPath(), /* void */ );
KIID_PATH path = aSheetPath.Path();
KIID_PATH path = aSheetPath.PathWithoutRootUuid();
for( SCH_SHEET_INSTANCE& instance : m_instances )
{

View File

@ -283,6 +283,17 @@ KIID_PATH SCH_SHEET_PATH::Path() const
}
KIID_PATH SCH_SHEET_PATH::PathWithoutRootUuid() const
{
KIID_PATH path;
for( size_t i = 1; i < size(); i++ )
path.push_back( at( i )->m_Uuid );
return path;
}
wxString SCH_SHEET_PATH::PathHumanReadable( bool aUseShortRootName ) const
{
wxString s;
@ -525,94 +536,6 @@ void SCH_SHEET_PATH::SetPageNumber( const wxString& aPageNumber )
}
void SCH_SHEET_PATH::AddNewSymbolInstances( const SCH_SHEET_PATH& aPrefixSheetPath )
{
for( SCH_ITEM* item : LastScreen()->Items().OfType( SCH_SYMBOL_T ) )
{
SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
wxCHECK2( symbol, continue );
SYMBOL_INSTANCE_REFERENCE newSymbolInstance;
SCH_SHEET_PATH newSheetPath( aPrefixSheetPath );
SCH_SHEET_PATH currentSheetPath( *this );
// Remove the root sheet from this path.
currentSheetPath.m_sheets.erase( currentSheetPath.m_sheets.begin() );
// Prefix the new hierarchical path.
newSheetPath = newSheetPath + currentSheetPath;
newSymbolInstance.m_Path = newSheetPath.Path();
if( symbol->GetInstance( newSymbolInstance, Path() ) )
{
// Use an existing symbol instance for this path if it exists.
newSymbolInstance.m_Path = newSheetPath.Path();
symbol->AddHierarchicalReference( newSymbolInstance );
}
else if( !symbol->GetInstanceReferences().empty() )
{
// Use the first symbol instance if any symbol exists.
newSymbolInstance = symbol->GetInstanceReferences()[0];
newSymbolInstance.m_Path = newSheetPath.Path();
symbol->AddHierarchicalReference( newSymbolInstance );
}
else if( symbol->GetLibSymbolRef() )
{
// Fall back to library symbol reference prefix, value, and footprint fields and
// set the unit to 1 if the library symbol is valid.
newSymbolInstance.m_Reference = symbol->GetLibSymbolRef()->GetReferenceField().GetText();
newSymbolInstance.m_Reference += wxT( "?" );
newSymbolInstance.m_Unit = 1;
newSymbolInstance.m_Value = symbol->GetLibSymbolRef()->GetValueField().GetText();
newSymbolInstance.m_Footprint = symbol->GetLibSymbolRef()->GetFootprintField().GetText();
symbol->AddHierarchicalReference( newSymbolInstance );
}
else
{
// All hope is lost so set the reference to 'U' and the unit to 1.
newSymbolInstance.m_Reference += wxT( "U?" );
newSymbolInstance.m_Unit = 1;
symbol->AddHierarchicalReference( newSymbolInstance );
}
}
}
int SCH_SHEET_PATH::AddNewSheetInstances( const SCH_SHEET_PATH& aPrefixSheetPath,
int aNextVirtualPageNumber )
{
int nextVirtualPageNumber = aNextVirtualPageNumber;
for( SCH_ITEM* item : LastScreen()->Items().OfType( SCH_SHEET_T ) )
{
SCH_SHEET* sheet = static_cast<SCH_SHEET*>( item );
wxCHECK2( sheet, continue );
SCH_SHEET_PATH newSheetPath( aPrefixSheetPath );
SCH_SHEET_PATH currentSheetPath( *this );
// Remove the root sheet from current sheet path.
currentSheetPath.m_sheets.erase( currentSheetPath.m_sheets.begin() );
// Prefix the new hierarchical path.
newSheetPath = newSheetPath + currentSheetPath;
newSheetPath.push_back( sheet );
wxString pageNumber;
pageNumber.Printf( wxT( "%d" ), nextVirtualPageNumber );
sheet->AddInstance( newSheetPath );
newSheetPath.SetVirtualPageNumber( nextVirtualPageNumber );
newSheetPath.SetPageNumber( pageNumber );
nextVirtualPageNumber += 1;
}
return nextVirtualPageNumber;
}
void SCH_SHEET_PATH::MakeFilePathRelativeToParentSheet()
{
wxCHECK( m_sheets.size() > 1, /* void */ );
@ -1057,37 +980,51 @@ SCH_SHEET_LIST SCH_SHEET_LIST::FindAllSheetsForScreen( const SCH_SCREEN* aScreen
void SCH_SHEET_LIST::UpdateSymbolInstances(
const std::vector<SYMBOL_INSTANCE_REFERENCE>& aSymbolInstances )
{
for( SCH_SHEET_PATH& sheetPath : *this )
SCH_REFERENCE_LIST symbolInstances;
GetSymbols( symbolInstances, true, true );
std::map<KIID_PATH, wxString> pathNameCache;
// Calculating the name of a path is somewhat expensive; on large designs with many symbols
// this can blow up to a serious amount of time when loading the schematic
auto getName = [&pathNameCache]( const KIID_PATH& aPath ) -> const wxString&
{
if( pathNameCache.count( aPath ) )
return pathNameCache.at( aPath );
pathNameCache[aPath] = aPath.AsString();
return pathNameCache[aPath];
};
for( size_t i = 0; i < symbolInstances.GetCount(); i++ )
{
for( SCH_ITEM* item : sheetPath.LastScreen()->Items().OfType( SCH_SYMBOL_T ) )
// The instance paths are stored in the file sans root path so the comparison
// should not include the root path.
wxString path = symbolInstances[i].GetPath();
auto it = std::find_if( aSymbolInstances.begin(), aSymbolInstances.end(),
[ path, &getName ]( const SYMBOL_INSTANCE_REFERENCE& r ) -> bool
{
return path == getName( r.m_Path );
} );
if( it == aSymbolInstances.end() )
{
SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
wxCHECK2( symbol, continue );
KIID_PATH sheetPathWithSymbolUuid = sheetPath.Path();
sheetPathWithSymbolUuid.push_back( symbol->m_Uuid );
auto it = std::find_if( aSymbolInstances.begin(), aSymbolInstances.end(),
[ sheetPathWithSymbolUuid ]( const SYMBOL_INSTANCE_REFERENCE& r ) -> bool
{
return sheetPathWithSymbolUuid == r.m_Path;
} );
if( it == aSymbolInstances.end() )
{
wxLogTrace( traceSchSheetPaths, "No symbol instance found for symbol '%s'",
sheetPathWithSymbolUuid.AsString() );
continue;
}
// Symbol instance paths are stored and looked up in memory with the root path so use
// the full path here.
symbol->AddHierarchicalReference( sheetPath.Path(),
it->m_Reference, it->m_Unit, it->m_Value,
it->m_Footprint );
symbol->GetField( REFERENCE_FIELD )->SetText( it->m_Reference );
wxLogTrace( traceSchSheetPaths, "No symbol instance found for path '%s'", path );
continue;
}
SCH_SYMBOL* symbol = symbolInstances[ i ].GetSymbol();
wxCHECK2( symbol, continue );
// Symbol instance paths are stored and looked up in memory with the root path so use
// the full path here.
symbol->AddHierarchicalReference( symbolInstances[i].GetSheetPath().Path(),
it->m_Reference, it->m_Unit, it->m_Value,
it->m_Footprint );
symbol->GetField( REFERENCE_FIELD )->SetText( it->m_Reference );
}
if( size() >= 1 && at( 0 ).LastScreen()->GetFileFormatVersionAtLoad() < 20220622 )
@ -1102,24 +1039,24 @@ void SCH_SHEET_LIST::UpdateSheetInstances( const std::vector<SCH_SHEET_INSTANCE>
{
SCH_SHEET* sheet = path.Last();
wxCHECK2( sheet && path.Last(), continue );
wxCHECK2( sheet, continue );
auto it = std::find_if( aSheetInstances.begin(), aSheetInstances.end(),
[ path ]( const SCH_SHEET_INSTANCE& r ) -> bool
{
return path.Last()->m_Uuid == r.m_Path.back();
return path.PathWithoutRootUuid() == r.m_Path;
} );
if( it == aSheetInstances.end() )
{
wxLogTrace( traceSchSheetPaths, "No sheet instance found for path '%s'",
path.Path().AsString() );
path.PathWithoutRootUuid().AsString() );
continue;
}
wxLogTrace( traceSchSheetPaths, "Setting sheet '%s' instance '%s' page number '%s'",
( sheet->GetName().IsEmpty() ) ? wxT( "root" ) : sheet->GetName(),
path.Path().AsString(), it->m_PageNumber );
path.PathWithoutRootUuid().AsString(), it->m_PageNumber );
sheet->AddInstance( path );
sheet->SetPageNumber( path, it->m_PageNumber );
}
@ -1148,7 +1085,7 @@ std::vector<SCH_SHEET_INSTANCE> SCH_SHEET_LIST::GetSheetInstances() const
wxCHECK2( sheet, continue );
SCH_SHEET_INSTANCE instance;
instance.m_Path = path.Path();
instance.m_Path = path.PathWithoutRootUuid();
instance.m_PageNumber = sheet->GetPageNumber( path );
retval.push_back( instance );
@ -1196,38 +1133,6 @@ void SCH_SHEET_LIST::SetInitialPageNumbers()
}
void SCH_SHEET_LIST::AddNewSymbolInstances( const SCH_SHEET_PATH& aPrefixSheetPath )
{
for( SCH_SHEET_PATH& sheetPath : *this )
sheetPath.AddNewSymbolInstances( aPrefixSheetPath );
}
void SCH_SHEET_LIST::AddNewSheetInstances( const SCH_SHEET_PATH& aPrefixSheetPath,
int aLastVirtualPageNumber )
{
int nextVirtualPageNumber = aLastVirtualPageNumber + 1;
for( SCH_SHEET_PATH& sheetPath : *this )
nextVirtualPageNumber = sheetPath.AddNewSheetInstances( aPrefixSheetPath,
nextVirtualPageNumber );
}
int SCH_SHEET_LIST::GetLastVirtualPageNumber() const
{
int lastVirtualPageNumber = 1;
for( const SCH_SHEET_PATH& sheetPath : *this )
{
if( sheetPath.GetVirtualPageNumber() > lastVirtualPageNumber )
lastVirtualPageNumber = sheetPath.GetVirtualPageNumber();
}
return lastVirtualPageNumber;
}
void SCH_SHEET_LIST::MigrateSimModelNameFields()
{
LOCALE_IO toggle;
@ -1236,8 +1141,8 @@ void SCH_SHEET_LIST::MigrateSimModelNameFields()
{
SCH_SCREEN* screen = at( sheetIndex ).LastScreen();
// V6 schematics may specify model names in Value fields, which we don't do in V7.
// Migrate by adding an equivalent model for these symbols.
// V6 schematics may specify model names in Value fields, which we don't do in V7. Migrate by
// adding an equivalent model for these symbols.
bool mayHaveModelsInValues = false;

View File

@ -265,6 +265,13 @@ public:
*/
KIID_PATH Path() const;
/**
* Get the sheet path as an #KIID_PATH without the root sheet UUID prefix.
*
* @note This #KIID_PATH does not include the root sheet UUID prefixed to the path.
*/
KIID_PATH PathWithoutRootUuid() const;
/**
* Return the sheet path in a human readable form made from the sheet names.
*
@ -366,23 +373,6 @@ public:
*/
void MakeFilePathRelativeToParentSheet();
/**
* Attempt to add new symbol instances for all symbols in this sheet path prefixed
* with \a aPrefixSheetPath.
*
* The new symbol instance data will be assigned by the following criteria:
* - If the instance data can be found for this sheet path, use the instance data.
* - If the instance data cannot be found for this sheet path and the instance data cache
* for the symbol is not empty, use the first instance data in the cache.
* - If the cache is empty and the library symbol link is valid, set the instance data
* from the library symbol.
* - If all else fails, set the reference to "U?", the unit to 1, and everything else to
* an empty string.
*/
void AddNewSymbolInstances( const SCH_SHEET_PATH& aPrefixSheetPath );
int AddNewSheetInstances( const SCH_SHEET_PATH& aPrefixSheetPath, int aNextVirtualPageNumber );
bool operator==( const SCH_SHEET_PATH& d1 ) const;
bool operator!=( const SCH_SHEET_PATH& d1 ) const { return !( *this == d1 ) ; }
@ -644,19 +634,6 @@ public:
*/
void MigrateSimModelNameFields();
/**
* Attempt to add new symbol instances for all symbols in this list of sheet paths prefixed
* with \a aPrefixSheetPath.
*
* @param aPrefixSheetPath is the sheet path to append the new symbol instances to.
*/
void AddNewSymbolInstances( const SCH_SHEET_PATH& aPrefixSheetPath );
void AddNewSheetInstances( const SCH_SHEET_PATH& aPrefixSheetPath,
int aLastVirtualPageNumber );
int GetLastVirtualPageNumber() const;
private:
SCH_SHEET_PATH m_currentSheetPath;
};

View File

@ -472,22 +472,6 @@ void SCH_SYMBOL::Print( const RENDER_SETTINGS* aSettings, const VECTOR2I& aOffse
}
bool SCH_SYMBOL::GetInstance( SYMBOL_INSTANCE_REFERENCE& aInstance,
const KIID_PATH& aSheetPath ) const
{
for( const SYMBOL_INSTANCE_REFERENCE& instance : m_instanceReferences )
{
if( instance.m_Path == aSheetPath )
{
aInstance = instance;
return true;
}
}
return false;
}
void SCH_SYMBOL::AddHierarchicalReference( const KIID_PATH& aPath, const wxString& aRef,
int aUnit, const wxString& aValue,
const wxString& aFootprint )
@ -517,81 +501,15 @@ void SCH_SYMBOL::AddHierarchicalReference( const KIID_PATH& aPath, const wxStrin
instance.m_Value = aValue;
instance.m_Footprint = aFootprint;
wxLogTrace( traceSchSheetPaths,
"Adding symbol '%s' instance:\n"
" sheet path '%s'\n"
" reference '%s'\n"
" unit %d\n"
" value '%s'\n"
" footprint '%s'",
m_Uuid.AsString(),
aPath.AsString(),
aRef,
aUnit,
aValue,
aFootprint );
wxLogTrace( traceSchSheetPaths, "Adding symbol instance:\n"
" sheet path %s\n"
" reference %s, unit %d to symbol %s.",
aPath.AsString(),
aRef,
aUnit,
m_Uuid.AsString() );
m_instanceReferences.push_back( instance );
// This should set the default instance to the first saved instance data for each symbol
// when importing sheets.
if( m_instanceReferences.size() == 1 )
{
m_fields[ REFERENCE_FIELD ].SetText( aRef );
m_fields[ VALUE_FIELD ].SetText( aValue );
m_unit = aUnit;
m_fields[ FOOTPRINT_FIELD ].SetText( aFootprint );
}
}
void SCH_SYMBOL::AddHierarchicalReference( const SYMBOL_INSTANCE_REFERENCE& aInstance )
{
// Search for an existing path and remove it if found (should not occur)
for( unsigned ii = 0; ii < m_instanceReferences.size(); ii++ )
{
if( m_instanceReferences[ii].m_Path == aInstance.m_Path )
{
wxLogTrace( traceSchSheetPaths, "Removing symbol instance:\n"
" sheet path %s\n"
" reference %s, unit %d from symbol %s.",
aInstance.m_Path.AsString(),
m_instanceReferences[ii].m_Reference,
m_instanceReferences[ii].m_Unit,
m_Uuid.AsString() );
m_instanceReferences.erase( m_instanceReferences.begin() + ii );
ii--;
}
}
SYMBOL_INSTANCE_REFERENCE instance = aInstance;
wxLogTrace( traceSchSheetPaths,
"Adding symbol '%s' instance:\n"
" sheet path '%s'\n"
" reference '%s'\n"
" unit %d\n"
" value '%s'\n"
" footprint '%s'",
m_Uuid.AsString(),
instance.m_Path.AsString(),
instance.m_Reference,
instance.m_Unit,
instance.m_Value,
instance.m_Footprint );
m_instanceReferences.push_back( instance );
// This should set the default instance to the first saved instance data for each symbol
// when importing sheets.
if( m_instanceReferences.size() == 1 )
{
m_fields[ REFERENCE_FIELD ].SetText( instance.m_Reference );
m_fields[ VALUE_FIELD ].SetText( instance.m_Value );
m_unit = instance.m_Unit;
m_fields[ FOOTPRINT_FIELD ].SetText( instance.m_Footprint );
}
}
@ -1300,7 +1218,7 @@ void SCH_SYMBOL::ClearAnnotation( const SCH_SHEET_PATH* aSheetPath, bool aResetP
bool SCH_SYMBOL::AddSheetPathReferenceEntryIfMissing( const KIID_PATH& aSheetPath )
{
// An empty sheet path is illegal, at a minimum the root sheet UUID must be present.
// a empty sheet path is illegal:
wxCHECK( aSheetPath.size() > 0, false );
for( const SYMBOL_INSTANCE_REFERENCE& instance : m_instanceReferences )

View File

@ -51,7 +51,6 @@
#include <transform.h>
struct PICKED_SYMBOL;
class KIID_PATH;
class SCH_SCREEN;
class LIB_ITEM;
class LIB_PIN;
@ -141,9 +140,6 @@ public:
return m_instanceReferences;
}
bool GetInstance( SYMBOL_INSTANCE_REFERENCE& aInstance,
const KIID_PATH& aSheetPath ) const;
void SetDefaultInstance( const SYMBOL_INSTANCE_REFERENCE& aInstance )
{
m_defaultInstance = aInstance;
@ -595,8 +591,6 @@ public:
const wxString& aValue = wxEmptyString,
const wxString& aFootprint = wxEmptyString );
void AddHierarchicalReference( const SYMBOL_INSTANCE_REFERENCE& aInstance );
/// Return the instance-specific unit selection for the given sheet path.
int GetUnitSelection( const SCH_SHEET_PATH* aSheet ) const;
@ -719,11 +713,10 @@ public:
void Plot( PLOTTER* aPlotter, bool aBackground ) const override;
/**
* Plot just the symbol pins. This is separated to match the GAL display order. The pins
* are ALSO plotted with the symbol group. This replotting allows us to ensure that they
* are shown above other elements in the schematic.
*
* @param aPlotter is the #PLOTTER object used to plot pins.
* Plot just the symbol pins. This is separated to match the GAL display order. The pins are
* ALSO plotted with the symbol group. This replotting allows us to ensure that they are shown above
* other elements in the schematic
* @param aPlotter
*/
void PlotPins( PLOTTER* aPlotter ) const;

View File

@ -51,7 +51,6 @@ id
image
input
input_low
instances
inverted
inverted_clock
in_bom

View File

@ -182,29 +182,12 @@ bool SCH_EDIT_FRAME::LoadSheetFromFile( SCH_SHEET* aSheet, SCH_SHEET_PATH* aHier
if( wxFileName::GetPathSeparator() == '\\' )
topLevelSheetPath.Replace( "\\", "/" );
// Update the paths to the loaded sheets.
std::vector< SCH_ITEM* > sheetsInLoadedSchematic;
newSheet->GetScreen()->GetSheets( &sheetsInLoadedSchematic );
for( SCH_ITEM* item : sheetsInLoadedSchematic )
{
SCH_SHEET* sheet = static_cast< SCH_SHEET* >( item );
wxCHECK2( sheet, continue );
wxFileName loadedSheetFileName = sheet->GetFileName();
wxString newSheetFilePath = topLevelSheetPath + loadedSheetFileName.GetFullName();
sheet->SetFileName( newSheetFilePath );
}
}
SCH_SHEET_LIST sheetHierarchy( newSheet.get() ); // This is the hierarchy of the loaded file.
SCH_SHEET_LIST hierarchy = Schematic().GetSheets(); // This is the schematic sheet hierarchy.
// Make sure any new sheet changes do not cause any recursion issues.
SCH_SHEET_LIST hierarchy = Schematic().GetSheets(); // This is the schematic sheet hierarchy.
SCH_SHEET_LIST sheetHierarchy( newSheet.get() ); // This is the hierarchy of the loaded file.
if( CheckSheetForRecursion( newSheet.get(), aHierarchy )
|| checkForNoFullyDefinedLibIds( newSheet.get() ) )
{
@ -223,29 +206,6 @@ bool SCH_EDIT_FRAME::LoadSheetFromFile( SCH_SHEET* aSheet, SCH_SHEET_PATH* aHier
wxMessageDialog::ButtonLabel okButtonLabel( _( "Continue Load" ) );
wxMessageDialog::ButtonLabel cancelButtonLabel( _( "Cancel Load" ) );
// Prior to schematic file format 20220919, all symbol instance data was saved in the root
// sheet so loading a hierarchical sheet that is not the root sheet will have no symbol
// instance data. Give the user a chance to go back and save the project that contains this
// hierarchical sheet so the symbol instance data will be correct on load.
if( ( newSheet->GetScreen()->GetFileFormatVersionAtLoad() < 20220919 )
&& newSheet->GetScreen()->GetSymbolInstances().empty() )
{
msg = _( "There hierarchical sheets in the loaded schematic file from an older "
"file version resulting in missing symbol instance data. This will "
"result in all of the symbols in the loaded schematic to use either the "
"default instance setting or fall back to the library symbol settings. "
"Loading the project that uses this schematic file and saving to the "
"lastest file version will resolve this issue.\n\n"
"Do you wish to continue?" );
wxMessageDialog msgDlg7( this, msg, _( "Continue Load Schematic" ),
wxOK | wxCANCEL | wxCANCEL_DEFAULT |
wxCENTER | wxICON_QUESTION );
msgDlg7.SetOKCancelLabels( okButtonLabel, cancelButtonLabel );
if( msgDlg7.ShowModal() == wxID_CANCEL )
return false;
}
if( !prjScreens.HasSchematic( fullFilename ) )
{
if( fileName.GetPathWithSep() == Prj().GetProjectPath() )
@ -485,29 +445,6 @@ bool SCH_EDIT_FRAME::LoadSheetFromFile( SCH_SHEET* aSheet, SCH_SHEET_PATH* aHier
SYMBOL_LIB_TABLE::GetSymbolLibTableFileName() );
}
// Make the best attempt to set the symbol instance data for the loaded scheamtic.
if( newScreen->GetFileFormatVersionAtLoad() < 20220919 )
{
if( !newScreen->GetSymbolInstances().empty() )
{
// If the loaded schematic is a root sheet for another project, update the symbol
// instances.
sheetHierarchy.UpdateSymbolInstances( newScreen->GetSymbolInstances() );
}
else
{
// Otherwise, fall back to the default instance data which still exists in this
// schematic file version.
newScreens.SetAllSymbolDefaultInstances();
}
}
// Attempt to create new symbol instances using the instance data loaded above.
sheetHierarchy.AddNewSymbolInstances( *aHierarchy );
// Add new sheet instance data.
sheetHierarchy.AddNewSheetInstances( *aHierarchy, hierarchy.GetLastVirtualPageNumber() );
// It is finally safe to add or append the imported schematic.
if( aSheet->GetScreen() == nullptr )
aSheet->SetScreen( newScreen );