Add cli option for zone refill before drc

Note: Does not save yet
This commit is contained in:
Mark Roszko 2025-07-24 20:40:33 -04:00
parent d538f8d848
commit dc6e0223c7
11 changed files with 137 additions and 22 deletions

View File

@ -81,6 +81,12 @@ DIALOG_RC_JOB_BASE::DIALOG_RC_JOB_BASE( wxWindow* parent, wxWindowID id, const w
bSizerBottom->Add( m_cbSchParity, 0, wxBOTTOM|wxLEFT, 5 ); bSizerBottom->Add( m_cbSchParity, 0, wxBOTTOM|wxLEFT, 5 );
bSizerBottom->Add( 0, 3, 0, wxEXPAND, 5 );
m_cbRefillZones = new wxCheckBox( this, wxID_ANY, _("Refill all zones before performing DRC"), wxDefaultPosition, wxDefaultSize, 0 );
bSizerBottom->Add( m_cbRefillZones, 0, wxBOTTOM|wxLEFT, 5 );
bSizerMain->Add( bSizerBottom, 0, wxEXPAND|wxRIGHT|wxLEFT, 5 ); bSizerMain->Add( bSizerBottom, 0, wxEXPAND|wxRIGHT|wxLEFT, 5 );
m_sdbSizer1 = new wxStdDialogButtonSizer(); m_sdbSizer1 = new wxStdDialogButtonSizer();
@ -95,7 +101,6 @@ DIALOG_RC_JOB_BASE::DIALOG_RC_JOB_BASE( wxWindow* parent, wxWindowID id, const w
this->SetSizer( bSizerMain ); this->SetSizer( bSizerMain );
this->Layout(); this->Layout();
bSizerMain->Fit( this );
this->Centre( wxBOTH ); this->Centre( wxBOTH );

View File

@ -50,7 +50,7 @@
<property name="minimum_size"></property> <property name="minimum_size"></property>
<property name="name">DIALOG_RC_JOB_BASE</property> <property name="name">DIALOG_RC_JOB_BASE</property>
<property name="pos"></property> <property name="pos"></property>
<property name="size">443,239</property> <property name="size">443,255</property>
<property name="style">wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER</property> <property name="style">wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER</property>
<property name="subclass">DIALOG_SHIM; dialog_shim.h; forward_declare</property> <property name="subclass">DIALOG_SHIM; dialog_shim.h; forward_declare</property>
<property name="title"></property> <property name="title"></property>
@ -774,6 +774,81 @@
<property name="window_style"></property> <property name="window_style"></property>
</object> </object>
</object> </object>
<object class="sizeritem" expanded="true">
<property name="border">5</property>
<property name="flag">wxEXPAND</property>
<property name="proportion">0</property>
<object class="spacer" expanded="true">
<property name="height">3</property>
<property name="permission">protected</property>
<property name="width">0</property>
</object>
</object>
<object class="sizeritem" expanded="true">
<property name="border">5</property>
<property name="flag">wxBOTTOM|wxLEFT</property>
<property name="proportion">0</property>
<object class="wxCheckBox" expanded="true">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
<property name="TopDockable">1</property>
<property name="aui_layer">0</property>
<property name="aui_name"></property>
<property name="aui_position">0</property>
<property name="aui_row">0</property>
<property name="best_size"></property>
<property name="bg"></property>
<property name="caption"></property>
<property name="caption_visible">1</property>
<property name="center_pane">0</property>
<property name="checked">0</property>
<property name="close_button">1</property>
<property name="context_help"></property>
<property name="context_menu">1</property>
<property name="default_pane">0</property>
<property name="dock">Dock</property>
<property name="dock_fixed">0</property>
<property name="docking">Left</property>
<property name="drag_accept_files">0</property>
<property name="enabled">1</property>
<property name="fg"></property>
<property name="floatable">1</property>
<property name="font"></property>
<property name="gripper">0</property>
<property name="hidden">0</property>
<property name="id">wxID_ANY</property>
<property name="label">Refill all zones before performing DRC</property>
<property name="max_size"></property>
<property name="maximize_button">0</property>
<property name="maximum_size"></property>
<property name="min_size"></property>
<property name="minimize_button">0</property>
<property name="minimum_size"></property>
<property name="moveable">1</property>
<property name="name">m_cbRefillZones</property>
<property name="pane_border">1</property>
<property name="pane_position"></property>
<property name="pane_size"></property>
<property name="permission">protected</property>
<property name="pin_button">1</property>
<property name="pos"></property>
<property name="resize">Resizable</property>
<property name="show">1</property>
<property name="size"></property>
<property name="style"></property>
<property name="subclass">; ; forward_declare</property>
<property name="toolbar_pane">0</property>
<property name="tooltip"></property>
<property name="validator_data_type"></property>
<property name="validator_style">wxFILTER_NONE</property>
<property name="validator_type">wxDefaultValidator</property>
<property name="validator_variable"></property>
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style"></property>
</object>
</object>
</object> </object>
</object> </object>
<object class="sizeritem" expanded="false"> <object class="sizeritem" expanded="false">

View File

@ -46,6 +46,7 @@ class KICOMMON_API DIALOG_RC_JOB_BASE : public DIALOG_SHIM
wxCheckBox* m_cbHaltOutput; wxCheckBox* m_cbHaltOutput;
wxCheckBox* m_cbAllTrackViolations; wxCheckBox* m_cbAllTrackViolations;
wxCheckBox* m_cbSchParity; wxCheckBox* m_cbSchParity;
wxCheckBox* m_cbRefillZones;
wxStdDialogButtonSizer* m_sdbSizer1; wxStdDialogButtonSizer* m_sdbSizer1;
wxButton* m_sdbSizer1OK; wxButton* m_sdbSizer1OK;
wxButton* m_sdbSizer1Cancel; wxButton* m_sdbSizer1Cancel;
@ -56,7 +57,7 @@ class KICOMMON_API DIALOG_RC_JOB_BASE : public DIALOG_SHIM
public: public:
DIALOG_RC_JOB_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = wxEmptyString, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 443,239 ), long style = wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER ); DIALOG_RC_JOB_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = wxEmptyString, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 443,255 ), long style = wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER );
~DIALOG_RC_JOB_BASE(); ~DIALOG_RC_JOB_BASE();

View File

@ -25,10 +25,13 @@
JOB_PCB_DRC::JOB_PCB_DRC() : JOB_PCB_DRC::JOB_PCB_DRC() :
JOB_RC( "drc" ), JOB_RC( "drc" ),
m_reportAllTrackErrors( false ), m_reportAllTrackErrors( false ),
m_parity( true ) m_parity( true ),
m_refillZones( false )
{ {
m_params.emplace_back( new JOB_PARAM<bool>( "parity", &m_parity, m_parity ) ); m_params.emplace_back( new JOB_PARAM<bool>( "parity", &m_parity, m_parity ) );
m_params.emplace_back( new JOB_PARAM<bool>( "report_all_track_errors", &m_reportAllTrackErrors, m_reportAllTrackErrors ) ); m_params.emplace_back(
new JOB_PARAM<bool>( "report_all_track_errors", &m_reportAllTrackErrors, m_reportAllTrackErrors ) );
m_params.emplace_back( new JOB_PARAM<bool>( "refill_zones", &m_refillZones, m_refillZones ) );
} }

View File

@ -31,4 +31,6 @@ public:
bool m_reportAllTrackErrors; bool m_reportAllTrackErrors;
bool m_parity; bool m_parity;
bool m_refillZones;
}; };

View File

@ -27,6 +27,7 @@ DIALOG_ERC_JOB_CONFIG::DIALOG_ERC_JOB_CONFIG( wxWindow* parent, JOB_SCH_ERC* aJo
m_cbAllTrackViolations->Hide(); m_cbAllTrackViolations->Hide();
m_cbSchParity->Hide(); m_cbSchParity->Hide();
m_cbRefillZones->Hide();
Fit(); Fit();
Layout(); Layout();

View File

@ -38,6 +38,7 @@
#define ARG_SEVERITY_EXCLUSIONS "--severity-exclusions" #define ARG_SEVERITY_EXCLUSIONS "--severity-exclusions"
#define ARG_EXIT_CODE_VIOLATIONS "--exit-code-violations" #define ARG_EXIT_CODE_VIOLATIONS "--exit-code-violations"
#define ARG_PARITY "--schematic-parity" #define ARG_PARITY "--schematic-parity"
#define ARG_ZONE_FILL "--refill-zones"
CLI::PCB_DRC_COMMAND::PCB_DRC_COMMAND() : COMMAND( "drc" ) CLI::PCB_DRC_COMMAND::PCB_DRC_COMMAND() : COMMAND( "drc" )
{ {
@ -88,6 +89,10 @@ CLI::PCB_DRC_COMMAND::PCB_DRC_COMMAND() : COMMAND( "drc" )
m_argParser.add_argument( ARG_EXIT_CODE_VIOLATIONS ) m_argParser.add_argument( ARG_EXIT_CODE_VIOLATIONS )
.help( UTF8STDSTR( _( "Return a nonzero exit code if DRC violations exist" ) ) ) .help( UTF8STDSTR( _( "Return a nonzero exit code if DRC violations exist" ) ) )
.flag(); .flag();
m_argParser.add_argument( ARG_ZONE_FILL )
.help( UTF8STDSTR( _( "Refill zones before running DRC" ) ) )
.flag();
} }
@ -163,6 +168,7 @@ int CLI::PCB_DRC_COMMAND::doPerform( KIWAY& aKiway )
} }
drcJob->m_parity = m_argParser.get<bool>( ARG_PARITY ); drcJob->m_parity = m_argParser.get<bool>( ARG_PARITY );
drcJob->m_refillZones = m_argParser.get<bool>( ARG_ZONE_FILL );
int exitCode = aKiway.ProcessJob( KIWAY::FACE_PCB, drcJob.get() ); int exitCode = aKiway.ProcessJob( KIWAY::FACE_PCB, drcJob.get() );

View File

@ -36,6 +36,7 @@ bool DIALOG_DRC_JOB_CONFIG::TransferDataToWindow()
m_cbAllTrackViolations->SetValue( m_drcJob->m_reportAllTrackErrors ); m_cbAllTrackViolations->SetValue( m_drcJob->m_reportAllTrackErrors );
m_cbSchParity->SetValue( m_drcJob->m_parity ); m_cbSchParity->SetValue( m_drcJob->m_parity );
m_cbRefillZones->SetValue( m_drcJob->m_refillZones );
return true; return true;
} }
@ -47,5 +48,6 @@ bool DIALOG_DRC_JOB_CONFIG::TransferDataFromWindow()
m_drcJob->m_reportAllTrackErrors = m_cbAllTrackViolations->GetValue(); m_drcJob->m_reportAllTrackErrors = m_cbAllTrackViolations->GetValue();
m_drcJob->m_parity = m_cbSchParity->GetValue(); m_drcJob->m_parity = m_cbSchParity->GetValue();
m_drcJob->m_refillZones = m_cbRefillZones->GetValue();
return true; return true;
} }

View File

@ -93,6 +93,7 @@
#include <dialogs/dialog_render_job.h> #include <dialogs/dialog_render_job.h>
#include <dialogs/dialog_gencad_export_options.h> #include <dialogs/dialog_gencad_export_options.h>
#include <paths.h> #include <paths.h>
#include <tools/zone_filler_tool.h>
#include "pcbnew_scripting_helpers.h" #include "pcbnew_scripting_helpers.h"
#include <locale_io.h> #include <locale_io.h>
@ -2134,6 +2135,14 @@ int PCBNEW_JOBS_HANDLER::JobExportDrc( JOB* aJob )
drcEngine->SetSchematicNetlist( netlist.get() ); drcEngine->SetSchematicNetlist( netlist.get() );
} }
if( drcJob->m_refillZones )
{
toolManager->RegisterTool( new ZONE_FILLER_TOOL );
ZONE_FILLER_TOOL* zoneFiller = toolManager->GetTool<ZONE_FILLER_TOOL>();
zoneFiller->FillAllZones( nullptr, m_progressReporter, true );
}
drcEngine->SetProgressReporter( m_progressReporter ); drcEngine->SetProgressReporter( m_progressReporter );
drcEngine->SetViolationHandler( drcEngine->SetViolationHandler(
[&]( const std::shared_ptr<DRC_ITEM>& aItem, VECTOR2I aPos, int aLayer, [&]( const std::shared_ptr<DRC_ITEM>& aItem, VECTOR2I aPos, int aLayer,

View File

@ -115,14 +115,17 @@ void ZONE_FILLER_TOOL::singleShotRefocus( wxIdleEvent& )
} }
void ZONE_FILLER_TOOL::FillAllZones( wxWindow* aCaller, PROGRESS_REPORTER* aReporter ) void ZONE_FILLER_TOOL::FillAllZones( wxWindow* aCaller, PROGRESS_REPORTER* aReporter, bool aHeadless )
{ {
if( m_fillInProgress ) if( m_fillInProgress )
return; return;
m_fillInProgress = true; m_fillInProgress = true;
PCB_EDIT_FRAME* frame = getEditFrame<PCB_EDIT_FRAME>(); PCB_EDIT_FRAME* frame = nullptr;
if( !aHeadless )
frame = getEditFrame<PCB_EDIT_FRAME>();
BOARD_COMMIT commit( this ); BOARD_COMMIT commit( this );
std::unique_ptr<WX_PROGRESS_REPORTER> reporter; std::unique_ptr<WX_PROGRESS_REPORTER> reporter;
TEARDROP_MANAGER teardropMgr( board(), m_toolMgr ); TEARDROP_MANAGER teardropMgr( board(), m_toolMgr );
@ -137,7 +140,7 @@ void ZONE_FILLER_TOOL::FillAllZones( wxWindow* aCaller, PROGRESS_REPORTER* aRepo
m_filler = std::make_unique<ZONE_FILLER>( board(), &commit ); m_filler = std::make_unique<ZONE_FILLER>( board(), &commit );
if( !board()->GetDesignSettings().m_DRCEngine->RulesValid() ) if( !aHeadless && !board()->GetDesignSettings().m_DRCEngine->RulesValid() )
{ {
WX_INFOBAR* infobar = frame->GetInfoBar(); WX_INFOBAR* infobar = frame->GetInfoBar();
wxHyperlinkCtrl* button = new wxHyperlinkCtrl( infobar, wxID_ANY, _( "Show DRC rules" ), wxEmptyString ); wxHyperlinkCtrl* button = new wxHyperlinkCtrl( infobar, wxID_ANY, _( "Show DRC rules" ), wxEmptyString );
@ -160,7 +163,7 @@ void ZONE_FILLER_TOOL::FillAllZones( wxWindow* aCaller, PROGRESS_REPORTER* aRepo
{ {
m_filler->SetProgressReporter( aReporter ); m_filler->SetProgressReporter( aReporter );
} }
else else if( !aHeadless )
{ {
reporter = std::make_unique<WX_PROGRESS_REPORTER>( aCaller, _( "Fill All Zones" ), 5, PR_CAN_ABORT ); reporter = std::make_unique<WX_PROGRESS_REPORTER>( aCaller, _( "Fill All Zones" ), 5, PR_CAN_ABORT );
m_filler->SetProgressReporter( reporter.get() ); m_filler->SetProgressReporter( reporter.get() );
@ -168,28 +171,35 @@ void ZONE_FILLER_TOOL::FillAllZones( wxWindow* aCaller, PROGRESS_REPORTER* aRepo
if( m_filler->Fill( toFill ) ) if( m_filler->Fill( toFill ) )
{ {
m_filler->GetProgressReporter()->AdvancePhase(); if( m_filler->GetProgressReporter() )
m_filler->GetProgressReporter()->AdvancePhase();
commit.Push( _( "Fill Zone(s)" ), SKIP_CONNECTIVITY | ZONE_FILL_OP ); commit.Push( _( "Fill Zone(s)" ), SKIP_CONNECTIVITY | ZONE_FILL_OP );
frame->m_ZoneFillsDirty = false; if( !aHeadless )
frame->m_ZoneFillsDirty = false;
} }
else else
{ {
commit.Revert(); commit.Revert();
} }
rebuildConnectivity(); rebuildConnectivity( aHeadless );
refresh();
if( m_filler->IsDebug() ) if( !aHeadless )
frame->UpdateUserInterface(); {
refresh();
if( m_filler->IsDebug() )
frame->UpdateUserInterface();
}
m_fillInProgress = false; m_fillInProgress = false;
m_filler.reset( nullptr ); m_filler.reset( nullptr );
// wxWidgets has keyboard focus issues after the progress reporter. Re-setting the focus if( !aHeadless )
// here doesn't work, so we delay it to an idle event. // wxWidgets has keyboard focus issues after the progress reporter. Re-setting the focus
canvas()->Bind( wxEVT_IDLE, &ZONE_FILLER_TOOL::singleShotRefocus, this ); // here doesn't work, so we delay it to an idle event.
canvas()->Bind( wxEVT_IDLE, &ZONE_FILLER_TOOL::singleShotRefocus, this );
} }
@ -440,11 +450,12 @@ PROGRESS_REPORTER* ZONE_FILLER_TOOL::GetProgressReporter()
} }
void ZONE_FILLER_TOOL::rebuildConnectivity() void ZONE_FILLER_TOOL::rebuildConnectivity( bool aHeadless )
{ {
board()->BuildConnectivity(); board()->BuildConnectivity();
m_toolMgr->PostEvent( EVENTS::ConnectivityChangedEvent ); m_toolMgr->PostEvent( EVENTS::ConnectivityChangedEvent );
canvas()->RedrawRatsnest(); if( !aHeadless )
canvas()->RedrawRatsnest();
} }

View File

@ -50,7 +50,7 @@ public:
void Reset( RESET_REASON aReason ) override; void Reset( RESET_REASON aReason ) override;
void CheckAllZones( wxWindow* aCaller, PROGRESS_REPORTER* aReporter = nullptr ); void CheckAllZones( wxWindow* aCaller, PROGRESS_REPORTER* aReporter = nullptr );
void FillAllZones( wxWindow* aCaller, PROGRESS_REPORTER* aReporter = nullptr ); void FillAllZones( wxWindow* aCaller, PROGRESS_REPORTER* aReporter = nullptr, bool aHeadless = false );
int ZoneFill( const TOOL_EVENT& aEvent ); int ZoneFill( const TOOL_EVENT& aEvent );
int ZoneFillAll( const TOOL_EVENT& aEvent ); int ZoneFillAll( const TOOL_EVENT& aEvent );
@ -73,7 +73,7 @@ private:
///< Refocus on an idle event (used after the Progress Reporter messes up the focus). ///< Refocus on an idle event (used after the Progress Reporter messes up the focus).
void singleShotRefocus( wxIdleEvent& ); void singleShotRefocus( wxIdleEvent& );
void rebuildConnectivity(); void rebuildConnectivity( bool aHeadless = false );
void refresh(); void refresh();
///< Set up handlers for various events. ///< Set up handlers for various events.