From 6d0a8cd346d7b9e225d8df4c522daebed5169fde Mon Sep 17 00:00:00 2001 From: Mike Williams <mike@mikebwilliams.com> Date: Mon, 24 Mar 2025 10:21:27 -0400 Subject: [PATCH] pcb design blocks: fix net code mismatch when saving selection --- pcbnew/pcb_design_block_utils.cpp | 187 ++++++++++++------------------ pcbnew/pcb_edit_frame.h | 4 + 2 files changed, 81 insertions(+), 110 deletions(-) diff --git a/pcbnew/pcb_design_block_utils.cpp b/pcbnew/pcb_design_block_utils.cpp index 8499cf8740..22f1db90d4 100644 --- a/pcbnew/pcb_design_block_utils.cpp +++ b/pcbnew/pcb_design_block_utils.cpp @@ -26,6 +26,8 @@ #include <board_commit.h> #include <design_block.h> #include <design_block_lib_table.h> +#include <footprint.h> +#include <pad.h> #include <widgets/pcb_design_block_pane.h> #include <pcb_edit_frame.h> #include <pcb_io/pcb_io.h> @@ -236,6 +238,78 @@ bool PCB_EDIT_FRAME::SaveBoardToDesignBlock( const LIB_ID& aLibId ) } +bool PCB_EDIT_FRAME::saveSelectionToDesignBlock( const wxString& aNickname, PCB_SELECTION& aSelection, + DESIGN_BLOCK& aBlock ) +{ + // Create a temporary board + BOARD* tempBoard = new BOARD(); + tempBoard->SetDesignSettings( GetBoard()->GetDesignSettings() ); + tempBoard->SetProject( &Prj(), true ); + tempBoard->SynchronizeProperties(); + + // For copying net info of selected items into the new board + auto addNetIfNeeded = + [&]( EDA_ITEM* aItem ) + { + BOARD_CONNECTED_ITEM* cItem = dynamic_cast<BOARD_CONNECTED_ITEM*>( aItem ); + + if( cItem && cItem->GetNetCode() ) + { + NETINFO_ITEM* netinfo = cItem->GetNet(); + + if( netinfo && !tempBoard->FindNet( netinfo->GetNetname() ) ) + tempBoard->Add( netinfo ); + } + }; + + // Copy the selected items to the temporary board + for( EDA_ITEM* item : aSelection ) + { + EDA_ITEM* copy = item->Clone(); + tempBoard->Add( static_cast<BOARD_ITEM*>( copy ), ADD_MODE::APPEND, false ); + + if( FOOTPRINT* fp = dynamic_cast<FOOTPRINT*>( item ) ) + fp->RunOnChildren( addNetIfNeeded ); + else + addNetIfNeeded( copy ); + } + + // Rebuild connectivity, remove any unused nets + tempBoard->BuildListOfNets(); + tempBoard->BuildConnectivity(); + + wxString tempFile = wxFileName::CreateTempFileName( "design_block" ); + + if( !saveBoardAsFile( tempBoard, tempFile, false ) ) + { + DisplayErrorMessage( this, _( "Error saving temporary board file to create design block." ) ); + wxRemoveFile( tempFile ); + return false; + } + + aBlock.SetBoardFile( tempFile ); + + bool success = false; + + try + { + success = Prj().DesignBlockLibs()->DesignBlockSave( aNickname, &aBlock ) == DESIGN_BLOCK_LIB_TABLE::SAVE_OK; + } + catch( const IO_ERROR& ioe ) + { + DisplayError( this, ioe.What() ); + } + + // Clean up the temporary file + wxRemoveFile( tempFile ); + + m_designBlocksPane->RefreshLibs(); + m_designBlocksPane->SelectLibId( aBlock.GetLibId() ); + + return success; +} + + bool PCB_EDIT_FRAME::SaveSelectionAsDesignBlock( const wxString& aLibraryName ) { // Make sure the user has selected a library to save into @@ -272,67 +346,14 @@ bool PCB_EDIT_FRAME::SaveSelectionAsDesignBlock( const wxString& aLibraryName ) return false; } - // Create a temporary board - BOARD* tempBoard = new BOARD(); - tempBoard->SetDesignSettings( GetBoard()->GetDesignSettings() ); - tempBoard->SetProject( &Prj(), true ); - tempBoard->SynchronizeProperties(); - - // Copy all net info into the new board - for( NETINFO_ITEM* netInfo : GetBoard()->GetNetInfo() ) - { - EDA_ITEM* copy = netInfo->Clone(); - tempBoard->Add( static_cast<BOARD_ITEM*>( copy ), ADD_MODE::APPEND, false ); - } - - // Copy the selected items to the temporary board - for( EDA_ITEM* item : selection ) - { - EDA_ITEM* copy = item->Clone(); - tempBoard->Add( static_cast<BOARD_ITEM*>( copy ), ADD_MODE::APPEND, false ); - } - - // Rebuild connectivity, remove any unused nets - tempBoard->BuildListOfNets(); - tempBoard->BuildConnectivity(); - tempBoard->RemoveUnusedNets( nullptr ); - - wxString tempFile = wxFileName::CreateTempFileName( "design_block" ); - - if( !saveBoardAsFile( tempBoard, tempFile, false ) ) - { - DisplayErrorMessage( this, _( "Error saving temporary board file to create design block." ) ); - wxRemoveFile( tempFile ); - return false; - } - - blk.SetBoardFile( tempFile ); - - bool success = false; - - try - { - success = Prj().DesignBlockLibs()->DesignBlockSave( aLibraryName, &blk ) == DESIGN_BLOCK_LIB_TABLE::SAVE_OK; - } - catch( const IO_ERROR& ioe ) - { - DisplayError( this, ioe.What() ); - } - - // Clean up the temporary file - wxRemoveFile( tempFile ); - - m_designBlocksPane->RefreshLibs(); - m_designBlocksPane->SelectLibId( blk.GetLibId() ); - - return success; + return saveSelectionToDesignBlock( libName, selection, blk ); } bool PCB_EDIT_FRAME::SaveSelectionToDesignBlock( const LIB_ID& aLibId ) { // Make sure the user has selected a library to save into - if( m_designBlocksPane->GetSelectedLibId().GetLibNickname().empty() ) + if( !aLibId.IsValid() ) { DisplayErrorMessage( this, _( "Please select a library to save the design block to." ) ); return false; @@ -364,59 +385,5 @@ bool PCB_EDIT_FRAME::SaveSelectionToDesignBlock( const LIB_ID& aLibId ) return false; } - // Create a temporary board - BOARD* tempBoard = new BOARD(); - tempBoard->SetDesignSettings( GetBoard()->GetDesignSettings() ); - tempBoard->SetProject( &Prj(), true ); - tempBoard->SynchronizeProperties(); - - // Copy all net info into the new board - for( NETINFO_ITEM* netInfo : GetBoard()->GetNetInfo() ) - { - EDA_ITEM* copy = netInfo->Clone(); - tempBoard->Add( static_cast<BOARD_ITEM*>( copy ), ADD_MODE::APPEND, false ); - } - - // Copy the selected items to the temporary board - for( EDA_ITEM* item : selection ) - { - EDA_ITEM* copy = item->Clone(); - tempBoard->Add( static_cast<BOARD_ITEM*>( copy ), ADD_MODE::APPEND, false ); - } - - // Rebuild connectivity, remove any unused nets - tempBoard->BuildListOfNets(); - tempBoard->BuildConnectivity(); - tempBoard->RemoveUnusedNets( nullptr ); - - wxString tempFile = wxFileName::CreateTempFileName( "design_block" ); - - if( !saveBoardAsFile( tempBoard, tempFile, false ) ) - { - DisplayErrorMessage( this, _( "Error saving temporary board file to create design block." ) ); - wxRemoveFile( tempFile ); - return false; - } - - blk->SetBoardFile( tempFile ); - - bool success = false; - - try - { - success = Prj().DesignBlockLibs()->DesignBlockSave( aLibId.GetLibNickname(), blk ) - == DESIGN_BLOCK_LIB_TABLE::SAVE_OK; - } - catch( const IO_ERROR& ioe ) - { - DisplayError( this, ioe.What() ); - } - - // Clean up the temporary file - wxRemoveFile( tempFile ); - - m_designBlocksPane->RefreshLibs(); - m_designBlocksPane->SelectLibId( blk->GetLibId() ); - - return success; + return saveSelectionToDesignBlock( aLibId.GetLibNickname(), selection, *blk ); } diff --git a/pcbnew/pcb_edit_frame.h b/pcbnew/pcb_edit_frame.h index 36c31daf06..626c2ebd9a 100644 --- a/pcbnew/pcb_edit_frame.h +++ b/pcbnew/pcb_edit_frame.h @@ -32,11 +32,13 @@ class PCB_SCREEN; class BOARD; class BOARD_COMMIT; class BOARD_ITEM_CONTAINER; +class DESIGN_BLOCK; class DIALOG_BOOK_REPORTER; class FOOTPRINT; class PCB_TRACK; class PCB_VIA; class PAD; +class PCB_SELECTION; class PCB_TARGET; class PCB_GROUP; class PCB_DIMENSION_BASE; @@ -853,6 +855,8 @@ protected: */ bool saveBoardAsFile( BOARD* aBoard, const wxString& aFileName, bool aHeadless = false ); + bool saveSelectionToDesignBlock( const wxString& aNickname, PCB_SELECTION& aSelection, DESIGN_BLOCK& aBlock ); + bool canCloseWindow( wxCloseEvent& aCloseEvent ) override; void doCloseWindow() override;