Handle exporting symbols into libraries already under LIB_MGR.

Fixes https://gitlab.com/kicad/code/kicad/-/issues/17840
This commit is contained in:
Jeff Young 2025-03-03 13:36:57 +00:00
parent 6b146874c1
commit afa4ebcc84
2 changed files with 142 additions and 98 deletions

View File

@ -692,7 +692,9 @@ public:
SYMBOL_SAVE_AS_HANDLER( LIB_SYMBOL_LIBRARY_MANAGER& aLibMgr, CONFLICT_STRATEGY aStrategy,
bool aValueFollowsName ) :
m_libMgr( aLibMgr ), m_strategy( aStrategy ), m_valueFollowsName( aValueFollowsName )
m_libMgr( aLibMgr ),
m_strategy( aStrategy ),
m_valueFollowsName( aValueFollowsName )
{
}
@ -990,7 +992,7 @@ void SYMBOL_EDIT_FRAME::saveSymbolCopyAs( bool aOpenCopy )
if( conflicts.size() == 1 && conflicts.front() == newName )
{
// The simplest case is when the symbol itself has a conflict
msg = wxString::Format( _( "Symbol '%s' already exists in library '%s'."
msg = wxString::Format( _( "Symbol '%s' already exists in library '%s'. "
"Do you want to overwrite it?" ),
newName, newLib );
@ -1082,6 +1084,144 @@ void SYMBOL_EDIT_FRAME::saveSymbolCopyAs( bool aOpenCopy )
}
void SYMBOL_EDIT_FRAME::ExportSymbol()
{
wxString msg;
LIB_SYMBOL* symbol = getTargetSymbol();
if( !symbol )
{
ShowInfoBarError( _( "There is no symbol selected to save." ) );
return;
}
wxFileName fn;
fn.SetName( symbol->GetName().Lower() );
fn.SetExt( FILEEXT::KiCadSymbolLibFileExtension );
wxFileDialog dlg( this, _( "Export Symbol" ), m_mruPath, fn.GetFullName(),
FILEEXT::KiCadSymbolLibFileWildcard(), wxFD_SAVE );
if( dlg.ShowModal() == wxID_CANCEL )
return;
auto strategy = SYMBOL_SAVE_AS_HANDLER::CONFLICT_STRATEGY::OVERWRITE;
fn = dlg.GetPath();
fn.MakeAbsolute();
wxString libraryName;
std::unique_ptr<LIB_SYMBOL> flattenedSymbol = symbol->Flatten();
for( const wxString& candidate : m_libMgr->GetLibraryNames() )
{
if( m_libMgr->GetLibrary( candidate )->GetFullURI( true ) == fn.GetFullPath() )
libraryName = candidate;
}
if( !libraryName.IsEmpty() )
{
SYMBOL_SAVE_AS_HANDLER saver( *m_libMgr, strategy, false );
if( m_libMgr->IsLibraryReadOnly( libraryName ) )
{
msg = wxString::Format( _( "Library '%s' is read-only." ), libraryName );
DisplayError( this, msg );
return;
}
if( m_libMgr->SymbolNameInUse( symbol->GetName(), libraryName ) )
{
msg = wxString::Format( _( "Symbol '%s' already exists in library '%s'." ),
symbol->GetName(), libraryName );
KIDIALOG errorDlg( this, msg, _( "Confirmation" ), wxOK | wxCANCEL | wxICON_WARNING );
errorDlg.SetOKLabel( _( "Overwrite" ) );
errorDlg.DoNotShowCheckbox( __FILE__, __LINE__ );
if( errorDlg.ShowModal() == wxID_CANCEL )
return;
}
saver.DoSave( *flattenedSymbol, symbol->GetName(), libraryName );
SyncLibraries( false );
return;
}
LIB_SYMBOL* old_symbol = nullptr;
SCH_IO_MGR::SCH_FILE_T pluginType = SCH_IO_MGR::GuessPluginTypeFromLibPath( fn.GetFullPath() );
if( pluginType == SCH_IO_MGR::SCH_FILE_UNKNOWN )
pluginType = SCH_IO_MGR::SCH_KICAD;
IO_RELEASER<SCH_IO> pi( SCH_IO_MGR::FindPlugin( pluginType ) );
if( fn.FileExists() )
{
try
{
old_symbol = pi->LoadSymbol( fn.GetFullPath(), symbol->GetName() );
}
catch( const IO_ERROR& ioe )
{
msg.Printf( _( "Error occurred attempting to load symbol library file '%s'." ),
fn.GetFullPath() );
DisplayErrorMessage( this, msg, ioe.What() );
return;
}
if( old_symbol )
{
msg.Printf( _( "Symbol %s already exists in library '%s'." ),
UnescapeString( symbol->GetName() ),
fn.GetFullName() );
KIDIALOG errorDlg( this, msg, _( "Confirmation" ), wxOK | wxCANCEL | wxICON_WARNING );
errorDlg.SetOKLabel( _( "Overwrite" ) );
errorDlg.DoNotShowCheckbox( __FILE__, __LINE__ );
if( errorDlg.ShowModal() == wxID_CANCEL )
return;
}
}
if( !fn.IsDirWritable() )
{
msg.Printf( _( "Insufficient permissions to save library '%s'." ), fn.GetFullPath() );
DisplayError( this, msg );
return;
}
try
{
if( !fn.FileExists() )
pi->CreateLibrary( fn.GetFullPath() );
// The flattened symbol is most likely what the user would want. As some point in
// the future as more of the symbol library inheritance is implemented, this may have
// to be changes to save symbols of inherited symbols.
pi->SaveSymbol( fn.GetFullPath(), flattenedSymbol.release() );
}
catch( const IO_ERROR& ioe )
{
msg.Printf( _( "Failed to create symbol library file '%s'." ), fn.GetFullPath() );
DisplayErrorMessage( this, msg, ioe.What() );
msg.Printf( _( "Error creating symbol library '%s'." ), fn.GetFullName() );
SetStatusText( msg );
return;
}
m_mruPath = fn.GetPath();
msg.Printf( _( "Symbol %s saved to library '%s'." ),
UnescapeString( symbol->GetName() ),
fn.GetFullPath() );
SetStatusText( msg );
}
void SYMBOL_EDIT_FRAME::UpdateAfterSymbolProperties( wxString* aOldName )
{
wxCHECK( m_symbol, /* void */ );

View File

@ -150,99 +150,3 @@ void SYMBOL_EDIT_FRAME::ImportSymbol()
}
void SYMBOL_EDIT_FRAME::ExportSymbol()
{
wxString msg;
LIB_SYMBOL* symbol = getTargetSymbol();
if( !symbol )
{
ShowInfoBarError( _( "There is no symbol selected to save." ) );
return;
}
wxFileName fn;
fn.SetName( symbol->GetName().Lower() );
fn.SetExt( FILEEXT::KiCadSymbolLibFileExtension );
wxFileDialog dlg( this, _( "Export Symbol" ), m_mruPath, fn.GetFullName(),
FILEEXT::KiCadSymbolLibFileWildcard(), wxFD_SAVE );
if( dlg.ShowModal() == wxID_CANCEL )
return;
fn = dlg.GetPath();
fn.MakeAbsolute();
LIB_SYMBOL* old_symbol = nullptr;
SCH_IO_MGR::SCH_FILE_T pluginType = SCH_IO_MGR::GuessPluginTypeFromLibPath( fn.GetFullPath() );
if( pluginType == SCH_IO_MGR::SCH_FILE_UNKNOWN )
pluginType = SCH_IO_MGR::SCH_KICAD;
IO_RELEASER<SCH_IO> pi( SCH_IO_MGR::FindPlugin( pluginType ) );
if( fn.FileExists() )
{
try
{
old_symbol = pi->LoadSymbol( fn.GetFullPath(), symbol->GetName() );
}
catch( const IO_ERROR& ioe )
{
msg.Printf( _( "Error occurred attempting to load symbol library file '%s'." ),
fn.GetFullPath() );
DisplayErrorMessage( this, msg, ioe.What() );
return;
}
if( old_symbol )
{
msg.Printf( _( "Symbol %s already exists in library '%s'." ),
UnescapeString( symbol->GetName() ),
fn.GetFullName() );
KIDIALOG errorDlg( this, msg, _( "Confirmation" ), wxOK | wxCANCEL | wxICON_WARNING );
errorDlg.SetOKLabel( _( "Overwrite" ) );
errorDlg.DoNotShowCheckbox( __FILE__, __LINE__ );
if( errorDlg.ShowModal() == wxID_CANCEL )
return;
}
}
if( fn.Exists() && !fn.IsDirWritable() )
{
msg.Printf( _( "Insufficient permissions to save library '%s'." ),
fn.GetFullPath() );
DisplayError( this, msg );
return;
}
try
{
if( !fn.FileExists() )
pi->CreateLibrary( fn.GetFullPath() );
// The flattened symbol is most likely what the user would want. As some point in
// the future as more of the symbol library inheritance is implemented, this may have
// to be changes to save symbols of inherited symbols.
pi->SaveSymbol( fn.GetFullPath(), symbol->Flatten().release() );
}
catch( const IO_ERROR& ioe )
{
msg.Printf( _( "Failed to create symbol library file '%s'." ), fn.GetFullPath() );
DisplayErrorMessage( this, msg, ioe.What() );
msg.Printf( _( "Error creating symbol library '%s'." ), fn.GetFullName() );
SetStatusText( msg );
return;
}
m_mruPath = fn.GetPath();
msg.Printf( _( "Symbol %s saved to library '%s'." ),
UnescapeString( symbol->GetName() ),
fn.GetFullPath() );
SetStatusText( msg );
}