altium: Allow extraction of names of footprints stored in *.PcbLib file
See: https://gitlab.com/kicad/code/kicad/-/issues/10274
This commit is contained in:
parent
c6504628f0
commit
2cc9517cfd
|
@ -54,7 +54,8 @@ public:
|
|||
template <typename Type>
|
||||
Type Read()
|
||||
{
|
||||
if( GetRemainingBytes() >= sizeof( Type ) )
|
||||
const size_t remainingBytes = GetRemainingBytes();
|
||||
if( remainingBytes >= sizeof( Type ) )
|
||||
{
|
||||
Type val = *(Type*) ( m_pos );
|
||||
m_pos += sizeof( Type );
|
||||
|
@ -62,6 +63,7 @@ public:
|
|||
}
|
||||
else
|
||||
{
|
||||
m_pos += remainingBytes; // Ensure remaining bytes are zero
|
||||
m_error = true;
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -156,6 +156,7 @@ const std::string FootprintPlaceFileExtension( "pos" );
|
|||
|
||||
const std::string KiCadFootprintLibPathExtension( "pretty" ); // this is a directory
|
||||
const std::string LegacyFootprintLibPathExtension( "mod" ); // this is a file
|
||||
const std::string AltiumFootprintLibPathExtension( "PcbLib" ); // this is a file
|
||||
const std::string EagleFootprintLibPathExtension( "lbr" ); // this is a file
|
||||
const std::string GedaPcbFootprintLibFileExtension( "fp" ); // this is a file
|
||||
|
||||
|
@ -361,6 +362,12 @@ wxString LegacyFootprintLibPathWildcard()
|
|||
}
|
||||
|
||||
|
||||
wxString AltiumFootprintLibPathWildcard()
|
||||
{
|
||||
return _( "Altium PCB footprint library files" ) + AddFileExtListToFilter( { "PcbLib" } );
|
||||
}
|
||||
|
||||
|
||||
wxString EagleFootprintLibPathWildcard()
|
||||
{
|
||||
return _( "Eagle ver. 6.x XML library files" ) + AddFileExtListToFilter( { "lbr" } );
|
||||
|
|
|
@ -147,6 +147,7 @@ extern const std::string ReportFileExtension;
|
|||
extern const std::string FootprintPlaceFileExtension;
|
||||
extern const std::string KiCadFootprintFileExtension;
|
||||
extern const std::string KiCadFootprintLibPathExtension;
|
||||
extern const std::string AltiumFootprintLibPathExtension;
|
||||
extern const std::string GedaPcbFootprintLibFileExtension;
|
||||
extern const std::string EagleFootprintLibPathExtension;
|
||||
extern const std::string DrawingSheetFileExtension;
|
||||
|
@ -223,6 +224,7 @@ extern wxString DocModulesFileName();
|
|||
extern wxString LegacyFootprintLibPathWildcard();
|
||||
extern wxString KiCadFootprintLibFileWildcard();
|
||||
extern wxString KiCadFootprintLibPathWildcard();
|
||||
extern wxString AltiumFootprintLibPathWildcard();
|
||||
extern wxString GedaPcbFootprintLibFileWildcard();
|
||||
extern wxString EagleFootprintLibPathWildcard();
|
||||
extern wxString TextFileWildcard();
|
||||
|
|
|
@ -84,6 +84,7 @@ struct SUPPORTED_FILE_TYPE
|
|||
*/
|
||||
enum {
|
||||
ID_PANEL_FPLIB_ADD_KICADMOD = ID_PCBNEW_END_LIST,
|
||||
ID_PANEL_FPLIB_ADD_ALTIUM,
|
||||
ID_PANEL_FPLIB_ADD_EAGLE6,
|
||||
ID_PANEL_FPLIB_ADD_KICADLEGACY,
|
||||
ID_PANEL_FPLIB_ADD_GEDA,
|
||||
|
@ -111,6 +112,11 @@ static const std::map<int, SUPPORTED_FILE_TYPE>& fileTypes()
|
|||
false, IO_MGR::KICAD_SEXP
|
||||
}
|
||||
},
|
||||
{ ID_PANEL_FPLIB_ADD_ALTIUM,
|
||||
{
|
||||
"Altium (*.PcbLib)", AltiumFootprintLibPathWildcard(), "", true, IO_MGR::ALTIUM_DESIGNER
|
||||
}
|
||||
},
|
||||
{ ID_PANEL_FPLIB_ADD_EAGLE6,
|
||||
{
|
||||
"Eagle 6.x (*.lbr)", EagleFootprintLibPathWildcard(), "", true, IO_MGR::EAGLE
|
||||
|
@ -369,6 +375,7 @@ PANEL_FP_LIB_TABLE::PANEL_FP_LIB_TABLE( DIALOG_EDIT_LIBRARY_TABLES* aParent,
|
|||
|
||||
choices.Add( IO_MGR::ShowType( IO_MGR::KICAD_SEXP ) );
|
||||
choices.Add( IO_MGR::ShowType( IO_MGR::LEGACY ) );
|
||||
choices.Add( IO_MGR::ShowType( IO_MGR::ALTIUM_DESIGNER ) );
|
||||
choices.Add( IO_MGR::ShowType( IO_MGR::EAGLE ) );
|
||||
choices.Add( IO_MGR::ShowType( IO_MGR::GEDA_PCB ) );
|
||||
|
||||
|
|
|
@ -138,6 +138,10 @@ IO_MGR::PCB_FILE_T IO_MGR::GuessPluginTypeFromLibPath( const wxString& aLibPath
|
|||
{
|
||||
ret = EAGLE;
|
||||
}
|
||||
else if( fn.GetExt() == AltiumFootprintLibPathExtension )
|
||||
{
|
||||
ret = ALTIUM_DESIGNER;
|
||||
}
|
||||
|
||||
// Test this one anyways, even though it's the default guess, to avoid
|
||||
// the wxURI instantiation below.
|
||||
|
|
|
@ -104,3 +104,37 @@ BOARD* ALTIUM_DESIGNER_PLUGIN::Load( const wxString& aFileName, BOARD* aAppendTo
|
|||
|
||||
return m_board;
|
||||
}
|
||||
|
||||
long long ALTIUM_DESIGNER_PLUGIN::GetLibraryTimestamp( const wxString& aLibraryPath ) const
|
||||
{
|
||||
// File hasn't been loaded yet.
|
||||
if( aLibraryPath.IsEmpty() )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
wxFileName fn( aLibraryPath );
|
||||
|
||||
if( fn.IsFileReadable() )
|
||||
{
|
||||
return fn.GetModificationTime().GetValue().GetValue();
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void ALTIUM_DESIGNER_PLUGIN::FootprintEnumerate( wxArrayString& aFootprintNames,
|
||||
const wxString& aLibraryPath, bool aBestEfforts,
|
||||
const PROPERTIES* aProperties )
|
||||
{
|
||||
ParseAltiumPcbLibFootprintNames( aFootprintNames, aLibraryPath );
|
||||
}
|
||||
|
||||
FOOTPRINT* ALTIUM_DESIGNER_PLUGIN::FootprintLoad( const wxString& aLibraryPath,
|
||||
const wxString& aFootprintName, bool aKeepUUID,
|
||||
const PROPERTIES* aProperties )
|
||||
{
|
||||
return nullptr; // TODO: implement
|
||||
}
|
||||
|
|
|
@ -46,11 +46,18 @@ public:
|
|||
|
||||
const wxString GetFileExtension() const override;
|
||||
|
||||
long long GetLibraryTimestamp( const wxString& aLibraryPath ) const override
|
||||
{
|
||||
// TODO?
|
||||
return 0;
|
||||
}
|
||||
long long GetLibraryTimestamp( const wxString& aLibraryPath ) const override;
|
||||
|
||||
void FootprintEnumerate( wxArrayString& aFootprintNames, const wxString& aLibraryPath,
|
||||
bool aBestEfforts, const PROPERTIES* aProperties = nullptr ) override;
|
||||
|
||||
FOOTPRINT* FootprintLoad( const wxString& aLibraryPath, const wxString& aFootprintName,
|
||||
bool aKeepUUID = false,
|
||||
const PROPERTIES* aProperties = nullptr ) override;
|
||||
|
||||
//bool FootprintExists( const wxString& aLibraryPath, const wxString& aFootprintName, const PROPERTIES* aProperties = nullptr );
|
||||
|
||||
bool IsFootprintLibWritable( const wxString& aLibraryPath ) override { return false; }
|
||||
|
||||
// -----</PUBLIC PLUGIN API>-------------------------------------------------
|
||||
|
||||
|
|
|
@ -58,16 +58,14 @@
|
|||
constexpr double BOLD_FACTOR = 1.75; // CSS font-weight-normal is 400; bold is 700
|
||||
|
||||
|
||||
void ParseAltiumPcb( BOARD* aBoard, const wxString& aFileName, PROGRESS_REPORTER* aProgressReporter,
|
||||
const std::map<ALTIUM_PCB_DIR, std::string>& aFileMapping )
|
||||
static std::vector<char> ReadFileIntoVector( const wxString& aFileName )
|
||||
{
|
||||
// Open file
|
||||
FILE* fp = wxFopen( aFileName, "rb" );
|
||||
|
||||
if( fp == nullptr )
|
||||
{
|
||||
wxLogError( _( "Cannot open file '%s'." ), aFileName );
|
||||
return;
|
||||
THROW_IO_ERROR( wxString::Format( _( "Cannot open file '%s'." ), aFileName ) );
|
||||
}
|
||||
|
||||
fseek( fp, 0, SEEK_END );
|
||||
|
@ -79,10 +77,11 @@ void ParseAltiumPcb( BOARD* aBoard, const wxString& aFileName, PROGRESS_REPORTER
|
|||
THROW_IO_ERROR( _( "Error reading file: cannot determine length." ) );
|
||||
}
|
||||
|
||||
std::unique_ptr<unsigned char[]> buffer( new unsigned char[len] );
|
||||
std::vector<char> buffer( len );
|
||||
|
||||
fseek( fp, 0, SEEK_SET );
|
||||
|
||||
size_t bytesRead = fread( buffer.get(), sizeof( unsigned char ), len, fp );
|
||||
size_t bytesRead = fread( buffer.data(), sizeof( unsigned char ), len, fp );
|
||||
fclose( fp );
|
||||
|
||||
if( static_cast<size_t>( len ) != bytesRead )
|
||||
|
@ -90,9 +89,18 @@ void ParseAltiumPcb( BOARD* aBoard, const wxString& aFileName, PROGRESS_REPORTER
|
|||
THROW_IO_ERROR( _( "Error reading file." ) );
|
||||
}
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
|
||||
void ParseAltiumPcb( BOARD* aBoard, const wxString& aFileName, PROGRESS_REPORTER* aProgressReporter,
|
||||
const std::map<ALTIUM_PCB_DIR, std::string>& aFileMapping )
|
||||
{
|
||||
std::vector<char> buffer = ReadFileIntoVector( aFileName );
|
||||
|
||||
try
|
||||
{
|
||||
CFB::CompoundFileReader reader( buffer.get(), bytesRead );
|
||||
CFB::CompoundFileReader reader( buffer.data(), buffer.size() );
|
||||
|
||||
// Parse File
|
||||
ALTIUM_PCB pcb( aBoard, aProgressReporter );
|
||||
|
@ -105,6 +113,51 @@ void ParseAltiumPcb( BOARD* aBoard, const wxString& aFileName, PROGRESS_REPORTER
|
|||
}
|
||||
|
||||
|
||||
void ParseAltiumPcbLibFootprintNames( wxArrayString& aFootprintNames, const wxString& aLibraryPath )
|
||||
{
|
||||
std::vector<char> buffer = ReadFileIntoVector( aLibraryPath );
|
||||
|
||||
try
|
||||
{
|
||||
CFB::CompoundFileReader reader( buffer.data(), buffer.size() );
|
||||
|
||||
std::string streamName = "Library\\Data";
|
||||
const CFB::COMPOUND_FILE_ENTRY* libraryData = FindStream( reader, streamName );
|
||||
if( libraryData == nullptr )
|
||||
{
|
||||
THROW_IO_ERROR( wxString::Format( _( "File not found: '%s'." ), streamName ) );
|
||||
}
|
||||
|
||||
ALTIUM_PARSER parser( reader, libraryData );
|
||||
|
||||
std::map<wxString, wxString> properties = parser.ReadProperties();
|
||||
|
||||
uint32_t numberOfFootprints = parser.Read<uint32_t>();
|
||||
aFootprintNames.Alloc( numberOfFootprints );
|
||||
for( size_t i = 0; i < numberOfFootprints; i++ )
|
||||
{
|
||||
parser.ReadAndSetSubrecordLength();
|
||||
wxString footprintName = parser.ReadWxString();
|
||||
aFootprintNames.Add( footprintName );
|
||||
}
|
||||
|
||||
if( parser.HasParsingError() )
|
||||
{
|
||||
THROW_IO_ERROR( wxString::Format( "%s stream was not parsed correctly", streamName ) );
|
||||
}
|
||||
|
||||
if( parser.GetRemainingBytes() != 0 )
|
||||
{
|
||||
THROW_IO_ERROR( wxString::Format( "%s stream is not fully parsed", streamName ) );
|
||||
}
|
||||
}
|
||||
catch( CFB::CFBException& exception )
|
||||
{
|
||||
THROW_IO_ERROR( exception.what() );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool IsAltiumLayerCopper( ALTIUM_LAYER aLayer )
|
||||
{
|
||||
return aLayer >= ALTIUM_LAYER::TOP_LAYER && aLayer <= ALTIUM_LAYER::BOTTOM_LAYER;
|
||||
|
|
|
@ -100,6 +100,14 @@ class PROGRESS_REPORTER;
|
|||
void ParseAltiumPcb( BOARD* aBoard, const wxString& aFileName, PROGRESS_REPORTER* aProgressReporter,
|
||||
const std::map<ALTIUM_PCB_DIR, std::string>& aFileMapping );
|
||||
|
||||
/**
|
||||
* Helper method to get all footprint names in a given library
|
||||
*
|
||||
* @param aFootprintNames footprint names to populate
|
||||
* @param aLibraryPath path to PcbLib
|
||||
*/
|
||||
void ParseAltiumPcbLibFootprintNames( wxArrayString& aFootprintNames,
|
||||
const wxString& aLibraryPath );
|
||||
|
||||
namespace CFB
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue