kicad_cli: Allow upgrade of legacy and non-kicad symbol libraries

This commit is contained in:
Roberto Fernandez Bautista 2024-02-13 21:53:09 +01:00
parent 8dce6c0b67
commit f7ddd211d9
5 changed files with 116 additions and 90 deletions

View File

@ -912,7 +912,7 @@ void PANEL_SYM_LIB_TABLE::onConvertLegacyLibraries( wxCommandEvent& event )
wxString options = m_cur_grid->GetCellValue( row, COL_OPTIONS );
std::unique_ptr<STRING_UTF8_MAP> props( LIB_TABLE::ParseOptions( options.ToStdString() ) );
if( convertLibrary( props.get(), legacyLib.GetFullPath(), newLib.GetFullPath() ) )
if( SCH_IO_MGR::ConvertLibrary( props.get(), legacyLib.GetFullPath(), newLib.GetFullPath() ) )
{
relPath = NormalizePath( newLib.GetFullPath(), &Pgm().GetLocalEnvVariables(),
m_project );
@ -938,66 +938,6 @@ void PANEL_SYM_LIB_TABLE::onConvertLegacyLibraries( wxCommandEvent& event )
}
bool PANEL_SYM_LIB_TABLE::convertLibrary( STRING_UTF8_MAP* aOldFileProps, const wxString& aOldFilePath,
const wxString& aNewFilepath )
{
SCH_IO_MGR::SCH_FILE_T oldFileType = SCH_IO_MGR::GuessPluginTypeFromLibPath( aOldFilePath );
if( oldFileType == SCH_IO_MGR::SCH_FILE_UNKNOWN )
return false;
IO_RELEASER<SCH_IO> oldFilePI( SCH_IO_MGR::FindPlugin( oldFileType ) );
IO_RELEASER<SCH_IO> kicadPI( SCH_IO_MGR::FindPlugin( SCH_IO_MGR::SCH_KICAD ) );
std::vector<LIB_SYMBOL*> symbols;
std::vector<LIB_SYMBOL*> newSymbols;
std::map<LIB_SYMBOL*, LIB_SYMBOL*> symbolMap;
try
{
oldFilePI->EnumerateSymbolLib( symbols, aOldFilePath, aOldFileProps );
// Copy non-aliases first so we can build a map from symbols to newSymbols
for( LIB_SYMBOL* symbol : symbols )
{
if( symbol->IsAlias() )
continue;
symbol->SetName( EscapeString( symbol->GetName(), CTX_LIBID ) );
newSymbols.push_back( new LIB_SYMBOL( *symbol ) );
symbolMap[symbol] = newSymbols.back();
}
// Now do the aliases using the map to hook them up to their newSymbol parents
for( LIB_SYMBOL* symbol : symbols )
{
if( !symbol->IsAlias() )
continue;
symbol->SetName( EscapeString( symbol->GetName(), CTX_LIBID ) );
newSymbols.push_back( new LIB_SYMBOL( *symbol ) );
newSymbols.back()->SetParent( symbolMap[ symbol->GetParent().lock().get() ] );
}
// Create a blank library
kicadPI->SaveLibrary( aNewFilepath );
// Finally write out newSymbols
for( LIB_SYMBOL* symbol : newSymbols )
{
kicadPI->SaveSymbol( aNewFilepath, symbol );
}
}
catch( ... )
{
return false;
}
return true;
}
bool PANEL_SYM_LIB_TABLE::TransferDataFromWindow()
{
if( !m_cur_grid->CommitPendingChanges() )

View File

@ -65,9 +65,6 @@ private:
/// by examining all the full_uri columns.
void populateEnvironReadOnlyTable();
bool convertLibrary( STRING_UTF8_MAP* aOldFileProps, const wxString& aOldFilePath,
const wxString& aNewFilePath );
SYMBOL_LIB_TABLE_GRID* global_model() const;
SYMBOL_LIB_TABLE_GRID* project_model() const;

View File

@ -879,17 +879,7 @@ int EESCHEMA_JOBS_HANDLER::JobSymUpgrade( JOB* aJob )
wxFileName fn( upgradeJob->m_libraryPath );
fn.MakeAbsolute();
SCH_IO_KICAD_SEXPR_LIB_CACHE schLibrary( fn.GetFullPath() );
try
{
schLibrary.Load();
}
catch( ... )
{
m_reporter->Report( _( "Unable to load library\n" ), RPT_SEVERITY_ERROR );
return CLI::EXIT_CODES::ERR_UNKNOWN;
}
SCH_IO_MGR::SCH_FILE_T fileType = SCH_IO_MGR::GuessPluginTypeFromLibPath( fn.GetFullPath() );
if( !upgradeJob->m_outputLibraryPath.IsEmpty() )
{
@ -901,33 +891,65 @@ int EESCHEMA_JOBS_HANDLER::JobSymUpgrade( JOB* aJob )
return CLI::EXIT_CODES::ERR_INVALID_OUTPUT_CONFLICT;
}
}
bool shouldSave = upgradeJob->m_force
|| schLibrary.GetFileFormatVersionAtLoad() < SEXPR_SYMBOL_LIB_FILE_VERSION;
if( shouldSave )
else if( fileType != SCH_IO_MGR::SCH_KICAD )
{
m_reporter->Report( _( "Saving symbol library in updated format\n" ), RPT_SEVERITY_ACTION );
m_reporter->Report( _( "Output path must be specified to convert legacy and non-KiCad libraries\n" ),
RPT_SEVERITY_ERROR );
return CLI::EXIT_CODES::ERR_INVALID_OUTPUT_CONFLICT;
}
if( fileType == SCH_IO_MGR::SCH_KICAD )
{
SCH_IO_KICAD_SEXPR_LIB_CACHE schLibrary( fn.GetFullPath() );
try
{
if( !upgradeJob->m_outputLibraryPath.IsEmpty() )
{
schLibrary.SetFileName( upgradeJob->m_outputLibraryPath );
}
schLibrary.SetModified();
schLibrary.Save();
schLibrary.Load();
}
catch( ... )
{
m_reporter->Report( ( "Unable to save library\n" ), RPT_SEVERITY_ERROR );
m_reporter->Report( _( "Unable to load library\n" ), RPT_SEVERITY_ERROR );
return CLI::EXIT_CODES::ERR_UNKNOWN;
}
bool shouldSave =
upgradeJob->m_force
|| schLibrary.GetFileFormatVersionAtLoad() < SEXPR_SYMBOL_LIB_FILE_VERSION;
if( shouldSave )
{
m_reporter->Report( _( "Saving symbol library in updated format\n" ),
RPT_SEVERITY_ACTION );
try
{
if( !upgradeJob->m_outputLibraryPath.IsEmpty() )
{
schLibrary.SetFileName( upgradeJob->m_outputLibraryPath );
}
schLibrary.SetModified();
schLibrary.Save();
}
catch( ... )
{
m_reporter->Report( ( "Unable to save library\n" ), RPT_SEVERITY_ERROR );
return CLI::EXIT_CODES::ERR_UNKNOWN;
}
}
else
{
m_reporter->Report( _( "Symbol library was not updated\n" ), RPT_SEVERITY_INFO );
}
}
else
{
m_reporter->Report( _( "Symbol library was not updated\n" ), RPT_SEVERITY_INFO );
if( !SCH_IO_MGR::ConvertLibrary( nullptr, fn.GetAbsolutePath(), upgradeJob->m_outputLibraryPath ) )
{
m_reporter->Report( ( "Unable to convert library\n" ), RPT_SEVERITY_ERROR );
return CLI::EXIT_CODES::ERR_UNKNOWN;
}
}
return CLI::EXIT_CODES::OK;

View File

@ -39,6 +39,7 @@
#include <wildcards_and_files_ext.h>
#include <kiway_player.h>
#include <string_utils.h>
#define FMT_UNIMPLEMENTED _( "Plugin \"%s\" does not implement the \"%s\" function." )
#define FMT_NOTFOUND _( "Plugin type \"%s\" is not found." )
@ -185,3 +186,63 @@ SCH_IO_MGR::SCH_FILE_T SCH_IO_MGR::GuessPluginTypeFromSchPath( const wxString& a
return SCH_IO_MGR::SCH_FILE_UNKNOWN;
}
bool SCH_IO_MGR::ConvertLibrary( STRING_UTF8_MAP* aOldFileProps, const wxString& aOldFilePath,
const wxString& aNewFilepath )
{
SCH_IO_MGR::SCH_FILE_T oldFileType = SCH_IO_MGR::GuessPluginTypeFromLibPath( aOldFilePath );
if( oldFileType == SCH_IO_MGR::SCH_FILE_UNKNOWN )
return false;
IO_RELEASER<SCH_IO> oldFilePI( SCH_IO_MGR::FindPlugin( oldFileType ) );
IO_RELEASER<SCH_IO> kicadPI( SCH_IO_MGR::FindPlugin( SCH_IO_MGR::SCH_KICAD ) );
std::vector<LIB_SYMBOL*> symbols;
std::vector<LIB_SYMBOL*> newSymbols;
std::map<LIB_SYMBOL*, LIB_SYMBOL*> symbolMap;
try
{
oldFilePI->EnumerateSymbolLib( symbols, aOldFilePath, aOldFileProps );
// Copy non-aliases first, so we can build a map from symbols to newSymbols
for( LIB_SYMBOL* symbol : symbols )
{
if( symbol->IsAlias() )
continue;
symbol->SetName( EscapeString( symbol->GetName(), CTX_LIBID ) );
newSymbols.push_back( new LIB_SYMBOL( *symbol ) );
symbolMap[symbol] = newSymbols.back();
}
// Now do the aliases using the map to hook them up to their newSymbol parents
for( LIB_SYMBOL* symbol : symbols )
{
if( !symbol->IsAlias() )
continue;
symbol->SetName( EscapeString( symbol->GetName(), CTX_LIBID ) );
newSymbols.push_back( new LIB_SYMBOL( *symbol ) );
newSymbols.back()->SetParent( symbolMap[ symbol->GetParent().lock().get() ] );
}
// Create a blank library
kicadPI->SaveLibrary( aNewFilepath );
// Finally write out newSymbols
for( LIB_SYMBOL* symbol : newSymbols )
{
kicadPI->SaveSymbol( aNewFilepath, symbol );
}
}
catch( ... )
{
return false;
}
return true;
}

View File

@ -106,6 +106,12 @@ public:
* Return a plugin type given a schematic using the file extension of \a aSchematicPath.
*/
static SCH_FILE_T GuessPluginTypeFromSchPath( const wxString& aSchematicPath, int aCtl = 0 );
/**
* Convert a schematic symbol library to the latest KiCad format
*/
static bool ConvertLibrary( STRING_UTF8_MAP* aOldFileProps, const wxString& aOldFilePath,
const wxString& aNewFilepath );
};
#endif // _SCH_IO_MGR_H_