Auto-recognition of nested library tables.

This commit is contained in:
Jeff Young
2025-11-06 17:33:26 +00:00
parent fa582d23f7
commit bd831fc959
9 changed files with 71 additions and 53 deletions
+21 -13
View File
@@ -39,13 +39,16 @@
#include <ki_exception.h>
#include <trace_helpers.h>
#include <fstream>
#include <libraries/library_table.h>
#include <libraries/library_table_parser.h>
const wxString DESIGN_BLOCK_IO_MGR::ShowType( DESIGN_BLOCK_FILE_T aFileType )
{
switch( aFileType )
{
case KICAD_SEXP: return _( "KiCad" );
default: return wxString::Format( _( "UNKNOWN (%d)" ), aFileType );
case KICAD_SEXP: return _( "KiCad" );
case NESTED_TABLE: return LIBRARY_TABLE_ROW::TABLE_TYPE_NAME;
default: return wxString::Format( _( "UNKNOWN (%d)" ), aFileType );
}
}
@@ -54,7 +57,9 @@ DESIGN_BLOCK_IO_MGR::DESIGN_BLOCK_FILE_T
DESIGN_BLOCK_IO_MGR::EnumFromStr( const wxString& aFileType )
{
if( aFileType == _( "KiCad" ) )
return DESIGN_BLOCK_FILE_T( KICAD_SEXP );
return DESIGN_BLOCK_FILE_T::KICAD_SEXP;
else if( aFileType == LIBRARY_TABLE_ROW::TABLE_TYPE_NAME )
return DESIGN_BLOCK_FILE_T::NESTED_TABLE;
return DESIGN_BLOCK_FILE_T( DESIGN_BLOCK_FILE_UNKNOWN );
}
@@ -64,8 +69,8 @@ DESIGN_BLOCK_IO* DESIGN_BLOCK_IO_MGR::FindPlugin( DESIGN_BLOCK_FILE_T aFileType
{
switch( aFileType )
{
case KICAD_SEXP: return new DESIGN_BLOCK_IO();
default: return nullptr;
case KICAD_SEXP: return new DESIGN_BLOCK_IO();
default: return nullptr;
}
}
@@ -73,6 +78,11 @@ DESIGN_BLOCK_IO* DESIGN_BLOCK_IO_MGR::FindPlugin( DESIGN_BLOCK_FILE_T aFileType
DESIGN_BLOCK_IO_MGR::DESIGN_BLOCK_FILE_T
DESIGN_BLOCK_IO_MGR::GuessPluginTypeFromLibPath( const wxString& aLibPath, int aCtl )
{
LIBRARY_TABLE_PARSER parser;
if( parser.Parse( aLibPath.ToStdString() ).has_value() )
return NESTED_TABLE;
if( IO_RELEASER<DESIGN_BLOCK_IO>( FindPlugin( KICAD_SEXP ) )->CanReadLibrary( aLibPath )
&& aCtl != KICTL_NONKICAD_ONLY )
{
@@ -95,8 +105,7 @@ bool DESIGN_BLOCK_IO_MGR::ConvertLibrary( std::map<std::string, UTF8>* aOldFileP
IO_RELEASER<DESIGN_BLOCK_IO> oldFilePI( DESIGN_BLOCK_IO_MGR::FindPlugin( oldFileType ) );
IO_RELEASER<DESIGN_BLOCK_IO> kicadPI(
DESIGN_BLOCK_IO_MGR::FindPlugin( DESIGN_BLOCK_IO_MGR::KICAD_SEXP ) );
IO_RELEASER<DESIGN_BLOCK_IO> kicadPI( DESIGN_BLOCK_IO_MGR::FindPlugin( DESIGN_BLOCK_IO_MGR::KICAD_SEXP ) );
wxArrayString dbNames;
wxFileName newFileName( aNewFilePath );
@@ -118,8 +127,8 @@ bool DESIGN_BLOCK_IO_MGR::ConvertLibrary( std::map<std::string, UTF8>* aOldFileP
for( const wxString& dbName : dbNames )
{
std::unique_ptr<const DESIGN_BLOCK> db(
oldFilePI->GetEnumeratedDesignBlock( aOldFilePath, dbName, aOldFileProps ) );
std::unique_ptr<const DESIGN_BLOCK> db( oldFilePI->GetEnumeratedDesignBlock( aOldFilePath, dbName,
aOldFileProps ) );
kicadPI->DesignBlockSave( aNewFilePath, db.get() );
}
}
@@ -227,8 +236,7 @@ bool DESIGN_BLOCK_IO::DeleteLibrary( const wxString& aLibrary
if( tmp.GetExt() != FILEEXT::KiCadDesignBlockLibPathExtension )
{
THROW_IO_ERROR( wxString::Format( _( "Unexpected folder '%s' found in library "
"path '%s'." ),
THROW_IO_ERROR( wxString::Format( _( "Unexpected folder '%s' found in library path '%s'." ),
dirs[i].GetData(), aLibraryPath.GetData() ) );
}
}
@@ -340,8 +348,8 @@ DESIGN_BLOCK* DESIGN_BLOCK_IO::DesignBlockLoad( const wxString& aLibraryPath,
catch( ... )
{
delete newDB;
THROW_IO_ERROR( wxString::Format(
_( "Design block metadata file '%s' could not be read." ), dbMetadataPath ) );
THROW_IO_ERROR( wxString::Format( _( "Design block metadata file '%s' could not be read." ),
dbMetadataPath ) );
}
}
+2 -1
View File
@@ -40,7 +40,8 @@ public:
DESIGN_BLOCK_FILE_UNKNOWN = 0, ///< 0 is not a legal menu id on Mac
KICAD_SEXP, ///< S-expression KiCad file format.
FILE_TYPE_NONE
FILE_TYPE_NONE,
NESTED_TABLE
};
static const wxString ShowType( DESIGN_BLOCK_FILE_T aFileType );
@@ -176,10 +176,8 @@ public:
DESIGN_BLOCK_IO_MGR::DESIGN_BLOCK_FILE_T pluginType =
DESIGN_BLOCK_IO_MGR::GuessPluginTypeFromLibPath( uri );
if( pluginType == DESIGN_BLOCK_IO_MGR::FILE_TYPE_NONE )
pluginType = DESIGN_BLOCK_IO_MGR::KICAD_SEXP;
SetValue( aRow, COL_TYPE, DESIGN_BLOCK_IO_MGR::ShowType( pluginType ) );
if( pluginType != DESIGN_BLOCK_IO_MGR::FILE_TYPE_NONE )
SetValue( aRow, COL_TYPE, DESIGN_BLOCK_IO_MGR::ShowType( pluginType ) );
}
}
+4 -7
View File
@@ -603,10 +603,9 @@ void PANEL_SYM_LIB_TABLE::browseLibrariesHandler( wxCommandEvent& event )
{
// The cancel button adds the library to the table anyway
addDuplicates = OKOrCancelDialog( wxGetTopLevelParent( this ), _( "Warning: Duplicate Nickname" ),
wxString::Format( _( "A library nicknamed '%s' already exists." ),
wxString::Format( _( "An item nicknamed '%s' already exists." ),
nickname ),
_( "One of the nicknames will need to be changed after adding "
"this library." ),
_( "One of the nicknames will need to be changed." ),
_( "Skip" ), _( "Add Anyway" ),
&applyToAll ) == wxID_CANCEL;
}
@@ -623,10 +622,8 @@ void PANEL_SYM_LIB_TABLE::browseLibrariesHandler( wxCommandEvent& event )
// attempt to auto-detect the plugin type
SCH_IO_MGR::SCH_FILE_T pluginType = SCH_IO_MGR::GuessPluginTypeFromLibPath( filePath );
if( pluginType == SCH_IO_MGR::SCH_FILE_UNKNOWN )
pluginType = SCH_IO_MGR::SCH_KICAD;
m_cur_grid->SetCellValue( last_row, COL_TYPE, SCH_IO_MGR::ShowType( pluginType ) );
if( pluginType != SCH_IO_MGR::SCH_FILE_UNKNOWN )
m_cur_grid->SetCellValue( last_row, COL_TYPE, SCH_IO_MGR::ShowType( pluginType ) );
// try to use path normalized to an environmental variable or project path
wxString path = NormalizePath( filePath, &envVars, m_project->GetProjectPath() );
+10 -4
View File
@@ -40,6 +40,7 @@
#include <wildcards_and_files_ext.h>
#include <kiway_player.h>
#include <string_utils.h>
#include <libraries/library_table_parser.h>
#define FMT_UNIMPLEMENTED _( "Plugin '%s' does not implement the '%s' function." )
#define FMT_NOTFOUND _( "Plugin type '%s' is not found." )
@@ -98,8 +99,8 @@ const wxString SCH_IO_MGR::ShowType( SCH_FILE_T aType )
case SCH_EASYEDAPRO: return wxString( wxT( "EasyEDA (JLCEDA) Pro" ) );
case SCH_LTSPICE: return wxString( wxT( "LTspice" ) );
case SCH_HTTP: return wxString( wxT( "HTTP" ) );
default: return wxString::Format( _( "Unknown SCH_FILE_T value: %d" ),
aType );
case SCH_NESTED_TABLE: return LIBRARY_TABLE_ROW::TABLE_TYPE_NAME;
default: return wxString::Format( _( "Unknown SCH_FILE_T value: %d" ), aType );
}
}
@@ -130,8 +131,8 @@ SCH_IO_MGR::SCH_FILE_T SCH_IO_MGR::EnumFromStr( const wxString& aType )
return SCH_LTSPICE;
else if( aType == wxT( "HTTP" ) )
return SCH_HTTP;
// wxASSERT( blow up here )
else if( aType == LIBRARY_TABLE_ROW::TABLE_TYPE_NAME )
return SCH_NESTED_TABLE;
return SCH_FILE_UNKNOWN;
}
@@ -139,6 +140,11 @@ SCH_IO_MGR::SCH_FILE_T SCH_IO_MGR::EnumFromStr( const wxString& aType )
SCH_IO_MGR::SCH_FILE_T SCH_IO_MGR::GuessPluginTypeFromLibPath( const wxString& aLibPath, int aCtl )
{
LIBRARY_TABLE_PARSER parser;
if( parser.Parse( aLibPath.ToStdString() ).has_value() )
return SCH_NESTED_TABLE;
for( const SCH_IO_MGR::SCH_FILE_T& fileType : SCH_IO_MGR::SCH_FILE_T_vector )
{
bool isKiCad = fileType == SCH_IO_MGR::SCH_KICAD || fileType == SCH_IO_MGR::SCH_LEGACY;
+2 -1
View File
@@ -69,7 +69,8 @@ public:
SCH_HTTP, ///< KiCad HTTP library
// Add your schematic type here.
SCH_FILE_UNKNOWN
SCH_FILE_UNKNOWN,
SCH_NESTED_TABLE
} )
// clang-format on
+15 -17
View File
@@ -103,10 +103,8 @@ public:
wxString uri = LIBRARY_MANAGER::ExpandURI( row.URI(), Pgm().GetSettingsManager().Prj() );
PCB_IO_MGR::PCB_FILE_T pluginType = PCB_IO_MGR::GuessPluginTypeFromLibPath( uri );
if( pluginType == PCB_IO_MGR::FILE_TYPE_NONE )
pluginType = PCB_IO_MGR::KICAD_SEXP;
SetValue( aRow, COL_TYPE, PCB_IO_MGR::ShowType( pluginType ) );
if( pluginType != PCB_IO_MGR::FILE_TYPE_NONE )
SetValue( aRow, COL_TYPE, PCB_IO_MGR::ShowType( pluginType ) );
}
}
@@ -115,12 +113,8 @@ protected:
{
FP_LIB_TABLE_GRID_DATA_MODEL* table = static_cast<FP_LIB_TABLE_GRID_DATA_MODEL*>( aGrid->GetTable() );
LIBRARY_TABLE_ROW& tableRow = table->at( aRow );
if( tableRow.Type() == LIBRARY_TABLE_ROW::TABLE_TYPE_NAME )
return wxEmptyString;
PCB_IO_MGR::PCB_FILE_T fileType = PCB_IO_MGR::EnumFromStr( tableRow.Type() );
const IO_BASE::IO_FILE_DESC& pluginDesc = m_supportedFpFiles.at( fileType );
PCB_IO_MGR::PCB_FILE_T fileType = PCB_IO_MGR::EnumFromStr( tableRow.Type() );
const IO_BASE::IO_FILE_DESC& pluginDesc = m_supportedFpFiles.at( fileType );
if( pluginDesc.m_IsFile )
return pluginDesc.FileFilter();
@@ -270,10 +264,6 @@ PANEL_FP_LIB_TABLE::PANEL_FP_LIB_TABLE( DIALOG_EDIT_LIBRARY_TABLES* aParent, PRO
for( auto& [fileType, desc] : m_supportedFpFiles )
m_pluginChoices.Add( PCB_IO_MGR::ShowType( fileType ) );
// TODO(JE) should use translated string here but type is stored as untranslated string
// Maybe type storage needs to be enum?
m_pluginChoices.Add( wxT( "Table" ) );
std::optional<LIBRARY_TABLE*> table = Pgm().GetLibraryManager().Table( LIBRARY_TABLE_TYPE::FOOTPRINT,
LIBRARY_TABLE_SCOPE::GLOBAL );
wxASSERT( table );
@@ -424,6 +414,9 @@ void PANEL_FP_LIB_TABLE::populatePluginList()
if( const IO_BASE::IO_FILE_DESC& desc = pi->GetLibraryDesc() )
m_supportedFpFiles.emplace( plugin.m_type, desc );
}
m_supportedFpFiles.emplace( PCB_IO_MGR::NESTED_TABLE,
IO_BASE::IO_FILE_DESC( _( "Table (nested library table)" ), {} ) );
}
@@ -799,10 +792,15 @@ void PANEL_FP_LIB_TABLE::browseLibrariesHandler( wxCommandEvent& event )
const IO_BASE::IO_FILE_DESC& fileDesc = m_supportedFpFiles.at( fileType );
PCBNEW_SETTINGS* cfg = GetAppSettings<PCBNEW_SETTINGS>( "pcbnew" );
wxString title = wxString::Format( _( "Select %s Library" ), PCB_IO_MGR::ShowType( fileType ) );
wxString title;
wxString dummy;
wxString* lastDir;
if( fileType == PCB_IO_MGR::NESTED_TABLE )
title = _( "Select Library Table" );
else
title = wxString::Format( _( "Select %s Library" ), PCB_IO_MGR::ShowType( fileType ) );
if( m_cur_grid == m_project_grid )
lastDir = &m_lastProjectLibDir;
else
@@ -848,8 +846,8 @@ void PANEL_FP_LIB_TABLE::browseLibrariesHandler( wxCommandEvent& event )
bool addDuplicates = false;
bool applyToAll = false;
wxString warning = _( "Warning: Duplicate Nicknames" );
wxString msg = _( "A library nicknamed '%s' already exists." );
wxString detailedMsg = _( "One of the nicknames will need to be changed after adding this library." );
wxString msg = _( "An item nicknamed '%s' already exists." );
wxString detailedMsg = _( "One of the nicknames will need to be changed." );
for( const wxString& filePath : files )
{
+13 -5
View File
@@ -28,6 +28,7 @@
#include <config.h>
#include <kiway_player.h>
#include <wildcards_and_files_ext.h>
#include <libraries/library_table.h>
#include <pcb_io/pcb_io_mgr.h>
#include <pcb_io/eagle/pcb_io_eagle.h>
@@ -46,7 +47,7 @@
#include <pcb_io/ipc2581/pcb_io_ipc2581.h>
#include <pcb_io/odbpp/pcb_io_odbpp.h>
#include <reporter.h>
#include <libraries/library_table_parser.h>
#define FMT_UNIMPLEMENTED _( "Plugin '%s' does not implement the '%s' function." )
@@ -76,14 +77,15 @@ PCB_IO* PCB_IO_MGR::FindPlugin( PCB_FILE_T aFileType )
const wxString PCB_IO_MGR::ShowType( PCB_FILE_T aType )
{
if( aType == PCB_IO_MGR::NESTED_TABLE )
return LIBRARY_TABLE_ROW::TABLE_TYPE_NAME;
const auto& plugins = PLUGIN_REGISTRY::Instance()->AllPlugins();
for( const auto& plugin : plugins )
{
if ( plugin.m_type == aType )
{
return plugin.m_name;
}
}
return wxString::Format( _( "UNKNOWN (%d)" ), aType );
@@ -92,14 +94,15 @@ const wxString PCB_IO_MGR::ShowType( PCB_FILE_T aType )
PCB_IO_MGR::PCB_FILE_T PCB_IO_MGR::EnumFromStr( const wxString& aType )
{
if( aType == LIBRARY_TABLE_ROW::TABLE_TYPE_NAME )
return PCB_IO_MGR::NESTED_TABLE;
const auto& plugins = PLUGIN_REGISTRY::Instance()->AllPlugins();
for( const auto& plugin : plugins )
{
if( plugin.m_name.CmpNoCase( aType ) == 0 )
{
return plugin.m_type;
}
}
return PCB_IO_MGR::PCB_FILE_UNKNOWN;
@@ -134,6 +137,11 @@ PCB_IO_MGR::PCB_FILE_T PCB_IO_MGR::FindPluginTypeFromBoardPath( const wxString&
PCB_IO_MGR::PCB_FILE_T PCB_IO_MGR::GuessPluginTypeFromLibPath( const wxString& aLibPath, int aCtl )
{
LIBRARY_TABLE_PARSER parser;
if( parser.Parse( aLibPath.ToStdString() ).has_value() )
return NESTED_TABLE;
const auto& plugins = PCB_IO_MGR::PLUGIN_REGISTRY::Instance()->AllPlugins();
for( const auto& plugin : plugins )
+2 -1
View File
@@ -74,7 +74,8 @@ public:
// etc.
FILE_TYPE_NONE
FILE_TYPE_NONE,
NESTED_TABLE
};
/**