Prune orphaned schematic sheet instances.
Pasting from the clipboard when copying from another project can leave sheet instance information that is not valid for the current project. This change prunes all sheet instance information that is not relevant to the current project. It also prunes invalid paths created by pasting sheets from different paths in the same project.
This commit is contained in:
parent
a452213546
commit
482aff3f0b
|
@ -502,6 +502,7 @@ bool SCH_EDIT_FRAME::OpenProjectFiles( const std::vector<wxString>& aFileSet, in
|
||||||
}
|
}
|
||||||
|
|
||||||
schematic.PruneOrphanedSymbolInstances( Prj().GetProjectName(), Schematic().GetSheets() );
|
schematic.PruneOrphanedSymbolInstances( Prj().GetProjectName(), Schematic().GetSheets() );
|
||||||
|
schematic.PruneOrphanedSheetInstances( Prj().GetProjectName(), Schematic().GetSheets() );
|
||||||
|
|
||||||
Schematic().ConnectionGraph()->Reset();
|
Schematic().ConnectionGraph()->Reset();
|
||||||
|
|
||||||
|
|
|
@ -1684,6 +1684,51 @@ void SCH_SCREEN::PruneOrphanedSymbolInstances( const wxString& aProjectName,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SCH_SCREEN::PruneOrphanedSheetInstances( const wxString& aProjectName,
|
||||||
|
const SCH_SHEET_LIST& aValidSheetPaths )
|
||||||
|
{
|
||||||
|
// The project name cannot be empty. Projects older than 7.0 did not save project names
|
||||||
|
// when saving instance data. Running this algorithm with an empty project name would
|
||||||
|
// clobber all instance data for projects other than the current one when a schematic
|
||||||
|
// file is shared across multiple projects.
|
||||||
|
wxCHECK( !aProjectName.IsEmpty(), /* void */ );
|
||||||
|
|
||||||
|
for( SCH_ITEM* item : Items().OfType( SCH_SHEET_T ) )
|
||||||
|
{
|
||||||
|
SCH_SHEET* sheet = static_cast<SCH_SHEET*>( item );
|
||||||
|
|
||||||
|
wxCHECK2( sheet, continue );
|
||||||
|
|
||||||
|
std::set<KIID_PATH> pathsToPrune;
|
||||||
|
const std::vector<SCH_SHEET_INSTANCE> instances = sheet->GetInstances();
|
||||||
|
|
||||||
|
for( const SCH_SHEET_INSTANCE& instance : instances )
|
||||||
|
{
|
||||||
|
// Ignore instance paths from other projects.
|
||||||
|
if( aProjectName != instance.m_ProjectName )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
std::optional<SCH_SHEET_PATH> pathFound =
|
||||||
|
aValidSheetPaths.GetSheetPathByKIIDPath( instance.m_Path );
|
||||||
|
|
||||||
|
// Check for paths that do not exist in the current project and paths that do
|
||||||
|
// not contain the current symbol.
|
||||||
|
if( !pathFound )
|
||||||
|
pathsToPrune.emplace( instance.m_Path );
|
||||||
|
else if( pathFound.value().LastScreen() != this )
|
||||||
|
pathsToPrune.emplace( pathFound.value().Path() );
|
||||||
|
}
|
||||||
|
|
||||||
|
for( const KIID_PATH& sheetPath : pathsToPrune )
|
||||||
|
{
|
||||||
|
wxLogTrace( traceSchSheetPaths, wxS( "Pruning project '%s' sheet instance %s." ),
|
||||||
|
aProjectName, sheetPath.AsString() );
|
||||||
|
sheet->RemoveInstance( sheetPath );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#if defined(DEBUG)
|
#if defined(DEBUG)
|
||||||
void SCH_SCREEN::Show( int nestLevel, std::ostream& os ) const
|
void SCH_SCREEN::Show( int nestLevel, std::ostream& os ) const
|
||||||
{
|
{
|
||||||
|
@ -2110,7 +2155,6 @@ void SCH_SCREEN::MigrateSimModels()
|
||||||
|
|
||||||
|
|
||||||
void SCH_SCREENS::PruneOrphanedSymbolInstances( const wxString& aProjectName,
|
void SCH_SCREENS::PruneOrphanedSymbolInstances( const wxString& aProjectName,
|
||||||
|
|
||||||
const SCH_SHEET_LIST& aValidSheetPaths )
|
const SCH_SHEET_LIST& aValidSheetPaths )
|
||||||
{
|
{
|
||||||
wxCHECK( !aProjectName.IsEmpty(), /* void */ );
|
wxCHECK( !aProjectName.IsEmpty(), /* void */ );
|
||||||
|
@ -2118,3 +2162,13 @@ void SCH_SCREENS::PruneOrphanedSymbolInstances( const wxString& aProjectName,
|
||||||
for( SCH_SCREEN* screen = GetFirst(); screen; screen = GetNext() )
|
for( SCH_SCREEN* screen = GetFirst(); screen; screen = GetNext() )
|
||||||
screen->PruneOrphanedSymbolInstances( aProjectName, aValidSheetPaths );
|
screen->PruneOrphanedSymbolInstances( aProjectName, aValidSheetPaths );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SCH_SCREENS::PruneOrphanedSheetInstances( const wxString& aProjectName,
|
||||||
|
const SCH_SHEET_LIST& aValidSheetPaths )
|
||||||
|
{
|
||||||
|
wxCHECK( !aProjectName.IsEmpty(), /* void */ );
|
||||||
|
|
||||||
|
for( SCH_SCREEN* screen = GetFirst(); screen; screen = GetNext() )
|
||||||
|
screen->PruneOrphanedSheetInstances( aProjectName, aValidSheetPaths );
|
||||||
|
}
|
||||||
|
|
|
@ -566,6 +566,21 @@ public:
|
||||||
void PruneOrphanedSymbolInstances( const wxString& aProjectName,
|
void PruneOrphanedSymbolInstances( const wxString& aProjectName,
|
||||||
const SCH_SHEET_LIST& aValidSheetPaths );
|
const SCH_SHEET_LIST& aValidSheetPaths );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove all invalid sheet instance data in this screen object for the project defined
|
||||||
|
* by \a aProjectName and the list of \a aValidSheetPaths.
|
||||||
|
*
|
||||||
|
* @warning This method will assert and exit on debug builds when \a aProjectName is empty.
|
||||||
|
*
|
||||||
|
* @note This method does not affect instance data for any other projects.
|
||||||
|
*
|
||||||
|
* @param aProjectName is the name of the current project.
|
||||||
|
* @param aValidSheetPaths is the list of valid #SCH_SHEET_PATH objects for the current
|
||||||
|
* project.
|
||||||
|
*/
|
||||||
|
void PruneOrphanedSheetInstances( const wxString& aProjectName,
|
||||||
|
const SCH_SHEET_LIST& aValidSheetPaths );
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend SCH_EDIT_FRAME; // Only to populate m_symbolInstances.
|
friend SCH_EDIT_FRAME; // Only to populate m_symbolInstances.
|
||||||
friend SCH_IO_KICAD_SEXPR_PARSER; // Only to load instance information from schematic file.
|
friend SCH_IO_KICAD_SEXPR_PARSER; // Only to load instance information from schematic file.
|
||||||
|
@ -598,7 +613,8 @@ private:
|
||||||
*/
|
*/
|
||||||
struct BusAliasCmp
|
struct BusAliasCmp
|
||||||
{
|
{
|
||||||
bool operator()( const std::shared_ptr<BUS_ALIAS>& a, const std::shared_ptr<BUS_ALIAS>& b ) const
|
bool operator()( const std::shared_ptr<BUS_ALIAS>& a,
|
||||||
|
const std::shared_ptr<BUS_ALIAS>& b ) const
|
||||||
{
|
{
|
||||||
return a->GetName() < b->GetName();
|
return a->GetName() < b->GetName();
|
||||||
}
|
}
|
||||||
|
@ -823,6 +839,9 @@ public:
|
||||||
void PruneOrphanedSymbolInstances( const wxString& aProjectName,
|
void PruneOrphanedSymbolInstances( const wxString& aProjectName,
|
||||||
const SCH_SHEET_LIST& aValidSheetPaths );
|
const SCH_SHEET_LIST& aValidSheetPaths );
|
||||||
|
|
||||||
|
void PruneOrphanedSheetInstances( const wxString& aProjectName,
|
||||||
|
const SCH_SHEET_LIST& aValidSheetPaths );
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void addScreenToList( SCH_SCREEN* aScreen, SCH_SHEET* aSheet );
|
void addScreenToList( SCH_SCREEN* aScreen, SCH_SHEET* aSheet );
|
||||||
void buildScreenList( SCH_SHEET* aSheet);
|
void buildScreenList( SCH_SHEET* aSheet);
|
||||||
|
|
|
@ -1920,6 +1920,21 @@ int SCH_EDITOR_CONTROL::Paste( const TOOL_EVENT& aEvent )
|
||||||
|
|
||||||
pastedSheet.SetPageNumber( pageNum );
|
pastedSheet.SetPageNumber( pageNum );
|
||||||
hierarchy.push_back( pastedSheet );
|
hierarchy.push_back( pastedSheet );
|
||||||
|
|
||||||
|
// Remove all pasted sheet instance data that is not part of the current project.
|
||||||
|
std::vector<KIID_PATH> instancesToRemove;
|
||||||
|
SCH_SHEET* sheet = pastedSheet.Last();
|
||||||
|
|
||||||
|
wxCHECK2( sheet, continue );
|
||||||
|
|
||||||
|
for( const SCH_SHEET_INSTANCE& instance : sheet->GetInstances() )
|
||||||
|
{
|
||||||
|
if( instance.m_ProjectName != m_frame->Prj().GetProjectName() )
|
||||||
|
instancesToRemove.push_back( instance.m_Path );
|
||||||
|
}
|
||||||
|
|
||||||
|
for( const KIID_PATH& instancePath : instancesToRemove )
|
||||||
|
sheet->RemoveInstance( instancePath );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1975,15 +1990,17 @@ int SCH_EDITOR_CONTROL::Paste( const TOOL_EVENT& aEvent )
|
||||||
|
|
||||||
m_frame->GetCurrentSheet().UpdateAllScreenReferences();
|
m_frame->GetCurrentSheet().UpdateAllScreenReferences();
|
||||||
|
|
||||||
prunePastedSymbolInstances();
|
|
||||||
|
|
||||||
// The copy operation creates instance paths that are not valid for the current project or
|
// The copy operation creates instance paths that are not valid for the current project or
|
||||||
// saved as part of another project. Prune them now so they do not accumulate in the saved
|
// saved as part of another project. Prune them now so they do not accumulate in the saved
|
||||||
// schematic file.
|
// schematic file.
|
||||||
|
prunePastedSymbolInstances();
|
||||||
|
|
||||||
SCH_SCREENS allScreens( m_frame->Schematic().Root() );
|
SCH_SCREENS allScreens( m_frame->Schematic().Root() );
|
||||||
|
|
||||||
allScreens.PruneOrphanedSymbolInstances( m_frame->Prj().GetProjectName(),
|
allScreens.PruneOrphanedSymbolInstances( m_frame->Prj().GetProjectName(),
|
||||||
m_frame->Schematic().GetSheets() );
|
m_frame->Schematic().GetSheets() );
|
||||||
|
allScreens.PruneOrphanedSheetInstances( m_frame->Prj().GetProjectName(),
|
||||||
|
m_frame->Schematic().GetSheets() );
|
||||||
|
|
||||||
// Now clear the previous selection, select the pasted items, and fire up the "move" tool.
|
// Now clear the previous selection, select the pasted items, and fire up the "move" tool.
|
||||||
m_toolMgr->RunAction( EE_ACTIONS::clearSelection );
|
m_toolMgr->RunAction( EE_ACTIONS::clearSelection );
|
||||||
|
|
Loading…
Reference in New Issue