Symbol Library Editor: fix crash after renaming a symbol

Crash was caused by removal of the selected item from the
wxDataViewModel, which was later accessed in
COMPONENT_TREE::GetSelectedLibId(). To avoid the problem, the selection
is validated before regenerating the tree widget.

Fixes: lp:1740952
* https://bugs.launchpad.net/kicad/+bug/1740952
This commit is contained in:
Maciej Suminski 2018-01-09 13:48:00 +01:00
parent 6e65049a56
commit 8c42abc10c
5 changed files with 50 additions and 13 deletions

View File

@ -378,10 +378,6 @@ void LIB_EDIT_FRAME::OnRemovePart( wxCommandEvent& aEvent )
if( isCurrentPart( libId ) ) if( isCurrentPart( libId ) )
emptyScreen(); emptyScreen();
// Keeping a removed item selected may lead to a crash
if( m_treePane->GetCmpTree()->GetSelectedLibId( nullptr ) == libId )
m_treePane->GetCmpTree()->SelectLibId( LIB_ID( libId.GetLibNickname(), "" ) );
m_libMgr->RemovePart( libId.GetLibItemName(), libId.GetLibNickname() ); m_libMgr->RemovePart( libId.GetLibItemName(), libId.GetLibNickname() );
} }
@ -389,7 +385,8 @@ void LIB_EDIT_FRAME::OnRemovePart( wxCommandEvent& aEvent )
void LIB_EDIT_FRAME::OnCopyCutPart( wxCommandEvent& aEvent ) void LIB_EDIT_FRAME::OnCopyCutPart( wxCommandEvent& aEvent )
{ {
int unit = 0; int unit = 0;
LIB_ID partId = m_treePane->GetCmpTree()->GetSelectedLibId( &unit ); auto cmpTree = m_treePane->GetCmpTree();
LIB_ID partId = cmpTree->GetSelectedLibId( &unit );
LIB_PART* part = m_libMgr->GetBufferedPart( partId.GetLibItemName(), partId.GetLibNickname() ); LIB_PART* part = m_libMgr->GetBufferedPart( partId.GetLibItemName(), partId.GetLibNickname() );
if( !part ) if( !part )
@ -403,10 +400,6 @@ void LIB_EDIT_FRAME::OnCopyCutPart( wxCommandEvent& aEvent )
if( isCurrentPart( libId ) ) if( isCurrentPart( libId ) )
emptyScreen(); emptyScreen();
// Keeping a removed item selected may lead to a crash
if( m_treePane->GetCmpTree()->GetSelectedLibId( nullptr ) == libId )
m_treePane->GetCmpTree()->SelectLibId( LIB_ID( libId.GetLibNickname(), "" ) );
m_libMgr->RemovePart( libId.GetLibItemName(), libId.GetLibNickname() ); m_libMgr->RemovePart( libId.GetLibItemName(), libId.GetLibNickname() );
} }
} }

View File

@ -1635,6 +1635,11 @@ wxString LIB_EDIT_FRAME::getTargetLib() const
void LIB_EDIT_FRAME::SyncLibraries( bool aProgress ) void LIB_EDIT_FRAME::SyncLibraries( bool aProgress )
{ {
LIB_ID selected;
if( m_treePane )
selected = m_treePane->GetCmpTree()->GetSelectedLibId();
if( aProgress ) if( aProgress )
{ {
wxProgressDialog progressDlg( _( "Loading Symbol Libraries" ), wxProgressDialog progressDlg( _( "Loading Symbol Libraries" ),
@ -1650,7 +1655,31 @@ void LIB_EDIT_FRAME::SyncLibraries( bool aProgress )
} }
if( m_treePane ) if( m_treePane )
{
wxDataViewItem found;
if( selected.IsValid() )
{
// Check if the previously selected item is still valid,
// if not - it has to be unselected to prevent crash
found = m_libMgr->GetAdapter()->FindItem( selected );
if( !found )
m_treePane->GetCmpTree()->Unselect();
}
m_treePane->Regenerate(); m_treePane->Regenerate();
// Try to select the parent library, in case the part is not found
if( !found && selected.IsValid() )
{
selected.SetLibItemName( "" );
found = m_libMgr->GetAdapter()->FindItem( selected );
if( found )
m_treePane->GetCmpTree()->SelectLibId( selected );
}
}
} }

View File

@ -35,7 +35,10 @@
#include <symbol_lib_table.h> #include <symbol_lib_table.h>
#include <template_fieldnames.h> #include <template_fieldnames.h>
#include <dialog_edit_one_field.h> #include <dialog_edit_one_field.h>
#include <lib_manager.h> #include <lib_manager.h>
#include <widgets/cmp_tree_pane.h>
#include <component_tree.h>
void LIB_EDIT_FRAME::EditField( LIB_FIELD* aField ) void LIB_EDIT_FRAME::EditField( LIB_FIELD* aField )
@ -166,10 +169,11 @@ void LIB_EDIT_FRAME::EditField( LIB_FIELD* aField )
if( !parent->HasAlias( m_aliasName ) ) if( !parent->HasAlias( m_aliasName ) )
m_aliasName = newFieldValue; m_aliasName = newFieldValue;
if( newFieldValue != fieldText ) m_libMgr->RemovePart( fieldText, lib );
m_libMgr->RemovePart( fieldText, lib );
m_libMgr->UpdatePart( parent, lib ); m_libMgr->UpdatePart( parent, lib );
// Reselect the renamed part
m_treePane->GetCmpTree()->SelectLibId( LIB_ID( lib, newFieldValue ) );
} }

View File

@ -146,6 +146,12 @@ void COMPONENT_TREE::SelectLibId( const LIB_ID& aLibId )
} }
void COMPONENT_TREE::Unselect()
{
m_tree_ctrl->UnselectAll();
}
void COMPONENT_TREE::Regenerate() void COMPONENT_TREE::Regenerate()
{ {
STATE current; STATE current;
@ -232,7 +238,7 @@ void COMPONENT_TREE::setState( const STATE& aState )
// command is issued, otherwise it selects a random item (Windows) // command is issued, otherwise it selects a random item (Windows)
m_tree_ctrl->Thaw(); m_tree_ctrl->Thaw();
if( aState.selection.IsValid() ) if( !aState.selection.GetLibItemName().empty() || !aState.selection.GetLibNickname().empty() )
SelectLibId( aState.selection ); SelectLibId( aState.selection );
} }

View File

@ -77,6 +77,11 @@ public:
*/ */
void SelectLibId( const LIB_ID& aLibId ); void SelectLibId( const LIB_ID& aLibId );
/**
* Unselect currently selected item in wxDataViewCtrl
*/
void Unselect();
/** /**
* Associates a right click context menu for a specific node type. * Associates a right click context menu for a specific node type.
* @param aType is the node type to have a menu associated. * @param aType is the node type to have a menu associated.