handle circular reference on delete

This commit is contained in:
Magnus Lundmark
2025-11-25 07:44:01 +01:00
committed by Jeff Young
parent 2044e2ff43
commit 598beacaf3
4 changed files with 10 additions and 82 deletions
+1 -4
View File
@@ -186,10 +186,7 @@ public:
{
if( cell->GetFlags() & STRUCT_DELETED )
{
fprintf( stderr, "DELETE_ROW: Removing cell UUID=%s from table (commit system will delete)\n",
cell->m_Uuid.AsString().c_str().AsChar() );
// Don't delete here! The commit system handles deletion.
// delete cell;
delete cell;
return true;
}
return false;
+8 -4
View File
@@ -253,10 +253,14 @@ wxString SCH_TABLECELL::GetShownText( const RENDER_SETTINGS* aSettings, const SC
SCH_TABLECELL* targetCell = table->GetCell( targetRow, targetCol );
if( targetCell )
{
// Return the fully evaluated/displayed text from the target cell
// Variables and expressions are evaluated in the target cell's context
// (e.g., ${ROW} in the target cell refers to the target's row, not the referencing cell's row)
// Increment aDepth to prevent infinite recursion in circular references
// Check for excessive recursion depth (circular references)
const int maxDepth = ADVANCED_CFG::GetCfg().m_ResolveTextRecursionDepth;
if( aDepth >= maxDepth )
{
*token = wxT( "<Circular reference>" );
return true;
}
*token = targetCell->GetShownText( aSettings, aPath, aAllowExtraText, aDepth + 1 );
return true;
}
-45
View File
@@ -1746,21 +1746,6 @@ int SCH_EDITOR_CONTROL::Paste( const TOOL_EVENT& aEvent )
if( clipboardTable )
{
// Regenerate UUIDs for the clipboard table and all its cells to avoid duplicates
wxLogDebug( "Regenerating UUIDs for clipboard table %s", clipboardTable->m_Uuid.AsString() );
const_cast<KIID&>( clipboardTable->m_Uuid ) = KIID();
wxLogDebug( " New table UUID: %s", clipboardTable->m_Uuid.AsString() );
clipboardTable->RunOnChildren(
[]( SCH_ITEM* aChild )
{
KIID oldUuid = aChild->m_Uuid;
const_cast<KIID&>( aChild->m_Uuid ) = KIID();
wxLogDebug( " Cell UUID changed from %s to %s",
oldUuid.AsString(), aChild->m_Uuid.AsString() );
},
RECURSE_MODE::RECURSE );
SCH_EDIT_TABLE_TOOL* tableEditTool = m_toolMgr->GetTool<SCH_EDIT_TABLE_TOOL>();
if( tableEditTool )
@@ -1867,18 +1852,10 @@ int SCH_EDITOR_CONTROL::Paste( const TOOL_EVENT& aEvent )
for( SCH_ITEM* item : tempScreen->Items() )
{
fprintf( stderr, "PASTE: Item from clipboard: type=%s, UUID=%s\n",
item->GetTypeDesc().c_str().AsChar(), item->m_Uuid.AsString().c_str().AsChar() );
if( item->Type() == SCH_SHEET_T )
sortedLoadedItems.push_back( item );
else
{
loadedItems.push_back( item );
if( item->Type() == SCH_TABLE_T )
fprintf( stderr, "PASTE: -> TABLE added to loadedItems\n" );
}
}
sort( sortedLoadedItems.begin(), sortedLoadedItems.end(),
@@ -1921,9 +1898,6 @@ int SCH_EDITOR_CONTROL::Paste( const TOOL_EVENT& aEvent )
for( EDA_ITEM* item : loadedItems )
{
fprintf( stderr, "PASTE: Processing loadedItem: type=%s, UUID=%s\n",
item->GetTypeDesc().c_str().AsChar(), item->m_Uuid.AsString().c_str().AsChar() );
KIID_PATH clipPath( wxT( "/" ) ); // clipboard is at root
SCH_ITEM* schItem = static_cast<SCH_ITEM*>( item );
@@ -1935,7 +1909,6 @@ int SCH_EDITOR_CONTROL::Paste( const TOOL_EVENT& aEvent )
if( item->Type() == SCH_SYMBOL_T )
{
wxLogDebug( " -> Taking SYMBOL path" );
SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
// The library symbol gets set from the cached library symbols in the current
@@ -2019,7 +1992,6 @@ int SCH_EDITOR_CONTROL::Paste( const TOOL_EVENT& aEvent )
}
else if( item->Type() == SCH_SHEET_T )
{
wxLogDebug( " -> Taking SHEET path" );
SCH_SHEET* sheet = (SCH_SHEET*) item;
SCH_FIELD* nameField = sheet->GetField( FIELD_T::SHEET_NAME );
wxString baseName = nameField->GetText();
@@ -2104,28 +2076,11 @@ int SCH_EDITOR_CONTROL::Paste( const TOOL_EVENT& aEvent )
}
else
{
fprintf( stderr, "PASTE: -> Taking ELSE path (should be tables, labels, etc.)\n" );
SCH_ITEM* srcItem = dynamic_cast<SCH_ITEM*>( itemMap[item->m_Uuid] );
SCH_ITEM* destItem = dynamic_cast<SCH_ITEM*>( item );
// Everything gets a new KIID
KIID oldUuid = item->m_Uuid;
const_cast<KIID&>( item->m_Uuid ) = KIID();
fprintf( stderr, "PASTE: Changed UUID from %s to %s for %s\n",
oldUuid.AsString().c_str().AsChar(), item->m_Uuid.AsString().c_str().AsChar(),
item->GetTypeDesc().c_str().AsChar() );
destItem->RunOnChildren(
[]( SCH_ITEM* aChild )
{
KIID oldChildUuid = aChild->m_Uuid;
const_cast<KIID&>( aChild->m_Uuid ) = KIID();
fprintf( stderr, "PASTE: Child: Changed UUID from %s to %s for %s\n",
oldChildUuid.AsString().c_str().AsChar(),
aChild->m_Uuid.AsString().c_str().AsChar(),
aChild->GetTypeDesc().c_str().AsChar() );
},
RECURSE_MODE::RECURSE );
if( srcItem && destItem )
{
+1 -29
View File
@@ -360,9 +360,7 @@ protected:
}
else
{
// Don't call commit.Modify(table) - we're removing individual cells
// The table structure changes when cells are removed, which confuses the commit system
// commit.Modify( table, getScreen() );
commit.Modify( table, getScreen() );
VECTOR2I pos = table->GetPosition();
@@ -371,27 +369,9 @@ protected:
for( int row = 0; row < table->GetRowCount(); ++row )
oldRowHeights[row] = table->GetRowHeight( row );
fprintf( stderr, "DELETE_ROW: Before DeleteMarkedCells: rows=%d, cells=%zu\n",
table->GetRowCount(), table->GetCells().size() );
// Tell commit system about each cell being removed BEFORE deleting them
for( T_TABLECELL* cell : table->GetCells() )
{
if( cell->GetFlags() & STRUCT_DELETED )
{
fprintf( stderr, "DELETE_ROW: Calling commit.Remove() for cell UUID=%s\n",
cell->m_Uuid.AsString().c_str().AsChar() );
// commit.Remove() should handle removing from view
commit.Remove( cell, this->getScreen() );
}
}
clearSelection();
table->DeleteMarkedCells();
fprintf( stderr, "DELETE_ROW: After DeleteMarkedCells: rows=%d, cells=%zu\n",
table->GetRowCount(), table->GetCells().size() );
for( int row = 0; row < table->GetRowCount(); ++row )
{
int old_row = row;
@@ -402,29 +382,21 @@ protected:
old_row++;
}
fprintf( stderr, "DELETE_ROW: Remapping row %d -> old_row %d (rowCount=%d)\n",
row, old_row, table->GetRowCount() );
// Use saved old heights instead of querying the modified table
int height = ( oldRowHeights.count( old_row ) ) ? oldRowHeights[old_row] : 0;
table->SetRowHeight( row, height );
}
fprintf( stderr, "DELETE_ROW: Before Normalize\n" );
table->SetPosition( pos );
table->Normalize();
fprintf( stderr, "DELETE_ROW: After Normalize\n" );
fprintf( stderr, "DELETE_ROW: Before PostEvent\n" );
getToolMgr()->PostEvent( EVENTS::SelectedEvent );
fprintf( stderr, "DELETE_ROW: After PostEvent\n" );
}
fprintf( stderr, "DELETE_ROW: Before commit.Push()\n" );
if( deleted.size() > 1 )
commit.Push( _( "Delete Rows" ) );
else
commit.Push( _( "Delete Row" ) );
fprintf( stderr, "DELETE_ROW: After commit.Push()\n" );
return 0;
}