Symbol editor: fix crash caused by broken root symbol name.

The symbol editor selection criteria did not include LIB_FIELD objects
which allowed the root symbol name to be changed causing broken derived
symbol links.  Disable the symbols fields from being edited when a
derived part is shown in the editor to prevent this.

Add a missing warning that deleting a root symbol used to derive other
symbols would also delete all derived symbols from a library.  Give the
user a chance to cancel the delete operation in this case.

Fixes kicad/code/kicad#3654
This commit is contained in:
Wayne Stambaugh 2019-12-12 10:44:53 -05:00
parent eb3d32f967
commit bec878640c
4 changed files with 56 additions and 6 deletions

View File

@ -642,6 +642,15 @@ void LIB_MANAGER::GetRootSymbolNames( const wxString& aLibraryName,
}
bool LIB_MANAGER:: HasDerivedSymbols( const wxString& aSymbolName,
const wxString& aLibraryName )
{
LIB_BUFFER& libBuf = getLibraryBuffer( aLibraryName );
return libBuf.HasDerivedSymbols( aSymbolName );
}
wxString LIB_MANAGER::getLibraryName( const wxString& aFilePath )
{
wxFileName fn( aFilePath );

View File

@ -290,6 +290,14 @@ public:
void GetRootSymbolNames( const wxString& aLibName, wxArrayString& aRootSymbolNames );
/**
* Check if symbol \a aSymbolName in library \a aLibraryName is a root symbol that
* has derived symbols.
*
* @return true if \aSymbolName in \a aLibraryName has derived symbols.
*/
bool HasDerivedSymbols( const wxString& aSymbolName, const wxString& aLibraryName );
private:
///> Extracts library name basing on the file name
static wxString getLibraryName( const wxString& aFilePath );

View File

@ -460,7 +460,7 @@ void LIB_EDIT_FRAME::savePartAs()
if( new_lib.IsEmpty() )
{
DisplayError( NULL, _( "No library specified. Symbol could not be saved." ) );
DisplayError( this, _( "No library specified. Symbol could not be saved." ) );
return;
}
@ -471,7 +471,7 @@ void LIB_EDIT_FRAME::savePartAs()
if( new_name.IsEmpty() )
{
DisplayError( NULL, _( "No symbol name specified. Symbol could not be saved." ) );
DisplayError( this, _( "No symbol name specified. Symbol could not be saved." ) );
return;
}
@ -487,7 +487,6 @@ void LIB_EDIT_FRAME::savePartAs()
LIB_PART new_part( *part );
new_part.SetName( new_name );
fixDuplicateAliases( &new_part, new_lib );
m_libMgr->UpdatePart( &new_part, new_lib );
SyncLibraries( false );
m_treePane->GetLibTree()->SelectLibId( LIB_ID( new_lib, new_part.GetName() ) );
@ -539,13 +538,33 @@ void LIB_EDIT_FRAME::DeletePartFromLibrary()
LIB_ID libId = getTargetLibId();
if( m_libMgr->IsPartModified( libId.GetLibItemName(), libId.GetLibNickname() )
&& !IsOK( this, _( wxString::Format( "Component %s has been modified\n"
&& !IsOK( this, _( wxString::Format( "The symbol \"%s\" has been modified\n"
"Do you want to remove it from the library?",
libId.GetUniStringLibItemName() ) ) ) )
{
return;
}
if( m_libMgr->HasDerivedSymbols( libId.GetLibItemName(), libId.GetLibNickname() ) )
{
wxString msg;
msg.Printf( _( "The symbol \"%s\" is used to derive other symbols.\n"
"Deleting this symbol will delete all of the symbols derived from it.\n\n"
"Do you wish to delete this symbol and all of it's derivatives?" ),
libId.GetLibItemName().wx_str() );
wxMessageDialog::ButtonLabel yesButtonLabel( _( "Delete Symbol" ) );
wxMessageDialog::ButtonLabel noButtonLabel( _( "Keep Symbol" ) );
wxMessageDialog dlg( this, msg, _( "Warning" ),
wxYES_NO | wxYES_DEFAULT | wxICON_QUESTION | wxCENTER );
dlg.SetYesNoLabels( yesButtonLabel, noButtonLabel );
if( dlg.ShowModal() == wxID_NO )
return;
}
if( isCurrentPart( libId ) )
emptyScreen();

View File

@ -1083,17 +1083,31 @@ bool EE_SELECTION_TOOL::doSelectionMenu( EE_COLLECTOR* aCollector )
bool EE_SELECTION_TOOL::Selectable( const EDA_ITEM* aItem, bool checkVisibilityOnly ) const
{
// NOTE: in the future this is where eeschema layer/itemtype visibility will be handled
LIB_EDIT_FRAME* editFrame = dynamic_cast< LIB_EDIT_FRAME* >( m_frame );
wxCHECK( editFrame, false );
switch( aItem->Type() )
{
case SCH_PIN_T:
if( !static_cast<const SCH_PIN*>( aItem )->IsVisible() && !m_frame->GetShowAllPins() )
if( !static_cast<const SCH_PIN*>( aItem )->IsVisible() && !editFrame->GetShowAllPins() )
return false;
break;
case LIB_PART_T: // In libedit we do not want to select the symbol itself.
return false;
case LIB_FIELD_T:
{
LIB_PART* currentPart = editFrame->GetCurPart();
// Nothing in derived symbols is editable at the moment.
if( currentPart && currentPart->IsAlias() )
return false;
break;
}
case LIB_ARC_T:
case LIB_CIRCLE_T:
case LIB_TEXT_T:
@ -1102,7 +1116,6 @@ bool EE_SELECTION_TOOL::Selectable( const EDA_ITEM* aItem, bool checkVisibilityO
case LIB_BEZIER_T:
case LIB_PIN_T:
{
LIB_EDIT_FRAME* editFrame = (LIB_EDIT_FRAME*) m_frame;
LIB_ITEM* lib_item = (LIB_ITEM*) aItem;
if( lib_item->GetUnit() && lib_item->GetUnit() != editFrame->GetUnit() )
@ -1113,6 +1126,7 @@ bool EE_SELECTION_TOOL::Selectable( const EDA_ITEM* aItem, bool checkVisibilityO
break;
}
case SCH_MARKER_T: // Always selectable
return true;