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.
|
* 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) 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
|
* This program is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU General Public License
|
* 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;
|
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 );
|
Append( testItem );
|
||||||
|
|
||||||
return SEARCH_CONTINUE;
|
return SEARCH_CONTINUE;
|
||||||
|
|
|
@ -29,6 +29,9 @@
|
||||||
|
|
||||||
#include <confirm.h>
|
#include <confirm.h>
|
||||||
#include <pcbnew.h>
|
#include <pcbnew.h>
|
||||||
|
#include <pcb_edit_frame.h>
|
||||||
|
#include <view/view.h>
|
||||||
|
|
||||||
#include <invoke_pcb_dialog.h>
|
#include <invoke_pcb_dialog.h>
|
||||||
|
|
||||||
#include <class_board.h>
|
#include <class_board.h>
|
||||||
|
@ -43,11 +46,6 @@
|
||||||
// if not displays always 1=the full set (32 copper layers)
|
// if not displays always 1=the full set (32 copper layers)
|
||||||
#define HIDE_INACTIVE_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.
|
* 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
|
class DIALOG_LAYERS_SETUP : public DIALOG_LAYERS_SETUP_BASE
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
DIALOG_LAYERS_SETUP( wxTopLevelWindow* aCaller, BOARD* aBoard );
|
DIALOG_LAYERS_SETUP( PCB_EDIT_FRAME* aCaller, BOARD* aBoard );
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int m_copperLayerCount;
|
int m_copperLayerCount;
|
||||||
|
@ -152,6 +150,8 @@ private:
|
||||||
|
|
||||||
void setLayerCheckBox( LAYER_NUM layer, bool isChecked );
|
void setLayerCheckBox( LAYER_NUM layer, bool isChecked );
|
||||||
void setCopperLayerCheckBoxes( int copperCount );
|
void setCopperLayerCheckBoxes( int copperCount );
|
||||||
|
// Force mandatory non copper layers enabled
|
||||||
|
void enableMandatoryLayerCheckBoxes();
|
||||||
|
|
||||||
void showCopperChoice( int copperCount );
|
void showCopperChoice( int copperCount );
|
||||||
void showBoardLayerNames();
|
void showBoardLayerNames();
|
||||||
|
@ -179,6 +179,11 @@ private:
|
||||||
*/
|
*/
|
||||||
LSEQ getRemovedLayersWithItems();
|
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
|
* Map \a aLayerNumber to the wx IDs for that layer which are
|
||||||
* the layer name control ID, checkbox control ID, and choice control ID
|
* 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 )
|
DIALOG_LAYERS_SETUP_BASE( aParent )
|
||||||
{
|
{
|
||||||
m_pcb = aBoard;
|
m_pcb = aBoard;
|
||||||
|
@ -382,6 +387,7 @@ bool DIALOG_LAYERS_SETUP::TransferDataToWindow()
|
||||||
showSelectedLayerCheckBoxes( m_enabledLayers );
|
showSelectedLayerCheckBoxes( m_enabledLayers );
|
||||||
showPresets( m_enabledLayers );
|
showPresets( m_enabledLayers );
|
||||||
showLayerTypes();
|
showLayerTypes();
|
||||||
|
enableMandatoryLayerCheckBoxes();
|
||||||
|
|
||||||
// All widgets are now initialized. Fix the min sizes:
|
// All widgets are now initialized. Fix the min sizes:
|
||||||
GetSizer()->SetSizeHints( this );
|
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 )
|
void DIALOG_LAYERS_SETUP::OnSize( wxSizeEvent& event )
|
||||||
{
|
{
|
||||||
moveTitles();
|
moveTitles();
|
||||||
event.Skip();
|
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.
|
// Check for removed layers with items which will get deleted from the board.
|
||||||
LSEQ removedLayers = getRemovedLayersWithItems();
|
LSEQ removedLayers = getRemovedLayersWithItems();
|
||||||
|
|
||||||
if( !removedLayers.empty()
|
// Check for non copper layers in use in footprints, and therefore not removable.
|
||||||
&& !IsOK( this, _( "Items have been found on removed layers. This operation will delete "
|
LSEQ notremovableLayers = getNonRemovableLayers();
|
||||||
"all items from removed layers and cannot be undone. Do you wish to "
|
|
||||||
"continue?" ) ) )
|
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;
|
return false;
|
||||||
|
|
||||||
// Delete all objects on layers that have been removed. Leaving them in copper layers
|
// 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.
|
// can (will?) result in DRC errors and it pollutes the board file with cruft.
|
||||||
|
bool hasRemovedBoardItems = false;
|
||||||
|
|
||||||
if( !removedLayers.empty() )
|
if( !removedLayers.empty() )
|
||||||
{
|
{
|
||||||
PCB_LAYER_COLLECTOR collector;
|
PCB_LAYER_COLLECTOR collector;
|
||||||
|
@ -654,8 +690,14 @@ bool DIALOG_LAYERS_SETUP::TransferDataFromWindow()
|
||||||
// Bye-bye items on on removed layer.
|
// Bye-bye items on on removed layer.
|
||||||
if( collector.GetCount() != 0 )
|
if( collector.GetCount() != 0 )
|
||||||
{
|
{
|
||||||
|
hasRemovedBoardItems = true;
|
||||||
|
|
||||||
for( int i = 0; i < collector.GetCount(); i++ )
|
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 );
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -800,7 +852,7 @@ LSEQ DIALOG_LAYERS_SETUP::getRemovedLayersWithItems()
|
||||||
LSET newLayers = getUILayerMask();
|
LSET newLayers = getUILayerMask();
|
||||||
LSET curLayers = m_pcb->GetEnabledLayers();
|
LSET curLayers = m_pcb->GetEnabledLayers();
|
||||||
|
|
||||||
if( newLayers == curLayers )
|
if( newLayers == curLayers ) // return a empty list if no change
|
||||||
return removedLayers;
|
return removedLayers;
|
||||||
|
|
||||||
PCB_LAYER_COLLECTOR collector;
|
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 );
|
DIALOG_LAYERS_SETUP dlg( aCaller, aBoard );
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
/* This program source code file is part of KiCad, a free EDA CAD application.
|
/* 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 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
|
* This program is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU General Public License
|
* 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
|
// Often this is not used in the prototypes, since wxFrame is good enough and would
|
||||||
// represent maximum information hiding.
|
// represent maximum information hiding.
|
||||||
class PCB_BASE_FRAME;
|
class PCB_BASE_FRAME;
|
||||||
|
class PCB_EDIT_FRAME;
|
||||||
class FOOTPRINT_EDIT_FRAME;
|
class FOOTPRINT_EDIT_FRAME;
|
||||||
class FP_LIB_TABLE;
|
class FP_LIB_TABLE;
|
||||||
class BOARD;
|
class BOARD;
|
||||||
|
@ -137,11 +138,11 @@ bool InvokeDXFDialogModuleImport( PCB_BASE_FRAME* aCaller, MODULE* aModule );
|
||||||
/**
|
/**
|
||||||
* Function InvokeLayerSetup
|
* Function InvokeLayerSetup
|
||||||
* shows the layer setup dialog
|
* 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.
|
* @param aBoard is the currently edited board.
|
||||||
* @return bool - true if user pressed OK (did not abort), else false.
|
* @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
|
* Function InvokeSVGPrint
|
||||||
|
|
Loading…
Reference in New Issue