diff --git a/pcbnew/tools/edit_tool.cpp b/pcbnew/tools/edit_tool.cpp index 12fb28cbc1..9db02f2184 100644 --- a/pcbnew/tools/edit_tool.cpp +++ b/pcbnew/tools/edit_tool.cpp @@ -213,7 +213,7 @@ void EditToolSelectionFilter( GENERAL_COLLECTOR& aCollector, int aFlags ) EDIT_TOOL::EDIT_TOOL() : PCB_TOOL( "pcbnew.InteractiveEdit" ), m_selectionTool( NULL ), - m_dragging( false ) + m_dragging( false ), m_lockedSelected( false ) { } @@ -553,8 +553,10 @@ int EDIT_TOOL::Main( const TOOL_EVENT& aEvent ) { break; // Finish } + } while( ( evt = Wait() ) ); //Should be assignment not equality test + m_lockedSelected = false; controls->ForceCursorPosition( false ); controls->ShowCursor( false ); controls->SetSnapping( false ); @@ -864,26 +866,36 @@ int EDIT_TOOL::Remove( const TOOL_EVENT& aEvent ) if( routerTool && routerTool->Router() && routerTool->Router()->RoutingInProgress() ) return 0; + std::vector lockedItems; + // get a copy instead of reference (as we're going to clear the selection before removing items) auto selectionCopy = m_selectionTool->RequestSelection( []( const VECTOR2I& aPt, GENERAL_COLLECTOR& aCollector ) - { EditToolSelectionFilter( aCollector, EXCLUDE_LOCKED | EXCLUDE_LOCKED_PADS | EXCLUDE_TRANSIENTS ); } ); + { EditToolSelectionFilter( aCollector, EXCLUDE_LOCKED_PADS | EXCLUDE_TRANSIENTS ); } ); - // is this "alternative" remove? + bool isHover = selectionCopy.IsHover(); const bool isAlt = aEvent.Parameter() == (int) PCB_ACTIONS::REMOVE_FLAGS::ALT; // in "alternative" mode, deletion is not just a simple list of selected items, // it removes whole tracks, not just segments - if( isAlt && selectionCopy.IsHover() + if( isAlt && isHover && ( selectionCopy.HasType( PCB_TRACE_T ) || selectionCopy.HasType( PCB_VIA_T ) ) ) { m_toolMgr->RunAction( PCB_ACTIONS::expandSelectedConnection, true ); - selectionCopy = m_selectionTool->GetSelection(); } if( selectionCopy.Empty() ) return 0; + if( !m_lockedSelected ) + { + // Second RequestSelection removes locked items but keeps a copy of their pointers + selectionCopy = m_selectionTool->RequestSelection( + []( const VECTOR2I& aPt, GENERAL_COLLECTOR& aCollector ) + { EditToolSelectionFilter( aCollector, EXCLUDE_LOCKED ); }, &lockedItems ); + } + + // As we are about to remove items, they have to be removed from the selection first m_toolMgr->RunAction( PCB_ACTIONS::selectionClear, true ); @@ -919,6 +931,29 @@ int EDIT_TOOL::Remove( const TOOL_EVENT& aEvent ) m_commit->Push( _( "Delete" ) ); + if( !m_lockedSelected && lockedItems.size() > 0 ) + { + ///> Popup nag for deleting locked items + STATUS_TEXT_POPUP statusPopup( frame() ); + + m_lockedSelected = true; + m_toolMgr->RunAction( PCB_ACTIONS::selectItems, true, &lockedItems ); + statusPopup.SetText( _( "Delete again to remove locked items" ) ); + statusPopup.Expire( 2000 ); + statusPopup.Popup(); + statusPopup.Move( wxGetMousePosition() + wxPoint( 20, 20 ) ); + + Activate(); + + while( m_lockedSelected && statusPopup.IsShown() ) + { + statusPopup.Move( wxGetMousePosition() + wxPoint( 20, 20 ) ); + Wait(); + } + } + + m_lockedSelected = false; + return 0; } diff --git a/pcbnew/tools/edit_tool.h b/pcbnew/tools/edit_tool.h index 7b92887426..e3d4dcbe5d 100644 --- a/pcbnew/tools/edit_tool.h +++ b/pcbnew/tools/edit_tool.h @@ -29,6 +29,7 @@ #include #include #include +#include class BOARD_COMMIT; @@ -48,7 +49,6 @@ class CONNECTIVITY_DATA; void EditToolSelectionFilter( GENERAL_COLLECTOR& aCollector, int aFlags ); - /** * Class EDIT_TOOL * @@ -193,6 +193,9 @@ private: ///> Flag determining if anything is being dragged right now bool m_dragging; + ///> Flag determining whether we are prompting for locked removal + bool m_lockedSelected; + ///> Last cursor position (needed for getModificationPoint() to avoid changes ///> of edit reference point). VECTOR2I m_cursor; diff --git a/pcbnew/tools/selection_tool.cpp b/pcbnew/tools/selection_tool.cpp index bdffafc4a9..8a22fdbb54 100644 --- a/pcbnew/tools/selection_tool.cpp +++ b/pcbnew/tools/selection_tool.cpp @@ -395,7 +395,8 @@ static EDA_RECT getRect( const BOARD_ITEM* aItem ) } -SELECTION& SELECTION_TOOL::RequestSelection( CLIENT_SELECTION_FILTER aClientFilter ) +SELECTION& SELECTION_TOOL::RequestSelection( CLIENT_SELECTION_FILTER aClientFilter, + std::vector* aFiltered ) { bool selectionEmpty = m_selection.Empty(); m_selection.SetIsHover( selectionEmpty ); @@ -429,6 +430,12 @@ SELECTION& SELECTION_TOOL::RequestSelection( CLIENT_SELECTION_FILTER aClientFilt std::set_difference( m_selection.begin(), m_selection.end(), collector.begin(), collector.end(), std::back_inserter( diff ) ); + if( aFiltered ) + { + for( auto item : diff ) + aFiltered->push_back( static_cast( item ) ); + } + /** * Once we find the adjustments to m_selection that are required by the client filter, we * apply them both diff --git a/pcbnew/tools/selection_tool.h b/pcbnew/tools/selection_tool.h index 2ec519c5de..88eaca35fc 100644 --- a/pcbnew/tools/selection_tool.h +++ b/pcbnew/tools/selection_tool.h @@ -93,8 +93,10 @@ public: * Returns the current selection set, filtered according to aFlags * and aClientFilter. * If the set is empty, performs the legacy-style hover selection. + * @param aFiltered is an optional vector, that is filled with items removed by the filter */ - SELECTION& RequestSelection( CLIENT_SELECTION_FILTER aClientFilter ); + SELECTION& RequestSelection( CLIENT_SELECTION_FILTER aClientFilter, + std::vector* aFiltered = NULL ); inline TOOL_MENU& GetToolMenu()