From f8a5e2c1c895ea40fd6fc0595841b3ac54f0b5df Mon Sep 17 00:00:00 2001 From: Jeff Young Date: Mon, 30 Jul 2018 14:18:37 +0100 Subject: [PATCH] Performance enhancements in fp loading, string cmp, etc. Knocks about 1/3 off the first footprint load, and more than 1/2 off subsequent loads. --- common/common.cpp | 135 +++++++++++++++++- common/footprint_filter.cpp | 4 +- common/footprint_info.cpp | 2 +- common/fp_lib_table.cpp | 12 +- common/lib_tree_model.cpp | 39 +++-- common/lib_tree_model.h | 4 +- common/lib_tree_model_adapter.cpp | 6 +- common/lib_tree_model_adapter.h | 4 +- common/string.cpp | 39 +++-- common/widgets/footprint_select_widget.cpp | 2 +- cvpcb/display_footprints_frame.cpp | 2 +- cvpcb/footprints_listbox.cpp | 2 +- eeschema/class_libentry.cpp | 2 +- eeschema/class_libentry.h | 18 ++- eeschema/sch_component.cpp | 2 +- .../symbol_tree_synchronizing_adapter.cpp | 4 +- include/footprint_info.h | 5 +- include/fp_lib_table.h | 8 +- include/lib_tree_item.h | 11 +- pcbnew/footprint_edit_frame.h | 25 ++-- pcbnew/footprint_info_impl.cpp | 34 +++-- pcbnew/footprint_info_impl.h | 9 +- pcbnew/fp_tree_model_adapter.cpp | 2 +- pcbnew/fp_tree_synchronizing_adapter.cpp | 21 +-- pcbnew/gpcb_plugin.cpp | 22 +-- pcbnew/gpcb_plugin.h | 13 +- pcbnew/io_mgr.h | 12 +- pcbnew/kicad_plugin.cpp | 111 +++++++------- pcbnew/kicad_plugin.h | 13 +- pcbnew/load_select_footprint.cpp | 2 +- pcbnew/plugin.cpp | 19 +-- 31 files changed, 370 insertions(+), 214 deletions(-) diff --git a/common/common.cpp b/common/common.cpp index 11fc07601a..296856737f 100644 --- a/common/common.cpp +++ b/common/common.cpp @@ -250,6 +250,139 @@ wxString GetKicadConfigPath() } +enum Bracket +{ + Bracket_None, + Bracket_Normal = ')', + Bracket_Curly = '}', +#ifdef __WINDOWS__ + Bracket_Windows = '%', // yeah, Windows people are a bit strange ;-) +#endif + Bracket_Max +}; + + +// +// Stolen from wxExpandEnvVars and then heavily optimized +// +wxString KIwxExpandEnvVars(const wxString& str) +{ + size_t strlen = str.length(); + + wxString strResult; + strResult.Alloc(strlen); + + for ( size_t n = 0; n < strlen; n++ ) { + wxUniChar str_n = str[n]; + + switch ( str_n.GetValue() ) { +#ifdef __WINDOWS__ + case wxT('%'): +#endif // __WINDOWS__ + case wxT('$'): + { + Bracket bracket; +#ifdef __WINDOWS__ + if ( str_n == wxT('%') ) + bracket = Bracket_Windows; + else +#endif // __WINDOWS__ + if ( n == strlen - 1 ) { + bracket = Bracket_None; + } + else { + switch ( str[n + 1].GetValue() ) { + case wxT('('): + bracket = Bracket_Normal; + n++; // skip the bracket + break; + + case wxT('{'): + bracket = Bracket_Curly; + n++; // skip the bracket + break; + + default: + bracket = Bracket_None; + } + } + + size_t m = n + 1; + wxUniChar str_m = str[m]; + + while ( m < strlen && (wxIsalnum(str_m) || str_m == wxT('_')) ) + str_m = str[++m]; + + wxString strVarName(str.c_str() + n + 1, m - n - 1); + +#ifdef __WXWINCE__ + const bool expanded = false; +#else + // NB: use wxGetEnv instead of wxGetenv as otherwise variables + // set through wxSetEnv may not be read correctly! + bool expanded = false; + wxString tmp; + if (wxGetEnv(strVarName, &tmp)) + { + strResult += tmp; + expanded = true; + } + else +#endif + { + // variable doesn't exist => don't change anything +#ifdef __WINDOWS__ + if ( bracket != Bracket_Windows ) +#endif + if ( bracket != Bracket_None ) + strResult << str[n - 1]; + strResult << str_n << strVarName; + } + + // check the closing bracket + if ( bracket != Bracket_None ) { + if ( m == strlen || str_m != (wxChar)bracket ) { + // under MSW it's common to have '%' characters in the registry + // and it's annoying to have warnings about them each time, so + // ignroe them silently if they are not used for env vars + // + // under Unix, OTOH, this warning could be useful for the user to + // understand why isn't the variable expanded as intended +#ifndef __WINDOWS__ + wxLogWarning(_("Environment variables expansion failed: missing '%c' at position %u in '%s'."), + (char)bracket, (unsigned int) (m + 1), str.c_str()); +#endif // __WINDOWS__ + } + else { + // skip closing bracket unless the variables wasn't expanded + if ( !expanded ) + strResult << (wxChar)bracket; + str_m = str[++m]; + } + } + + n = m - 1; // skip variable name + } + break; + + case wxT('\\'): + // backslash can be used to suppress special meaning of % and $ + if ( n != strlen - 1 && (str[n + 1] == wxT('%') || str[n + 1] == wxT('$')) ) { + strResult += str[++n]; + + break; + } + //else: fall through + + default: + strResult += str_n; + } + } + + return strResult; +} + + #include const wxString ExpandEnvVarSubstitutions( const wxString& aString ) { @@ -261,7 +394,7 @@ const wxString ExpandEnvVarSubstitutions( const wxString& aString ) // We reserve the right to do this another way, by providing our own member // function. - return wxExpandEnvVars( aString ); + return KIwxExpandEnvVars( aString ); } diff --git a/common/footprint_filter.cpp b/common/footprint_filter.cpp index c8f70fb57c..58bbafb5ed 100644 --- a/common/footprint_filter.cpp +++ b/common/footprint_filter.cpp @@ -83,7 +83,7 @@ void FOOTPRINT_FILTER_IT::increment() // include the library name in the search string // e.g. LibName:FootprintName if( filter_pattern.Contains( ":" ) ) - currname = list->GetItem( m_pos ).GetNickname().Lower() + ":"; + currname = list->GetItem( m_pos ).GetLibNickname().Lower() + ":"; currname += list->GetItem( m_pos ).GetFootprintName().Lower(); @@ -135,7 +135,7 @@ bool FOOTPRINT_FILTER_IT::FootprintFilterMatch( FOOTPRINT_INFO& aItem ) // If the filter contains a ':' character, include the library name in the pattern if( each_filter->GetPattern().Contains( ":" ) ) { - name = aItem.GetNickname().Lower() + ":"; + name = aItem.GetLibNickname().Lower() + ":"; } name += aItem.GetFootprintName().Lower(); diff --git a/common/footprint_info.cpp b/common/footprint_info.cpp index 3ad15516b5..5a8c7d6fac 100644 --- a/common/footprint_info.cpp +++ b/common/footprint_info.cpp @@ -59,7 +59,7 @@ FOOTPRINT_INFO* FOOTPRINT_LIST::GetModuleInfo( const wxString& aLibNickname, for( auto& fp : m_list ) { - if( aLibNickname == fp->GetNickname() && aFootprintName == fp->GetFootprintName() ) + if( aLibNickname == fp->GetLibNickname() && aFootprintName == fp->GetFootprintName() ) return &*fp; } diff --git a/common/fp_lib_table.cpp b/common/fp_lib_table.cpp index dae4f25ff3..06085d086d 100644 --- a/common/fp_lib_table.cpp +++ b/common/fp_lib_table.cpp @@ -323,18 +323,14 @@ static void setLibNickname( MODULE* aModule, } -MODULE* FP_LIB_TABLE::LoadEnumeratedFootprint( const wxString& aNickname, - const wxString& aFootprintName ) +const MODULE* FP_LIB_TABLE::GetEnumeratedFootprint( const wxString& aNickname, + const wxString& aFootprintName ) { const FP_LIB_TABLE_ROW* row = FindRow( aNickname ); wxASSERT( (PLUGIN*) row->plugin ); - MODULE* ret = row->plugin->LoadEnumeratedFootprint( row->GetFullURI( true ), aFootprintName, - row->GetProperties() ); - - setLibNickname( ret, row->GetNickName(), aFootprintName ); - - return ret; + return row->plugin->GetEnumeratedFootprint( row->GetFullURI( true ), aFootprintName, + row->GetProperties() ); } diff --git a/common/lib_tree_model.cpp b/common/lib_tree_model.cpp index 73a60671bb..6ec5d9d4e0 100644 --- a/common/lib_tree_model.cpp +++ b/common/lib_tree_model.cpp @@ -141,13 +141,24 @@ LIB_TREE_NODE_UNIT::LIB_TREE_NODE_UNIT( LIB_TREE_NODE* aParent, LIB_TREE_ITEM* a } -LIB_TREE_NODE_LIB_ID::LIB_TREE_NODE_LIB_ID( LIB_TREE_NODE* aParent, LIB_TREE_ITEM* aAlias ) +LIB_TREE_NODE_LIB_ID::LIB_TREE_NODE_LIB_ID( LIB_TREE_NODE* aParent, LIB_TREE_ITEM* aItem ) { - wxASSERT( aParent && aAlias ); - Type = LIBID; Parent = aParent; - Update( aAlias ); + + LibId = aItem->GetLibId(); + + Name = aItem->GetName(); + Desc = aItem->GetDescription(); + + MatchName = aItem->GetName().Lower(); + SearchText = aItem->GetSearchText(); + SearchTextNormalized = false; + + IsRoot = aItem->IsRoot(); + + for( int u = 1; u <= aItem->GetUnitCount(); ++u ) + AddUnit( aItem, u ); } @@ -161,21 +172,19 @@ LIB_TREE_NODE_UNIT& LIB_TREE_NODE_LIB_ID::AddUnit( LIB_TREE_ITEM* aItem, int aUn void LIB_TREE_NODE_LIB_ID::Update( LIB_TREE_ITEM* aItem ) { - IsRoot = aItem->IsRoot(); - LibId = aItem->GetLibId(); + // Update is called when the names match, so just update the other fields. + + LibId.SetLibNickname( aItem->GetLibNickname() ); - Name = aItem->GetName(); Desc = aItem->GetDescription(); - MatchName = aItem->GetName().Lower(); SearchText = aItem->GetSearchText(); SearchTextNormalized = false; + IsRoot = aItem->IsRoot(); Children.clear(); - int unitCount = aItem->GetUnitCount(); - - for( int u = 1; u <= unitCount; ++u ) + for( int u = 1; u <= aItem->GetUnitCount(); ++u ) AddUnit( aItem, u ); } @@ -246,11 +255,11 @@ LIB_TREE_NODE_LIB::LIB_TREE_NODE_LIB( LIB_TREE_NODE* aParent, wxString const& aN } -LIB_TREE_NODE_LIB_ID& LIB_TREE_NODE_LIB::AddComp( LIB_TREE_ITEM* aAlias ) +LIB_TREE_NODE_LIB_ID& LIB_TREE_NODE_LIB::AddItem( LIB_TREE_ITEM* aItem ) { - LIB_TREE_NODE_LIB_ID* alias = new LIB_TREE_NODE_LIB_ID( this, aAlias ); - Children.push_back( std::unique_ptr( alias ) ); - return *alias; + LIB_TREE_NODE_LIB_ID* item = new LIB_TREE_NODE_LIB_ID( this, aItem ); + Children.push_back( std::unique_ptr( item ) ); + return *item; } diff --git a/common/lib_tree_model.h b/common/lib_tree_model.h index 81866684e0..ee9c724f24 100644 --- a/common/lib_tree_model.h +++ b/common/lib_tree_model.h @@ -249,9 +249,9 @@ public: /** * Construct a new alias node, add it to this library, and return it. * - * @param aAlias LIB_COMPONENT to provide data + * @param aItem LIB_COMPONENT to provide data */ - LIB_TREE_NODE_LIB_ID& AddComp( LIB_TREE_ITEM* aAlias ); + LIB_TREE_NODE_LIB_ID& AddItem( LIB_TREE_ITEM* aItem ); virtual void UpdateScore( EDA_COMBINED_MATCHER& aMatcher ) override; }; diff --git a/common/lib_tree_model_adapter.cpp b/common/lib_tree_model_adapter.cpp index 8dbd74943c..90e152663f 100644 --- a/common/lib_tree_model_adapter.cpp +++ b/common/lib_tree_model_adapter.cpp @@ -107,12 +107,12 @@ void LIB_TREE_MODEL_ADAPTER::SetPreselectNode( LIB_ID const& aLibId, int aUnit ) void LIB_TREE_MODEL_ADAPTER::DoAddLibrary( wxString const& aNodeName, wxString const& aDesc, - std::vector const& aCompList ) + std::vector const& aItemList ) { auto& lib_node = m_tree.AddLib( aNodeName, aDesc ); - for( auto a: aCompList ) - lib_node.AddComp( a ); + for( auto item: aItemList ) + lib_node.AddItem( item ); lib_node.AssignIntrinsicRanks(); m_tree.AssignIntrinsicRanks(); diff --git a/common/lib_tree_model_adapter.h b/common/lib_tree_model_adapter.h index 4016fef101..e3253c2975 100644 --- a/common/lib_tree_model_adapter.h +++ b/common/lib_tree_model_adapter.h @@ -148,10 +148,10 @@ public: * * @param aNodeName the parent node the components will appear under * @param aDesc the description field of the parent node - * @param aCompList list of components + * @param aItemList list of components */ void DoAddLibrary( wxString const& aNodeName, wxString const& aDesc, - std::vector const& aCompList ); + std::vector const& aItemList ); /** * Set the search string provided by the user. diff --git a/common/string.cpp b/common/string.cpp index 13b1d46cb0..08ed5e8861 100644 --- a/common/string.cpp +++ b/common/string.cpp @@ -242,55 +242,50 @@ int StrNumCmp( const wxString& aString1, const wxString& aString2, int aLength, wxString::const_iterator str1 = aString1.begin(), str2 = aString2.begin(); - if( ( str1 == aString1.end() ) || ( str2 == aString2.end() ) ) - return 0; - for( i = 0; i < aLength; i++ ) { - if( isdigit( *str1 ) && isdigit( *str2 ) ) /* digit found */ + wxUniChar c1 = *str1; + wxUniChar c2 = *str2; + + if( isdigit( c1 ) && isdigit( c2 ) ) /* digit found */ { nb1 = 0; nb2 = 0; - while( isdigit( *str1 ) ) + while( isdigit( c1 ) ) { - nb1 = nb1 * 10 + (int) *str1 - '0'; - ++str1; + nb1 = nb1 * 10 + (int) c1 - '0'; + c1 = *(++str1); } - while( isdigit( *str2 ) ) + while( isdigit( c2 ) ) { - nb2 = nb2 * 10 + (int) *str2 - '0'; - ++str2; + nb2 = nb2 * 10 + (int) c2 - '0'; + c2 = *(++str2); } if( nb1 < nb2 ) return -1; - - if( nb1 > nb2 ) + else if( nb1 > nb2 ) return 1; } if( aIgnoreCase ) { - if( toupper( *str1 ) < toupper( *str2 ) ) + if( toupper( c1 ) < toupper(c2 ) ) return -1; - - if( toupper( *str1 ) > toupper( *str2 ) ) + else if( toupper( c1 ) > toupper( c2 ) ) return 1; - - if( ( *str1 == 0 ) && ( *str2 == 0 ) ) + else if( ( c1 == 0 ) && ( c2 == 0 ) ) return 0; } else { - if( *str1 < *str2 ) + if( c1 < c2 ) return -1; - - if( *str1 > *str2 ) + else if( c1 > c2 ) return 1; - - if( ( str1 == aString1.end() ) && ( str2 == aString2.end() ) ) + else if( ( c1 == 0 ) && ( c2 == 0 ) ) return 0; } diff --git a/common/widgets/footprint_select_widget.cpp b/common/widgets/footprint_select_widget.cpp index e686bf950e..6cc27ae730 100644 --- a/common/widgets/footprint_select_widget.cpp +++ b/common/widgets/footprint_select_widget.cpp @@ -242,7 +242,7 @@ bool FOOTPRINT_SELECT_WIDGET::UpdateList() { for( auto& fpinfo : m_fp_filter ) { - wxString display_name( fpinfo.GetNickname() + ":" + fpinfo.GetFootprintName() ); + wxString display_name( fpinfo.GetLibNickname() + ":" + fpinfo.GetFootprintName() ); m_fp_sel_ctrl->Append( display_name, new wxStringClientData( display_name ) ); ++n_items; diff --git a/cvpcb/display_footprints_frame.cpp b/cvpcb/display_footprints_frame.cpp index 55434be6f6..db8f92a358 100644 --- a/cvpcb/display_footprints_frame.cpp +++ b/cvpcb/display_footprints_frame.cpp @@ -496,7 +496,7 @@ void DISPLAY_FOOTPRINTS_FRAME::InitDisplay() GetBoard()->m_Modules.PushBack( module ); if( module_info ) - SetStatusText( wxString::Format( _( "Lib: %s" ), module_info->GetNickname() ), 0 ); + SetStatusText( wxString::Format( _( "Lib: %s" ), module_info->GetLibNickname() ), 0 ); else SetStatusText( wxEmptyString, 0 ); diff --git a/cvpcb/footprints_listbox.cpp b/cvpcb/footprints_listbox.cpp index 06d0874bc2..295b51d3fd 100644 --- a/cvpcb/footprints_listbox.cpp +++ b/cvpcb/footprints_listbox.cpp @@ -154,7 +154,7 @@ void FOOTPRINTS_LISTBOX::SetFootprints( FOOTPRINT_LIST& aList, const wxString& a for( auto& i: filter ) { msg.Printf( "%3d %s:%s", int( newList.GetCount() + 1 ), - GetChars( i.GetNickname() ), + GetChars( i.GetLibNickname() ), GetChars( i.GetFootprintName() ) ); newList.Add( msg ); } diff --git a/eeschema/class_libentry.cpp b/eeschema/class_libentry.cpp index b9176cc890..46d94b8fb5 100644 --- a/eeschema/class_libentry.cpp +++ b/eeschema/class_libentry.cpp @@ -94,7 +94,7 @@ LIB_ALIAS::~LIB_ALIAS() } -const wxString LIB_ALIAS::GetLibraryName() +wxString LIB_ALIAS::GetLibNickname() const { wxASSERT_MSG( shared, wxT( "LIB_ALIAS without a LIB_PART" ) ); diff --git a/eeschema/class_libentry.h b/eeschema/class_libentry.h index bb25fa75fd..c7238ea92e 100644 --- a/eeschema/class_libentry.h +++ b/eeschema/class_libentry.h @@ -109,14 +109,11 @@ public: return shared; } - const wxString GetLibraryName(); - - bool IsRoot() const override; + PART_LIB* GetLib(); LIB_ID GetLibId() const override; - PART_LIB* GetLib(); - + wxString GetLibNickname() const override; const wxString& GetName() const override { return name; } void SetName( const wxString& aName ); @@ -144,8 +141,19 @@ public: wxString GetSearchText() override; + /** + * For symbols having aliases, IsRoot() indicates the principal item. + */ + bool IsRoot() const override; + + /** + * For symbols with units, return the number of units. + */ int GetUnitCount() override; + /** + * For symbols with units, return an identifier for unit x. + */ wxString GetUnitReference( int aUnit ) override; /** diff --git a/eeschema/sch_component.cpp b/eeschema/sch_component.cpp index e326faa7ee..db26f647cb 100644 --- a/eeschema/sch_component.cpp +++ b/eeschema/sch_component.cpp @@ -1409,7 +1409,7 @@ void SCH_COMPONENT::GetMsgPanelInfo( EDA_UNITS_T aUnits, MSG_PANEL_ITEMS& aList aList.push_back( MSG_PANEL_ITEM( _( "Alias of" ), part->GetName(), BROWN ) ); if( alias->GetLib() && alias->GetLib()->IsCache() ) - aList.push_back( MSG_PANEL_ITEM( _( "Library" ), alias->GetLibraryName(), RED ) ); + aList.push_back( MSG_PANEL_ITEM( _( "Library" ), alias->GetLibNickname(), RED ) ); else if( !m_lib_id.GetLibNickname().empty() ) aList.push_back( MSG_PANEL_ITEM( _( "Library" ), m_lib_id.GetLibNickname(), BROWN ) ); diff --git a/eeschema/symbol_tree_synchronizing_adapter.cpp b/eeschema/symbol_tree_synchronizing_adapter.cpp index a933180594..9161ffb4d6 100644 --- a/eeschema/symbol_tree_synchronizing_adapter.cpp +++ b/eeschema/symbol_tree_synchronizing_adapter.cpp @@ -130,7 +130,7 @@ void SYMBOL_TREE_SYNCHRONIZING_ADAPTER::updateLibrary( LIB_TREE_NODE_LIB& aLibNo { // add a new library for( auto alias : m_libMgr->GetAliases( aLibNode.Name ) ) - aLibNode.AddComp( alias ); + aLibNode.AddItem( alias ); } else if( hashIt->second != m_libMgr->GetLibraryHash( aLibNode.Name ) ) { @@ -162,7 +162,7 @@ void SYMBOL_TREE_SYNCHRONIZING_ADAPTER::updateLibrary( LIB_TREE_NODE_LIB& aLibNo // now the aliases list contains only new aliases that need to be added to the tree for( auto alias : aliases ) - aLibNode.AddComp( alias ); + aLibNode.AddItem( alias ); } aLibNode.AssignIntrinsicRanks(); diff --git a/include/footprint_info.h b/include/footprint_info.h index ac1870577f..49b75a6c1a 100644 --- a/include/footprint_info.h +++ b/include/footprint_info.h @@ -44,9 +44,6 @@ #include -#define USE_FPI_LAZY 0 // 1:yes lazy, 0:no early - - class FP_LIB_TABLE; class FOOTPRINT_LIST; class FOOTPRINT_LIST_IMPL; @@ -80,7 +77,7 @@ public: return m_fpname; } - const wxString& GetNickname() const + wxString GetLibNickname() const override { return m_nickname; } diff --git a/include/fp_lib_table.h b/include/fp_lib_table.h index 63ba0a0a2a..0ec94ac742 100644 --- a/include/fp_lib_table.h +++ b/include/fp_lib_table.h @@ -187,12 +187,14 @@ public: MODULE* FootprintLoad( const wxString& aNickname, const wxString& aFootprintName ); /** - * Function LoadEnumeratedFootprint + * Function GetEnumeratedFootprint * * a version of FootprintLoad() for use after FootprintEnumerate() for more efficient - * cache management. + * cache management. Return value is const to allow it to return a reference to a cached + * item. */ - MODULE* LoadEnumeratedFootprint( const wxString& aNickname, const wxString& aFootprintName ); + const MODULE* GetEnumeratedFootprint( const wxString& aNickname, + const wxString& aFootprintName ); /** * Enum SAVE_T * is the set of return values from FootprintSave() below. diff --git a/include/lib_tree_item.h b/include/lib_tree_item.h index 6e3ef097c0..9786cf3e04 100644 --- a/include/lib_tree_item.h +++ b/include/lib_tree_item.h @@ -39,19 +39,20 @@ class LIB_TREE_ITEM { public: - /** - * For items having aliases, IsRoot() indicates the principal item. - */ - virtual bool IsRoot() const { return true; } - virtual LIB_ID GetLibId() const = 0; virtual const wxString& GetName() const = 0; + virtual wxString GetLibNickname() const = 0; virtual wxString GetDescription() { return wxEmptyString; } virtual wxString GetSearchText() { return wxEmptyString; } + /** + * For items having aliases, IsRoot() indicates the principal item. + */ + virtual bool IsRoot() const { return true; } + /** * For items with units, return the number of units. */ diff --git a/pcbnew/footprint_edit_frame.h b/pcbnew/footprint_edit_frame.h index f7688c14d5..28cac3a612 100644 --- a/pcbnew/footprint_edit_frame.h +++ b/pcbnew/footprint_edit_frame.h @@ -463,18 +463,6 @@ public: */ bool OpenProjectFiles( const std::vector& aFileSet, int aCtl = 0 ) override; - /** - * Build the footprint library tree. Displays a progress dialog. - */ - void initLibraryTree(); - - /** - * Synchronize the footprint library tree to the current state of the footprint library - * table. - * @param aProgress - */ - void syncLibraryTree( bool aProgress ); - /** * Allows Modedit to install its preferences panel into the preferences dialog. */ @@ -506,6 +494,19 @@ protected: /// List of footprint editor configuration parameters. PARAM_CFG_ARRAY m_configParams; + /** + * Make sure the footprint info list is loaded (with a progress dialog) and then initialize + * the footprint library tree. + */ + void initLibraryTree(); + + /** + * Synchronize the footprint library tree to the current state of the footprint library + * table. + * @param aProgress + */ + void syncLibraryTree( bool aProgress ); + /** * Function UpdateTitle * updates window title according to getLibNickName(). diff --git a/pcbnew/footprint_info_impl.cpp b/pcbnew/footprint_info_impl.cpp index 4d9abff17e..6da16e178b 100644 --- a/pcbnew/footprint_info_impl.cpp +++ b/pcbnew/footprint_info_impl.cpp @@ -48,8 +48,9 @@ void FOOTPRINT_INFO_IMPL::load() wxASSERT( fptable ); - std::unique_ptr footprint( fptable->LoadEnumeratedFootprint( m_nickname, m_fpname ) ); - if( footprint.get() == NULL ) // Should happen only with malformed/broken libraries + const MODULE* footprint = fptable->GetEnumeratedFootprint( m_nickname, m_fpname ); + + if( footprint == NULL ) // Should happen only with malformed/broken libraries { m_pad_count = 0; m_unique_pad_count = 0; @@ -60,10 +61,9 @@ void FOOTPRINT_INFO_IMPL::load() m_unique_pad_count = footprint->GetUniquePadCount( DO_NOT_INCLUDE_NPTH ); m_keywords = footprint->GetKeywords(); m_doc = footprint->GetDescription(); - - // tell ensure_loaded() I'm loaded. - m_loaded = true; } + + m_loaded = true; } @@ -119,7 +119,9 @@ void FOOTPRINT_LIST_IMPL::loader_job() bool FOOTPRINT_LIST_IMPL::ReadFootprintFiles( FP_LIB_TABLE* aTable, const wxString* aNickname, PROGRESS_REPORTER* aProgressReporter ) { - if( m_list_timestamp == aTable->GenerateTimestamp( aNickname ) ) + long long int generatedTimestamp = aTable->GenerateTimestamp( aNickname ); + + if( generatedTimestamp == m_list_timestamp ) return true; m_progress_reporter = aProgressReporter; @@ -163,6 +165,11 @@ bool FOOTPRINT_LIST_IMPL::ReadFootprintFiles( FP_LIB_TABLE* aTable, const wxStri m_progress_reporter->AdvancePhase(); } + if( m_cancelled ) + m_list_timestamp = 0; // God knows what we got before we were cancelled + else + m_list_timestamp = generatedTimestamp; + return m_errors.empty(); } @@ -296,7 +303,7 @@ bool FOOTPRINT_LIST_IMPL::JoinWorkers() if( m_progress_reporter && !m_progress_reporter->KeepRefreshing() ) m_cancelled = true; - wxMilliSleep( 20 ); + wxMilliSleep( 30 ); } for( auto& thr : threads ) @@ -307,14 +314,11 @@ bool FOOTPRINT_LIST_IMPL::JoinWorkers() while( queue_parsed.pop( fpi ) ) m_list.push_back( std::move( fpi ) ); - std::sort( m_list.begin(), m_list.end(), - []( std::unique_ptr const& lhs, - std::unique_ptr const& rhs ) -> bool { return *lhs < *rhs; } ); - - if( m_cancelled ) - m_list_timestamp = 0; // God knows what we got before we were cancelled - else - m_list_timestamp = m_lib_table->GenerateTimestamp( m_library ); + std::sort( m_list.begin(), m_list.end(), []( std::unique_ptr const& lhs, + std::unique_ptr const& rhs ) -> bool + { + return *lhs < *rhs; + } ); return m_errors.empty(); } diff --git a/pcbnew/footprint_info_impl.h b/pcbnew/footprint_info_impl.h index 5af8c34a2b..905cf28f6b 100644 --- a/pcbnew/footprint_info_impl.h +++ b/pcbnew/footprint_info_impl.h @@ -44,9 +44,14 @@ public: m_num = 0; m_pad_count = 0; m_unique_pad_count = 0; -#if !USE_FPI_LAZY + load(); -#endif + } + + // A dummy constructor for use as a target in a binary search + FOOTPRINT_INFO_IMPL( const wxString& aFootprintName ) + { + m_fpname = aFootprintName; } protected: diff --git a/pcbnew/fp_tree_model_adapter.cpp b/pcbnew/fp_tree_model_adapter.cpp index 0eaf3ce485..789687caef 100644 --- a/pcbnew/fp_tree_model_adapter.cpp +++ b/pcbnew/fp_tree_model_adapter.cpp @@ -61,7 +61,7 @@ std::vector FP_TREE_MODEL_ADAPTER::getFootprints( const wxString for( auto& footprint : GFootprintList.GetList() ) { - if( footprint->GetNickname() != aLibName ) + if( footprint->GetLibNickname() != aLibName ) { if( found ) return list; diff --git a/pcbnew/fp_tree_synchronizing_adapter.cpp b/pcbnew/fp_tree_synchronizing_adapter.cpp index 1d2645efb4..4c540dda84 100644 --- a/pcbnew/fp_tree_synchronizing_adapter.cpp +++ b/pcbnew/fp_tree_synchronizing_adapter.cpp @@ -95,16 +95,19 @@ void FP_TREE_SYNCHRONIZING_ADAPTER::updateLibrary( LIB_TREE_NODE_LIB& aLibNode ) // remove the common part from the aliases list for( auto nodeIt = aLibNode.Children.begin(); nodeIt != aLibNode.Children.end(); ) { - auto footprintIt = std::find_if( footprints.begin(), footprints.end(), - [&] ( const LIB_TREE_ITEM* a ) - { - return a->GetName() == (*nodeIt)->Name; - } ); + // Since the list is sorted we can use a binary search to speed up searches within + // libraries with lots of footprints. + FOOTPRINT_INFO_IMPL dummy( (*nodeIt)->Name ); + auto footprintIt = std::lower_bound( footprints.begin(), footprints.end(), &dummy, + []( LIB_TREE_ITEM* a, LIB_TREE_ITEM* b ) + { + return a->GetName() < b->GetName(); + } ); - if( footprintIt != footprints.end() ) + if( footprintIt != footprints.end() && dummy.GetName() == (*footprintIt)->GetName() ) { - // alias exists both in the component tree and the library manager, - // update only the node data + // footprint exists both in the lib tree and the footprint info list; just + // update the node data static_cast( nodeIt->get() )->Update( *footprintIt ); footprints.erase( footprintIt ); ++nodeIt; @@ -118,7 +121,7 @@ void FP_TREE_SYNCHRONIZING_ADAPTER::updateLibrary( LIB_TREE_NODE_LIB& aLibNode ) // now the aliases list contains only new aliases that need to be added to the tree for( auto footprint : footprints ) - aLibNode.AddComp( footprint ); + aLibNode.AddItem( footprint ); aLibNode.AssignIntrinsicRanks(); m_libMap.insert( aLibNode.Name ); diff --git a/pcbnew/gpcb_plugin.cpp b/pcbnew/gpcb_plugin.cpp index f3d8dd4875..7421b80975 100644 --- a/pcbnew/gpcb_plugin.cpp +++ b/pcbnew/gpcb_plugin.cpp @@ -954,10 +954,10 @@ void GPCB_PLUGIN::FootprintEnumerate( wxArrayString& aFootprintNames, } -MODULE* GPCB_PLUGIN::doLoadFootprint( const wxString& aLibraryPath, - const wxString& aFootprintName, - const PROPERTIES* aProperties, - bool checkModified ) +const MODULE* GPCB_PLUGIN::getFootprint( const wxString& aLibraryPath, + const wxString& aFootprintName, + const PROPERTIES* aProperties, + bool checkModified ) { LOCALE_IO toggle; // toggles on, then off, the C locale. @@ -974,23 +974,23 @@ MODULE* GPCB_PLUGIN::doLoadFootprint( const wxString& aLibraryPath, return NULL; } - // copy constructor to clone the already loaded MODULE - return new MODULE( *it->second->GetModule() ); + return it->second->GetModule(); } -MODULE* GPCB_PLUGIN::LoadEnumeratedFootprint( const wxString& aLibraryPath, - const wxString& aFootprintName, - const PROPERTIES* aProperties ) +const MODULE* GPCB_PLUGIN::GetEnumeratedFootprint( const wxString& aLibraryPath, + const wxString& aFootprintName, + const PROPERTIES* aProperties ) { - return doLoadFootprint( aLibraryPath, aFootprintName, aProperties, false ); + return getFootprint( aLibraryPath, aFootprintName, aProperties, false ); } MODULE* GPCB_PLUGIN::FootprintLoad( const wxString& aLibraryPath, const wxString& aFootprintName, const PROPERTIES* aProperties ) { - return doLoadFootprint( aLibraryPath, aFootprintName, aProperties, true ); + const MODULE* footprint = getFootprint( aLibraryPath, aFootprintName, aProperties, true ); + return footprint ? new MODULE( *footprint ) : nullptr; } diff --git a/pcbnew/gpcb_plugin.h b/pcbnew/gpcb_plugin.h index 8ae6dc5e8b..9d15ab51a6 100644 --- a/pcbnew/gpcb_plugin.h +++ b/pcbnew/gpcb_plugin.h @@ -65,14 +65,15 @@ public: void FootprintEnumerate( wxArrayString& aFootprintNames, const wxString& aLibraryPath, const PROPERTIES* aProperties = NULL) override; - MODULE* LoadEnumeratedFootprint( const wxString& aLibraryPath, const wxString& aFootprintName, - const PROPERTIES* aProperties = NULL ) override; + const MODULE* GetEnumeratedFootprint( const wxString& aLibraryPath, + const wxString& aFootprintName, + const PROPERTIES* aProperties = NULL ) override; MODULE* FootprintLoad( const wxString& aLibraryPath, const wxString& aFootprintName, - const PROPERTIES* aProperties = NULL ) override; + const PROPERTIES* aProperties = NULL ) override; void FootprintDelete( const wxString& aLibraryPath, const wxString& aFootprintName, - const PROPERTIES* aProperties = NULL ) override; + const PROPERTIES* aProperties = NULL ) override; bool FootprintLibDelete( const wxString& aLibraryPath, const PROPERTIES* aProperties = NULL ) override; @@ -101,8 +102,8 @@ protected: private: void validateCache( const wxString& aLibraryPath, bool checkModified = true ); - MODULE* doLoadFootprint( const wxString& aLibraryPath, const wxString& aFootprintName, - const PROPERTIES* aProperties, bool checkModified ); + const MODULE* getFootprint( const wxString& aLibraryPath, const wxString& aFootprintName, + const PROPERTIES* aProperties, bool checkModified ); void init( const PROPERTIES* aProperties ); }; diff --git a/pcbnew/io_mgr.h b/pcbnew/io_mgr.h index c6e3905ab7..976e02f31f 100644 --- a/pcbnew/io_mgr.h +++ b/pcbnew/io_mgr.h @@ -407,13 +407,13 @@ public: const PROPERTIES* aProperties = NULL ); /** - * Function LoadEnumeratedFootprint - * a version of FootprintLoad() for use after FootprintEnumerate() for more - * efficient cache management. + * Function GetEnumeratedFootprint + * a version of FootprintLoad() for use after FootprintEnumerate() for more efficient + * cache management. */ - virtual MODULE* LoadEnumeratedFootprint( const wxString& aLibraryPath, - const wxString& aFootprintName, - const PROPERTIES* aProperties = NULL ); + virtual const MODULE* GetEnumeratedFootprint( const wxString& aLibraryPath, + const wxString& aFootprintName, + const PROPERTIES* aProperties = NULL ); /** * Function FootprintSave diff --git a/pcbnew/kicad_plugin.cpp b/pcbnew/kicad_plugin.cpp index 93234dfc1e..e95f7e91b4 100644 --- a/pcbnew/kicad_plugin.cpp +++ b/pcbnew/kicad_plugin.cpp @@ -91,10 +91,10 @@ class FP_CACHE_ITEM public: FP_CACHE_ITEM( MODULE* aModule, const wxFileName& aFileName ); - wxString GetName() const { return m_file_name.GetDirs().Last(); } - wxFileName GetFileName() const { return m_file_name; } + const wxString& GetName() const { return m_file_name.GetDirs().Last(); } + const wxFileName& GetFileName() const { return m_file_name; } - MODULE* GetModule() const { return m_module.get(); } + const MODULE* GetModule() const { return m_module.get(); } }; @@ -112,9 +112,10 @@ typedef MODULE_MAP::const_iterator MODULE_CITER; class FP_CACHE { - PCB_IO* m_owner; /// Plugin object that owns the cache. - wxFileName m_lib_path; /// The path of the library. - MODULE_MAP m_modules; /// Map of footprint file name per MODULE*. + PCB_IO* m_owner; // Plugin object that owns the cache. + wxFileName m_lib_path; // The path of the library. + wxString m_lib_raw_path; // For quick comparisons. + MODULE_MAP m_modules; // Map of footprint file name per MODULE*. bool m_cache_dirty; // Stored separately because it's expensive to check // m_cache_timestamp against all the files. @@ -124,7 +125,7 @@ class FP_CACHE public: FP_CACHE( PCB_IO* aOwner, const wxString& aLibraryPath ); - wxString GetPath() const { return m_lib_path.GetPath(); } + wxString GetPath() const { return m_lib_raw_path; } bool IsWritable() const { return m_lib_path.IsOk() && m_lib_path.IsDirWritable(); } bool Exists() const { return m_lib_path.IsOk() && m_lib_path.DirExists(); } MODULE_MAP& GetModules() { return m_modules; } @@ -178,6 +179,7 @@ public: FP_CACHE::FP_CACHE( PCB_IO* aOwner, const wxString& aLibraryPath ) { m_owner = aOwner; + m_lib_raw_path = aLibraryPath; m_lib_path.SetPath( aLibraryPath ); m_cache_timestamp = 0; m_cache_dirty = true; @@ -191,13 +193,13 @@ void FP_CACHE::Save( MODULE* aModule ) if( !m_lib_path.DirExists() && !m_lib_path.Mkdir() ) { THROW_IO_ERROR( wxString::Format( _( "Cannot create footprint library path \"%s\"" ), - m_lib_path.GetPath().GetData() ) ); + m_lib_raw_path ) ); } if( !m_lib_path.IsDirWritable() ) { THROW_IO_ERROR( wxString::Format( _( "Footprint library path \"%s\" is read only" ), - GetChars( m_lib_path.GetPath() ) ) ); + m_lib_raw_path ) ); } for( MODULE_ITER it = m_modules.begin(); it != m_modules.end(); ++it ) @@ -255,18 +257,15 @@ void FP_CACHE::Save( MODULE* aModule ) void FP_CACHE::Load() { - wxDir dir( m_lib_path.GetPath() ); + wxDir dir( m_lib_raw_path ); if( !dir.IsOpened() ) { m_cache_timestamp = 0; m_cache_dirty = false; - wxString msg = wxString::Format( - _( "Footprint library path \"%s\" does not exist" ), - GetChars( m_lib_path.GetPath() ) - ); - + wxString msg = wxString::Format( _( "Footprint library path \"%s\" does not exist" ), + m_lib_raw_path ); THROW_IO_ERROR( msg ); } else @@ -285,7 +284,7 @@ void FP_CACHE::Load() do { // prepend the libpath into fullPath - wxFileName fullPath( m_lib_path.GetPath(), fpFileName ); + wxFileName fullPath( m_lib_raw_path, fpFileName ); // Queue I/O errors so only files that fail to parse don't get loaded. try @@ -325,11 +324,9 @@ void FP_CACHE::Remove( const wxString& aFootprintName ) if( it == m_modules.end() ) { - wxString msg = wxString::Format( - _( "library \"%s\" has no footprint \"%s\" to delete" ), - GetChars( m_lib_path.GetPath() ), - GetChars( aFootprintName ) - ); + wxString msg = wxString::Format( _( "library \"%s\" has no footprint \"%s\" to delete" ), + m_lib_raw_path, + aFootprintName ); THROW_IO_ERROR( msg ); } @@ -342,11 +339,7 @@ void FP_CACHE::Remove( const wxString& aFootprintName ) bool FP_CACHE::IsPath( const wxString& aPath ) const { - // Converts path separators to native path separators - wxFileName newPath; - newPath.AssignDir( aPath ); - - return m_lib_path == newPath; + return aPath == m_lib_raw_path; } @@ -373,10 +366,18 @@ long long FP_CACHE::GetTimestamp() for( MODULE_CITER it = m_modules.begin(); it != m_modules.end(); ++it ) { - wxFileName fn = it->second->GetFileName(); -#ifndef __WINDOWS__ + const wxFileName& fn = it->second->GetFileName(); +#ifdef __WINDOWS__ + if( fn.FileExists() ) + files_timestamp += fn.GetModificationTime().GetValue().GetValue(); +#else + // By stat-ing the file ourselves we save wxWidgets from doing it three times: + // fn.Exists( wxFILE_EXISTS_SYMLINK ), fn.FileExists() & fn.GetModificationTime() + struct stat fn_stat; + wxLstat( fn.GetFullPath(), &fn_stat ); + // Timestamp the source file, not the symlink - if( fn.Exists( wxFILE_EXISTS_SYMLINK ) ) + if( S_ISLNK( fn_stat.st_mode ) ) // wxFILE_EXISTS_SYMLINK { char buffer[ PATH_MAX + 1 ]; ssize_t pathLen = readlink( TO_UTF8( fn.GetFullPath() ), buffer, PATH_MAX ); @@ -384,13 +385,16 @@ long long FP_CACHE::GetTimestamp() if( pathLen > 0 ) { buffer[ pathLen ] = '\0'; - fn.Assign( fn.GetPath() + wxT( "/" ) + wxString::FromUTF8( buffer ) ); - fn.Normalize(); + wxFileName srcFn; + srcFn.Assign( fn.GetPath() + wxT( "/" ) + wxString::FromUTF8( buffer ) ); + srcFn.Normalize(); + wxLstat( srcFn.GetFullPath(), &fn_stat ); } } + + if( S_ISREG( fn_stat.st_mode ) ) // wxFileExists() + files_timestamp += fn_stat.st_mtime * 1000; #endif - if( fn.FileExists() ) - files_timestamp += fn.GetModificationTime().GetValue().GetValue(); } } @@ -2028,10 +2032,10 @@ void PCB_IO::FootprintEnumerate( wxArrayString& aFootprintNames, } -MODULE* PCB_IO::doLoadFootprint( const wxString& aLibraryPath, - const wxString& aFootprintName, - const PROPERTIES* aProperties, - bool checkModified ) +const MODULE* PCB_IO::getFootprint( const wxString& aLibraryPath, + const wxString& aFootprintName, + const PROPERTIES* aProperties, + bool checkModified ) { LOCALE_IO toggle; // toggles on, then off, the C locale. @@ -2055,23 +2059,23 @@ MODULE* PCB_IO::doLoadFootprint( const wxString& aLibraryPath, return NULL; } - // copy constructor to clone the already loaded MODULE - return new MODULE( *it->second->GetModule() ); + return it->second->GetModule(); } -MODULE* PCB_IO::LoadEnumeratedFootprint( const wxString& aLibraryPath, - const wxString& aFootprintName, - const PROPERTIES* aProperties ) +const MODULE* PCB_IO::GetEnumeratedFootprint( const wxString& aLibraryPath, + const wxString& aFootprintName, + const PROPERTIES* aProperties ) { - return doLoadFootprint( aLibraryPath, aFootprintName, aProperties, false ); + return getFootprint( aLibraryPath, aFootprintName, aProperties, false ); } MODULE* PCB_IO::FootprintLoad( const wxString& aLibraryPath, const wxString& aFootprintName, const PROPERTIES* aProperties ) { - return doLoadFootprint( aLibraryPath, aFootprintName, aProperties, true ); + const MODULE* footprint = getFootprint( aLibraryPath, aFootprintName, aProperties, true ); + return footprint ? new MODULE( *footprint ) : nullptr; } @@ -2093,12 +2097,10 @@ void PCB_IO::FootprintSave( const wxString& aLibraryPath, const MODULE* aFootpri if( !m_cache->Exists() ) { const wxString msg = wxString::Format( _( "Library \"%s\" does not exist.\n" - "Would you like to create it?"), - GetChars( aLibraryPath ) ); - const wxString title = wxString::Format( _( "Create new library \"%s\"?"), - GetChars( aLibraryPath ) ); + "Would you like to create it?"), + GetChars( aLibraryPath ) ); - if( wxMessageBox( msg, title, wxYES_NO | wxICON_QUESTION ) != wxYES ) + if( 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 @@ -2106,12 +2108,9 @@ void PCB_IO::FootprintSave( const wxString& aLibraryPath, const MODULE* aFootpri } else { - wxString msg = wxString::Format( _( "Library \"%s\" is read only" ), - GetChars( aLibraryPath ) ); + wxString msg = wxString::Format( _( "Library \"%s\" is read only" ), aLibraryPath ); THROW_IO_ERROR( msg ); } - - } wxString footprintName = aFootprint->GetFPID().GetLibItemName(); @@ -2141,13 +2140,13 @@ void PCB_IO::FootprintSave( const wxString& aLibraryPath, const MODULE* aFootpri if( !fn.IsOk() ) { THROW_IO_ERROR( wxString::Format( _( "Footprint file name \"%s\" is not valid." ), - GetChars( fn.GetFullPath() ) ) ); + fn.GetFullPath() ) ); } if( fn.FileExists() && !fn.IsFileWritable() ) { - THROW_IO_ERROR( wxString::Format( _( "user does not have write permission to delete file \"%s\" " ), - GetChars( fn.GetFullPath() ) ) ); + THROW_IO_ERROR( wxString::Format( _( "No write permissions to delete file \"%s\" " ), + fn.GetFullPath() ) ); } MODULE_CITER it = mods.find( footprintName ); diff --git a/pcbnew/kicad_plugin.h b/pcbnew/kicad_plugin.h index 762358d13c..2f408cc3bc 100644 --- a/pcbnew/kicad_plugin.h +++ b/pcbnew/kicad_plugin.h @@ -119,13 +119,14 @@ public: const PROPERTIES* aProperties = NULL ) override; void FootprintEnumerate( wxArrayString& aFootprintNames, const wxString& aLibraryPath, - const PROPERTIES* aProperties = NULL ) override; + const PROPERTIES* aProperties = NULL ) override; - MODULE* LoadEnumeratedFootprint( const wxString& aLibraryPath, const wxString& aFootprintName, - const PROPERTIES* aProperties = NULL ) override; + const MODULE* GetEnumeratedFootprint( const wxString& aLibraryPath, + const wxString& aFootprintName, + const PROPERTIES* aProperties = NULL ) override; MODULE* FootprintLoad( const wxString& aLibraryPath, const wxString& aFootprintName, - const PROPERTIES* aProperties = NULL ) override; + const PROPERTIES* aProperties = NULL ) override; void FootprintSave( const wxString& aLibraryPath, const MODULE* aFootprint, const PROPERTIES* aProperties = NULL ) override; @@ -193,8 +194,8 @@ protected: void validateCache( const wxString& aLibraryPath, bool checkModified = true ); - MODULE* doLoadFootprint( const wxString& aLibraryPath, const wxString& aFootprintName, - const PROPERTIES* aProperties, bool checkModified ); + const MODULE* getFootprint( const wxString& aLibraryPath, const wxString& aFootprintName, + const PROPERTIES* aProperties, bool checkModified ); void init( const PROPERTIES* aProperties ); diff --git a/pcbnew/load_select_footprint.cpp b/pcbnew/load_select_footprint.cpp index 0aa3459328..d7f27b2afc 100644 --- a/pcbnew/load_select_footprint.cpp +++ b/pcbnew/load_select_footprint.cpp @@ -421,7 +421,7 @@ bool FOOTPRINT_EDIT_FRAME::SaveLibraryAs( const wxString& aLibraryPath ) for( unsigned i = 0; i < footprints.size(); ++i ) { - const MODULE* footprint = cur->LoadEnumeratedFootprint( curLibPath, footprints[i] ); + const MODULE* footprint = cur->GetEnumeratedFootprint( curLibPath, footprints[i] ); dst->FootprintSave( dstLibPath, footprint ); msg = wxString::Format( _( "Footprint \"%s\" saved" ), footprints[i] ); diff --git a/pcbnew/plugin.cpp b/pcbnew/plugin.cpp index af75fefce5..5ca5a351dd 100644 --- a/pcbnew/plugin.cpp +++ b/pcbnew/plugin.cpp @@ -38,9 +38,8 @@ static void not_implemented( PLUGIN* aPlugin, const char* aCaller ) { THROW_IO_ERROR( wxString::Format( FMT_UNIMPLEMENTED, - aPlugin->PluginName().GetData(), - wxString::FromUTF8( aCaller ).GetData() ) - ); + aPlugin->PluginName().GetData(), + wxString::FromUTF8( aCaller ).GetData() ) ); } @@ -73,9 +72,9 @@ void PLUGIN::PrefetchLib( const wxString& aLibraryPath, const PROPERTIES* aPrope } -MODULE* PLUGIN::LoadEnumeratedFootprint( const wxString& aLibraryPath, - const wxString& aFootprintName, - const PROPERTIES* aProperties ) +const MODULE* PLUGIN::GetEnumeratedFootprint( const wxString& aLibraryPath, + const wxString& aFootprintName, + const PROPERTIES* aProperties ) { // default implementation return FootprintLoad( aLibraryPath, aFootprintName, aProperties ); @@ -83,7 +82,7 @@ MODULE* PLUGIN::LoadEnumeratedFootprint( const wxString& aLibraryPath, MODULE* PLUGIN::FootprintLoad( const wxString& aLibraryPath, const wxString& aFootprintName, - const PROPERTIES* aProperties ) + const PROPERTIES* aProperties ) { // not pure virtual so that plugins only have to implement subset of the PLUGIN interface. not_implemented( this, __FUNCTION__ ); @@ -91,14 +90,16 @@ MODULE* PLUGIN::FootprintLoad( const wxString& aLibraryPath, const wxString& aFo } -void PLUGIN::FootprintSave( const wxString& aLibraryPath, const MODULE* aFootprint, const PROPERTIES* aProperties ) +void PLUGIN::FootprintSave( const wxString& aLibraryPath, const MODULE* aFootprint, + const PROPERTIES* aProperties ) { // not pure virtual so that plugins only have to implement subset of the PLUGIN interface. not_implemented( this, __FUNCTION__ ); } -void PLUGIN::FootprintDelete( const wxString& aLibraryPath, const wxString& aFootprintName, const PROPERTIES* aProperties ) +void PLUGIN::FootprintDelete( const wxString& aLibraryPath, const wxString& aFootprintName, + const PROPERTIES* aProperties ) { // not pure virtual so that plugins only have to implement subset of the PLUGIN interface. not_implemented( this, __FUNCTION__ );