diff --git a/pcbnew/tools/common_actions.cpp b/pcbnew/tools/common_actions.cpp index da2694db59..9a7b45cae8 100644 --- a/pcbnew/tools/common_actions.cpp +++ b/pcbnew/tools/common_actions.cpp @@ -137,6 +137,11 @@ TOOL_ACTION COMMON_ACTIONS::removeAlt( "pcbnew.InteractiveEdit.removeAlt", AS_GLOBAL, TOOL_ACTION::LegacyHotKey( HK_BACK_SPACE ), _( "Remove (alterative)" ), _( "Deletes selected item(s)" ), delete_xpm ); +TOOL_ACTION COMMON_ACTIONS::exchangeFootprints( "pcbnew.InteractiveEdit.ExchangeFootprints", + AS_GLOBAL, 0, + _( "Exchange footprint(s)" ), _( "Change the footprint used for modules" ), + import_module_xpm ); + TOOL_ACTION COMMON_ACTIONS::properties( "pcbnew.InteractiveEdit.properties", AS_GLOBAL, TOOL_ACTION::LegacyHotKey( HK_EDIT_ITEM ), diff --git a/pcbnew/tools/common_actions.h b/pcbnew/tools/common_actions.h index a878520da3..b8167cf3c9 100644 --- a/pcbnew/tools/common_actions.h +++ b/pcbnew/tools/common_actions.h @@ -94,6 +94,9 @@ public: /// Activation of the duplication tool with incrementing (e.g. pad number) static TOOL_ACTION duplicateIncrement; + /// Exchange footprints of modules + static TOOL_ACTION exchangeFootprints; + /// Deleting a BOARD_ITEM static TOOL_ACTION remove; static TOOL_ACTION removeAlt; diff --git a/pcbnew/tools/edit_tool.cpp b/pcbnew/tools/edit_tool.cpp index 4847fc57e1..d2af325680 100644 --- a/pcbnew/tools/edit_tool.cpp +++ b/pcbnew/tools/edit_tool.cpp @@ -56,6 +56,7 @@ using namespace std::placeholders; #include #include +#include #include @@ -90,6 +91,9 @@ bool EDIT_TOOL::Init() return m_editModules; }; + auto singleModuleCondition = SELECTION_CONDITIONS::OnlyType( PCB_MODULE_T ) + && SELECTION_CONDITIONS::Count( 1 ); + // Add context menu entries that are displayed when selection tool is active CONDITIONAL_MENU& menu = m_selectionTool->GetToolMenu().GetMenu(); menu.AddItem( COMMON_ACTIONS::editActivate, SELECTION_CONDITIONS::NotEmpty ); @@ -107,8 +111,9 @@ bool EDIT_TOOL::Init() // Footprint actions menu.AddItem( COMMON_ACTIONS::editFootprintInFpEditor, - SELECTION_CONDITIONS::OnlyType( PCB_MODULE_T ) && - SELECTION_CONDITIONS::Count( 1 ) ); + singleModuleCondition ); + menu.AddItem( COMMON_ACTIONS::exchangeFootprints, + singleModuleCondition ); m_offset.x = 0; m_offset.y = 0; @@ -776,6 +781,38 @@ int EDIT_TOOL::CreateArray( const TOOL_EVENT& aEvent ) } +int EDIT_TOOL::ExchangeFootprints( const TOOL_EVENT& aEvent ) +{ + if( !hoverSelection() ) + return 0; + + MODULE* mod = uniqueSelected(); + + if( !mod ) + return 0; + + auto& editFrame = *getEditFrame(); + + editFrame.SetCurItem( mod ); + + // Footprint exchange could remove modules, so they have to be + // removed from the selection first + m_toolMgr->RunAction( COMMON_ACTIONS::selectionClear, true ); + + // invoke the exchange dialog process + { + DIALOG_EXCHANGE_MODULE dialog( &editFrame, mod ); + dialog.ShowQuasiModal(); + } + + // The current item can be deleted by exchange module, and the + // selection is emptied, so remove current item from frame info area + editFrame.SetCurItem( nullptr ); + + return 0; +} + + void EDIT_TOOL::SetTransitions() { Go( &EDIT_TOOL::Main, COMMON_ACTIONS::editActivate.MakeEvent() ); @@ -789,6 +826,7 @@ void EDIT_TOOL::SetTransitions() Go( &EDIT_TOOL::CreateArray,COMMON_ACTIONS::createArray.MakeEvent() ); Go( &EDIT_TOOL::Mirror, COMMON_ACTIONS::mirror.MakeEvent() ); Go( &EDIT_TOOL::editFootprintInFpEditor, COMMON_ACTIONS::editFootprintInFpEditor.MakeEvent() ); + Go( &EDIT_TOOL::ExchangeFootprints, COMMON_ACTIONS::exchangeFootprints.MakeEvent() ); } diff --git a/pcbnew/tools/edit_tool.h b/pcbnew/tools/edit_tool.h index 260cdeab9b..52310d1868 100644 --- a/pcbnew/tools/edit_tool.h +++ b/pcbnew/tools/edit_tool.h @@ -116,6 +116,13 @@ public: */ int CreateArray( const TOOL_EVENT& aEvent ); + /** + * Function ExchangeFootprints() + * + * Invoke the dialog used to change the footprints used for modules + * and update module footprints based on result + */ + int ExchangeFootprints( const TOOL_EVENT& aEvent ); ///> Sets up handlers for various events. void SetTransitions() override;