diff --git a/eeschema/sch_table.h b/eeschema/sch_table.h index df2b65247a..747e168f58 100644 --- a/eeschema/sch_table.h +++ b/eeschema/sch_table.h @@ -186,7 +186,10 @@ public: { if( cell->GetFlags() & STRUCT_DELETED ) { - delete cell; + 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; return true; } return false; diff --git a/eeschema/tools/sch_editor_control.cpp b/eeschema/tools/sch_editor_control.cpp index d9f406fdad..849a9a3765 100644 --- a/eeschema/tools/sch_editor_control.cpp +++ b/eeschema/tools/sch_editor_control.cpp @@ -1746,6 +1746,21 @@ 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( 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( 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(); if( tableEditTool ) @@ -1852,10 +1867,18 @@ 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(), @@ -1898,6 +1921,9 @@ 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( item ); @@ -1909,6 +1935,7 @@ int SCH_EDITOR_CONTROL::Paste( const TOOL_EVENT& aEvent ) if( item->Type() == SCH_SYMBOL_T ) { + wxLogDebug( " -> Taking SYMBOL path" ); SCH_SYMBOL* symbol = static_cast( item ); // The library symbol gets set from the cached library symbols in the current @@ -1992,11 +2019,12 @@ int SCH_EDITOR_CONTROL::Paste( const TOOL_EVENT& aEvent ) } else if( item->Type() == SCH_SHEET_T ) { - SCH_SHEET* sheet = (SCH_SHEET*) item; - SCH_FIELD* nameField = sheet->GetField( FIELD_T::SHEET_NAME ); - wxString baseName = nameField->GetText(); - wxString candidateName = baseName; - wxString number; + wxLogDebug( " -> Taking SHEET path" ); + SCH_SHEET* sheet = (SCH_SHEET*) item; + SCH_FIELD* nameField = sheet->GetField( FIELD_T::SHEET_NAME ); + wxString baseName = nameField->GetText(); + wxString candidateName = baseName; + wxString number; while( !baseName.IsEmpty() && wxIsdigit( baseName.Last() ) ) { @@ -2076,11 +2104,28 @@ 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( itemMap[item->m_Uuid] ); SCH_ITEM* destItem = dynamic_cast( item ); // Everything gets a new KIID + KIID oldUuid = item->m_Uuid; const_cast( 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( 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 ) { diff --git a/include/tool/edit_table_tool_base.h b/include/tool/edit_table_tool_base.h index 9532ba82ee..03e54f37fe 100644 --- a/include/tool/edit_table_tool_base.h +++ b/include/tool/edit_table_tool_base.h @@ -360,13 +360,38 @@ protected: } else { - commit.Modify( table, getScreen() ); + // 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() ); VECTOR2I pos = table->GetPosition(); + // Save old row heights BEFORE deleting cells + std::map oldRowHeights; + 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; @@ -377,19 +402,29 @@ protected: old_row++; } - table->SetRowHeight( row, table->GetRowHeight( 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; }