diff --git a/common/design_block.cpp b/common/design_block.cpp index 4b523b3abc..8cef2da84c 100644 --- a/common/design_block.cpp +++ b/common/design_block.cpp @@ -22,22 +22,23 @@ #include -std::vector DESIGN_BLOCK::GetSearchTerms() +std::vector& DESIGN_BLOCK::GetSearchTerms() { - std::vector terms; + m_searchTerms.clear(); + m_searchTerms.reserve( 6 ); - terms.emplace_back( SEARCH_TERM( GetLibNickname(), 4 ) ); - terms.emplace_back( SEARCH_TERM( GetName(), 8 ) ); - terms.emplace_back( SEARCH_TERM( GetLIB_ID().Format(), 16 ) ); + m_searchTerms.emplace_back( SEARCH_TERM( GetLibNickname(), 4 ) ); + m_searchTerms.emplace_back( SEARCH_TERM( GetName(), 8 ) ); + m_searchTerms.emplace_back( SEARCH_TERM( GetLIB_ID().Format(), 16 ) ); wxStringTokenizer keywordTokenizer( GetKeywords(), wxS( " " ), wxTOKEN_STRTOK ); while( keywordTokenizer.HasMoreTokens() ) - terms.emplace_back( SEARCH_TERM( keywordTokenizer.GetNextToken(), 4 ) ); + m_searchTerms.emplace_back( SEARCH_TERM( keywordTokenizer.GetNextToken(), 4 ) ); // Also include keywords as one long string, just in case - terms.emplace_back( SEARCH_TERM( GetKeywords(), 1 ) ); - terms.emplace_back( SEARCH_TERM( GetDesc(), 1 ) ); + m_searchTerms.emplace_back( SEARCH_TERM( GetKeywords(), 1 ) ); + m_searchTerms.emplace_back( SEARCH_TERM( GetDesc(), 1 ) ); - return terms; + return m_searchTerms; } diff --git a/common/design_block.h b/common/design_block.h index a9ea7bac5a..888b30958f 100644 --- a/common/design_block.h +++ b/common/design_block.h @@ -39,7 +39,7 @@ public: wxString GetName() const override { return m_lib_id.GetLibItemName(); } wxString GetLibNickname() const override { return m_lib_id.GetLibNickname(); } wxString GetDesc() override { return GetLibDescription(); } - std::vector GetSearchTerms() override; + std::vector& GetSearchTerms() override; void SetLibId( const LIB_ID& aName ) { m_lib_id = aName; } const LIB_ID& GetLibId() const { return m_lib_id; } @@ -73,6 +73,7 @@ private: wxString m_keywords; ///< Search keywords to find design block in library. nlohmann::ordered_map m_fields; + std::vector m_searchTerms; }; #endif diff --git a/common/footprint_filter.cpp b/common/footprint_filter.cpp index bcffd0ef5d..c2866cb626 100644 --- a/common/footprint_filter.cpp +++ b/common/footprint_filter.cpp @@ -90,9 +90,7 @@ void FOOTPRINT_FILTER_IT::increment() for( std::unique_ptr& matcher : m_filter->m_pattern_filters ) { - std::vector searchTerms = candidate.GetSearchTerms(); - - if( !matcher->ScoreTerms( searchTerms ) ) + if( !matcher->ScoreTerms( candidate.GetSearchTerms() ) ) { exclude = true; break; diff --git a/common/footprint_info.cpp b/common/footprint_info.cpp index 1d3ac9b47d..23dd0ba769 100644 --- a/common/footprint_info.cpp +++ b/common/footprint_info.cpp @@ -64,24 +64,25 @@ FOOTPRINT_INFO* FOOTPRINT_LIST::GetFootprintInfo( const wxString& aFootprintName } -std::vector FOOTPRINT_INFO::GetSearchTerms() +std::vector& FOOTPRINT_INFO::GetSearchTerms() { - std::vector terms; + m_searchTerms.clear(); + m_searchTerms.reserve( 6 ); - terms.emplace_back( SEARCH_TERM( GetLibNickname(), 4 ) ); - terms.emplace_back( SEARCH_TERM( GetName(), 8 ) ); - terms.emplace_back( SEARCH_TERM( GetLIB_ID().Format(), 16 ) ); + m_searchTerms.emplace_back( SEARCH_TERM( GetLibNickname(), 4 ) ); + m_searchTerms.emplace_back( SEARCH_TERM( GetName(), 8 ) ); + m_searchTerms.emplace_back( SEARCH_TERM( GetLIB_ID().Format(), 16 ) ); wxStringTokenizer keywordTokenizer( GetKeywords(), " \t\r\n", wxTOKEN_STRTOK ); while( keywordTokenizer.HasMoreTokens() ) - terms.emplace_back( SEARCH_TERM( keywordTokenizer.GetNextToken(), 4 ) ); + m_searchTerms.emplace_back( SEARCH_TERM( keywordTokenizer.GetNextToken(), 4 ) ); // Also include keywords as one long string, just in case - terms.emplace_back( SEARCH_TERM( GetKeywords(), 1 ) ); - terms.emplace_back( SEARCH_TERM( GetDesc(), 1 ) ); + m_searchTerms.emplace_back( SEARCH_TERM( GetKeywords(), 1 ) ); + m_searchTerms.emplace_back( SEARCH_TERM( GetDesc(), 1 ) ); - return terms; + return m_searchTerms; } diff --git a/common/lib_tree_model.cpp b/common/lib_tree_model.cpp index 2e43b14bd3..e83236d44e 100644 --- a/common/lib_tree_model.cpp +++ b/common/lib_tree_model.cpp @@ -33,7 +33,7 @@ void LIB_TREE_NODE::RebuildSearchTerms( const std::vector& aShownColumns ) { - m_SearchTerms = m_sourceSearchTerms; + m_SearchTerms.assign( m_sourceSearchTerms.begin(), m_sourceSearchTerms.end() ); for( const auto& [name, value] : m_Fields ) { diff --git a/eeschema/lib_symbol.cpp b/eeschema/lib_symbol.cpp index 87986cc2ed..a3a916fac7 100644 --- a/eeschema/lib_symbol.cpp +++ b/eeschema/lib_symbol.cpp @@ -100,17 +100,35 @@ static std::shared_ptr GetSafeRootSymbol( const LIB_SYMBOL* aSymbol, wxString LIB_SYMBOL::GetShownDescription( int aDepth ) const { - wxString shownText = GetDescriptionField().GetShownText( false, aDepth ); + return m_shownDescriptionCache; +} + +void LIB_SYMBOL::cacheShownDescription() +{ + wxString shownText = GetDescriptionField().GetShownText( false, 0 ); if( shownText.IsEmpty() && IsDerived() ) { std::shared_ptr root = GetSafeRootSymbol( this, __FUNCTION__ ); if( root.get() != this ) - shownText = root->GetDescriptionField().GetShownText( false, aDepth ); + shownText = root->GetDescriptionField().GetShownText( false, 0 ); } +} - return shownText; + +void LIB_SYMBOL::SetDescription( const wxString& aDescription ) +{ + GetDescriptionField().SetText( aDescription ); + cacheSearchTerms(); + cacheShownDescription(); +} + + +void LIB_SYMBOL::SetKeyWords( const wxString& aKeyWords ) +{ + m_keyWords = aKeyWords; + cacheSearchTerms(); } @@ -129,48 +147,64 @@ wxString LIB_SYMBOL::GetShownKeyWords( int aDepth ) const } -std::vector LIB_SYMBOL::GetSearchTerms() +enum SEARCH_TERM_CACHE_INDEX { - std::vector terms; + STCI_LIB_NICKNAME = 0, + STCI_LIB_SYMBOL_NAME, + STCI_LIB_ID +}; - terms.emplace_back( SEARCH_TERM( GetLibNickname(), 4 ) ); - terms.emplace_back( SEARCH_TERM( GetName(), 8 ) ); - terms.emplace_back( SEARCH_TERM( GetLIB_ID().Format(), 16 ) ); + +void LIB_SYMBOL::cacheSearchTerms() +{ + m_searchTermsCache.clear(); + m_searchTermsCache.reserve( 6 ); + + // Order matters, see SEARCH_TERM_CACHE_INDEX + m_searchTermsCache.emplace_back( SEARCH_TERM( GetLibNickname(), 4 ) ); + m_searchTermsCache.emplace_back( SEARCH_TERM( GetName(), 8 ) ); + m_searchTermsCache.emplace_back( SEARCH_TERM( GetLIB_ID().Format(), 16 ) ); wxStringTokenizer keywordTokenizer( GetShownKeyWords(), " \t\r\n", wxTOKEN_STRTOK ); while( keywordTokenizer.HasMoreTokens() ) - terms.emplace_back( SEARCH_TERM( keywordTokenizer.GetNextToken(), 4 ) ); + m_searchTermsCache.emplace_back( SEARCH_TERM( keywordTokenizer.GetNextToken(), 4 ) ); // Also include keywords as one long string, just in case - terms.emplace_back( SEARCH_TERM( GetShownKeyWords(), 1 ) ); - terms.emplace_back( SEARCH_TERM( GetShownDescription(), 1 ) ); + m_searchTermsCache.emplace_back( SEARCH_TERM( GetShownKeyWords(), 1 ) ); + m_searchTermsCache.emplace_back( SEARCH_TERM( GetShownDescription(), 1 ) ); wxString footprint = GetFootprint(); if( !footprint.IsEmpty() ) - terms.emplace_back( SEARCH_TERM( footprint, 1 ) ); - - return terms; + m_searchTermsCache.emplace_back( SEARCH_TERM( footprint, 1 ) ); } void LIB_SYMBOL::GetChooserFields( std::map& aColumnMap ) { + aColumnMap = m_chooserFieldsCache; +} + + +void LIB_SYMBOL::cacheChooserFields() +{ + m_chooserFieldsCache.clear(); + for( SCH_ITEM& item : m_drawings[SCH_FIELD_T] ) { SCH_FIELD* field = static_cast( &item ); if( field->ShowInChooser() ) - aColumnMap[field->GetName()] = field->EDA_TEXT::GetShownText( false ); + m_chooserFieldsCache[field->GetName()] = field->EDA_TEXT::GetShownText( false ); } // If the user has a field named "Keywords", then prefer that. Otherwise add the KiCad // keywords. const wxString localizedKeywords = _( "Keywords" ); - if( !aColumnMap.contains( localizedKeywords ) ) - aColumnMap[localizedKeywords] = GetShownKeyWords(); + if( !m_chooserFieldsCache.contains( localizedKeywords ) ) + m_chooserFieldsCache[localizedKeywords] = GetShownKeyWords(); } @@ -198,6 +232,7 @@ LIB_SYMBOL::LIB_SYMBOL( const wxString& aName, LIB_SYMBOL* aParent, LEGACY_SYMBO m_options = ENTRY_NORMAL; m_unitsLocked = false; m_duplicatePinNumbersAreJumpers = false; + m_library = nullptr; auto addField = [&]( FIELD_T id, bool visible ) { @@ -216,6 +251,10 @@ LIB_SYMBOL::LIB_SYMBOL( const wxString& aName, LIB_SYMBOL* aParent, LEGACY_SYMBO SetName( aName ); SetParent( aParent ); SetLib( aLibrary ); + cacheSearchTerms(); + cachePinCount(); + cacheShownDescription(); + cacheChooserFields(); } @@ -263,6 +302,10 @@ LIB_SYMBOL::LIB_SYMBOL( const LIB_SYMBOL& aSymbol, LEGACY_SYMBOL_LIB* aLibrary, } SetParent( aSymbol.m_parent.lock().get() ); + m_searchTermsCache = aSymbol.m_searchTermsCache; + m_pinCountCache = aSymbol.m_pinCountCache; + m_shownDescriptionCache = aSymbol.m_shownDescriptionCache; + m_chooserFieldsCache = aSymbol.m_chooserFieldsCache; } @@ -308,6 +351,11 @@ const LIB_SYMBOL& LIB_SYMBOL::operator=( const LIB_SYMBOL& aSymbol ) EMBEDDED_FILES::operator=( aSymbol ); + m_searchTermsCache = aSymbol.m_searchTermsCache; + m_pinCountCache = aSymbol.m_pinCountCache; + m_shownDescriptionCache = aSymbol.m_shownDescriptionCache; + m_chooserFieldsCache = aSymbol.m_chooserFieldsCache; + return *this; } @@ -433,6 +481,23 @@ void LIB_SYMBOL::SetName( const wxString& aName ) { m_name = aName; m_libId.SetLibItemName( aName ); + + if( m_searchTermsCache.empty() ) + cacheSearchTerms(); + + m_searchTermsCache[STCI_LIB_SYMBOL_NAME].Text = aName; + m_searchTermsCache[STCI_LIB_ID].Text = GetLIB_ID().Format(); +} + + +void LIB_SYMBOL::SetLibId( const LIB_ID& aLibId ) +{ + m_libId = aLibId; + + if( m_searchTermsCache.empty() ) + cacheSearchTerms(); + + m_searchTermsCache[STCI_LIB_ID].Text = GetLIB_ID().Format(); } @@ -627,6 +692,17 @@ std::unique_ptr LIB_SYMBOL::Flatten() const } +void LIB_SYMBOL::SetLib( LEGACY_SYMBOL_LIB* aLibrary ) +{ + m_library = aLibrary; + + if( m_searchTermsCache.empty() ) + cacheSearchTerms(); + + m_searchTermsCache[STCI_LIB_NICKNAME].Text = GetLibraryName(); +} + + const wxString LIB_SYMBOL::GetLibraryName() const { if( m_library ) @@ -1012,6 +1088,9 @@ void LIB_SYMBOL::AddDrawItem( SCH_ITEM* aItem, bool aSort ) if( aSort ) m_drawings.sort(); + + cachePinCount(); + cacheChooserFields(); } } @@ -1176,15 +1255,19 @@ std::vector LIB_SYMBOL::GetLogicalPins( int aUnit, int int LIB_SYMBOL::GetPinCount() { - int count = 0; + return m_pinCountCache; +} + + +void LIB_SYMBOL::cachePinCount() +{ + m_pinCountCache = 0; for( SCH_PIN* pin : GetGraphicalPins( 0 /* all units */, 1 /* single body style */ ) ) { int pinCount = pin->GetStackedPinCount(); - count += pinCount; + m_pinCountCache += pinCount; } - - return count; } @@ -1370,6 +1453,8 @@ const BOX2I LIB_SYMBOL::GetBodyBoundingBox( int aUnit, int aBodyStyle, bool aInc void LIB_SYMBOL::deleteAllFields() { m_drawings[SCH_FIELD_T].clear(); + cacheSearchTerms(); + cacheChooserFields(); } @@ -1393,6 +1478,8 @@ void LIB_SYMBOL::SetFields( const std::vector& aFieldsList ) } m_drawings.sort(); + cacheSearchTerms(); + cacheChooserFields(); } diff --git a/eeschema/lib_symbol.h b/eeschema/lib_symbol.h index 2793f5089e..336fef49ab 100644 --- a/eeschema/lib_symbol.h +++ b/eeschema/lib_symbol.h @@ -150,7 +150,7 @@ public: int GetSubUnitCount() const override { return GetUnitCount(); } const LIB_ID& GetLibId() const override { return m_libId; } - void SetLibId( const LIB_ID& aLibId ) { m_libId = aLibId; } + void SetLibId( const LIB_ID& aLibId ); LIB_ID GetSourceLibId() const { return m_sourceLibId; } void SetSourceLibId( const LIB_ID& aLibId ) { m_sourceLibId = aLibId; } @@ -158,10 +158,7 @@ public: wxString GetLibNickname() const override { return GetLibraryName(); } ///< Sets the Description field text value - void SetDescription( const wxString& aDescription ) - { - GetDescriptionField().SetText( aDescription ); - } + void SetDescription( const wxString& aDescription ); ///< Gets the Description field text value */ wxString GetDescription() const override @@ -177,7 +174,7 @@ public: wxString GetShownDescription( int aDepth = 0 ) const override; - void SetKeyWords( const wxString& aKeyWords ) { m_keyWords = aKeyWords; } + void SetKeyWords( const wxString& aKeyWords ); wxString GetKeyWords() const override { @@ -192,7 +189,7 @@ public: wxString GetShownKeyWords( int aDepth = 0 ) const override; - std::vector GetSearchTerms() override; + std::vector& GetSearchTerms() override { return m_searchTermsCache; } void GetChooserFields( std::map& aColumnMap ) override; @@ -205,7 +202,7 @@ public: const wxString GetLibraryName() const; LEGACY_SYMBOL_LIB* GetLib() const { return m_library; } - void SetLib( LEGACY_SYMBOL_LIB* aLibrary ) { m_library = aLibrary; } + void SetLib( LEGACY_SYMBOL_LIB* aLibrary ); timestamp_t GetLastModDate() const { return m_lastModDate; } @@ -870,6 +867,11 @@ private: void deleteAllFields(); + void cacheSearchTerms(); + void cachePinCount(); + void cacheShownDescription(); + void cacheChooserFields(); + private: std::shared_ptr m_me; std::weak_ptr m_parent; ///< Use for inherited symbols. @@ -908,4 +910,12 @@ private: std::map m_unitDisplayNames; std::vector m_bodyStyleNames; + + // Caches for things that are expensive to compute but required every time + // the symbol chooser or other library list is created + + std::vector m_searchTermsCache; + int m_pinCountCache; + wxString m_shownDescriptionCache; + std::map m_chooserFieldsCache; }; diff --git a/eeschema/symbol_tree_model_adapter.cpp b/eeschema/symbol_tree_model_adapter.cpp index d43de53f73..c6be665d47 100644 --- a/eeschema/symbol_tree_model_adapter.cpp +++ b/eeschema/symbol_tree_model_adapter.cpp @@ -83,15 +83,24 @@ void SYMBOL_TREE_MODEL_ADAPTER::AddLibraries( SCH_BASE_FRAME* aFrame ) COMMON_SETTINGS* cfg = Pgm().GetCommonSettings(); PROJECT_FILE& project = aFrame->Prj().GetProjectFile(); + std::unordered_set pinned; + std::ranges::copy( cfg->m_Session.pinned_symbol_libs, std::inserter( pinned, pinned.begin() ) ); + std::ranges::copy( project.m_PinnedSymbolLibs, std::inserter( pinned, pinned.begin() ) ); + auto addFunc = [&]( const wxString& aLibName, const std::vector& aSymbolList, const wxString& aDescription ) { - std::vector treeItems( aSymbolList.begin(), aSymbolList.end() ); - bool pinned = alg::contains( cfg->m_Session.pinned_symbol_libs, aLibName ) - || alg::contains( project.m_PinnedSymbolLibs, aLibName ); + LIB_TREE_NODE_LIBRARY& lib_node = + DoAddLibraryNode( aLibName, aDescription, pinned.contains( aLibName ) ); - DoAddLibrary( aLibName, aDescription, treeItems, pinned, false ); + for( LIB_TREE_ITEM* item: aSymbolList ) + { + if( item ) + lib_node.AddItem( item ); + } + + lib_node.AssignIntrinsicRanks( m_shownColumns, false ); }; LIBRARY_MANAGER& manager = Pgm().GetLibraryManager(); diff --git a/eeschema/symbol_viewer_frame.cpp b/eeschema/symbol_viewer_frame.cpp index b69c54e302..1855abb419 100644 --- a/eeschema/symbol_viewer_frame.cpp +++ b/eeschema/symbol_viewer_frame.cpp @@ -631,8 +631,7 @@ bool SYMBOL_VIEWER_FRAME::ReCreateSymbolList() for( LIB_SYMBOL* symbol : symbols ) { - std::vector searchTerms = symbol->GetSearchTerms(); - int matched = matcher.ScoreTerms( searchTerms ); + int matched = matcher.ScoreTerms( symbol->GetSearchTerms() ); if( filterTerm.IsNumber() && wxAtoi( filterTerm ) == (int)symbol->GetPinCount() ) matched++; diff --git a/include/footprint_info.h b/include/footprint_info.h index 9da856d098..6a231b7515 100644 --- a/include/footprint_info.h +++ b/include/footprint_info.h @@ -83,7 +83,7 @@ public: return m_keywords; } - std::vector GetSearchTerms() override; + std::vector& GetSearchTerms() override; unsigned GetPadCount() { @@ -139,6 +139,8 @@ protected: unsigned m_unique_pad_count; ///< Number of unique pads wxString m_doc; ///< Footprint description. wxString m_keywords; ///< Footprint keywords. + + std::vector m_searchTerms; }; diff --git a/include/lib_tree_item.h b/include/lib_tree_item.h index f65dd51bfe..05a2b4bdd8 100644 --- a/include/lib_tree_item.h +++ b/include/lib_tree_item.h @@ -56,7 +56,7 @@ public: */ virtual void GetChooserFields( std::map& aColumnMap ) {} - virtual std::vector GetSearchTerms() { return std::vector(); } + virtual std::vector& GetSearchTerms() = 0; /** * For items having aliases, IsRoot() indicates the principal item. diff --git a/include/lib_tree_model.h b/include/lib_tree_model.h index 6f6e1c7d62..41dd16d9b8 100644 --- a/include/lib_tree_model.h +++ b/include/lib_tree_model.h @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -149,7 +150,7 @@ public: bool m_IsAlreadyPlacedGroup; protected: - std::vector m_sourceSearchTerms; + std::span m_sourceSearchTerms; }; diff --git a/pcbnew/footprint.cpp b/pcbnew/footprint.cpp index 7e8e2ebd00..a1ede8e31d 100644 --- a/pcbnew/footprint.cpp +++ b/pcbnew/footprint.cpp @@ -1684,23 +1684,24 @@ wxString FOOTPRINT::GetTypeName() const } -std::vector FOOTPRINT::GetSearchTerms() +std::vector& FOOTPRINT::GetSearchTerms() { - std::vector terms; + m_searchTerms.clear(); + m_searchTerms.reserve( 6 ); - terms.emplace_back( SEARCH_TERM( GetLibNickname(), 4 ) ); - terms.emplace_back( SEARCH_TERM( GetName(), 8 ) ); - terms.emplace_back( SEARCH_TERM( GetLIB_ID().Format(), 16 ) ); + m_searchTerms.emplace_back( SEARCH_TERM( GetLibNickname(), 4 ) ); + m_searchTerms.emplace_back( SEARCH_TERM( GetName(), 8 ) ); + m_searchTerms.emplace_back( SEARCH_TERM( GetLIB_ID().Format(), 16 ) ); wxStringTokenizer keywordTokenizer( GetKeywords(), wxS( " \t\r\n" ), wxTOKEN_STRTOK ); while( keywordTokenizer.HasMoreTokens() ) - terms.emplace_back( SEARCH_TERM( keywordTokenizer.GetNextToken(), 4 ) ); + m_searchTerms.emplace_back( SEARCH_TERM( keywordTokenizer.GetNextToken(), 4 ) ); - terms.emplace_back( SEARCH_TERM( GetKeywords(), 1 ) ); - terms.emplace_back( SEARCH_TERM( GetLibDescription(), 1 ) ); + m_searchTerms.emplace_back( SEARCH_TERM( GetKeywords(), 1 ) ); + m_searchTerms.emplace_back( SEARCH_TERM( GetLibDescription(), 1 ) ); - return terms; + return m_searchTerms; } diff --git a/pcbnew/footprint.h b/pcbnew/footprint.h index 15cb9ac5c5..652aa66ef6 100644 --- a/pcbnew/footprint.h +++ b/pcbnew/footprint.h @@ -363,7 +363,7 @@ public: wxString GetLibNickname() const override { return m_fpid.GetLibNickname(); } wxString GetDesc() override { return GetLibDescription(); } int GetPinCount() override { return static_cast( GetUniquePadCount( DO_NOT_INCLUDE_NPTH ) ); } - std::vector GetSearchTerms() override; + std::vector& GetSearchTerms() override; wxString GetLibDescription() const { return m_libDescription; } void SetLibDescription( const wxString& aDesc ) { m_libDescription = aDesc; } @@ -1388,6 +1388,8 @@ private: // Optional unit mapping information for multi-unit symbols std::vector m_unitInfo; + + std::vector m_searchTerms; }; #endif // FOOTPRINT_H diff --git a/pcbnew/footprint_viewer_frame.cpp b/pcbnew/footprint_viewer_frame.cpp index 2f47e8a1e1..3946bd8943 100644 --- a/pcbnew/footprint_viewer_frame.cpp +++ b/pcbnew/footprint_viewer_frame.cpp @@ -511,8 +511,7 @@ void FOOTPRINT_VIEWER_FRAME::ReCreateFootprintList() for( FOOTPRINT* footprint : footprints ) { - std::vector searchTerms = footprint->GetSearchTerms(); - int matched = matcher.ScoreTerms( searchTerms ); + int matched = matcher.ScoreTerms( footprint->GetSearchTerms() ); if( filterTerm.IsNumber() && wxAtoi( filterTerm ) == (int)footprint->GetPadCount( DO_NOT_INCLUDE_NPTH ) ) matched++;