Non-Kicad Project Importers: Fix the creation of project fp libraries

Adds a new function to PLUGIN GetImportedCachedLibraryFootprints() that
loads the library footprints of the board design that was imported
Fixes https://gitlab.com/kicad/code/kicad/-/issues/7449
This commit is contained in:
Roberto Fernandez Bautista 2021-01-31 21:55:51 +00:00 committed by Wayne Stambaugh
parent 297ff282f1
commit f559e94b00
10 changed files with 171 additions and 73 deletions

View File

@ -77,6 +77,7 @@ public:
// For the aCtl argument of OpenProjectFiles()
#define KICTL_EAGLE_BRD (1<<0) ///< chosen *.brd file is Eagle according to user.
#define KICTL_CREATE (1<<1) ///< caller thinks requested project files may not exist.
#define KICTL_IMPORT_LIB (1<<2) ///< import all footprints into a project library.
/**
* Open a project or set of files given by @a aFileList.

View File

@ -761,6 +761,90 @@ bool PCB_EDIT_FRAME::OpenProjectFiles( const std::vector<wxString>& aFileSet, in
"It will be converted to the new format when saved." ),
wxICON_WARNING );
}
// Import footprints into a project-specific library
//==================================================
// TODO: This should be refactored out of here into somewhere specific to the Project Import
// E.g. KICAD_MANAGER_FRAME::ImportNonKiCadProject
if( aCtl & KICTL_IMPORT_LIB )
{
wxFileName loadedBoardFn( fullFileName );
wxString libNickName = loadedBoardFn.GetName();
// Extract a footprint library from the design and add it to the fp-lib-table
// The footprints are saved in a new .pretty library.
// If this library already exists, all previous footprints will be deleted
std::vector<FOOTPRINT*> loadedFootprints = pi->GetImportedCachedLibraryFootprints();
wxString newLibPath = CreateNewLibrary( libNickName );
// Only create the new library if CreateNewLibrary succeeded (note that this fails if
// the library already exists and the user aborts after seeing the warning message
// which prompts the user to continue with overwrite or abort)
if( newLibPath.Length() > 0 )
{
PLUGIN::RELEASER piSexpr( IO_MGR::PluginFind( IO_MGR::KICAD_SEXP ) );
for( FOOTPRINT* footprint : loadedFootprints )
{
try
{
if( !footprint->GetFPID().GetLibItemName().empty() ) // Handle old boards.
{
footprint->SetReference( "REF**" );
piSexpr->FootprintSave( newLibPath, footprint );
delete footprint;
}
}
catch( const IO_ERROR& ioe )
{
wxLogError( wxString::Format( _( "Error occurred when saving footprint "
"'%s' to the project specific footprint "
"library: %s" ),
footprint->GetFPID().GetUniStringLibItemName(),
ioe.What() ) );
}
}
FP_LIB_TABLE* prjlibtable = Prj().PcbFootprintLibs();
const wxString& project_env = PROJECT_VAR_NAME;
wxString rel_path, env_path;
wxASSERT_MSG( wxGetEnv( project_env, &env_path ), "There is no project variable?" );
wxString result( newLibPath );
rel_path = result.Replace( env_path, wxString( "$(" + project_env + ")" ) ) ? result
: "";
FP_LIB_TABLE_ROW* row = new FP_LIB_TABLE_ROW( libNickName, rel_path,
wxT( "KiCad" ), wxEmptyString );
prjlibtable->InsertRow( row );
wxString tblName = Prj().FootprintLibTblName();
try
{
Prj().PcbFootprintLibs()->Save( tblName );
}
catch( const IO_ERROR& ioe )
{
wxLogError( wxString::Format( _( "Error occurred saving the project specific "
"footprint library table: %s" ),
ioe.What() ) );
}
// Update footprint LIB_IDs to point to the just imported library
for( FOOTPRINT* footprint : GetBoard()->Footprints() )
{
LIB_ID libId = footprint->GetFPID();
if( libId.GetLibItemName().empty() )
continue;
libId.SetLibNickname( libNickName );
footprint->SetFPID( libId );
}
}
}
}
{
@ -1101,76 +1185,8 @@ bool PCB_EDIT_FRAME::importFile( const wxString& aFileName, int aFileType )
{
case IO_MGR::CADSTAR_PCB_ARCHIVE:
case IO_MGR::EAGLE:
if( OpenProjectFiles( std::vector<wxString>( 1, aFileName ), KICTL_EAGLE_BRD ) )
{
wxString projectpath = Kiway().Prj().GetProjectPath();
wxFileName newfilename;
newfilename.SetPath( Prj().GetProjectPath() );
newfilename.SetName( Prj().GetProjectName() );
newfilename.SetExt( KiCadPcbFileExtension );
GetBoard()->SetFileName( newfilename.GetFullPath() );
UpdateTitle();
OnModify();
// Extract a footprint library from the design and add it to the fp-lib-table
wxString newLibPath;
ExportFootprintsToLibrary( true, newfilename.GetName(), &newLibPath );
if( newLibPath.Length() > 0 )
{
FP_LIB_TABLE* prjlibtable = Prj().PcbFootprintLibs();
const wxString& project_env = PROJECT_VAR_NAME;
wxString rel_path, env_path;
wxGetEnv( project_env, &env_path );
wxString result( newLibPath );
rel_path = result.Replace( env_path,
wxString( "$(" + project_env + ")" ) ) ? result : "" ;
if( !rel_path.IsEmpty() )
newLibPath = rel_path;
FP_LIB_TABLE_ROW* row = new FP_LIB_TABLE_ROW( newfilename.GetName(),
newLibPath, wxT( "KiCad" ), wxEmptyString );
prjlibtable->InsertRow( row );
}
if( !GetBoard()->GetFileName().IsEmpty() )
{
wxString tblName = Prj().FootprintLibTblName();
try
{
Prj().PcbFootprintLibs()->Save( tblName );
}
catch( const IO_ERROR& ioe )
{
wxString msg = wxString::Format( _(
"Error occurred saving project specific footprint library "
"table:\n\n%s" ), ioe.What() );
wxMessageBox( msg, _( "File Save Error" ), wxOK | wxICON_ERROR );
}
}
// Update footprint LIB_IDs to point to the just imported library
for( FOOTPRINT* footprint : GetBoard()->Footprints() )
{
LIB_ID libId = footprint->GetFPID();
if( libId.GetLibItemName().empty() )
continue;
libId.SetLibNickname( newfilename.GetName() );
footprint->SetFPID( libId );
}
return true;
}
return false;
return OpenProjectFiles( std::vector<wxString>( 1, aFileName ),
KICTL_EAGLE_BRD | KICTL_IMPORT_LIB );
default:
return false;

View File

@ -306,6 +306,16 @@ public:
virtual BOARD* Load( const wxString& aFileName, BOARD* aAppendToMe,
const PROPERTIES* aProperties = nullptr, PROJECT* aProject = nullptr );
/**
* Return a container with the cached library footprints generated in the last call to
* #Load. This function is intended to be used ONLY by the non-KiCad board importers for the
* purpose of obtaining the footprint library of the design and creating a project-specific
* library.
*
* @return Footprints (caller owns the objects)
*/
virtual std::vector<FOOTPRINT*> GetImportedCachedLibraryFootprints();
/**
* Write @a aBoard to a storage file in a format that this PLUGIN implementation knows
* about or it can be used to write a portion of \a aBoard to a special kind of export

View File

@ -51,6 +51,12 @@ BOARD* PLUGIN::Load( const wxString& aFileName, BOARD* aAppendToMe, const PROPER
}
std::vector<FOOTPRINT*> PLUGIN::GetImportedCachedLibraryFootprints()
{
not_implemented( this, __FUNCTION__ );
return std::vector<FOOTPRINT*>();
}
void PLUGIN::Save( const wxString& aFileName, BOARD* aBoard, const PROPERTIES* aProperties )
{
// not pure virtual so that plugins only have to implement subset of the PLUGIN interface.

View File

@ -128,6 +128,18 @@ void CADSTAR_PCB_ARCHIVE_LOADER::Load( ::BOARD* aBoard, ::PROJECT* aProject )
"Please review the import errors and warnings (if any)." ) );
}
std::vector<FOOTPRINT*> CADSTAR_PCB_ARCHIVE_LOADER::GetLoadedLibraryFootpints() const
{
std::vector<FOOTPRINT*> retval;
for( std::pair<SYMDEF_ID, FOOTPRINT*> fpPair : mLibraryMap )
{
retval.push_back( static_cast<FOOTPRINT*>( fpPair.second->Clone() ) );
}
return retval;
}
void CADSTAR_PCB_ARCHIVE_LOADER::logBoardStackupWarning(
const wxString& aCadstarLayerName,

View File

@ -71,6 +71,11 @@ public:
*/
void Load( ::BOARD* aBoard, ::PROJECT* aProject );
/**
* @brief Return a copy of the loaded library footprints (caller owns the objects)
* @return Container with all the footprint definitions that were loaded
*/
std::vector<FOOTPRINT*> GetLoadedLibraryFootpints() const;
private:
LAYER_MAPPING_HANDLER mLayerMappingHandler; ///< Callback to get layer mapping

View File

@ -27,6 +27,7 @@
#include <cadstar_pcb_archive_loader.h>
#include <cadstar_pcb_archive_plugin.h>
#include <board.h>
#include <footprint.h>
#include <properties.h>
@ -68,6 +69,17 @@ CADSTAR_PCB_ARCHIVE_PLUGIN::~CADSTAR_PCB_ARCHIVE_PLUGIN()
}
void CADSTAR_PCB_ARCHIVE_PLUGIN::clearLoadedFootprints()
{
for( FOOTPRINT* fp : m_loaded_footprints )
{
delete fp;
}
m_loaded_footprints.clear();
}
const wxString CADSTAR_PCB_ARCHIVE_PLUGIN::PluginName() const
{
return wxT( "CADSTAR PCB Archive" );
@ -80,11 +92,25 @@ const wxString CADSTAR_PCB_ARCHIVE_PLUGIN::GetFileExtension() const
}
std::vector<FOOTPRINT*> CADSTAR_PCB_ARCHIVE_PLUGIN::GetImportedCachedLibraryFootprints()
{
std::vector<FOOTPRINT*> retval;
for( FOOTPRINT* fp : m_loaded_footprints )
{
retval.push_back( static_cast<FOOTPRINT*>( fp->Clone() ) );
}
return retval;
}
BOARD* CADSTAR_PCB_ARCHIVE_PLUGIN::Load( const wxString& aFileName, BOARD* aAppendToMe,
const PROPERTIES* aProperties, PROJECT* aProject )
{
m_props = aProperties;
m_board = aAppendToMe ? aAppendToMe : new BOARD();
clearLoadedFootprints();
CADSTAR_PCB_ARCHIVE_LOADER tempPCB(
aFileName, m_layer_mapping_handler, m_show_layer_mapping_warnings );
@ -111,5 +137,7 @@ BOARD* CADSTAR_PCB_ARCHIVE_PLUGIN::Load( const wxString& aFileName, BOARD* aAppe
}
}
m_loaded_footprints = tempPCB.GetLoadedLibraryFootpints();
return m_board;
}

View File

@ -49,6 +49,8 @@ public:
return 0;
}
std::vector<FOOTPRINT*> GetImportedCachedLibraryFootprints() override;
/**
* Return the automapped layers.
*
@ -69,9 +71,12 @@ public:
~CADSTAR_PCB_ARCHIVE_PLUGIN();
private:
const PROPERTIES* m_props;
BOARD* m_board;
bool m_show_layer_mapping_warnings;
void clearLoadedFootprints();
const PROPERTIES* m_props;
BOARD* m_board;
std::vector<FOOTPRINT*> m_loaded_footprints;
bool m_show_layer_mapping_warnings;
};
#endif // CADSTAR_ARCHIVE_PLUGIN_H_

View File

@ -402,6 +402,19 @@ BOARD* EAGLE_PLUGIN::Load( const wxString& aFileName, BOARD* aAppendToMe,
}
std::vector<FOOTPRINT*> EAGLE_PLUGIN::GetImportedCachedLibraryFootprints()
{
std::vector<FOOTPRINT*> retval;
for( std::pair<wxString, FOOTPRINT*> fp : m_templates )
{
retval.push_back( static_cast<FOOTPRINT*>( fp.second->Clone() ) );
}
return retval;
}
void EAGLE_PLUGIN::init( const PROPERTIES* aProperties )
{
m_hole_count = 0;

View File

@ -132,6 +132,8 @@ public:
BOARD* Load( const wxString& aFileName, BOARD* aAppendToMe,
const PROPERTIES* aProperties = nullptr, PROJECT* aProject = nullptr ) override;
std::vector<FOOTPRINT*> GetImportedCachedLibraryFootprints() override;
const wxString GetFileExtension() const override;
void FootprintEnumerate( wxArrayString& aFootprintNames, const wxString& aLibraryPath,