Upgrade Cvpcb filtering to use a multi-term combined matcher.

Fixes: lp:1827135
* https://bugs.launchpad.net/kicad/+bug/1827135
This commit is contained in:
Jeff Young 2019-08-21 14:06:41 +01:00
parent 06cb21cc47
commit bfb8806682
3 changed files with 70 additions and 57 deletions

View File

@ -20,6 +20,7 @@
#include <footprint_filter.h> #include <footprint_filter.h>
#include <stdexcept> #include <stdexcept>
#include <wx/tokenzr.h>
using FOOTPRINT_FILTER_IT = FOOTPRINT_FILTER::ITERATOR; using FOOTPRINT_FILTER_IT = FOOTPRINT_FILTER::ITERATOR;
@ -44,62 +45,66 @@ FOOTPRINT_FILTER::ITERATOR::ITERATOR( FOOTPRINT_FILTER& aFilter )
void FOOTPRINT_FILTER_IT::increment() void FOOTPRINT_FILTER_IT::increment()
{ {
bool found = false;
if( !m_filter || !m_filter->m_list || m_filter->m_list->GetCount() == 0 ) if( !m_filter || !m_filter->m_list || m_filter->m_list->GetCount() == 0 )
{ {
m_pos = 0; m_pos = 0;
return; return;
} }
auto filter_type = m_filter->m_filter_type; int filter_type = m_filter->m_filter_type;
auto list = m_filter->m_list; FOOTPRINT_LIST* list = m_filter->m_list;
auto& lib_name = m_filter->m_lib_name; wxString& lib_name = m_filter->m_lib_name;
auto& filter_pattern = m_filter->m_filter_pattern;
auto& filter = m_filter->m_filter;
for( ++m_pos; m_pos < list->GetCount() && !found; ++m_pos ) for( ++m_pos; m_pos < list->GetCount(); ++m_pos )
{ {
found = true; FOOTPRINT_INFO& candidate = list->GetItem( m_pos );
if( ( filter_type & FOOTPRINT_FILTER::FILTERING_BY_LIBRARY ) && !lib_name.IsEmpty()
&& !list->GetItem( m_pos ).InLibrary( lib_name ) )
found = false;
if( ( filter_type & FOOTPRINT_FILTER::FILTERING_BY_COMPONENT_KEYWORD )
&& !FootprintFilterMatch( list->GetItem( m_pos ) ) )
found = false;
if( ( filter_type & FOOTPRINT_FILTER::FILTERING_BY_PIN_COUNT )
&& !PinCountMatch( list->GetItem( m_pos ) ) )
found = false;
if( ( filter_type & FOOTPRINT_FILTER::FILTERING_BY_NAME ) && !filter_pattern.IsEmpty() )
{
wxString currname;
// If the search string contains a ':' character,
// include the library name in the search string
// e.g. LibName:FootprintName
if( filter_pattern.Contains( ":" ) )
currname = list->GetItem( m_pos ).GetLibNickname().Lower() + ":";
currname += list->GetItem( m_pos ).GetFootprintName().Lower();
if( filter.Find( currname ) == EDA_PATTERN_NOT_FOUND )
found = false;
}
if( filter_type == FOOTPRINT_FILTER::UNFILTERED_FP_LIST ) if( filter_type == FOOTPRINT_FILTER::UNFILTERED_FP_LIST )
{ break;
// override
found = true;
}
}
// for loop will stop one past the correct item if( filter_type & FOOTPRINT_FILTER::FILTERING_BY_LIBRARY )
if( found ) {
--m_pos; if( !lib_name.IsEmpty() && !candidate.InLibrary( lib_name ) )
continue;
}
if( filter_type & FOOTPRINT_FILTER::FILTERING_BY_COMPONENT_KEYWORD )
{
if( !FootprintFilterMatch( candidate ) )
continue;
}
if( filter_type & FOOTPRINT_FILTER::FILTERING_BY_PIN_COUNT )
{
if( !PinCountMatch( candidate ) )
continue;
}
if( ( filter_type & FOOTPRINT_FILTER::FILTERING_BY_NAME ) )
{
wxString searchStr = wxString::Format( wxT( "%s:%s %s" ),
candidate.GetLibNickname(),
candidate.GetFootprintName(),
candidate.GetSearchText() );
int matches, position;
bool exclude = false;
for( auto& matcher : m_filter->m_pattern_filters )
{
if( !matcher->Find( searchStr.Lower(), matches, position ) )
{
exclude = true;
break;
}
}
if( exclude )
continue;
}
// Candidate passed all filters; exit loop
break;
}
} }
@ -180,7 +185,7 @@ void FOOTPRINT_FILTER::ClearFilters()
} }
void FOOTPRINT_FILTER::FilterByLibrary( wxString const& aLibName ) void FOOTPRINT_FILTER::FilterByLibrary( const wxString& aLibName )
{ {
m_lib_name = aLibName; m_lib_name = aLibName;
m_filter_type |= FILTERING_BY_LIBRARY; m_filter_type |= FILTERING_BY_LIBRARY;
@ -194,11 +199,11 @@ void FOOTPRINT_FILTER::FilterByPinCount( int aPinCount )
} }
void FOOTPRINT_FILTER::FilterByFootprintFilters( wxArrayString const& aFilters ) void FOOTPRINT_FILTER::FilterByFootprintFilters( const wxArrayString& aFilters )
{ {
m_footprint_filters.clear(); m_footprint_filters.clear();
for( auto const& each_pattern : aFilters ) for( const wxString& each_pattern : aFilters )
{ {
m_footprint_filters.push_back( std::make_unique<EDA_PATTERN_MATCH_WILDCARD_EXPLICIT>() ); m_footprint_filters.push_back( std::make_unique<EDA_PATTERN_MATCH_WILDCARD_EXPLICIT>() );
m_footprint_filters.back()->SetPattern( each_pattern.Lower() ); m_footprint_filters.back()->SetPattern( each_pattern.Lower() );
@ -211,7 +216,15 @@ void FOOTPRINT_FILTER::FilterByFootprintFilters( wxArrayString const& aFilters )
void FOOTPRINT_FILTER::FilterByPattern( wxString const& aPattern ) void FOOTPRINT_FILTER::FilterByPattern( wxString const& aPattern )
{ {
m_filter_pattern = aPattern; m_filter_pattern = aPattern;
m_filter.SetPattern( aPattern.Lower() );
wxStringTokenizer tokenizer( aPattern.Lower() );
while( tokenizer.HasMoreTokens() )
{
const wxString term = tokenizer.GetNextToken().Lower();
m_pattern_filters.push_back( std::make_unique<EDA_COMBINED_MATCHER>( term ) );
}
m_filter_type |= FILTERING_BY_NAME; m_filter_type |= FILTERING_BY_NAME;
} }

View File

@ -1,7 +1,7 @@
/* /*
* This program source code file is part of KiCad, a free EDA CAD application. * This program source code file is part of KiCad, a free EDA CAD application.
* *
* Copyright (C) 2017 KiCad Developers, see AUTHORS.txt for contributors. * Copyright (C) 2017-2019 KiCad Developers, see AUTHORS.txt for contributors.
* *
* This program is free software: you can redistribute it and/or modify it * This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the * under the terms of the GNU General Public License as published by the
@ -136,13 +136,13 @@ private:
FOOTPRINT_LIST* m_list; FOOTPRINT_LIST* m_list;
wxString m_lib_name; wxString m_lib_name;
wxString m_filter_pattern; wxString m_filter_pattern;
int m_pin_count; int m_pin_count;
int m_filter_type; int m_filter_type;
EDA_PATTERN_MATCH_WILDCARD m_filter;
std::vector<std::unique_ptr<EDA_PATTERN_MATCH>> m_footprint_filters; std::vector<std::unique_ptr<EDA_COMBINED_MATCHER>> m_pattern_filters;
std::vector<std::unique_ptr<EDA_PATTERN_MATCH>> m_footprint_filters;
}; };
#endif // FOOTPRINT_FILTER_H #endif // FOOTPRINT_FILTER_H

View File

@ -401,7 +401,7 @@ void FOOTPRINT_VIEWER_FRAME::ReCreateFootprintList()
for( const unique_ptr<FOOTPRINT_INFO>& footprint : fp_info_list->GetList() ) for( const unique_ptr<FOOTPRINT_INFO>& footprint : fp_info_list->GetList() )
{ {
wxString search = footprint->GetFootprintName() + footprint->GetSearchText(); wxString search = footprint->GetFootprintName() + " " + footprint->GetSearchText();
bool matched = matcher.Find( search.Lower(), matches, position ); bool matched = matcher.Find( search.Lower(), matches, position );
if( !matched && term.IsNumber() ) if( !matched && term.IsNumber() )