Fix crash when grid tries to access deleted field.

This commit is contained in:
Jeff Young 2022-12-11 22:59:27 +00:00
parent 419fe236ad
commit e890986e01
5 changed files with 110 additions and 31 deletions

View File

@ -606,24 +606,67 @@ void DIALOG_LIB_SYMBOL_PROPERTIES::OnMoveDown( wxCommandEvent& event )
void DIALOG_LIB_SYMBOL_PROPERTIES::OnEditSpiceModel( wxCommandEvent& event )
{
#ifdef KICAD_SPICE
int diff = m_fields->size();
if( !m_grid->CommitPendingChanges() )
return;
DIALOG_SIM_MODEL dialog( this, *m_libEntry, *m_fields );
std::vector<LIB_FIELD> fields;
for( const LIB_FIELD& field : *m_fields )
fields.emplace_back( field );
DIALOG_SIM_MODEL dialog( this, *m_libEntry, fields );
if( dialog.ShowModal() != wxID_OK )
return;
diff = (int) m_fields->size() - diff;
// Add in any new fields
for( const LIB_FIELD& editedField : fields )
{
bool found = false;
if( diff > 0 )
{
wxGridTableMessage msg( m_fields, wxGRIDTABLE_NOTIFY_ROWS_APPENDED, diff );
m_grid->ProcessTableMessage( msg );
for( LIB_FIELD& existingField : *m_fields )
{
if( existingField.GetName() == editedField.GetName() )
{
found = true;
existingField.SetText( editedField.GetText() );
break;
}
}
if( !found )
{
m_fields->emplace_back( editedField );
wxGridTableMessage msg( m_fields, wxGRIDTABLE_NOTIFY_ROWS_APPENDED, 1 );
m_grid->ProcessTableMessage( msg );
}
}
else if( diff < 0 )
// Remove any deleted fields
for( int ii = (int) m_fields->size() - 1; ii >= 0; /* advance in loop */ )
{
wxGridTableMessage msg( m_fields, wxGRIDTABLE_NOTIFY_ROWS_DELETED, 0, -diff );
m_grid->ProcessTableMessage( msg );
LIB_FIELD& existingField = m_fields->at( ii );
bool found = false;
for( LIB_FIELD& editedField : fields )
{
if( editedField.GetName() == existingField.GetName() )
{
found = true;
break;
}
}
if( found )
{
ii--;
}
else
{
m_fields->erase( m_fields->begin() + ii );
wxGridTableMessage msg( m_fields, wxGRIDTABLE_NOTIFY_ROWS_DELETED, ii, 1 );
m_grid->ProcessTableMessage( msg );
}
}
OnModify();

View File

@ -362,22 +362,22 @@ int DIALOG_SIM_COMMAND::ShowModal()
{ m_noiseRef, m_noiseRef->GetStringSelection() }
};
for( auto& c : cmbNet )
for( const std::pair<wxComboBox* const, wxString>& c : cmbNet )
c.first->Clear();
for( const auto& net : m_circuitModel->GetNets() )
for( const std::string& net : m_circuitModel->GetNets() )
{
for( auto& c : cmbNet )
for( const std::pair<wxComboBox* const, wxString>& c : cmbNet )
c.first->Append( net );
}
// Try to restore the previous selection, if possible
for( auto& c : cmbNet )
for( const std::pair<wxComboBox* const, wxString>& c : cmbNet )
{
int idx = c.first->FindString( c.second );
if( idx != wxNOT_FOUND )
c.first->SetSelection( idx );
c.first->SetSelection( idx );
}
return DIALOG_SIM_COMMAND_BASE::ShowModal();

View File

@ -50,7 +50,6 @@ DIALOG_SIM_MODEL<T_symbol, T_field>::DIALOG_SIM_MODEL( wxWindow* aParent, T_symb
: DIALOG_SIM_MODEL_BASE( aParent ),
m_symbol( aSymbol ),
m_fields( aFields ),
m_fieldsOrigin( aFields ),
m_libraryModelsMgr( Prj() ),
m_builtinModelsMgr( Prj() ),
m_prevModel( nullptr ),
@ -314,8 +313,6 @@ bool DIALOG_SIM_MODEL<T_symbol, T_field>::TransferDataFromWindow()
curModel().WriteFields( m_fields );
m_fieldsOrigin = m_fields;
return true;
}

View File

@ -82,7 +82,7 @@ public:
MODEL
};
DIALOG_SIM_MODEL( wxWindow* aParent, T_symbol& aSymbol, std::vector<T_field>& aSchFields );
DIALOG_SIM_MODEL( wxWindow* aParent, T_symbol& aSymbol, std::vector<T_field>& aFields );
~DIALOG_SIM_MODEL();
@ -143,8 +143,7 @@ private:
private:
T_symbol& m_symbol;
std::vector<T_field> m_fields; // Local copy of the fields
std::vector<T_field>& m_fieldsOrigin; // Pointer back to the source copy of the fields
std::vector<T_field>& m_fields;
SIM_LIB_MGR m_libraryModelsMgr;
SIM_LIB_MGR m_builtinModelsMgr;

View File

@ -544,24 +544,64 @@ void DIALOG_SYMBOL_PROPERTIES::OnEditSpiceModel( wxCommandEvent& event )
if( !m_fieldsGrid->CommitPendingChanges() )
return;
int diff = m_fields->size();
std::vector<SCH_FIELD> fields;
DIALOG_SIM_MODEL dialog( this, *m_symbol, *m_fields );
for( const SCH_FIELD& field : *m_fields )
fields.emplace_back( field );
DIALOG_SIM_MODEL dialog( this, *m_symbol, fields );
if( dialog.ShowModal() != wxID_OK )
return;
diff = (int) m_fields->size() - diff;
// Add in any new fields
for( const SCH_FIELD& editedField : fields )
{
bool found = false;
if( diff > 0 )
{
wxGridTableMessage msg( m_fields, wxGRIDTABLE_NOTIFY_ROWS_APPENDED, diff );
m_fieldsGrid->ProcessTableMessage( msg );
for( SCH_FIELD& existingField : *m_fields )
{
if( existingField.GetName() == editedField.GetName() )
{
found = true;
existingField.SetText( editedField.GetText() );
break;
}
}
if( !found )
{
m_fields->emplace_back( editedField );
wxGridTableMessage msg( m_fields, wxGRIDTABLE_NOTIFY_ROWS_APPENDED, 1 );
m_fieldsGrid->ProcessTableMessage( msg );
}
}
else if( diff < 0 )
// Remove any deleted fields
for( int ii = (int) m_fields->size() - 1; ii >= 0; /* advance in loop */ )
{
wxGridTableMessage msg( m_fields, wxGRIDTABLE_NOTIFY_ROWS_DELETED, 0, -diff );
m_fieldsGrid->ProcessTableMessage( msg );
SCH_FIELD& existingField = m_fields->at( ii );
bool found = false;
for( SCH_FIELD& editedField : fields )
{
if( editedField.GetName() == existingField.GetName() )
{
found = true;
break;
}
}
if( found )
{
ii--;
}
else
{
m_fields->erase( m_fields->begin() + ii );
wxGridTableMessage msg( m_fields, wxGRIDTABLE_NOTIFY_ROWS_DELETED, ii, 1 );
m_fieldsGrid->ProcessTableMessage( msg );
}
}
OnModify();