Shutdown safety. (Possibly KICAD-8S0.)

This commit is contained in:
Jeff Young 2025-07-18 11:48:54 +01:00
parent 8556bd45c2
commit be0da70839
6 changed files with 95 additions and 87 deletions

View File

@ -207,6 +207,16 @@ CVPCB_MAINFRAME::CVPCB_MAINFRAME( KIWAY* aKiway, wxWindow* aParent ) :
// Connect Events
setupEventHandlers();
// Toolbar events
Bind( wxEVT_TEXT, &CVPCB_MAINFRAME::onTextFilterChanged, this );
// Attach the events to the tool dispatcher
Bind( wxEVT_CHAR, &TOOL_DISPATCHER::DispatchWxEvent, m_toolDispatcher );
Bind( wxEVT_CHAR_HOOK, &TOOL_DISPATCHER::DispatchWxEvent, m_toolDispatcher );
m_filterTimer = new wxTimer( this );
Bind( wxEVT_TIMER, &CVPCB_MAINFRAME::onTextFilterChangedTimer, this, m_filterTimer->GetId() );
// Start the main processing loop
m_toolManager->InvokeTool( "cvpcb.Control" );
@ -225,13 +235,6 @@ CVPCB_MAINFRAME::~CVPCB_MAINFRAME()
Unbind( wxEVT_TIMER, &CVPCB_MAINFRAME::onTextFilterChangedTimer, this, m_filterTimer->GetId() );
Unbind( wxEVT_IDLE, &CVPCB_MAINFRAME::updateFootprintViewerOnIdle, this );
// Stop the timer during destruction early to avoid potential race conditions (that do happen)
m_filterTimer->Stop();
// Shutdown all running tools
if( m_toolManager )
m_toolManager->ShutdownAllTools();
// Clean up the tool infrastructure
delete m_actions;
delete m_toolManager;
@ -289,11 +292,10 @@ void CVPCB_MAINFRAME::setupUIConditions()
#define ENABLE( x ) ACTION_CONDITIONS().Enable( x )
#define CHECK( x ) ACTION_CONDITIONS().Check( x )
mgr->SetConditions( CVPCB_ACTIONS::saveAssociationsToSchematic,
ENABLE( cond.ContentModified() ) );
mgr->SetConditions( CVPCB_ACTIONS::saveAssociationsToFile, ENABLE( cond.ContentModified() ) );
mgr->SetConditions( ACTIONS::undo, ENABLE( cond.UndoAvailable() ) );
mgr->SetConditions( ACTIONS::redo, ENABLE( cond.RedoAvailable() ) );
mgr->SetConditions( CVPCB_ACTIONS::saveAssociationsToSchematic, ENABLE( cond.ContentModified() ) );
mgr->SetConditions( CVPCB_ACTIONS::saveAssociationsToFile, ENABLE( cond.ContentModified() ) );
mgr->SetConditions( ACTIONS::undo, ENABLE( cond.UndoAvailable() ) );
mgr->SetConditions( ACTIONS::redo, ENABLE( cond.RedoAvailable() ) );
auto compFilter =
[this] ( const SELECTION& )
@ -372,22 +374,12 @@ void CVPCB_MAINFRAME::setupEventHandlers()
Close( false );
}, wxID_EXIT );
// Toolbar events
Bind( wxEVT_TEXT, &CVPCB_MAINFRAME::onTextFilterChanged, this );
// Just skip the resize events
Bind( wxEVT_SIZE,
[]( wxSizeEvent& aEvent )
{
aEvent.Skip();
} );
// Attach the events to the tool dispatcher
Bind( wxEVT_CHAR, &TOOL_DISPATCHER::DispatchWxEvent, m_toolDispatcher );
Bind( wxEVT_CHAR_HOOK, &TOOL_DISPATCHER::DispatchWxEvent, m_toolDispatcher );
m_filterTimer = new wxTimer( this );
Bind( wxEVT_TIMER, &CVPCB_MAINFRAME::onTextFilterChangedTimer, this, m_filterTimer->GetId() );
}
@ -396,14 +388,10 @@ bool CVPCB_MAINFRAME::canCloseWindow( wxCloseEvent& aEvent )
if( m_modified )
{
// Shutdown blocks must be determined and vetoed as early as possible
if( KIPLATFORM::APP::SupportsShutdownBlockReason()
&& aEvent.GetId() == wxEVT_QUERY_END_SESSION )
{
if( KIPLATFORM::APP::SupportsShutdownBlockReason() && aEvent.GetId() == wxEVT_QUERY_END_SESSION )
return false;
}
if( !HandleUnsavedChanges( this, _( "Symbol to Footprint links have been modified. "
"Save changes?" ),
if( !HandleUnsavedChanges( this, _( "Symbol to Footprint links have been modified. Save changes?" ),
[&]() -> bool
{
return SaveFootprintAssociation( false );
@ -422,11 +410,21 @@ bool CVPCB_MAINFRAME::canCloseWindow( wxCloseEvent& aEvent )
void CVPCB_MAINFRAME::doCloseWindow()
{
m_symbolsListBox->Shutdown();
m_footprintListBox->Shutdown();
if( GetFootprintViewerFrame() )
GetFootprintViewerFrame()->Close( true );
m_modified = false;
// Stop the timer during destruction early to avoid potential race conditions (that do happen)
m_filterTimer->Stop();
// Shutdown all running tools
if( m_toolManager )
m_toolManager->ShutdownAllTools();
// clear symbol selection in schematic:
SendComponentSelectionToSch( true );
}
@ -533,9 +531,8 @@ void CVPCB_MAINFRAME::LoadSettings( APP_SETTINGS_BASE* aCfg )
{
EDA_BASE_FRAME::LoadSettings( aCfg );
CVPCB_SETTINGS* cfg = static_cast<CVPCB_SETTINGS*>( aCfg );
m_filteringOptions = cfg->m_FilterFlags;
if( CVPCB_SETTINGS* cfg = dynamic_cast<CVPCB_SETTINGS*>( aCfg ) )
m_filteringOptions = cfg->m_FilterFlags;
}
@ -543,12 +540,14 @@ void CVPCB_MAINFRAME::SaveSettings( APP_SETTINGS_BASE* aCfg )
{
EDA_BASE_FRAME::SaveSettings( aCfg );
CVPCB_SETTINGS* cfg = static_cast<CVPCB_SETTINGS*>( aCfg );
cfg->m_FilterFlags = m_filteringOptions;
cfg->m_FilterString = m_tcFilterString->GetValue();
if( CVPCB_SETTINGS* cfg = dynamic_cast<CVPCB_SETTINGS*>( aCfg ) )
{
cfg->m_FilterFlags = m_filteringOptions;
cfg->m_FilterString = m_tcFilterString->GetValue();
cfg->m_LibrariesWidth = m_librariesListBox->GetSize().x;
cfg->m_FootprintsWidth = m_footprintListBox->GetSize().x;
cfg->m_LibrariesWidth = m_librariesListBox->GetSize().x;
cfg->m_FootprintsWidth = m_footprintListBox->GetSize().x;
}
}

View File

@ -33,8 +33,7 @@
#include <tools/cvpcb_actions.h>
FOOTPRINTS_LISTBOX::FOOTPRINTS_LISTBOX( CVPCB_MAINFRAME* parent, wxWindowID id ) :
ITEMS_LISTBOX_BASE( parent, id, wxDefaultPosition, wxDefaultSize,
wxLC_SINGLE_SEL | wxNO_BORDER )
ITEMS_LISTBOX_BASE( parent, id, wxDefaultPosition, wxDefaultSize, wxLC_SINGLE_SEL | wxNO_BORDER )
{
}
@ -187,18 +186,27 @@ END_EVENT_TABLE()
void FOOTPRINTS_LISTBOX::OnLeftClick( wxListEvent& event )
{
if( m_isClosing )
return;
GetParent()->RefreshFootprintViewer();
}
void FOOTPRINTS_LISTBOX::OnLeftDClick( wxListEvent& event )
{
if( m_isClosing )
return;
GetParent()->GetToolManager()->RunAction( CVPCB_ACTIONS::associate );
}
void FOOTPRINTS_LISTBOX::OnChar( wxKeyEvent& event )
{
if( m_isClosing )
return;
wxLogTrace( kicadTraceKeyEvent, wxS( "FOOTPRINTS_LISTBOX::OnChar %s" ), dump( event ) );
int key = event.GetKeyCode();

View File

@ -34,18 +34,14 @@
ITEMS_LISTBOX_BASE::ITEMS_LISTBOX_BASE( CVPCB_MAINFRAME* aParent, wxWindowID aId,
const wxPoint& aLocation, const wxSize& aSize,
long aStyle ) :
wxListView( aParent, aId, aLocation, aSize, LISTBOX_STYLE | aStyle ),
columnWidth( 0 )
wxListView( aParent, aId, aLocation, aSize, LISTBOX_STYLE | aStyle ),
m_isClosing( false ),
m_columnWidth( 0 )
{
InsertColumn( 0, wxEmptyString );
}
ITEMS_LISTBOX_BASE::~ITEMS_LISTBOX_BASE()
{
}
void ITEMS_LISTBOX_BASE::UpdateWidth( int aLine )
{
wxClientDC dc( this );
@ -54,12 +50,10 @@ void ITEMS_LISTBOX_BASE::UpdateWidth( int aLine )
// Less than zero: recalculate width of all items.
if( aLine < 0 )
{
columnWidth = 0;
m_columnWidth = 0;
for( int ii = 0; ii < itemCount; ii++ )
{
UpdateLineWidth( (unsigned)ii, dc );
}
}
// Zero or above: update from a single line.
else
@ -87,10 +81,10 @@ void ITEMS_LISTBOX_BASE::UpdateLineWidth( unsigned aLine, wxClientDC& dc )
dc.GetTextExtent( str, &w, nullptr );
newWidth += w;
if( newWidth > columnWidth )
if( newWidth > m_columnWidth )
{
columnWidth = newWidth;
SetColumnWidth( 0, columnWidth );
m_columnWidth = newWidth;
SetColumnWidth( 0, m_columnWidth );
}
}

View File

@ -46,7 +46,7 @@ public:
const wxPoint& aLocation = wxDefaultPosition,
const wxSize& aSize = wxDefaultSize, long aStyle = 0 );
~ITEMS_LISTBOX_BASE();
virtual ~ITEMS_LISTBOX_BASE() = default;
/**
* @return the index of the selected item in lists allowing only one item selected
@ -70,6 +70,8 @@ public:
*/
void UpdateWidth( int aLine = -1 );
void Shutdown() { m_isClosing = true; }
private:
/**
* Calculate the width of the given line, and increase the column width
@ -78,7 +80,11 @@ private:
*/
void UpdateLineWidth( unsigned aLine, wxClientDC& dc );
int columnWidth;
protected:
bool m_isClosing;
private:
int m_columnWidth;
};
@ -98,7 +104,7 @@ public:
};
FOOTPRINTS_LISTBOX( CVPCB_MAINFRAME* parent, wxWindowID id );
~FOOTPRINTS_LISTBOX() override {};
virtual ~FOOTPRINTS_LISTBOX() = default;
int GetCount();
void SetSelection( int aIndex, bool aState = true );
@ -143,7 +149,7 @@ class LIBRARY_LISTBOX : public ITEMS_LISTBOX_BASE
{
public:
LIBRARY_LISTBOX( CVPCB_MAINFRAME* parent, wxWindowID id );
~LIBRARY_LISTBOX() override {};
virtual ~LIBRARY_LISTBOX() = default;
int GetCount();
void SetSelection( int index, bool State = true );
@ -181,8 +187,7 @@ class SYMBOLS_LISTBOX : public ITEMS_LISTBOX_BASE
{
public:
SYMBOLS_LISTBOX( CVPCB_MAINFRAME* parent, wxWindowID id );
~SYMBOLS_LISTBOX();
virtual ~SYMBOLS_LISTBOX() = default;
void Clear();
int GetCount();
@ -223,7 +228,7 @@ public:
DECLARE_EVENT_TABLE();
public:
wxArrayString m_SymbolList;
wxArrayString m_SymbolList;
private:
std::vector<long> m_symbolWarning;

View File

@ -35,19 +35,14 @@
SYMBOLS_LISTBOX::SYMBOLS_LISTBOX( CVPCB_MAINFRAME* parent, wxWindowID id ) :
ITEMS_LISTBOX_BASE( parent, id ),
m_warningAttr( std::make_unique<wxListItemAttr>() )
ITEMS_LISTBOX_BASE( parent, id ),
m_warningAttr( std::make_unique<wxListItemAttr>() )
{
m_warningAttr->SetBackgroundColour( KIPLATFORM::UI::IsDarkTheme() ? wxColour( 112, 96, 32 )
: wxColour( 255, 248, 212 ) );
}
SYMBOLS_LISTBOX::~SYMBOLS_LISTBOX()
{
}
;
BEGIN_EVENT_TABLE( SYMBOLS_LISTBOX, ITEMS_LISTBOX_BASE )
EVT_CHAR( SYMBOLS_LISTBOX::OnChar )
EVT_LIST_ITEM_SELECTED( ID_CVPCB_COMPONENT_LIST, SYMBOLS_LISTBOX::OnSelectComponent )
@ -117,9 +112,8 @@ wxString SYMBOLS_LISTBOX::OnGetItemText( long item, long column ) const
wxListItemAttr* SYMBOLS_LISTBOX::OnGetItemAttr( long item ) const
{
if( std::count( m_symbolWarning.begin(), m_symbolWarning.end(), item ) )
{
return m_warningAttr.get();
}
return nullptr;
}
@ -143,6 +137,9 @@ void SYMBOLS_LISTBOX::SetSelection( int index, bool State )
void SYMBOLS_LISTBOX::OnChar( wxKeyEvent& event )
{
if( m_isClosing )
return;
wxLogTrace( kicadTraceKeyEvent, wxS( "SYMBOLS_LISTBOX::OnChar %s" ), dump( event ) );
int key = event.GetKeyCode();
@ -201,6 +198,9 @@ void SYMBOLS_LISTBOX::OnChar( wxKeyEvent& event )
void SYMBOLS_LISTBOX::OnSelectComponent( wxListEvent& event )
{
if( m_isClosing )
return;
SetFocus();
GetParent()->OnSelectComponent( event );
}

View File

@ -43,35 +43,35 @@ void PANEL_PCBNEW_DISPLAY_ORIGIN::loadSettings( APP_SETTINGS_BASE* aCfg )
{
if( m_frameType == FRAME_FOOTPRINT_EDITOR )
{
FOOTPRINT_EDITOR_SETTINGS* cfg = static_cast<FOOTPRINT_EDITOR_SETTINGS*>( aCfg );
FOOTPRINT_EDITOR_SETTINGS* cfg = GetAppSettings<FOOTPRINT_EDITOR_SETTINGS>( "fpedit" );
if( cfg->m_DisplayInvertXAxis )
if( cfg && cfg->m_DisplayInvertXAxis )
m_xIncreasesLeft->SetValue( true );
else
m_xIncreasesRight->SetValue( true );
if( cfg->m_DisplayInvertYAxis )
if( cfg && cfg->m_DisplayInvertYAxis )
m_yIncreasesUp->SetValue( true );
else
m_yIncreasesDown->SetValue( true );
}
else
{
PCBNEW_SETTINGS* cfg = static_cast<PCBNEW_SETTINGS*>( aCfg );
PCBNEW_SETTINGS* cfg = GetAppSettings<PCBNEW_SETTINGS>( "pcbnew" );
if( cfg->m_Display.m_DisplayOrigin == PCB_DISPLAY_ORIGIN::PCB_ORIGIN_PAGE )
if( cfg && cfg->m_Display.m_DisplayOrigin == PCB_DISPLAY_ORIGIN::PCB_ORIGIN_PAGE )
m_pageOrigin->SetValue( true );
else if( cfg->m_Display.m_DisplayOrigin == PCB_DISPLAY_ORIGIN::PCB_ORIGIN_GRID )
else if( cfg && cfg->m_Display.m_DisplayOrigin == PCB_DISPLAY_ORIGIN::PCB_ORIGIN_GRID )
m_gridOrigin->SetValue( true );
else
m_drillPlaceOrigin->SetValue( true );
if( cfg->m_Display.m_DisplayInvertXAxis )
if( cfg &&cfg->m_Display.m_DisplayInvertXAxis )
m_xIncreasesLeft->SetValue( true );
else
m_xIncreasesRight->SetValue( true );
if( cfg->m_Display.m_DisplayInvertYAxis )
if( cfg && cfg->m_Display.m_DisplayInvertYAxis )
m_yIncreasesUp->SetValue( true );
else
m_yIncreasesDown->SetValue( true );
@ -91,24 +91,26 @@ bool PANEL_PCBNEW_DISPLAY_ORIGIN::TransferDataFromWindow()
{
if( m_frameType == FRAME_FOOTPRINT_EDITOR )
{
FOOTPRINT_EDITOR_SETTINGS* cfg = static_cast<FOOTPRINT_EDITOR_SETTINGS*>( m_cfg );
if( FOOTPRINT_EDITOR_SETTINGS* cfg = GetAppSettings<FOOTPRINT_EDITOR_SETTINGS>( "fpedit" ) )
{
cfg->m_DisplayInvertXAxis = m_xIncreasesLeft->GetValue();
cfg->m_DisplayInvertYAxis = m_yIncreasesUp->GetValue();
}
}
else
{
PCBNEW_SETTINGS* cfg = static_cast<PCBNEW_SETTINGS*>( m_cfg );
if( PCBNEW_SETTINGS* cfg = GetAppSettings<PCBNEW_SETTINGS>( "pcbnew" ) )
{
if( m_pageOrigin->GetValue() )
cfg->m_Display.m_DisplayOrigin = PCB_DISPLAY_ORIGIN::PCB_ORIGIN_PAGE;
else if( m_gridOrigin->GetValue() )
cfg->m_Display.m_DisplayOrigin = PCB_DISPLAY_ORIGIN::PCB_ORIGIN_GRID;
else
cfg->m_Display.m_DisplayOrigin = PCB_DISPLAY_ORIGIN::PCB_ORIGIN_AUX;
if( m_pageOrigin->GetValue() )
cfg->m_Display.m_DisplayOrigin = PCB_DISPLAY_ORIGIN::PCB_ORIGIN_PAGE;
else if( m_gridOrigin->GetValue() )
cfg->m_Display.m_DisplayOrigin = PCB_DISPLAY_ORIGIN::PCB_ORIGIN_GRID;
else
cfg->m_Display.m_DisplayOrigin = PCB_DISPLAY_ORIGIN::PCB_ORIGIN_AUX;
cfg->m_Display.m_DisplayInvertXAxis = m_xIncreasesLeft->GetValue();
cfg->m_Display.m_DisplayInvertYAxis = m_yIncreasesUp->GetValue();
cfg->m_Display.m_DisplayInvertXAxis = m_xIncreasesLeft->GetValue();
cfg->m_Display.m_DisplayInvertYAxis = m_yIncreasesUp->GetValue();
}
}
return true;