Thread-safety (potentially KICAD-VMX...)

... KICAD-6PV, KICAD-82, KICAD-R3A, and others.
This commit is contained in:
Jeff Young 2025-07-13 14:56:22 +01:00
parent 8bb9c47f9b
commit 68d4940087
27 changed files with 190 additions and 113 deletions

View File

@ -37,6 +37,7 @@
#include <utility>
#include <wx/tokenzr.h>
#include <kiface_base.h>
#include <locale_io.h>
DESIGN_BLOCK_INFO* DESIGN_BLOCK_LIST::GetDesignBlockInfo( const wxString& aLibNickname,
const wxString& aDesignBlockName )
@ -95,6 +96,16 @@ bool DESIGN_BLOCK_INFO::InLibrary( const wxString& aLibrary ) const
}
void DESIGN_BLOCK_INFO::ensure_loaded()
{
// Lazy-loading. MUST NOT be called from multi-threaded environment.
LOCALE_IO toggle_locale;
if( !m_loaded )
load();
}
bool operator<( const DESIGN_BLOCK_INFO& lhs, const DESIGN_BLOCK_INFO& rhs )
{
int retv = StrNumCmp( lhs.m_nickname, rhs.m_nickname, false );

View File

@ -106,11 +106,7 @@ public:
friend bool operator<( const DESIGN_BLOCK_INFO& lhs, const DESIGN_BLOCK_INFO& rhs );
protected:
void ensure_loaded()
{
if( !m_loaded )
load();
}
void ensure_loaded();
/// lazily load stuff not filled in by constructor. This may throw IO_ERRORS.
virtual void load(){};

View File

@ -41,8 +41,8 @@ void DESIGN_BLOCK_INFO_IMPL::load()
wxASSERT( dbtable );
std::unique_ptr<const DESIGN_BLOCK> design_block( dbtable->GetEnumeratedDesignBlock( m_nickname,
m_dbname ) );
std::unique_ptr<const DESIGN_BLOCK> design_block( dbtable->GetEnumeratedDesignBlock( m_nickname, m_dbname,
true ) );
if( design_block )
{
@ -176,7 +176,7 @@ void DESIGN_BLOCK_LIST_IMPL::loadDesignBlocks()
CatchErrors(
[&]()
{
m_lib_table->DesignBlockEnumerate( dbnames, nickname, false );
m_lib_table->DesignBlockEnumerate( dbnames, nickname, false, true );
} );
for( wxString dbname : dbnames )

View File

@ -39,6 +39,7 @@
#include <wx/dir.h>
#include <wx/hash.h>
#include <locale_io.h>
#define OPT_SEP '|' ///< options separator character
@ -332,13 +333,24 @@ long long DESIGN_BLOCK_LIB_TABLE::GenerateTimestamp( const wxString* aNickname )
}
void DESIGN_BLOCK_LIB_TABLE::DesignBlockEnumerate( wxArrayString& aDesignBlockNames,
const wxString& aNickname, bool aBestEfforts )
void DESIGN_BLOCK_LIB_TABLE::DesignBlockEnumerate( wxArrayString& aDesignBlockNames, const wxString& aNickname,
bool aBestEfforts, bool aThreadSafe )
{
const DESIGN_BLOCK_LIB_TABLE_ROW* row = FindRow( aNickname, true );
wxASSERT( row->plugin );
row->plugin->DesignBlockEnumerate( aDesignBlockNames, row->GetFullURI( true ), aBestEfforts,
row->GetProperties() );
if( !aThreadSafe )
{
LOCALE_IO toggle_locale;
row->plugin->DesignBlockEnumerate( aDesignBlockNames, row->GetFullURI( true ), aBestEfforts,
row->GetProperties() );
}
else
{
row->plugin->DesignBlockEnumerate( aDesignBlockNames, row->GetFullURI( true ), aBestEfforts,
row->GetProperties() );
}
}
@ -389,19 +401,34 @@ static void setLibNickname( DESIGN_BLOCK* aModule, const wxString& aNickname,
const DESIGN_BLOCK*
DESIGN_BLOCK_LIB_TABLE::GetEnumeratedDesignBlock( const wxString& aNickname,
const wxString& aDesignBlockName )
const wxString& aDesignBlockName,
bool aThreadSafe )
{
const DESIGN_BLOCK_LIB_TABLE_ROW* row = FindRow( aNickname, true );
wxASSERT( row->plugin );
return row->plugin->GetEnumeratedDesignBlock( row->GetFullURI( true ), aDesignBlockName,
row->GetProperties() );
if( !aThreadSafe )
{
LOCALE_IO toggle_locale;
return row->plugin->GetEnumeratedDesignBlock( row->GetFullURI( true ), aDesignBlockName,
row->GetProperties() );
}
else
{
return row->plugin->GetEnumeratedDesignBlock( row->GetFullURI( true ), aDesignBlockName,
row->GetProperties() );
}
}
bool DESIGN_BLOCK_LIB_TABLE::DesignBlockExists( const wxString& aNickname,
const wxString& aDesignBlockName )
{
// NOT THREAD-SAFE! LOCALE_IO is global!
LOCALE_IO toggle_locale;
try
{
const DESIGN_BLOCK_LIB_TABLE_ROW* row = FindRow( aNickname, true );
@ -421,6 +448,10 @@ DESIGN_BLOCK* DESIGN_BLOCK_LIB_TABLE::DesignBlockLoad( const wxString& aNickname
const wxString& aDesignBlockName,
bool aKeepUUID )
{
// NOT THREAD-SAFE! LOCALE_IO is global!
LOCALE_IO toggle_locale;
const DESIGN_BLOCK_LIB_TABLE_ROW* row = FindRow( aNickname, true );
wxASSERT( row->plugin );
@ -437,6 +468,10 @@ DESIGN_BLOCK_LIB_TABLE::SAVE_T
DESIGN_BLOCK_LIB_TABLE::DesignBlockSave( const wxString& aNickname,
const DESIGN_BLOCK* aDesignBlock, bool aOverwrite )
{
// NOT THREAD-SAFE! LOCALE_IO is global!
LOCALE_IO toggle_locale;
const DESIGN_BLOCK_LIB_TABLE_ROW* row = FindRow( aNickname, true );
wxASSERT( row->plugin );

View File

@ -141,7 +141,7 @@ wxString DESIGN_BLOCK_TREE_MODEL_ADAPTER::GenerateInfo( LIB_ID const& aLibId, in
try
{
db = m_libs->GetEnumeratedDesignBlock( aLibId.GetLibNickname(), aLibId.GetLibItemName() );
db = m_libs->GetEnumeratedDesignBlock( aLibId.GetLibNickname(), aLibId.GetLibItemName(), false );
}
catch( const IO_ERROR& ioe )
{

View File

@ -39,6 +39,7 @@
#include <utility>
#include <wx/tokenzr.h>
#include <kiface_base.h>
#include <locale_io.h>
FOOTPRINT_INFO* FOOTPRINT_LIST::GetFootprintInfo( const wxString& aLibNickname,
const wxString& aFootprintName )
@ -97,6 +98,16 @@ bool FOOTPRINT_INFO::InLibrary( const wxString& aLibrary ) const
}
void FOOTPRINT_INFO::ensure_loaded()
{
// Lazy-loading. MUST NOT be called from multi-threaded environment.
LOCALE_IO toggle_locale;
if( !m_loaded )
load();
}
bool operator<( const FOOTPRINT_INFO& lhs, const FOOTPRINT_INFO& rhs )
{
int retv = StrNumCmp( lhs.m_nickname, rhs.m_nickname, false );

View File

@ -40,6 +40,7 @@
#include <wx/dir.h>
#include <wx/hash.h>
#include <locale_io.h>
#define OPT_SEP '|' ///< options separator character
@ -307,12 +308,23 @@ long long FP_LIB_TABLE::GenerateTimestamp( const wxString* aNickname )
void FP_LIB_TABLE::FootprintEnumerate( wxArrayString& aFootprintNames, const wxString& aNickname,
bool aBestEfforts )
bool aBestEfforts, bool aThreadSafe )
{
const FP_LIB_TABLE_ROW* row = FindRow( aNickname, true );
wxASSERT( row->plugin );
row->plugin->FootprintEnumerate( aFootprintNames, row->GetFullURI( true ), aBestEfforts,
row->GetProperties() );
if( !aThreadSafe )
{
LOCALE_IO toggle_locale;
row->plugin->FootprintEnumerate( aFootprintNames, row->GetFullURI( true ), aBestEfforts,
row->GetProperties() );
}
else
{
row->plugin->FootprintEnumerate( aFootprintNames, row->GetFullURI( true ), aBestEfforts,
row->GetProperties() );
}
}
@ -362,18 +374,33 @@ static void setLibNickname( FOOTPRINT* aModule, const wxString& aNickname,
const FOOTPRINT* FP_LIB_TABLE::GetEnumeratedFootprint( const wxString& aNickname,
const wxString& aFootprintName )
const wxString& aFootprintName,
bool aThreadSafe )
{
const FP_LIB_TABLE_ROW* row = FindRow( aNickname, true );
wxASSERT( row->plugin );
return row->plugin->GetEnumeratedFootprint( row->GetFullURI( true ), aFootprintName,
row->GetProperties() );
if( !aThreadSafe )
{
LOCALE_IO toggle_locale;
return row->plugin->GetEnumeratedFootprint( row->GetFullURI( true ), aFootprintName,
row->GetProperties() );
}
else
{
return row->plugin->GetEnumeratedFootprint( row->GetFullURI( true ), aFootprintName,
row->GetProperties() );
}
}
bool FP_LIB_TABLE::FootprintExists( const wxString& aNickname, const wxString& aFootprintName )
{
// NOT THREAD-SAFE! LOCALE_IO is global!
LOCALE_IO toggle_locale;
try
{
const FP_LIB_TABLE_ROW* row = FindRow( aNickname, true );
@ -392,6 +419,10 @@ bool FP_LIB_TABLE::FootprintExists( const wxString& aNickname, const wxString& a
FOOTPRINT* FP_LIB_TABLE::FootprintLoad( const wxString& aNickname,
const wxString& aFootprintName, bool aKeepUUID )
{
// NOT THREAD-SAFE! LOCALE_IO is global!
LOCALE_IO toggle_locale;
const FP_LIB_TABLE_ROW* row = FindRow( aNickname, true );
wxASSERT( row->plugin );
@ -407,6 +438,10 @@ FOOTPRINT* FP_LIB_TABLE::FootprintLoad( const wxString& aNickname,
FP_LIB_TABLE::SAVE_T FP_LIB_TABLE::FootprintSave( const wxString& aNickname,
const FOOTPRINT* aFootprint, bool aOverwrite )
{
// NOT THREAD-SAFE! LOCALE_IO is global!
LOCALE_IO toggle_locale;
const FP_LIB_TABLE_ROW* row = FindRow( aNickname, true );
wxASSERT( row->plugin );

View File

@ -304,7 +304,7 @@ FOOTPRINT* DISPLAY_FOOTPRINTS_FRAME::GetFootprint( const wxString& aFootprintNam
try
{
if( const FOOTPRINT* fp = fpTable->GetEnumeratedFootprint( libNickname, fpName ) )
if( const FOOTPRINT* fp = fpTable->GetEnumeratedFootprint( libNickname, fpName, false ) )
footprint = static_cast<FOOTPRINT*>( fp->Duplicate( IGNORE_PARENT_GROUP ) );
}
catch( const IO_ERROR& ioe )

View File

@ -58,7 +58,7 @@ static int guessNickname( FP_LIB_TABLE* aTbl, LIB_ID* aFootprintId )
{
wxArrayString fpnames;
aTbl->FootprintEnumerate( fpnames, nicks[libNdx], true );
aTbl->FootprintEnumerate( fpnames, nicks[libNdx], true, false );
for( unsigned nameNdx = 0; nameNdx < fpnames.size(); ++nameNdx )
{

View File

@ -48,19 +48,13 @@ static const wxString LinkFormat = wxS( "<a href=\"__HREF__\">__TEXT__</a>" );
class FOOTPRINT_INFO_GENERATOR
{
wxString m_html;
SYMBOL_LIB_TABLE* m_sym_lib_table;
LIB_ID const m_lib_id;
LIB_SYMBOL* m_symbol;
int m_unit;
public:
FOOTPRINT_INFO_GENERATOR( SYMBOL_LIB_TABLE* aSymbolLibTable, LIB_ID const& aLibId, int aUnit )
: m_html( DescriptionFormat ),
m_sym_lib_table( aSymbolLibTable ),
m_lib_id( aLibId ),
m_symbol( nullptr ),
m_unit( aUnit )
FOOTPRINT_INFO_GENERATOR( SYMBOL_LIB_TABLE* aSymbolLibTable, LIB_ID const& aLibId, int aUnit ) :
m_html( DescriptionFormat ),
m_sym_lib_table( aSymbolLibTable ),
m_lib_id( aLibId ),
m_symbol( nullptr ),
m_unit( aUnit )
{ }
/**
@ -110,7 +104,6 @@ protected:
m_html.Replace( wxS( "__NAME__" ), EscapeHTML( UnescapeString( m_symbol->GetName() ) ) );
}
void SetHtmlAliasOf()
{
if( m_symbol->IsRoot() )
@ -130,14 +123,12 @@ protected:
root_desc = parent->GetDesc();
}
m_html.Replace( wxS( "__ALIASOF__" ),
wxString::Format( AliasOfFormat,
EscapeHTML( UnescapeString( root_name ) ),
EscapeHTML( root_desc ) ) );
m_html.Replace( wxS( "__ALIASOF__" ), wxString::Format( AliasOfFormat,
EscapeHTML( UnescapeString( root_name ) ),
EscapeHTML( root_desc ) ) );
}
}
void SetHtmlDesc()
{
wxString esc_desc = EscapeHTML( UnescapeString( m_symbol->GetDescription() ) );
@ -151,7 +142,6 @@ protected:
m_html.Replace( wxS( "__DESC__" ), wxString::Format( DescFormat, esc_desc ) );
}
void SetHtmlKeywords()
{
wxString keywords = m_symbol->GetKeyWords();
@ -159,11 +149,9 @@ protected:
if( keywords.empty() )
m_html.Replace( wxS( "__KEY__" ), wxEmptyString );
else
m_html.Replace( wxS( "__KEY__" ),
wxString::Format( KeywordsFormat, EscapeHTML( keywords ) ) );
m_html.Replace( wxS( "__KEY__" ), wxString::Format( KeywordsFormat, EscapeHTML( keywords ) ) );
}
wxString GetHtmlFieldRow( const SCH_FIELD& aField ) const
{
wxString name = aField.GetCanonicalName();
@ -263,6 +251,13 @@ protected:
m_html.Replace( wxS( "__FIELDS__" ), fieldtable );
}
private:
wxString m_html;
SYMBOL_LIB_TABLE* m_sym_lib_table;
LIB_ID const m_lib_id;
LIB_SYMBOL* m_symbol;
int m_unit;
};

View File

@ -158,11 +158,13 @@ public:
* \a aNickname.
* @param aNickname is a locator for the "library", it is a "name" in LIB_TABLE_ROW.
* @param aBestEfforts if true, don't throw on errors.
* @param aThreadSafe if true, do not set LOCALE_IO (which is global). Caller is responsible
* for setting it up correctly.
*
* @throw IO_ERROR if the library cannot be found, or design block cannot be loaded.
*/
void DesignBlockEnumerate( wxArrayString& aDesignBlockNames, const wxString& aNickname,
bool aBestEfforts );
bool aBestEfforts, bool aThreadSafe );
/**
* Generate a hashed timestamp representing the last-mod-times of the library indicated
@ -195,10 +197,13 @@ public:
* A version of #DesignBlockLoad() for use after #DesignBlockEnumerate() for more efficient
* cache management.
*
* @param aThreadSafe if true, do not set LOCALE_IO (which is global). Caller is responsible
* for setting it up correctly.
*
* The return value is const to allow it to return a reference to a cached item.
*/
const DESIGN_BLOCK* GetEnumeratedDesignBlock( const wxString& aNickname,
const wxString& aDesignBlockName );
const DESIGN_BLOCK* GetEnumeratedDesignBlock( const wxString& aNickname, const wxString& aDesignBlockName,
bool aThreadSafe );
/**
* The set of return values from DesignBlockSave() below.
*/

View File

@ -127,11 +127,7 @@ public:
friend bool operator<( const FOOTPRINT_INFO& lhs, const FOOTPRINT_INFO& rhs );
protected:
void ensure_loaded()
{
if( !m_loaded )
load();
}
void ensure_loaded();
/// lazily load stuff not filled in by constructor. This may throw IO_ERRORS.
virtual void load() { };

View File

@ -143,11 +143,13 @@ public:
* @param aFootprintNames is the list to fill with the footprint names found in \a aNickname
* @param aNickname is a locator for the "library", it is a "name" in LIB_TABLE_ROW.
* @param aBestEfforts if true, don't throw on errors.
* @param aThreadSafe if true, do not set LOCALE_IO (which is global). Caller is responsible
* for setting it up correctly.
*
* @throw IO_ERROR if the library cannot be found, or footprint cannot be loaded.
*/
void FootprintEnumerate( wxArrayString& aFootprintNames, const wxString& aNickname,
bool aBestEfforts );
bool aBestEfforts, bool aThreadSafe );
/**
* Generate a hashed timestamp representing the last-mod-times of the library indicated
@ -180,10 +182,14 @@ public:
* A version of #FootprintLoad() for use after #FootprintEnumerate() for more efficient
* cache management.
*
* @param aThreadSafe if true, do not set LOCALE_IO (which is global). Caller is responsible
* for setting it up correctly.
*
* The return value is const to allow it to return a reference to a cached item.
*/
const FOOTPRINT* GetEnumeratedFootprint( const wxString& aNickname,
const wxString& aFootprintName );
const wxString& aFootprintName,
bool aThreadSafe );
/**
* The set of return values from FootprintSave() below.
*/

View File

@ -75,7 +75,7 @@
#include <widgets/filedlg_import_non_kicad.h>
#include <widgets/wx_html_report_box.h>
#include <wx_filename.h> // For ::ResolvePossibleSymlinks()
#include <locale_io.h>
#include <kiplatform/io.h>
#include <wx/stdpaths.h>
@ -840,6 +840,7 @@ bool PCB_EDIT_FRAME::OpenProjectFiles( const std::vector<wxString>& aFileSet, in
// which prompts the user to continue with overwrite or abort)
if( newLibPath.Length() > 0 )
{
LOCALE_IO toggle_locale;
IO_RELEASER<PCB_IO> piSexpr( PCB_IO_MGR::PluginFind( PCB_IO_MGR::KICAD_SEXP ) );
for( FOOTPRINT* footprint : loadedFootprints )

View File

@ -47,7 +47,7 @@ void FOOTPRINT_INFO_IMPL::load()
wxASSERT( fptable );
const FOOTPRINT* footprint = fptable->GetEnumeratedFootprint( m_nickname, m_fpname );
const FOOTPRINT* footprint = fptable->GetEnumeratedFootprint( m_nickname, m_fpname, true );
if( footprint == nullptr ) // Should happen only with malformed/broken libraries
{
@ -192,7 +192,7 @@ void FOOTPRINT_LIST_IMPL::loadFootprints()
CatchErrors(
[&]()
{
m_lib_table->FootprintEnumerate( fpnames, nickname, false );
m_lib_table->FootprintEnumerate( fpnames, nickname, false, true );
} );
for( wxString fpname : fpnames )

View File

@ -51,6 +51,7 @@
#include <footprint_editor_settings.h>
#include <footprint_viewer_frame.h>
#include <io/kicad/kicad_io_utils.h>
#include <locale_io.h>
#include <view/view_controls.h>
#include <wx/choicdlg.h>
#include <wx/filedlg.h>
@ -691,6 +692,7 @@ void PCB_EDIT_FRAME::ExportFootprintsToLibrary( bool aStoreInNewLib, const wxStr
libNickname = row->GetNickName();
}
LOCALE_IO toggle_locale;
PCB_IO_MGR::PCB_FILE_T piType = PCB_IO_MGR::KICAD_SEXP;
IO_RELEASER<PCB_IO> pi( PCB_IO_MGR::PluginFind( piType ) );
std::map<std::string, UTF8> options { { "skip_cache_validation", "1" } }; // Skip cache validation -- we just created it
@ -1265,7 +1267,7 @@ FOOTPRINT* PCB_BASE_FRAME::CreateNewFootprint( wxString aFootprintName, const wx
// Try to infer the footprint attributes from an existing footprint in the library
try
{
tbl->FootprintEnumerate( fpnames, aLibName, true );
tbl->FootprintEnumerate( fpnames, aLibName, true, false );
if( !fpnames.empty() )
footprintAttrs = tbl->FootprintLoad( aLibName, fpnames.Last() )->GetAttributes();

View File

@ -177,8 +177,8 @@ bool FOOTPRINT_PREVIEW_PANEL::DisplayFootprint( const LIB_ID& aFPID )
try
{
const FOOTPRINT* fp = fptbl->GetEnumeratedFootprint( aFPID.GetLibNickname(),
aFPID.GetLibItemName() );
const FOOTPRINT* fp = fptbl->GetEnumeratedFootprint( aFPID.GetLibNickname(), aFPID.GetLibItemName(),
false );
if( fp )
m_currentFootprint.reset( static_cast<FOOTPRINT*>( fp->Duplicate( IGNORE_PARENT_GROUP ) ) );

View File

@ -1033,7 +1033,7 @@ void FOOTPRINT_VIEWER_FRAME::SelectAndViewFootprint( FPVIEWER_CONSTANTS aMode )
GetBoard()->RemoveUnusedNets( nullptr );
FOOTPRINT* footprint = PROJECT_PCB::PcbFootprintLibs( &Prj() )->FootprintLoad( getCurNickname(),
getCurFootprintName() );
getCurFootprintName() );
if( footprint )
displayFootprint( footprint );

View File

@ -101,18 +101,12 @@ std::optional<wxString> GetFootprintDocumentationURL( const FOOTPRINT& aFootprin
class FOOTPRINT_INFO_GENERATOR
{
wxString m_html;
FP_LIB_TABLE* m_fp_lib_table;
LIB_ID const m_lib_id;
const FOOTPRINT* m_footprint;
public:
FOOTPRINT_INFO_GENERATOR( FP_LIB_TABLE* aFpLibTable, LIB_ID const& aLibId )
: m_html( DescriptionFormat ),
m_fp_lib_table( aFpLibTable ),
m_lib_id( aLibId ),
m_footprint( nullptr )
FOOTPRINT_INFO_GENERATOR( FP_LIB_TABLE* aFpLibTable, LIB_ID const& aLibId ) :
m_html( DescriptionFormat ),
m_fp_lib_table( aFpLibTable ),
m_lib_id( aLibId ),
m_footprint( nullptr )
{ }
/**
@ -128,7 +122,8 @@ public:
try
{
m_footprint = m_fp_lib_table->GetEnumeratedFootprint( m_lib_id.GetLibNickname(),
m_lib_id.GetLibItemName() );
m_lib_id.GetLibItemName(),
false );
}
catch( const IO_ERROR& ioe )
{
@ -183,6 +178,12 @@ public:
return m_html;
}
private:
wxString m_html;
FP_LIB_TABLE* m_fp_lib_table;
LIB_ID const m_lib_id;
const FOOTPRINT* m_footprint;
};

View File

@ -49,6 +49,7 @@ using namespace std::placeholders;
#include <widgets/wx_progress_reporters.h>
#include <dialog_pad_properties.h>
#include <project_pcb.h>
#include <locale_io.h>
static wxArrayString s_FootprintHistoryList;
@ -334,6 +335,7 @@ bool FOOTPRINT_EDIT_FRAME::SaveLibraryAs( const wxString& aLibraryPath )
wxBusyCursor dummy;
wxString msg;
LOCALE_IO toggle_locale;
PCB_IO_MGR::PCB_FILE_T dstType = PCB_IO_MGR::GuessPluginTypeFromLibPath( dstLibPath );
PCB_IO_MGR::PCB_FILE_T curType = PCB_IO_MGR::GuessPluginTypeFromLibPath( curLibPath );
@ -363,12 +365,12 @@ bool FOOTPRINT_EDIT_FRAME::SaveLibraryAs( const wxString& aLibraryPath )
cur->FootprintEnumerate( footprints, curLibPath, false );
for( unsigned i = 0; i < footprints.size(); ++i )
for( const wxString& fp : footprints )
{
const FOOTPRINT* footprint = cur->GetEnumeratedFootprint( curLibPath, footprints[i] );
const FOOTPRINT* footprint = cur->GetEnumeratedFootprint( curLibPath, fp );
dst->FootprintSave( dstLibPath, footprint );
msg = wxString::Format( _( "Footprint '%s' saved." ), footprints[i] );
msg = wxString::Format( _( "Footprint '%s' saved." ), fp );
SetStatusText( msg );
}
}

View File

@ -355,9 +355,7 @@ void PCB_IO_EASYEDA::FootprintEnumerate( wxArrayString& aFootprintNames,
c_para = doc.head.c_para;
if( c_para )
{
packageName = get_def( *c_para, wxS( "package" ), packageName );
}
aFootprintNames.Add( packageName );
}
@ -457,9 +455,8 @@ FOOTPRINT* PCB_IO_EASYEDA::FootprintLoad( const wxString& aLibraryPath,
{
parts.RemoveAt( 0 );
FOOTPRINT* footprint =
parser.ParseFootprint( origin, orientation, layer, nullptr,
paramMap, m_loadedFootprints, parts );
FOOTPRINT* footprint = parser.ParseFootprint( origin, orientation, layer, nullptr,
paramMap, m_loadedFootprints, parts );
if( !footprint )
return nullptr;
@ -502,8 +499,8 @@ FOOTPRINT* PCB_IO_EASYEDA::FootprintLoad( const wxString& aLibraryPath,
VECTOR2D origin( doc.head.x, doc.head.y );
FOOTPRINT* footprint = parser.ParseFootprint(
origin, ANGLE_0, F_Cu, nullptr, *c_para, m_loadedFootprints, doc.shape );
FOOTPRINT* footprint = parser.ParseFootprint( origin, ANGLE_0, F_Cu, nullptr, *c_para,
m_loadedFootprints, doc.shape );
if( !footprint )
return nullptr;

View File

@ -860,7 +860,6 @@ FOOTPRINT* PCB_IO_GEDA::ImportFootprint( const wxString& aFootprintPath,
void PCB_IO_GEDA::FootprintEnumerate( wxArrayString& aFootprintNames, const wxString& aLibraryPath,
bool aBestEfforts, const std::map<std::string, UTF8>* aProperties )
{
LOCALE_IO toggle; // toggles on, then off, the C locale.
wxDir dir( aLibraryPath );
wxString errorMsg;
@ -869,10 +868,7 @@ void PCB_IO_GEDA::FootprintEnumerate( wxArrayString& aFootprintNames, const wxSt
if( aBestEfforts )
return;
else
{
THROW_IO_ERROR( wxString::Format( _( "Footprint library '%s' not found." ),
aLibraryPath ) );
}
THROW_IO_ERROR( wxString::Format( _( "Footprint library '%s' not found." ), aLibraryPath ) );
}
init( aProperties );
@ -902,8 +898,6 @@ const FOOTPRINT* PCB_IO_GEDA::getFootprint( const wxString& aLibraryPath,
const std::map<std::string, UTF8>* aProperties,
bool checkModified )
{
LOCALE_IO toggle; // toggles on, then off, the C locale.
init( aProperties );
validateCache( aLibraryPath, checkModified );

View File

@ -3210,7 +3210,6 @@ void PCB_IO_KICAD_LEGACY::cacheLib( const wxString& aLibraryPath )
void PCB_IO_KICAD_LEGACY::FootprintEnumerate( wxArrayString& aFootprintNames, const wxString& aLibPath,
bool aBestEfforts, const std::map<std::string, UTF8>* aProperties )
{
LOCALE_IO toggle; // toggles on, then off, the C locale.
wxString errorMsg;
init( aProperties );
@ -3236,22 +3235,18 @@ void PCB_IO_KICAD_LEGACY::FootprintEnumerate( wxArrayString& aFootprintNames, co
FOOTPRINT* PCB_IO_KICAD_LEGACY::FootprintLoad( const wxString& aLibraryPath,
const wxString& aFootprintName, bool aKeepUUID,
const std::map<std::string, UTF8>* aProperties )
const wxString& aFootprintName, bool aKeepUUID,
const std::map<std::string, UTF8>* aProperties )
{
LOCALE_IO toggle; // toggles on, then off, the C locale.
init( aProperties );
cacheLib( aLibraryPath );
const FOOTPRINT_MAP& footprints = m_cache->m_footprints;
const FOOTPRINT_MAP& footprints = m_cache->m_footprints;
FOOTPRINT_MAP::const_iterator it = footprints.find( TO_UTF8( aFootprintName ) );
if( it == footprints.end() )
{
return nullptr;
}
// Return copy of already loaded FOOTPRINT
FOOTPRINT* copy = (FOOTPRINT*) it->second->Duplicate( IGNORE_PARENT_GROUP );

View File

@ -2888,7 +2888,6 @@ void PCB_IO_KICAD_SEXPR::FootprintEnumerate( wxArrayString& aFootprintNames,
const wxString& aLibPath, bool aBestEfforts,
const std::map<std::string, UTF8>* aProperties )
{
LOCALE_IO toggle; // toggles on, then off, the C locale.
wxDir dir( aLibPath );
wxString errorMsg;
@ -2919,8 +2918,6 @@ const FOOTPRINT* PCB_IO_KICAD_SEXPR::getFootprint( const wxString& aLibraryPath,
const std::map<std::string, UTF8>* aProperties,
bool checkModified )
{
LOCALE_IO toggle; // toggles on, then off, the C locale.
init( aProperties );
try
@ -3015,8 +3012,6 @@ FOOTPRINT* PCB_IO_KICAD_SEXPR::FootprintLoad( const wxString& aLibraryPath,
void PCB_IO_KICAD_SEXPR::FootprintSave( const wxString& aLibraryPath, const FOOTPRINT* aFootprint,
const std::map<std::string, UTF8>* aProperties )
{
LOCALE_IO toggle; // toggles on, then off, the C locale.
init( aProperties );
// In this public PLUGIN API function, we can safely assume it was
@ -3033,9 +3028,7 @@ void PCB_IO_KICAD_SEXPR::FootprintSave( const wxString& aLibraryPath, const FOOT
"Would you like to create it?"),
aLibraryPath );
if( !Pgm().IsGUI()
|| wxMessageBox( msg, _( "Library Not Found" ), wxYES_NO | wxICON_QUESTION )
!= wxYES )
if( !Pgm().IsGUI() || wxMessageBox( msg, _( "Library Not Found" ), wxYES_NO | wxICON_QUESTION ) != wxYES )
return;
// Save throws its own IO_ERROR on failure, so no need to recreate here

View File

@ -28,7 +28,7 @@
#include <config.h>
#include <kiway_player.h>
#include <wildcards_and_files_ext.h>
#include <locale_io.h>
#include <pcb_io/pcb_io_mgr.h>
#include <pcb_io/eagle/pcb_io_eagle.h>
@ -196,6 +196,7 @@ bool PCB_IO_MGR::ConvertLibrary( std::map<std::string, UTF8>* aOldFileProps, con
if( oldFileType == PCB_IO_MGR::FILE_TYPE_NONE )
return false;
LOCALE_IO toggle_locale;
IO_RELEASER<PCB_IO> oldFilePI( PCB_IO_MGR::PluginFind( oldFileType ) );
IO_RELEASER<PCB_IO> kicadPI( PCB_IO_MGR::PluginFind( PCB_IO_MGR::KICAD_SEXP ) );
wxArrayString fpNames;
@ -220,8 +221,8 @@ bool PCB_IO_MGR::ConvertLibrary( std::map<std::string, UTF8>* aOldFileProps, con
for ( const wxString& fpName : fpNames )
{
std::unique_ptr<const FOOTPRINT> fp(
oldFilePI->GetEnumeratedFootprint( aOldFilePath, fpName, aOldFileProps ) );
std::unique_ptr<const FOOTPRINT> fp( oldFilePI->GetEnumeratedFootprint( aOldFilePath, fpName,
aOldFileProps ) );
try
{

View File

@ -392,7 +392,7 @@ wxArrayString GetFootprints( const wxString& aNickName )
if( !tbl )
return footprintNames;
tbl->FootprintEnumerate( footprintNames, aNickName, true );
tbl->FootprintEnumerate( footprintNames, aNickName, true, false );
return footprintNames;
}

View File

@ -27,7 +27,7 @@
#include <pcb_io/kicad_sexpr/pcb_io_kicad_sexpr.h>
#include <pcb_io/kicad_sexpr/pcb_io_kicad_sexpr_parser.h>
#include <richio.h>
#include <locale_io.h>
#include <board.h>
#include <footprint.h>
@ -148,6 +148,7 @@ std::unique_ptr<FOOTPRINT> ReadFootprintFromFileOrStream( const std::string& aFi
void DumpFootprintToFile( const FOOTPRINT& aFootprint, const std::string& aLibraryPath )
{
LOCALE_IO toggle_locale;
PCB_IO_KICAD_SEXPR io;
io.FootprintSave( aLibraryPath, &aFootprint, nullptr );
}