KiCad PCB EDA Suite
Loading...
Searching...
No Matches
footprint_select_widget.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 The KiCad Developers, see AUTHORS.txt for contributors.
5 *
6 * This program is free software: you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation, either version 3 of the License, or (at your
9 * option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <https://www.gnu.org/licenses/>.
18 */
19
20#include <eda_draw_frame.h>
21#include <kiway.h>
22#include <kiface_ids.h>
25#include <json_common.h>
26#include <set>
27#include <wx/wupdlock.h>
28
29
30wxDEFINE_EVENT( EVT_FOOTPRINT_SELECTED, wxCommandEvent );
31
33 int aMaxItems ) :
34 wxPanel( aParent ),
35 m_max_items( aMaxItems ),
36 m_pin_count( 0 ),
37 m_zero_filter( true ),
38 m_kiway( nullptr )
39{
40 m_sizer = new wxBoxSizer( wxVERTICAL );
41 m_fp_sel_ctrl = new FOOTPRINT_CHOICE( this, wxID_ANY );
42 m_sizer->Add( m_fp_sel_ctrl, 1, wxEXPAND, 5 );
43
44 SetSizer( m_sizer );
45 Layout();
46 m_sizer->Fit( this );
47
48 m_fp_sel_ctrl->Bind( wxEVT_COMBOBOX, &FOOTPRINT_SELECT_WIDGET::OnComboBox, this );
49}
50
51
53{
54 m_kiway = &aKiway;
55}
56
57
58void FOOTPRINT_SELECT_WIDGET::OnComboBox( wxCommandEvent& aEvent )
59{
60 wxCommandEvent evt( EVT_FOOTPRINT_SELECTED );
61 int sel = m_fp_sel_ctrl->GetSelection();
62
63 if( sel == wxNOT_FOUND )
64 return;
65
66 wxStringClientData* clientdata =
67 static_cast<wxStringClientData*>( m_fp_sel_ctrl->GetClientObject( sel ) );
68 wxASSERT( clientdata );
69
70 evt.SetString( clientdata->GetData() );
71 wxPostEvent( this, evt );
72}
73
74
76{
77 m_pin_count = 0;
78 m_filters.Clear();
79 m_default_footprint.Clear();
80 m_zero_filter = false;
81 m_always_included.clear();
82}
83
84
86{
87 if( !aFootprintId.IsValid() )
88 return;
89
90 for( const LIB_ID& existing : m_always_included )
91 {
92 if( existing == aFootprintId )
93 return;
94 }
95
96 m_always_included.push_back( aFootprintId );
97}
98
99
101{
102 m_pin_count = aPinCount;
103}
104
105
106void FOOTPRINT_SELECT_WIDGET::FilterByFootprintFilters( wxArrayString const& aFilters,
107 bool aZeroFilters )
108{
109 m_zero_filter = ( aZeroFilters && aFilters.size() == 0 );
110 m_filters = aFilters;
111}
112
113
115{
117}
118
119
121{
122 if( !m_kiway )
123 return false;
124
125 wxWindowUpdateLocker lock( m_fp_sel_ctrl );
126 m_fp_sel_ctrl->Clear();
127
128 // Add the default footprint entry at the top
129 wxString defaultLabel = m_default_footprint.IsEmpty()
130 ? _( "No default footprint" )
131 : wxS( "[" ) + _( "Default" ) + wxS( "] " ) + m_default_footprint;
132
133 m_fp_sel_ctrl->Append( defaultLabel, new wxStringClientData( m_default_footprint ) );
134
135 // Explicitly associated footprints are listed first and always shown, bypassing the
136 // pin-count and glob filters (issue #2282). Track their names so the filtered results below
137 // can be deduplicated against them.
138 std::set<wxString> alwaysIncludedNames;
139
140 for( const LIB_ID& fpId : m_always_included )
141 {
142 wxString fpName = fpId.Format().wx_str();
143
144 if( alwaysIncludedNames.insert( fpName ).second )
145 m_fp_sel_ctrl->Append( fpName, new wxStringClientData( fpName ) );
146 }
147
148 // If zero_filter is set and we have no filters, show only the always-included footprints
149 if( m_zero_filter && m_filters.IsEmpty() && m_pin_count == 0 )
150 {
152 return true;
153 }
154
155 // Build JSON request for pcbnew
156 using json = nlohmann::json;
157 json request;
158 request["pin_count"] = m_pin_count;
159 request["zero_filters"] = m_zero_filter;
160 request["max_results"] = m_max_items;
161
162 json filtersArray = json::array();
163
164 for( const wxString& filter : m_filters )
165 filtersArray.push_back( filter.ToStdString() );
166
167 request["filters"] = filtersArray;
168
169 // Get the filter function from pcbnew via KIWAY
170 try
171 {
172 KIFACE* kiface = m_kiway->KiFACE( KIWAY::FACE_PCB );
173
174 if( !kiface )
175 {
177 return true;
178 }
179
180 void* funcPtr = kiface->IfaceOrAddress( KIFACE_FILTER_FOOTPRINTS );
181
182 if( !funcPtr )
183 {
185 return true;
186 }
187
188 // Call the filter function
189 using FilterFunc = wxString ( * )( const wxString& );
190 FilterFunc filterFootprints = reinterpret_cast<FilterFunc>( funcPtr );
191
192 wxString requestStr = wxString::FromUTF8( request.dump() );
193 wxString responseStr = filterFootprints( requestStr );
194
195 // Parse the response
196 json response = json::parse( responseStr.ToStdString() );
197
198 if( response.is_array() )
199 {
200 for( const auto& item : response )
201 {
202 if( item.is_string() )
203 {
204 wxString fpName = wxString::FromUTF8( item.get<std::string>() );
205
206 if( alwaysIncludedNames.count( fpName ) )
207 continue;
208
209 m_fp_sel_ctrl->Append( fpName, new wxStringClientData( fpName ) );
210 }
211 }
212 }
213 }
214 catch( const std::exception& )
215 {
216 // JSON parsing or other error - just show default
217 }
218
220 return true;
221}
222
223
225{
226 m_fp_sel_ctrl->SetSelection( 0 );
227}
228
229
231{
232 return m_fp_sel_ctrl->Enable( aEnable );
233}
The base class for create windows for drawing purpose.
Customized combo box for footprint selection.
virtual bool Enable(bool aEnable=true) override
Enable or disable the control for input.
std::vector< LIB_ID > m_always_included
void OnComboBox(wxCommandEvent &aEvent)
void AddAlwaysIncludedFootprint(const LIB_ID &aFootprintId)
Add a footprint that is always listed regardless of the pin-count and glob filters (issue #2282).
void FilterByFootprintFilters(const wxArrayString &aFilters, bool aZeroFilters)
Filter by footprint filter list.
void SetDefaultFootprint(const wxString &aFp)
Set the default footprint for a part.
FOOTPRINT_SELECT_WIDGET(EDA_DRAW_FRAME *aFrame, wxWindow *aParent, int aMaxItems=400)
Construct a footprint selector widget.
void FilterByPinCount(int aPinCount)
Filter by pin count.
void SelectDefault()
Set current selection to the default footprint.
bool UpdateList()
Update the contents of the list by fetching filtered footprints from pcbnew.
void ClearFilters()
Clear all filters.
void Load(KIWAY &aKiway, PROJECT &aProject)
Initialize the widget with a KIWAY for cross-module communication.
A minimalistic software bus for communications between various DLLs/DSOs (DSOs) within the same KiCad...
Definition kiway.h:311
@ FACE_PCB
pcbnew DSO
Definition kiway.h:319
A logical library item identifier and consists of various portions much like a URI.
Definition lib_id.h:45
bool IsValid() const
Check if this LID_ID is valid.
Definition lib_id.h:168
Container for project specific data.
Definition project.h:62
#define _(s)
wxDEFINE_EVENT(EVT_FOOTPRINT_SELECTED, wxCommandEvent)
nlohmann::json json
Definition gerbview.cpp:49
@ KIFACE_FILTER_FOOTPRINTS
Function pointer type: wxString (*)(const wxString& aFilterJson) Input JSON: {"pin_count": N,...
Definition kiface_ids.h:35
static wxString filterFootprints(const wxString &aFilterJson)
Filter footprints based on criteria passed as JSON.
Definition pcbnew.cpp:110
Implement a participant in the KIWAY alchemy.
Definition kiway.h:152
IFACE KIFACE_BASE kiface("pcb_test_frame", KIWAY::FACE_PCB)