Layers setup management: Warn user if some removed layers are in use in footprints loaded on the board.
Fix also memory leak and missing connectivity rebuild.
This commit is contained in:
parent
602d9e1972
commit
78161b5922
|
@ -2,7 +2,7 @@
|
|||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2007-2008 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
|
||||
* Copyright (C) 2004-2017 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 2004-2018 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
|
@ -499,7 +499,12 @@ SEARCH_RESULT PCB_LAYER_COLLECTOR::Inspect( EDA_ITEM* testItem, void* testData )
|
|||
{
|
||||
BOARD_ITEM* item = (BOARD_ITEM*) testItem;
|
||||
|
||||
if( item->GetLayer() == m_layer_id )
|
||||
if( item->Type() == PCB_PAD_T ) // multilayer
|
||||
{
|
||||
if( static_cast<D_PAD*>( item )->IsOnLayer( m_layer_id ) )
|
||||
Append( testItem );
|
||||
}
|
||||
else if( item->GetLayer() == m_layer_id )
|
||||
Append( testItem );
|
||||
|
||||
return SEARCH_CONTINUE;
|
||||
|
|
|
@ -29,6 +29,9 @@
|
|||
|
||||
#include <confirm.h>
|
||||
#include <pcbnew.h>
|
||||
#include <pcb_edit_frame.h>
|
||||
#include <view/view.h>
|
||||
|
||||
#include <invoke_pcb_dialog.h>
|
||||
|
||||
#include <class_board.h>
|
||||
|
@ -43,11 +46,6 @@
|
|||
// if not displays always 1=the full set (32 copper layers)
|
||||
#define HIDE_INACTIVE_LAYERS
|
||||
|
||||
// if defined, use the layer manager copper layers order (from FRONT to BACK)
|
||||
// to display inner layers.
|
||||
// if not, use the default order (from BACK to FRONT)
|
||||
#define USE_LAYER_MANAGER_COPPER_LAYERS_ORDER
|
||||
|
||||
|
||||
/**
|
||||
* Holds the 3 UI control pointers for a single board layer.
|
||||
|
@ -138,7 +136,7 @@ static LSEQ dlg_layers()
|
|||
class DIALOG_LAYERS_SETUP : public DIALOG_LAYERS_SETUP_BASE
|
||||
{
|
||||
public:
|
||||
DIALOG_LAYERS_SETUP( wxTopLevelWindow* aCaller, BOARD* aBoard );
|
||||
DIALOG_LAYERS_SETUP( PCB_EDIT_FRAME* aCaller, BOARD* aBoard );
|
||||
|
||||
private:
|
||||
int m_copperLayerCount;
|
||||
|
@ -152,6 +150,8 @@ private:
|
|||
|
||||
void setLayerCheckBox( LAYER_NUM layer, bool isChecked );
|
||||
void setCopperLayerCheckBoxes( int copperCount );
|
||||
// Force mandatory non copper layers enabled
|
||||
void enableMandatoryLayerCheckBoxes();
|
||||
|
||||
void showCopperChoice( int copperCount );
|
||||
void showBoardLayerNames();
|
||||
|
@ -179,6 +179,11 @@ private:
|
|||
*/
|
||||
LSEQ getRemovedLayersWithItems();
|
||||
|
||||
/**
|
||||
* Return a list of layers in use in footprints, and therefore not removable.
|
||||
*/
|
||||
LSEQ getNonRemovableLayers();
|
||||
|
||||
/**
|
||||
* Map \a aLayerNumber to the wx IDs for that layer which are
|
||||
* the layer name control ID, checkbox control ID, and choice control ID
|
||||
|
@ -323,7 +328,7 @@ CTLs DIALOG_LAYERS_SETUP::getCTLs( LAYER_NUM aLayerNumber )
|
|||
}
|
||||
|
||||
|
||||
DIALOG_LAYERS_SETUP::DIALOG_LAYERS_SETUP( wxTopLevelWindow* aParent, BOARD* aBoard ) :
|
||||
DIALOG_LAYERS_SETUP::DIALOG_LAYERS_SETUP( PCB_EDIT_FRAME* aParent, BOARD* aBoard ) :
|
||||
DIALOG_LAYERS_SETUP_BASE( aParent )
|
||||
{
|
||||
m_pcb = aBoard;
|
||||
|
@ -382,6 +387,7 @@ bool DIALOG_LAYERS_SETUP::TransferDataToWindow()
|
|||
showSelectedLayerCheckBoxes( m_enabledLayers );
|
||||
showPresets( m_enabledLayers );
|
||||
showLayerTypes();
|
||||
enableMandatoryLayerCheckBoxes();
|
||||
|
||||
// All widgets are now initialized. Fix the min sizes:
|
||||
GetSizer()->SetSizeHints( this );
|
||||
|
@ -390,10 +396,23 @@ bool DIALOG_LAYERS_SETUP::TransferDataToWindow()
|
|||
}
|
||||
|
||||
|
||||
void DIALOG_LAYERS_SETUP::enableMandatoryLayerCheckBoxes()
|
||||
{
|
||||
// Currently, do nothing
|
||||
#if 0
|
||||
setLayerCheckBox( F_CrtYd, true );
|
||||
setLayerCheckBox( B_CrtYd, true );
|
||||
setLayerCheckBox( Edge_Cuts, true );
|
||||
setLayerCheckBox( Margin, true );
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void DIALOG_LAYERS_SETUP::OnSize( wxSizeEvent& event )
|
||||
{
|
||||
moveTitles();
|
||||
event.Skip();
|
||||
Refresh();
|
||||
}
|
||||
|
||||
|
||||
|
@ -634,14 +653,31 @@ bool DIALOG_LAYERS_SETUP::TransferDataFromWindow()
|
|||
// Check for removed layers with items which will get deleted from the board.
|
||||
LSEQ removedLayers = getRemovedLayersWithItems();
|
||||
|
||||
if( !removedLayers.empty()
|
||||
&& !IsOK( this, _( "Items have been found on removed layers. This operation will delete "
|
||||
"all items from removed layers and cannot be undone. Do you wish to "
|
||||
"continue?" ) ) )
|
||||
// Check for non copper layers in use in footprints, and therefore not removable.
|
||||
LSEQ notremovableLayers = getNonRemovableLayers();
|
||||
|
||||
if( !notremovableLayers.empty() )
|
||||
{
|
||||
for( unsigned int ii = 0; ii < notremovableLayers.size(); ii++ )
|
||||
msg << m_pcb->GetLayerName( notremovableLayers[ii] ) << "\n";
|
||||
|
||||
if( !IsOK( this, wxString::Format( _( "Footprints have some items on removed layers:\n"
|
||||
"%s\n"
|
||||
"These items will be no longer accessible\n"
|
||||
"Do you wish to continue?" ), msg ) ) )
|
||||
return false;
|
||||
}
|
||||
|
||||
if( !removedLayers.empty() &&
|
||||
!IsOK( this, _( "Items have been found on removed layers. This operation will delete "
|
||||
"all items from removed layers and cannot be undone. Do you wish to "
|
||||
"continue?" ) ) )
|
||||
return false;
|
||||
|
||||
// Delete all objects on layers that have been removed. Leaving them in copper layers
|
||||
// can (will?) result in DRC errors and it pollutes the board file with cruft.
|
||||
bool hasRemovedBoardItems = false;
|
||||
|
||||
if( !removedLayers.empty() )
|
||||
{
|
||||
PCB_LAYER_COLLECTOR collector;
|
||||
|
@ -654,8 +690,14 @@ bool DIALOG_LAYERS_SETUP::TransferDataFromWindow()
|
|||
// Bye-bye items on on removed layer.
|
||||
if( collector.GetCount() != 0 )
|
||||
{
|
||||
hasRemovedBoardItems = true;
|
||||
|
||||
for( int i = 0; i < collector.GetCount(); i++ )
|
||||
m_pcb->Remove( collector[i] );
|
||||
{
|
||||
BOARD_ITEM* item = collector[i];
|
||||
m_pcb->Remove( item );
|
||||
delete item;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -686,6 +728,16 @@ bool DIALOG_LAYERS_SETUP::TransferDataFromWindow()
|
|||
|
||||
m_pcb->GetDesignSettings().SetBoardThickness( thickness );
|
||||
|
||||
// If some board items are deleted: rebuild the connectivity,
|
||||
// because it is likely some tracks and vias where removed
|
||||
if( hasRemovedBoardItems )
|
||||
{
|
||||
PCB_EDIT_FRAME* editFrame = static_cast<PCB_EDIT_FRAME*>( GetParent() );
|
||||
// Rebuild list of nets (full ratsnest rebuild)
|
||||
editFrame->Compile_Ratsnest( NULL, true );
|
||||
m_pcb->BuildConnectivity();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -800,7 +852,7 @@ LSEQ DIALOG_LAYERS_SETUP::getRemovedLayersWithItems()
|
|||
LSET newLayers = getUILayerMask();
|
||||
LSET curLayers = m_pcb->GetEnabledLayers();
|
||||
|
||||
if( newLayers == curLayers )
|
||||
if( newLayers == curLayers ) // return a empty list if no change
|
||||
return removedLayers;
|
||||
|
||||
PCB_LAYER_COLLECTOR collector;
|
||||
|
@ -823,7 +875,40 @@ LSEQ DIALOG_LAYERS_SETUP::getRemovedLayersWithItems()
|
|||
}
|
||||
|
||||
|
||||
bool InvokeLayerSetup( wxTopLevelWindow* aCaller, BOARD* aBoard )
|
||||
LSEQ DIALOG_LAYERS_SETUP::getNonRemovableLayers()
|
||||
{
|
||||
//Build the list of non copper layers in use in footprints.
|
||||
LSEQ inUseLayers;
|
||||
LSET newLayers = getUILayerMask();
|
||||
LSET curLayers = m_pcb->GetEnabledLayers();
|
||||
|
||||
if( newLayers == curLayers ) // return a empty list if no change
|
||||
return inUseLayers;
|
||||
|
||||
PCB_LAYER_COLLECTOR collector;
|
||||
LSEQ newLayerSeq = newLayers.Seq();
|
||||
std::vector< PCB_LAYER_ID >::iterator it;
|
||||
|
||||
for( auto layer_id : curLayers.Seq() )
|
||||
{
|
||||
if( IsCopperLayer( layer_id ) ) // Copper layers are not taken in account here
|
||||
continue;
|
||||
|
||||
if( std::find( newLayerSeq.begin(), newLayerSeq.end(), layer_id ) == newLayerSeq.end() )
|
||||
{
|
||||
collector.SetLayerId( layer_id );
|
||||
collector.Collect( m_pcb, GENERAL_COLLECTOR::ModuleItems );
|
||||
|
||||
if( collector.GetCount() != 0 )
|
||||
inUseLayers.push_back( layer_id );
|
||||
}
|
||||
}
|
||||
|
||||
return inUseLayers;
|
||||
}
|
||||
|
||||
|
||||
bool InvokeLayerSetup( PCB_EDIT_FRAME* aCaller, BOARD* aBoard )
|
||||
{
|
||||
DIALOG_LAYERS_SETUP dlg( aCaller, aBoard );
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
/* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2013 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
|
||||
* Copyright (C) 2013-2016 KiCad Developers, see change_log.txt for contributors.
|
||||
* Copyright (C) 2013-2018 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
|
@ -54,6 +54,7 @@ class MODULE;
|
|||
// Often this is not used in the prototypes, since wxFrame is good enough and would
|
||||
// represent maximum information hiding.
|
||||
class PCB_BASE_FRAME;
|
||||
class PCB_EDIT_FRAME;
|
||||
class FOOTPRINT_EDIT_FRAME;
|
||||
class FP_LIB_TABLE;
|
||||
class BOARD;
|
||||
|
@ -137,11 +138,11 @@ bool InvokeDXFDialogModuleImport( PCB_BASE_FRAME* aCaller, MODULE* aModule );
|
|||
/**
|
||||
* Function InvokeLayerSetup
|
||||
* shows the layer setup dialog
|
||||
* @param aCaller is the wxTopLevelWindow which is invoking the dialog.
|
||||
* @param aCaller is the PCB_EDIT_FRAME which is invoking the dialog.
|
||||
* @param aBoard is the currently edited board.
|
||||
* @return bool - true if user pressed OK (did not abort), else false.
|
||||
*/
|
||||
bool InvokeLayerSetup( wxTopLevelWindow* aCaller, BOARD* aBoard );
|
||||
bool InvokeLayerSetup( PCB_EDIT_FRAME* aCaller, BOARD* aBoard );
|
||||
|
||||
/**
|
||||
* Function InvokeSVGPrint
|
||||
|
|
Loading…
Reference in New Issue