mirror of
https://gitlab.com/kicad/code/kicad.git
synced 2025-09-14 02:03:12 +02:00
Simplify libTree scoring algorithm.
Fixes https://gitlab.com/kicad/code/kicad/-/issues/20610
This commit is contained in:
parent
a661deb0ad
commit
598d446a38
@ -72,7 +72,9 @@ std::vector<SEARCH_TERM> DESIGN_BLOCK_INFO::GetSearchTerms()
|
||||
{
|
||||
std::vector<SEARCH_TERM> terms;
|
||||
|
||||
terms.emplace_back( SEARCH_TERM( GetLibNickname(), 4 ) );
|
||||
terms.emplace_back( SEARCH_TERM( GetName(), 8 ) );
|
||||
terms.emplace_back( SEARCH_TERM( GetLIB_ID().Format(), 16 ) );
|
||||
|
||||
wxStringTokenizer keywordTokenizer( GetKeywords(), wxS( " " ), wxTOKEN_STRTOK );
|
||||
|
||||
|
@ -74,7 +74,9 @@ std::vector<SEARCH_TERM> FOOTPRINT_INFO::GetSearchTerms()
|
||||
{
|
||||
std::vector<SEARCH_TERM> terms;
|
||||
|
||||
terms.emplace_back( SEARCH_TERM( GetLibNickname(), 4 ) );
|
||||
terms.emplace_back( SEARCH_TERM( GetName(), 8 ) );
|
||||
terms.emplace_back( SEARCH_TERM( GetLIB_ID().Format(), 16 ) );
|
||||
|
||||
wxStringTokenizer keywordTokenizer( GetKeywords(), wxS( " " ), wxTOKEN_STRTOK );
|
||||
|
||||
|
@ -171,11 +171,11 @@ LIB_TREE_NODE_UNIT::LIB_TREE_NODE_UNIT( LIB_TREE_NODE* aParent, LIB_TREE_ITEM* a
|
||||
}
|
||||
|
||||
|
||||
void LIB_TREE_NODE_UNIT::UpdateScore( EDA_COMBINED_MATCHER* aMatcher, const wxString& aLib,
|
||||
void LIB_TREE_NODE_UNIT::UpdateScore( const std::vector<std::unique_ptr<EDA_COMBINED_MATCHER>>& aMatchers,
|
||||
std::function<bool( LIB_TREE_NODE& aNode )>* aFilter )
|
||||
{
|
||||
// aMatcher test results are inherited from parent
|
||||
if( aMatcher )
|
||||
// aMatchers test results are inherited from parent
|
||||
if( !aMatchers.empty() )
|
||||
m_Score = m_Parent->m_Score;
|
||||
|
||||
// aFilter test is subtractive
|
||||
@ -183,7 +183,7 @@ void LIB_TREE_NODE_UNIT::UpdateScore( EDA_COMBINED_MATCHER* aMatcher, const wxSt
|
||||
m_Score = 0;
|
||||
|
||||
// show all nodes if no search/filter/etc. criteria are given
|
||||
if( !aMatcher && aLib.IsEmpty() && ( !aFilter || (*aFilter)(*this) ) )
|
||||
if( aMatchers.empty() && ( !aFilter || (*aFilter)(*this) ) )
|
||||
m_Score = 1;
|
||||
}
|
||||
|
||||
@ -243,35 +243,24 @@ void LIB_TREE_NODE_ITEM::Update( LIB_TREE_ITEM* aItem )
|
||||
}
|
||||
|
||||
|
||||
void LIB_TREE_NODE_ITEM::UpdateScore( EDA_COMBINED_MATCHER* aMatcher, const wxString& aLib,
|
||||
void LIB_TREE_NODE_ITEM::UpdateScore( const std::vector<std::unique_ptr<EDA_COMBINED_MATCHER>>& aMatchers,
|
||||
std::function<bool( LIB_TREE_NODE& aNode )>* aFilter )
|
||||
{
|
||||
// aMatcher test is additive, but if we don't match the given term at all, it nulls out
|
||||
if( aMatcher )
|
||||
{
|
||||
int currentScore = aMatcher->ScoreTerms( m_SearchTerms );
|
||||
m_Score = 0;
|
||||
|
||||
// This is a hack: the second phase of search in the adapter will look for a tokenized
|
||||
// LIB_ID and send the lib part down here. While we generally want to prune ourselves
|
||||
// out here (by setting score to -1) the first time we fail to match a search term,
|
||||
// we want to give the same search term a second chance if it has been split from a library
|
||||
// name.
|
||||
if( ( m_Score >= 0 || !aLib.IsEmpty() ) && currentScore > 0 )
|
||||
m_Score += currentScore;
|
||||
else
|
||||
m_Score = -1; // Item has failed to match this term, rule it out
|
||||
}
|
||||
for( const std::unique_ptr<EDA_COMBINED_MATCHER>& matcher : aMatchers )
|
||||
m_Score += matcher->ScoreTerms( m_SearchTerms );
|
||||
|
||||
// aFilter test is subtractive
|
||||
if( aFilter && !(*aFilter)(*this) )
|
||||
m_Score = 0;
|
||||
|
||||
// show all nodes if no search/filter/etc. criteria are given
|
||||
if( !aMatcher && aLib.IsEmpty() && ( !aFilter || (*aFilter)(*this) ) )
|
||||
if( aMatchers.empty() && ( !aFilter || (*aFilter)(*this) ) )
|
||||
m_Score = 1;
|
||||
|
||||
for( std::unique_ptr<LIB_TREE_NODE>& child: m_Children )
|
||||
child->UpdateScore( aMatcher, aLib, aFilter );
|
||||
child->UpdateScore( aMatchers, aFilter );
|
||||
}
|
||||
|
||||
|
||||
@ -296,52 +285,29 @@ LIB_TREE_NODE_ITEM& LIB_TREE_NODE_LIBRARY::AddItem( LIB_TREE_ITEM* aItem )
|
||||
}
|
||||
|
||||
|
||||
void LIB_TREE_NODE_LIBRARY::UpdateScore( EDA_COMBINED_MATCHER* aMatcher, const wxString& aLib,
|
||||
void LIB_TREE_NODE_LIBRARY::UpdateScore( const std::vector<std::unique_ptr<EDA_COMBINED_MATCHER>>& aMatchers,
|
||||
std::function<bool( LIB_TREE_NODE& aNode )>* aFilter )
|
||||
{
|
||||
int maxChildScore = 0;
|
||||
|
||||
// children are additive
|
||||
if( !m_Children.empty() )
|
||||
if( m_Children.empty() )
|
||||
{
|
||||
for( const std::unique_ptr<EDA_COMBINED_MATCHER>& matcher : aMatchers )
|
||||
m_Score += matcher->ScoreTerms( m_SearchTerms );
|
||||
}
|
||||
else
|
||||
{
|
||||
int maxChildScore = 0;
|
||||
|
||||
for( std::unique_ptr<LIB_TREE_NODE>& child: m_Children )
|
||||
{
|
||||
child->UpdateScore( aMatcher, aLib, aFilter );
|
||||
child->UpdateScore( aMatchers, aFilter );
|
||||
maxChildScore = std::max( maxChildScore, child->m_Score );
|
||||
}
|
||||
|
||||
m_Score = std::max( m_Score, maxChildScore );
|
||||
}
|
||||
|
||||
// aLib test is additive
|
||||
if( !aLib.IsEmpty() && m_Name.Lower().Matches( aLib ) )
|
||||
m_Score += 1;
|
||||
|
||||
// aMatcher test is additive
|
||||
if( aMatcher )
|
||||
{
|
||||
int ownScore = aMatcher->ScoreTerms( m_SearchTerms );
|
||||
m_Score += ownScore;
|
||||
|
||||
// If we have a hit on a library, show all children in that library that pass the filter
|
||||
if( maxChildScore <= 0 && ownScore > 0 )
|
||||
{
|
||||
for( std::unique_ptr<LIB_TREE_NODE>& child: m_Children )
|
||||
{
|
||||
if( !aFilter || (*aFilter)( *this ) )
|
||||
child->ForceScore( 1 );
|
||||
|
||||
maxChildScore = std::max( maxChildScore, child->m_Score );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If all children are excluded for one reason or another, drop the library from the list
|
||||
if( !m_Children.empty() && maxChildScore <= 0 )
|
||||
m_Score = 0;
|
||||
|
||||
// show all nodes if no search/filter/etc. criteria are given
|
||||
if( m_Children.empty() && !aMatcher && aLib.IsEmpty() && ( !aFilter || (*aFilter)(*this) ) )
|
||||
if( m_Children.empty() && aMatchers.empty() && ( !aFilter || (*aFilter)(*this) ) )
|
||||
m_Score = 1;
|
||||
}
|
||||
|
||||
@ -383,10 +349,10 @@ void LIB_TREE_NODE_ROOT::Clear()
|
||||
}
|
||||
|
||||
|
||||
void LIB_TREE_NODE_ROOT::UpdateScore( EDA_COMBINED_MATCHER* aMatcher, const wxString& aLib,
|
||||
void LIB_TREE_NODE_ROOT::UpdateScore( const std::vector<std::unique_ptr<EDA_COMBINED_MATCHER>>& aMatchers,
|
||||
std::function<bool( LIB_TREE_NODE& aNode )>* aFilter )
|
||||
{
|
||||
for( std::unique_ptr<LIB_TREE_NODE>& child: m_Children )
|
||||
child->UpdateScore( aMatcher, aLib, aFilter );
|
||||
child->UpdateScore( aMatchers, aFilter );
|
||||
}
|
||||
|
||||
|
@ -292,34 +292,16 @@ void LIB_TREE_MODEL_ADAPTER::UpdateSearchString( const wxString& aSearch, bool a
|
||||
// the search box.
|
||||
constexpr int MAX_TERMS = 100;
|
||||
|
||||
wxStringTokenizer tokenizer( aSearch );
|
||||
int termCount = 0;
|
||||
wxStringTokenizer tokenizer( aSearch );
|
||||
std::vector<std::unique_ptr<EDA_COMBINED_MATCHER>> termMatchers;
|
||||
|
||||
while( tokenizer.HasMoreTokens() && termCount < MAX_TERMS )
|
||||
while( tokenizer.HasMoreTokens() && termMatchers.size() < MAX_TERMS )
|
||||
{
|
||||
// First search for the full token, in case it appears in a search string
|
||||
wxString term = tokenizer.GetNextToken().Lower();
|
||||
EDA_COMBINED_MATCHER termMatcher( term, CTX_LIBITEM );
|
||||
|
||||
m_tree.UpdateScore( &termMatcher, wxEmptyString, m_filter );
|
||||
termCount++;
|
||||
|
||||
if( term.Contains( ":" ) )
|
||||
{
|
||||
// Next search for the library:item_name
|
||||
wxString lib = term.BeforeFirst( ':' );
|
||||
wxString itemName = term.AfterFirst( ':' );
|
||||
EDA_COMBINED_MATCHER itemNameMatcher( itemName, CTX_LIBITEM );
|
||||
|
||||
m_tree.UpdateScore( &itemNameMatcher, lib, m_filter );
|
||||
}
|
||||
wxString term = tokenizer.GetNextToken().Lower();
|
||||
termMatchers.emplace_back( std::make_unique<EDA_COMBINED_MATCHER>( term, CTX_LIBITEM ) );
|
||||
}
|
||||
|
||||
if( termCount == 0 )
|
||||
{
|
||||
// No terms processed; just run the filter
|
||||
m_tree.UpdateScore( nullptr, wxEmptyString, m_filter );
|
||||
}
|
||||
m_tree.UpdateScore( termMatchers, m_filter );
|
||||
|
||||
m_tree.SortNodes( m_sort_mode == BEST_MATCH );
|
||||
AfterReset();
|
||||
|
@ -41,7 +41,9 @@ std::vector<SEARCH_TERM> LIB_SYMBOL::GetSearchTerms()
|
||||
{
|
||||
std::vector<SEARCH_TERM> terms;
|
||||
|
||||
terms.emplace_back( SEARCH_TERM( GetLibNickname(), 4 ) );
|
||||
terms.emplace_back( SEARCH_TERM( GetName(), 8 ) );
|
||||
terms.emplace_back( SEARCH_TERM( GetLIB_ID().Format(), 16 ) );
|
||||
|
||||
wxStringTokenizer keywordTokenizer( GetKeyWords(), wxS( " " ), wxTOKEN_STRTOK );
|
||||
|
||||
|
@ -81,7 +81,7 @@ public:
|
||||
*
|
||||
* @param aMatcher an EDA_COMBINED_MATCHER initialized with the search term
|
||||
*/
|
||||
virtual void UpdateScore( EDA_COMBINED_MATCHER* aMatcher, const wxString& aLib,
|
||||
virtual void UpdateScore( const std::vector<std::unique_ptr<EDA_COMBINED_MATCHER>>& aMatchers,
|
||||
std::function<bool( LIB_TREE_NODE& aNode )>* aFilter ) = 0;
|
||||
|
||||
/**
|
||||
@ -178,7 +178,7 @@ public:
|
||||
*/
|
||||
LIB_TREE_NODE_UNIT( LIB_TREE_NODE* aParent, LIB_TREE_ITEM* aItem, int aUnit );
|
||||
|
||||
void UpdateScore( EDA_COMBINED_MATCHER* aMatcher, const wxString& aLib,
|
||||
void UpdateScore( const std::vector<std::unique_ptr<EDA_COMBINED_MATCHER>>& aMatchers,
|
||||
std::function<bool( LIB_TREE_NODE& aNode )>* aFilter ) override;
|
||||
};
|
||||
|
||||
@ -218,7 +218,7 @@ public:
|
||||
/**
|
||||
* Perform the actual search.
|
||||
*/
|
||||
void UpdateScore( EDA_COMBINED_MATCHER* aMatcher, const wxString& aLib,
|
||||
void UpdateScore( const std::vector<std::unique_ptr<EDA_COMBINED_MATCHER>>& aMatchers,
|
||||
std::function<bool( LIB_TREE_NODE& aNode )>* aFilter ) override;
|
||||
|
||||
protected:
|
||||
@ -260,7 +260,7 @@ public:
|
||||
*/
|
||||
LIB_TREE_NODE_ITEM& AddItem( LIB_TREE_ITEM* aItem );
|
||||
|
||||
void UpdateScore( EDA_COMBINED_MATCHER* aMatcher, const wxString& aLib,
|
||||
void UpdateScore( const std::vector<std::unique_ptr<EDA_COMBINED_MATCHER>>& aMatchers,
|
||||
std::function<bool( LIB_TREE_NODE& aNode )>* aFilter ) override;
|
||||
};
|
||||
|
||||
@ -298,7 +298,7 @@ public:
|
||||
*/
|
||||
void Clear();
|
||||
|
||||
void UpdateScore( EDA_COMBINED_MATCHER* aMatcher, const wxString& aLib,
|
||||
void UpdateScore( const std::vector<std::unique_ptr<EDA_COMBINED_MATCHER>>& aMatchers,
|
||||
std::function<bool( LIB_TREE_NODE& aNode )>* aFilter ) override;
|
||||
};
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user