Only delete grouped / generated BOARD_ITEMS from the root item
Fixes https://gitlab.com/kicad/code/kicad/-/issues/17527 This is required as during an undo / redo operation, rebuilding the previous selection can result in a group / generator being selected as well as all of their contained items. This prunes the contained items to remove the possibility of a double-delete.
This commit is contained in:
parent
fd501b4bc8
commit
79a3dd71e4
|
@ -2217,6 +2217,51 @@ int EDIT_TOOL::Flip( const TOOL_EVENT& aEvent )
|
|||
}
|
||||
|
||||
|
||||
void EDIT_TOOL::getChildItemsOfGroupsAndGenerators( EDA_ITEM* item,
|
||||
std::unordered_set<BOARD_ITEM*>& children )
|
||||
{
|
||||
wxASSERT( item->Type() == PCB_GROUP_T || item->Type() == PCB_GENERATOR_T );
|
||||
|
||||
std::unordered_set<BOARD_ITEM*>& childItems = static_cast<PCB_GROUP*>( item )->GetItems();
|
||||
|
||||
for( BOARD_ITEM* childItem : childItems )
|
||||
{
|
||||
children.insert( childItem );
|
||||
|
||||
if( childItem->Type() == PCB_GROUP_T || childItem->Type() == PCB_GENERATOR_T )
|
||||
getChildItemsOfGroupsAndGenerators( childItem, children );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void EDIT_TOOL::removeNonRootItems( std::unordered_set<EDA_ITEM*>& items )
|
||||
{
|
||||
auto itr = items.begin();
|
||||
|
||||
while( itr != items.end() )
|
||||
{
|
||||
BOARD_ITEM* curItem = dynamic_cast<BOARD_ITEM*>( *itr );
|
||||
|
||||
if( curItem )
|
||||
{
|
||||
if( curItem->Type() == PCB_GROUP_T || curItem->Type() == PCB_GENERATOR_T )
|
||||
{
|
||||
std::unordered_set<BOARD_ITEM*> childItems;
|
||||
getChildItemsOfGroupsAndGenerators( curItem, childItems );
|
||||
|
||||
std::for_each( childItems.begin(), childItems.end(),
|
||||
[&]( auto eraseItem )
|
||||
{
|
||||
items.erase( eraseItem );
|
||||
} );
|
||||
}
|
||||
}
|
||||
|
||||
++itr;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void EDIT_TOOL::DeleteItems( const PCB_SELECTION& aItems, bool aIsCut )
|
||||
{
|
||||
BOARD_COMMIT commit( this );
|
||||
|
@ -2224,7 +2269,12 @@ void EDIT_TOOL::DeleteItems( const PCB_SELECTION& aItems, bool aIsCut )
|
|||
// As we are about to remove items, they have to be removed from the selection first
|
||||
m_toolMgr->RunAction( PCB_ACTIONS::selectionClear );
|
||||
|
||||
for( EDA_ITEM* item : aItems )
|
||||
// Only delete items that are the root of a selected set (e.g. only delete grouped / generated
|
||||
// items from the parent item, not individually) - issue #17527
|
||||
std::unordered_set<EDA_ITEM*> rootItems( aItems.begin(), aItems.end() );
|
||||
removeNonRootItems( rootItems );
|
||||
|
||||
for( EDA_ITEM* item : rootItems )
|
||||
{
|
||||
BOARD_ITEM* board_item = dynamic_cast<BOARD_ITEM*>( item );
|
||||
wxCHECK2( board_item, continue );
|
||||
|
@ -2325,7 +2375,7 @@ void EDIT_TOOL::DeleteItems( const PCB_SELECTION& aItems, bool aIsCut )
|
|||
break;
|
||||
|
||||
case PCB_GENERATOR_T:
|
||||
if( aItems.Size() == 1 )
|
||||
if( rootItems.size() == 1 )
|
||||
{
|
||||
PCB_GENERATOR* generator = static_cast<PCB_GENERATOR*>( board_item );
|
||||
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
#include <tools/pcb_tool_base.h>
|
||||
#include <tools/pcb_selection_tool.h>
|
||||
#include <status_popup.h>
|
||||
#include <unordered_set>
|
||||
|
||||
|
||||
class BOARD_COMMIT;
|
||||
|
@ -210,6 +211,15 @@ private:
|
|||
///< Rebuilds the ratsnest for operations that require it outside the commit rebuild
|
||||
void rebuildConnectivity();
|
||||
|
||||
///< Removes all items from the set which are children of other PCB_GROUP or PCB_GENERATOR
|
||||
///< items in the set
|
||||
void removeNonRootItems( std::unordered_set<EDA_ITEM*>& items );
|
||||
|
||||
///< Recursively adds any child items of the given item to the set
|
||||
void getChildItemsOfGroupsAndGenerators( EDA_ITEM* item,
|
||||
std::unordered_set<BOARD_ITEM*>& children );
|
||||
|
||||
|
||||
private:
|
||||
PCB_SELECTION_TOOL* m_selectionTool;
|
||||
bool m_dragging; // Indicates objects are currently being dragged
|
||||
|
|
Loading…
Reference in New Issue