Prune pasted data of non-enabled layers.

Fixes https://gitlab.com/kicad/code/kicad/issues/11997
This commit is contained in:
Jeff Young 2022-09-09 21:01:34 +01:00
parent aeb7447102
commit 5b3bd9be83
3 changed files with 89 additions and 0 deletions

View File

@ -182,6 +182,12 @@ public:
virtual void SetLayerSet( LSET aLayers ) virtual void SetLayerSet( LSET aLayers )
{ {
if( aLayers.count() == 1 )
{
SetLayer( aLayers.Seq()[0] );
return;
}
wxFAIL_MSG( wxT( "Attempted to SetLayerSet() on a single-layer object." ) ); wxFAIL_MSG( wxT( "Attempted to SetLayerSet() on a single-layer object." ) );
// Derived classes which support multiple layers must implement this // Derived classes which support multiple layers must implement this

View File

@ -696,6 +696,77 @@ static void pasteFootprintItemsToFootprintEditor( FOOTPRINT* aClipFootprint, BOA
} }
void PCB_CONTROL::pruneItemLayers( std::vector<BOARD_ITEM*>& aItems )
{
LSET enabledLayers = board()->GetEnabledLayers();
std::vector<BOARD_ITEM*> returnItems;
bool fpItemDeleted = false;
auto processFPItem =
[&]( FOOTPRINT* aFootprint, BOARD_ITEM* aItem )
{
LSET allowed = aItem->GetLayerSet() & enabledLayers;
if( allowed.any() )
{
aItem->SetLayerSet( allowed );
}
else
{
aFootprint->Remove( aItem );
fpItemDeleted = true;
}
};
for( BOARD_ITEM* item : aItems )
{
if( item->Type() == PCB_FOOTPRINT_T )
{
FOOTPRINT* fp = static_cast<FOOTPRINT*>( item );
if( !enabledLayers.test( fp->Reference().GetLayer() ) )
fp->Reference().SetLayer( fp->IsFlipped() ? B_SilkS : F_SilkS );
if( !enabledLayers.test( fp->Value().GetLayer() ) )
fp->Value().SetLayer( fp->IsFlipped() ? B_Fab : F_Fab );
// NOTE: all traversals from the back as processFPItem() might delete the item
for( int ii = static_cast<int>( fp->Pads().size() ) - 1; ii >= 0; ii-- )
processFPItem( fp, fp->Pads()[ii] );
for( int ii = static_cast<int>( fp->Zones().size() ) - 1; ii >= 0; ii-- )
processFPItem( fp, fp->Zones()[ii] );
for( int ii = static_cast<int>( fp->GraphicalItems().size() ) - 1; ii >= 0; ii-- )
processFPItem( fp, fp->GraphicalItems()[ii] );
if( fp->GraphicalItems().size() || fp->Pads().size() || fp->Zones().size() )
returnItems.push_back( fp );
}
else
{
LSET allowed = item->GetLayerSet() & enabledLayers;
if( allowed.any() )
{
item->SetLayerSet( allowed );
returnItems.push_back( item );
}
}
}
if( ( returnItems.size() < aItems.size() ) || fpItemDeleted )
{
DisplayError( m_frame, _( "Warning: some pasted items were on layers which are not "
"present in the current board.\n"
"These items could not be pasted.\n" ) );
}
aItems = returnItems;
}
int PCB_CONTROL::Paste( const TOOL_EVENT& aEvent ) int PCB_CONTROL::Paste( const TOOL_EVENT& aEvent )
{ {
CLIPBOARD_IO pi; CLIPBOARD_IO pi;
@ -803,6 +874,8 @@ int PCB_CONTROL::Paste( const TOOL_EVENT& aEvent )
delete clipBoard; delete clipBoard;
pruneItemLayers( pastedItems );
placeBoardItems( pastedItems, true, true, mode == PASTE_MODE::UNIQUE_ANNOTATIONS ); placeBoardItems( pastedItems, true, true, mode == PASTE_MODE::UNIQUE_ANNOTATIONS );
} }
else else
@ -841,6 +914,8 @@ int PCB_CONTROL::Paste( const TOOL_EVENT& aEvent )
pastedItems.push_back( clipFootprint ); pastedItems.push_back( clipFootprint );
} }
pruneItemLayers( pastedItems );
placeBoardItems( pastedItems, true, true, mode == PASTE_MODE::UNIQUE_ANNOTATIONS ); placeBoardItems( pastedItems, true, true, mode == PASTE_MODE::UNIQUE_ANNOTATIONS );
break; break;
} }
@ -956,6 +1031,8 @@ int PCB_CONTROL::placeBoardItems( BOARD* aBoard, bool aAnchorAtOrigin, bool aRea
// selection created aBoard that has the group and all descendants in it. // selection created aBoard that has the group and all descendants in it.
moveUnflaggedItems( aBoard->Groups(), items, isNew ); moveUnflaggedItems( aBoard->Groups(), items, isNew );
pruneItemLayers( items );
return placeBoardItems( items, isNew, aAnchorAtOrigin, aReannotateDuplicates ); return placeBoardItems( items, isNew, aAnchorAtOrigin, aReannotateDuplicates );
} }

View File

@ -109,6 +109,12 @@ private:
*/ */
void unfilledZoneCheck(); void unfilledZoneCheck();
/**
* Helper for pasting. Remove non-enabled layers from the items in \a aItems. If an item
* exists only on non-enabled layers, it will be removed entirely.
*/
void pruneItemLayers( std::vector<BOARD_ITEM*>& aItems );
/** /**
* Add and select or just select for move/place command a list of board items. * Add and select or just select for move/place command a list of board items.
* *