Stage/add/delete group members when adding/deleting group.

Fixes https://gitlab.com/kicad/code/kicad/-/issues/16540
This commit is contained in:
Jeff Young 2024-01-07 12:57:22 +00:00
parent f795e40584
commit cd83dfa831
5 changed files with 59 additions and 33 deletions

View File

@ -173,12 +173,19 @@ void ARRAY_CREATOR::Invoke()
this_item->ClearSelected(); this_item->ClearSelected();
this_item->RunOnDescendants( this_item->RunOnDescendants(
[&]( BOARD_ITEM* aItem ) []( BOARD_ITEM* aItem )
{ {
aItem->ClearSelected(); aItem->ClearSelected();
}); } );
TransformItem( *array_opts, ptN, *this_item ); TransformItem( *array_opts, ptN, *this_item );
this_item->RunOnDescendants(
[&]( BOARD_ITEM* aItem )
{
commit.Add( aItem );
} );
commit.Add( this_item ); commit.Add( this_item );
} }
} }

View File

@ -2210,8 +2210,23 @@ BOARD_ITEM* FOOTPRINT::DuplicateItem( const BOARD_ITEM* aItem, bool aAddToFootpr
} }
case PCB_GROUP_T: case PCB_GROUP_T:
new_item = static_cast<const PCB_GROUP*>( aItem )->DeepDuplicate(); {
PCB_GROUP* group = static_cast<const PCB_GROUP*>( aItem )->DeepDuplicate();
if( aAddToFootprint )
{
group->RunOnDescendants(
[&]( BOARD_ITEM* aItem )
{
Add( aItem );
} );
Add( new_item );
}
new_item = group;
break; break;
}
case PCB_FOOTPRINT_T: case PCB_FOOTPRINT_T:
// Ignore the footprint itself // Ignore the footprint itself

View File

@ -2135,8 +2135,17 @@ void EDIT_TOOL::DeleteItems( const PCB_SELECTION& aItems, bool aIsCut )
break; break;
case PCB_GROUP_T: case PCB_GROUP_T:
for( BOARD_ITEM* member : static_cast<PCB_GROUP*>( board_item )->GetItems() ) board_item->RunOnDescendants(
commit.Stage( member, CHT_UNGROUP ); [&commit]( BOARD_ITEM* aItem )
{
commit.Stage( aItem, CHT_UNGROUP );
} );
board_item->RunOnDescendants(
[&commit]( BOARD_ITEM* aItem )
{
commit.Remove( aItem );
} );
commit.Remove( board_item ); commit.Remove( board_item );
break; break;
@ -2409,20 +2418,6 @@ int EDIT_TOOL::Duplicate( const TOOL_EVENT& aEvent )
sTool->FilterCollectorForFreePads( aCollector, true ); sTool->FilterCollectorForFreePads( aCollector, true );
sTool->FilterCollectorForMarkers( aCollector ); sTool->FilterCollectorForMarkers( aCollector );
sTool->FilterCollectorForHierarchy( aCollector, true ); sTool->FilterCollectorForHierarchy( aCollector, true );
// Iterate from the back so we don't have to worry about removals.
for( int i = aCollector.GetCount() - 1; i >= 0; --i )
{
BOARD_ITEM* item = aCollector[i];
if( item->Type() == PCB_GENERATOR_T )
{
// Could you duplicate something like a generated stitching pattern?
// Dunno. But duplicating a tuning pattern is a sure crash.
//
aCollector.Remove( item );
}
}
} ); } );
if( selection.Empty() ) if( selection.Empty() )
@ -2475,7 +2470,6 @@ int EDIT_TOOL::Duplicate( const TOOL_EVENT& aEvent )
case PCB_TEXT_T: case PCB_TEXT_T:
case PCB_TEXTBOX_T: case PCB_TEXTBOX_T:
case PCB_REFERENCE_IMAGE_T: case PCB_REFERENCE_IMAGE_T:
case PCB_GENERATOR_T:
case PCB_SHAPE_T: case PCB_SHAPE_T:
case PCB_TRACE_T: case PCB_TRACE_T:
case PCB_ARC_T: case PCB_ARC_T:
@ -2488,10 +2482,30 @@ int EDIT_TOOL::Duplicate( const TOOL_EVENT& aEvent )
case PCB_DIM_ORTHOGONAL_T: case PCB_DIM_ORTHOGONAL_T:
case PCB_DIM_LEADER_T: case PCB_DIM_LEADER_T:
dupe_item = orig_item->Duplicate(); dupe_item = orig_item->Duplicate();
// Clear the selection flag here, otherwise the PCB_SELECTION_TOOL
// will not properly select it later on
dupe_item->ClearSelected();
new_items.push_back( dupe_item );
commit.Add( dupe_item );
break; break;
case PCB_GENERATOR_T:
case PCB_GROUP_T: case PCB_GROUP_T:
dupe_item = static_cast<PCB_GROUP*>( orig_item )->DeepDuplicate(); dupe_item = static_cast<PCB_GROUP*>( orig_item )->DeepDuplicate();
dupe_item->RunOnDescendants(
[&]( BOARD_ITEM* aItem )
{
aItem->ClearSelected();
new_items.push_back( aItem );
commit.Add( aItem );
} );
dupe_item->ClearSelected();
new_items.push_back( dupe_item );
commit.Add( dupe_item );
break; break;
default: default:
@ -2500,16 +2514,6 @@ int EDIT_TOOL::Duplicate( const TOOL_EVENT& aEvent )
break; break;
} }
} }
if( dupe_item )
{
// Clear the selection flag here, otherwise the PCB_SELECTION_TOOL
// will not properly select it later on
dupe_item->ClearSelected();
new_items.push_back( dupe_item );
commit.Add( dupe_item );
}
} }
// Clear the old selection first // Clear the old selection first

View File

@ -142,12 +142,12 @@ public:
*/ */
int Remove( const TOOL_EVENT& aEvent ); int Remove( const TOOL_EVENT& aEvent );
void DeleteItems( const PCB_SELECTION& aItems, bool aIsCut ); void DeleteItems( const PCB_SELECTION& aItem, bool aIsCut );
/** /**
* Duplicate the current selection and starts a move action. * Duplicate the current selection and starts a move action.
*/ */
int Duplicate( const TOOL_EVENT& aEvent ); int Duplicate( const TOOL_EVENT& aItem );
/** /**
* Invoke a dialog box to allow moving of the item by an exact amount. * Invoke a dialog box to allow moving of the item by an exact amount.

View File

@ -1204,7 +1204,7 @@ bool PCB_CONTROL::placeBoardItems( BOARD_COMMIT* aCommit, std::vector<BOARD_ITEM
if( aReannotateDuplicates && m_isBoardEditor ) if( aReannotateDuplicates && m_isBoardEditor )
m_toolMgr->GetTool<BOARD_REANNOTATE_TOOL>()->ReannotateDuplicatesInSelection(); m_toolMgr->GetTool<BOARD_REANNOTATE_TOOL>()->ReannotateDuplicatesInSelection();
for( BOARD_ITEM* item : itemsToSel ) for( BOARD_ITEM* item : aItems )
{ {
if( aIsNew ) if( aIsNew )
aCommit->Add( item ); aCommit->Add( item );