KiCad PCB EDA Suite
footprint_filter.cpp
Go to the documentation of this file.
1 /*
2  * This program source code file is part of KiCad, a free EDA CAD application.
3  *
4  * Copyright (C) 2016 Jean-Pierre Charras, jp.charras at wanadoo.fr
5  * Copyright (C) 1992-2019 KiCad Developers, see AUTHORS.txt for contributors.
6  *
7  * This program is free software: you can redistribute it and/or modify it
8  * under the terms of the GNU General Public License as published by the
9  * Free Software Foundation, either version 3 of the License, or (at your
10  * option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful, but
13  * WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  * General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License along
18  * with this program. If not, see <http://www.gnu.org/licenses/>.
19  */
20 
21 #include <footprint_filter.h>
22 #include <stdexcept>
23 #include <wx/tokenzr.h>
24 
26 
27 
28 FOOTPRINT_FILTER::ITERATOR::ITERATOR() : m_pos( 0 ), m_filter( nullptr )
29 {
30 }
31 
32 
34  : m_pos( aOther.m_pos ), m_filter( aOther.m_filter )
35 {
36 }
37 
38 
40  : m_pos( (size_t) -1 ), m_filter( &aFilter )
41 {
42  increment();
43 }
44 
45 
47 {
48  if( !m_filter || !m_filter->m_list || m_filter->m_list->GetCount() == 0 )
49  {
50  m_pos = 0;
51  return;
52  }
53 
54  int filter_type = m_filter->m_filter_type;
55  FOOTPRINT_LIST* list = m_filter->m_list;
56  wxString& lib_name = m_filter->m_lib_name;
57 
58  for( ++m_pos; m_pos < list->GetCount(); ++m_pos )
59  {
60  FOOTPRINT_INFO& candidate = list->GetItem( m_pos );
61 
62  if( filter_type == FOOTPRINT_FILTER::UNFILTERED_FP_LIST )
63  break;
64 
65  if( filter_type & FOOTPRINT_FILTER::FILTERING_BY_LIBRARY )
66  {
67  if( !lib_name.IsEmpty() && !candidate.InLibrary( lib_name ) )
68  continue;
69  }
70 
72  {
73  if( !FootprintFilterMatch( candidate ) )
74  continue;
75  }
76 
78  {
79  if( !PinCountMatch( candidate ) )
80  continue;
81  }
82 
83  if( ( filter_type & FOOTPRINT_FILTER::FILTERING_BY_TEXT_PATTERN ) )
84  {
85  wxString searchStr = wxString::Format( wxT( "%s:%s %s" ),
86  candidate.GetLibNickname(),
87  candidate.GetFootprintName(),
88  candidate.GetSearchText() );
89  int matches, position;
90  bool exclude = false;
91 
92  for( auto& matcher : m_filter->m_pattern_filters )
93  {
94  if( !matcher->Find( searchStr.Lower(), matches, position ) )
95  {
96  exclude = true;
97  break;
98  }
99  }
100 
101  if( exclude )
102  continue;
103  }
104 
105  // Candidate passed all filters; exit loop
106  break;
107  }
108 }
109 
110 
112 {
113  // Invalid iterators are always equal
114  return ( m_pos == aOther.m_pos ) && ( m_filter == aOther.m_filter || m_pos == (size_t) -1 );
115 }
116 
117 
119 {
120  if( m_filter && m_filter->m_list && m_pos < m_filter->m_list->GetCount() )
121  return m_filter->m_list->GetItem( m_pos );
122  else
123  throw std::out_of_range( "Attempt to dereference past FOOTPRINT_FILTER::end()" );
124 }
125 
126 
128 {
129  if( m_filter->m_footprint_filters.empty() )
130  return true;
131 
132  // The matching is case insensitive
133  wxString name;
134 
135  for( auto const& each_filter : m_filter->m_footprint_filters )
136  {
137  name.Empty();
138 
139  // If the filter contains a ':' character, include the library name in the pattern
140  if( each_filter->GetPattern().Contains( ":" ) )
141  {
142  name = aItem.GetLibNickname().Lower() + ":";
143  }
144 
145  name += aItem.GetFootprintName().Lower();
146 
147  if( each_filter->Find( name ) != EDA_PATTERN_NOT_FOUND )
148  {
149  return true;
150  }
151  }
152 
153  return false;
154 }
155 
156 
158 {
159  return m_filter->m_pin_count >= 0 &&
160  (unsigned) m_filter->m_pin_count == aItem.GetUniquePadCount();
161 }
162 
163 
165 {
166  SetList( aList );
167 }
168 
169 
171  : m_list( nullptr ), m_pin_count( -1 ), m_filter_type( UNFILTERED_FP_LIST )
172 {
173 }
174 
175 
177 {
178  m_list = &aList;
179 }
180 
181 
183 {
185 }
186 
187 
188 void FOOTPRINT_FILTER::FilterByLibrary( const wxString& aLibName )
189 {
190  m_lib_name = aLibName;
192 }
193 
194 
196 {
197  m_pin_count = aPinCount;
199 }
200 
201 
202 void FOOTPRINT_FILTER::FilterByFootprintFilters( const wxArrayString& aFilters )
203 {
204  m_footprint_filters.clear();
205 
206  for( const wxString& each_pattern : aFilters )
207  {
208  m_footprint_filters.push_back( std::make_unique<EDA_PATTERN_MATCH_WILDCARD_EXPLICIT>() );
209  m_footprint_filters.back()->SetPattern( each_pattern.Lower() );
210  }
211 
213 }
214 
215 
216 void FOOTPRINT_FILTER::FilterByTextPattern( wxString const& aPattern )
217 {
218  m_filter_pattern = aPattern;
219 
220  wxStringTokenizer tokenizer( aPattern.Lower() );
221 
222  while( tokenizer.HasMoreTokens() )
223  {
224  const wxString term = tokenizer.GetNextToken().Lower();
225  m_pattern_filters.push_back( std::make_unique<EDA_COMBINED_MATCHER>( term ) );
226  }
227 
229 }
230 
231 
233 {
234  return FOOTPRINT_FILTER_IT( *this );
235 }
236 
237 
239 {
240  FOOTPRINT_FILTER_IT end_it( *this );
241  end_it.m_pos = m_list ? m_list->GetCount() : 0;
242  return end_it;
243 }
void SetList(FOOTPRINT_LIST &aList)
Set the list to filter.
wxString GetLibNickname() const override
bool InLibrary(const wxString &aLibrary) const
Test if the FOOTPRINT_INFO object was loaded from aLibrary.
void FilterByFootprintFilters(wxArrayString const &aFilters)
Set a list of footprint filters to filter by.
void ClearFilters()
Clear all filter criteria.
wxString GetSearchText() override
bool PinCountMatch(FOOTPRINT_INFO &aItem)
Check if the stored component matches an item by pin count.
void FilterByLibrary(wxString const &aLibName)
Add library name to filter criteria.
FOOTPRINT_FILTER::ITERATOR FOOTPRINT_FILTER_IT
FOOTPRINT_INFO & dereference() const
ITERATOR end()
Get an iterator to the end of the filtered view.
void FilterByPinCount(int aPinCount)
Set a pin count to filter by.
ITERATOR begin()
Get an iterator to the beginning of the filtered view.
std::vector< std::unique_ptr< EDA_PATTERN_MATCH > > m_footprint_filters
unsigned GetCount() const
FOOTPRINT_INFO & GetItem(unsigned aIdx)
Get info for a module by index.
bool FootprintFilterMatch(FOOTPRINT_INFO &aItem)
Check if the stored component matches an item by footprint filter.
Footprint display filter.
static const int EDA_PATTERN_NOT_FOUND
bool equal(ITERATOR const &aOther) const
Holds a list of FOOTPRINT_INFO objects, along with a list of IO_ERRORs or PARSE_ERRORs that were thro...
const char * name
Definition: DXF_plotter.cpp:60
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, CPTREE &aTree)
Function Format outputs a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
Definition: ptree.cpp:205
void FilterByTextPattern(wxString const &aPattern)
Add a pattern to filter by name, including wildcards and optionally a colon-delimited library name.
FOOTPRINT_LIST * m_list
unsigned GetUniquePadCount()
FOOTPRINT_FILTER * m_filter
std::vector< std::unique_ptr< EDA_COMBINED_MATCHER > > m_pattern_filters
FOOTPRINT_FILTER()
Construct a filter without assigning a footprint list.
Inner iterator class returned by begin() and end().
const wxString & GetFootprintName() const