KiCad PCB EDA Suite
Loading...
Searching...
No Matches
dialog_exchange_footprints.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) 2015 Jean-Pierre Charras, jp.charras at wanadoo.fr
5 * Copyright (C) 2013 SoftPLC Corporation, Dick Hollenbeck <[email protected]>
6 * Copyright (C) 2013 Wayne Stambaugh <[email protected]>
7 * Copyright (C) 1992-2023 KiCad Developers, see AUTHORS.txt for contributors.
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License
11 * as published by the Free Software Foundation; either version 2
12 * of the License, or (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, you may find one here:
21 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
22 * or you may search the http://www.gnu.org website for the version 2 license,
23 * or you may write to the Free Software Foundation, Inc.,
24 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
25 */
26
27#include <bitmaps.h>
28#include <board.h>
29#include <footprint.h>
30#include <pad.h>
32#include <string_utils.h>
33#include <kiway.h>
34#include <kiway_express.h>
35#include <macros.h>
36#include <pcb_edit_frame.h>
37#include <pcbnew_settings.h>
40#include <tool/tool_manager.h>
42
43
44#define ID_MATCH_FP_ALL 4200
45#define ID_MATCH_FP_SELECTED 4201
46#define ID_MATCH_FP_REF 4202
47#define ID_MATCH_FP_VAL 4203
48#define ID_MATCH_FP_ID 4204
49
50
55
56 // { update, change }
57bool g_removeExtraTextItems[2] = { false, false };
58bool g_resetTextItemLayers[2] = { false, true };
59bool g_resetTextItemEffects[2] = { false, true };
60bool g_resetTextItemContent[2] = { false, true };
61bool g_resetFabricationAttrs[2] = { false, true };
62bool g_reset3DModels[2] = { true, true };
63
64
66 FOOTPRINT* aFootprint,
67 bool updateMode, bool selectedMode ) :
69 m_commit( aParent ),
70 m_parent( aParent ),
71 m_currentFootprint( aFootprint ),
72 m_updateMode( updateMode )
73{
74 if( !updateMode )
75 {
76 SetTitle( _( "Change Footprints" ) );
77 m_matchAll->SetLabel( _( "Change all footprints on board" ) );
78 m_matchSelected->SetLabel( _( "Change selected footprint(s)" ) );
79 m_matchSpecifiedRef->SetLabel( _( "Change footprints matching reference designator:" ) );
80 m_matchSpecifiedValue->SetLabel( _( "Change footprints matching value:" ) );
81 m_matchSpecifiedID->SetLabel( _( "Change footprints with library id:" ) );
82 m_resetTextItemLayers->SetLabel( _( "Update text layers and visibilities" ) );
83 m_resetTextItemEffects->SetLabel( _( "Update text sizes, styles and positions" ) );
84 m_resetTextItemContent->SetLabel( _( "Update text content" ) );
85 m_resetFabricationAttrs->SetLabel( _( "Update fabrication attributes" ) );
86 m_reset3DModels->SetLabel( _( "Update 3D models" ) );
87 }
88
89#if 0 // translator hint
90 wxString x = _( "Update/reset strings: there are two cases these descriptions need to cover: "
91 "the user made overrides to a footprint on the PCB and wants to remove them, "
92 "or the user made changes to the library footprint and wants to propagate "
93 "them back to the PCB." );
94#endif
95
96 if( m_updateMode )
97 {
98 m_changeSizer->Show( false );
99 }
100 else
101 {
102 m_upperSizer->FindItem( m_matchAll )->Show( false );
103 m_newIDBrowseButton->SetBitmap( KiBitmapBundle( BITMAPS::small_library ) );
104 }
105
107 m_newID->AppendText( From_UTF8( m_currentFootprint->GetFPID().Format().c_str() ) );
108 else
109 m_upperSizer->FindItem( m_matchSelected )->Show( false );
110
111 // Use ChangeValue() instead of SetValue() so we don't generate events.
114
117
120
121 m_specifiedIDBrowseButton->SetBitmap( KiBitmapBundle( BITMAPS::small_library ) );
122
123 m_upperSizer->SetEmptyCellSize( wxSize( 0, 0 ) );
124 // The upper sizer has its content modified: re-layout it:
125 m_upperSizer->Layout();
126
127 // initialize match-mode
128 if( m_updateMode )
130 else
132
133 wxCommandEvent event;
134 event.SetEventObject( this );
135
136 switch( *m_matchMode )
137 {
138 case ID_MATCH_FP_ALL: OnMatchAllClicked( event ); break;
139 case ID_MATCH_FP_SELECTED: OnMatchSelectedClicked( event ); break;
140 case ID_MATCH_FP_REF: OnMatchRefClicked( event ); break;
141 case ID_MATCH_FP_VAL: OnMatchValueClicked( event ); break;
142 case ID_MATCH_FP_ID: OnMatchIDClicked( event ); break;
143 default: break;
144 }
145
151 m_reset3DModels->SetValue( g_reset3DModels[ m_updateMode ? 0 : 1 ] );
152
154 m_MessageWindow->SetFileName( Prj().GetProjectPath() + wxT( "report.txt" ) );
155
156 // DIALOG_SHIM needs a unique hash_key because classname is not sufficient
157 // because the update and change versions of this dialog have different controls.
158 m_hash_key = TO_UTF8( GetTitle() );
159
160 wxString okLabel = m_updateMode ? _( "Update" ) : _( "Change" );
161
162 SetupStandardButtons( { { wxID_OK, okLabel },
163 { wxID_CANCEL, _( "Close" ) } } );
164
165 // Now all widgets have the size fixed, call FinishDialogSettings
167}
168
169
171{
177 g_reset3DModels[ m_updateMode ? 0 : 1 ] = m_reset3DModels->GetValue();
178}
179
180
182{
183 LIB_ID specifiedID;
184
185 switch( *m_matchMode )
186 {
187 case ID_MATCH_FP_ALL:
188 return true;
190 return aFootprint == m_currentFootprint || aFootprint->IsSelected();
191 case ID_MATCH_FP_REF:
192 return WildCompareString( m_specifiedRef->GetValue(), aFootprint->GetReference(), false );
193 case ID_MATCH_FP_VAL:
194 return WildCompareString( m_specifiedValue->GetValue(), aFootprint->GetValue(), false );
195 case ID_MATCH_FP_ID:
196 specifiedID.Parse( m_specifiedID->GetValue() );
197 return aFootprint->GetFPID() == specifiedID;
198 default:
199 return false; // just to quiet compiler warnings....
200 }
201}
202
203
205{
206 switch( *m_matchMode )
207 {
208 case ID_MATCH_FP_ALL: return m_matchAll;
213 default: return nullptr;
214 }
215}
216
217
219{
220 wxRadioButton* rb_button = getRadioButtonForMode();
221
222 wxRadioButton* rb_butt_list[] =
223 {
229 nullptr // end of list
230 };
231
232 // Ensure the button state is ok. Only one button can be checked
233 // Change button state only if its state is incorrect, otherwise
234 // we have issues depending on the platform.
235 for( int ii = 0; rb_butt_list[ii]; ++ii )
236 {
237 bool state = rb_butt_list[ii] == rb_button;
238
239 if( rb_butt_list[ii]->GetValue() != state )
240 rb_butt_list[ii]->SetValue( state );
241 }
242}
243
244
246{
248
249 if( event.GetEventObject() == this )
251 else
252 m_matchAll->SetFocus();
253}
254
255
257{
259
260 if( event.GetEventObject() == this )
262 else
263 m_matchSelected->SetFocus();
264}
265
266
268{
270
271 if( event.GetEventObject() == this )
273 else if( event.GetEventObject() != m_specifiedRef )
274 m_specifiedRef->SetFocus();
275}
276
277
279{
281
282 if( event.GetEventObject() == this )
284 else if( event.GetEventObject() != m_specifiedValue )
285 m_specifiedValue->SetFocus();
286}
287
288
290{
292
293 if( event.GetEventObject() == this )
295 else if( event.GetEventObject() != m_specifiedID )
296 m_specifiedID->SetFocus();
297}
298
299
300void DIALOG_EXCHANGE_FOOTPRINTS::OnOKClicked( wxCommandEvent& event )
301{
303 wxBusyCursor dummy;
304
306 m_MessageWindow->Flush( false );
307
308 m_newFootprints.clear();
310 m_commit.Push( m_updateMode ? _( "Update Footprint" ) : _( "Change Footprint" ) );
311 selTool->AddItemsToSel( &m_newFootprints );
312
313 m_MessageWindow->Flush( false );
314
315 WINDOW_THAWER thawer( m_parent );
317}
318
319
321{
322 LIB_ID newFPID;
323
324 if( m_parent->GetBoard()->Footprints().empty() )
325 return;
326
327 if( !m_updateMode )
328 {
329 newFPID.Parse( m_newID->GetValue() );
330
331 if( !newFPID.IsValid() )
332 return;
333 }
334
335 /*
336 * NB: the change is done from the last footprint because processFootprint() modifies the
337 * last item in the list.
338 */
339 for( auto it = m_parent->GetBoard()->Footprints().rbegin();
340 it != m_parent->GetBoard()->Footprints().rend(); it++ )
341 {
342 FOOTPRINT* footprint = *it;
343
344 if( !isMatch( footprint ) )
345 continue;
346
347 if( m_updateMode )
348 processFootprint( footprint, footprint->GetFPID() );
349 else
350 processFootprint( footprint, newFPID );
351 }
352}
353
354
356{
357 LIB_ID oldFPID = aFootprint->GetFPID();
358 wxString msg;
359
360 // Load new footprint.
361 if( m_updateMode )
362 {
363 msg.Printf( _( "Updated footprint %s (%s)" ) + wxS( ": " ),
364 aFootprint->GetReference(),
365 oldFPID.Format().c_str() );
366 }
367 else
368 {
369 msg.Printf( _( "Changed footprint %s from '%s' to '%s'" ) + wxS( ": " ),
370 aFootprint->GetReference(),
371 oldFPID.Format().c_str(),
372 aNewFPID.Format().c_str() );
373 }
374
375 FOOTPRINT* newFootprint = m_parent->LoadFootprint( aNewFPID );
376
377 if( !newFootprint )
378 {
379 msg += _( "*** library footprint not found ***" );
381 return;
382 }
383
384 bool updated = !m_updateMode || aFootprint->FootprintNeedsUpdate( newFootprint );
385
386 m_parent->ExchangeFootprint( aFootprint, newFootprint, m_commit,
387 m_removeExtraBox->GetValue(),
388 m_resetTextItemLayers->GetValue(),
389 m_resetTextItemEffects->GetValue(),
390 m_resetTextItemContent->GetValue(),
391 m_resetFabricationAttrs->GetValue(),
392 m_reset3DModels->GetValue(),
393 &updated );
394
395 // Update footprint field with the new FPID
396 newFootprint->Footprint().SetText( aNewFPID.Format() );
397
398 if( aFootprint == m_currentFootprint )
399 m_currentFootprint = newFootprint;
400
401 if( newFootprint )
402 m_newFootprints.push_back( newFootprint );
403
404 if( m_updateMode && !updated )
405 {
406 msg += _( ": (no changes)" );
408 }
409 else
410 {
411 msg += _( ": OK" );
413 }
414}
415
416
418{
419 wxString newname = m_newID->GetValue();
420
421 if( KIWAY_PLAYER* frame = Kiway().Player( FRAME_FOOTPRINT_CHOOSER, true, this ) )
422 {
424 {
425 /*
426 * Symbol netlist format:
427 * pinNumber pinName <tab> pinNumber pinName...
428 * fpFilter fpFilter...
429 */
430 wxString netlist;
431
432 wxArrayString pins;
433
434 for( const wxString& pad : m_currentFootprint->GetUniquePadNumbers() )
435 pins.push_back( pad + ' ' + wxEmptyString /* leave pinName empty */ );
436
437 if( !pins.IsEmpty() )
438 netlist << EscapeString( wxJoin( pins, '\t' ), CTX_LINE );
439
440 netlist << wxS( "\r" );
441
443
444 std::string payload( netlist.ToStdString() );
446 frame->KiwayMailIn( mail );
447 }
448
449 if( frame->ShowModal( &newname, this ) )
450 {
451 if( event.GetEventObject() == m_newIDBrowseButton )
452 m_newID->SetValue( newname );
453 else
454 m_specifiedID->SetValue( newname );
455 }
456
457 frame->Destroy();
458 }
459}
460
461
wxBitmapBundle KiBitmapBundle(BITMAPS aBitmap)
Definition: bitmap.cpp:110
virtual void Push(const wxString &aMessage=wxEmptyString, int aCommitFlags=0) override
Revert the commit by restoring the modified items state.
const FOOTPRINTS & Footprints() const
Definition: board.h:329
Class DIALOG_EXCHANGE_FOOTPRINTS_BASE.
void updateMatchModeRadioButtons(wxUpdateUIEvent &event) override
void OnMatchValueClicked(wxCommandEvent &event) override
void processFootprint(FOOTPRINT *aFootprint, const LIB_ID &aNewFPID)
void ViewAndSelectFootprint(wxCommandEvent &event) override
DIALOG_EXCHANGE_FOOTPRINTS(PCB_EDIT_FRAME *aParent, FOOTPRINT *aFootprint, bool updateMode, bool selectedMode)
void OnMatchIDClicked(wxCommandEvent &event) override
void OnMatchSelectedClicked(wxCommandEvent &event) override
void OnMatchAllClicked(wxCommandEvent &event) override
void OnMatchRefClicked(wxCommandEvent &event) override
void OnOKClicked(wxCommandEvent &event) override
void SetInitialFocus(wxWindow *aWindow)
Sets the window (usually a wxTextCtrl) that should be focused when the dialog is shown.
Definition: dialog_shim.h:102
void SetupStandardButtons(std::map< int, wxString > aLabels={})
std::string m_hash_key
Definition: dialog_shim.h:210
void finishDialogSettings()
In all dialogs, we must call the same functions to fix minimal dlg size, the default position and per...
virtual void Refresh(bool aEraseBackground=true, const wxRect *aRect=nullptr) override
bool IsSelected() const
Definition: eda_item.h:109
virtual void SetText(const wxString &aText)
Definition: eda_text.cpp:181
std::set< wxString > GetUniquePadNumbers(INCLUDE_NPTH_T aIncludeNPTH=INCLUDE_NPTH_T(INCLUDE_NPTH)) const
Return the names of the unique, non-blank pads.
Definition: footprint.cpp:1871
PCB_FIELD & Footprint()
Definition: footprint.h:628
bool FootprintNeedsUpdate(const FOOTPRINT *aLibFP, int aCompareFlags=0, REPORTER *aReporter=nullptr)
Return true if a board footprint differs from the library version.
const LIB_ID & GetFPID() const
Definition: footprint.h:236
wxString GetFilters() const
Definition: footprint.h:260
const wxString & GetValue() const
Definition: footprint.h:612
const wxString & GetReference() const
Definition: footprint.h:590
Carry a payload from one KIWAY_PLAYER to another within a PROJECT.
Definition: kiway_express.h:40
PROJECT & Prj() const
Return a reference to the PROJECT associated with this KIWAY.
KIWAY & Kiway() const
Return a reference to the KIWAY that this object has an opportunity to participate in.
Definition: kiway_holder.h:55
A wxFrame capable of the OpenProjectFiles function, meaning it can load a portion of a KiCad project.
Definition: kiway_player.h:65
A logical library item identifier and consists of various portions much like a URI.
Definition: lib_id.h:49
int Parse(const UTF8 &aId, bool aFix=false)
Parse LIB_ID with the information from aId.
Definition: lib_id.cpp:51
bool IsValid() const
Check if this LID_ID is valid.
Definition: lib_id.h:172
UTF8 Format() const
Definition: lib_id.cpp:118
FOOTPRINT * LoadFootprint(const LIB_ID &aFootprintId)
Attempt to load aFootprintId from the footprint library table.
PCB_DRAW_PANEL_GAL * GetCanvas() const override
Return a pointer to GAL-based canvas of given EDA draw frame.
BOARD * GetBoard() const
The main frame for Pcbnew.
void ExchangeFootprint(FOOTPRINT *aExisting, FOOTPRINT *aNew, BOARD_COMMIT &aCommit, bool deleteExtraTexts=true, bool resetTextLayers=true, bool resetTextEffects=true, bool resetFabricationAttrs=true, bool resetTextContent=true, bool reset3DModels=true, bool *aUpdated=nullptr)
Replace aExisting footprint by aNew footprint using the Existing footprint settings (position,...
The selection tool: currently supports:
int AddItemsToSel(const TOOL_EVENT &aEvent)
void SetBitmap(const wxBitmapBundle &aBmp)
TOOL_MANAGER * GetToolManager() const
Return the MVC controller.
Definition: tools_holder.h:55
const char * c_str() const
Definition: utf8.h:103
void Clear()
return the number of messages matching the given severity mask.
void SetLazyUpdate(bool aLazyUpdate)
Forces updating the HTML page, after the report is built in lazy mode If aSort = true,...
void SetFileName(const wxString &aReportFileName)
void Report(const wxString &aText, SEVERITY aSeverity, REPORTER::LOCATION aLocation=REPORTER::LOC_BODY)
Reports the string.
void Flush(bool aSort=false)
Set the visible severity filter.
#define ID_MATCH_FP_ALL
bool g_resetTextItemLayers[2]
#define ID_MATCH_FP_VAL
bool g_resetFabricationAttrs[2]
bool g_resetTextItemEffects[2]
bool g_resetTextItemContent[2]
#define ID_MATCH_FP_SELECTED
#define ID_MATCH_FP_REF
int g_matchModeForExchange
int g_matchModeForUpdateSelected
int g_matchModeForUpdate
bool g_reset3DModels[2]
bool g_removeExtraTextItems[2]
#define ID_MATCH_FP_ID
int g_matchModeForExchangeSelected
#define _(s)
@ FRAME_FOOTPRINT_CHOOSER
Definition: frame_type.h:44
This file contains miscellaneous commonly used macros and functions.
@ MAIL_SYMBOL_NETLIST
Definition: mail_type.h:45
@ RPT_SEVERITY_ERROR
@ RPT_SEVERITY_INFO
@ RPT_SEVERITY_ACTION
std::vector< FAB_LAYER_COLOR > dummy
bool WildCompareString(const wxString &pattern, const wxString &string_to_tst, bool case_sensitive)
Compare a string against wild card (* and ?) pattern using the usual rules.
wxString From_UTF8(const char *cstring)
wxString EscapeString(const wxString &aSource, ESCAPE_CONTEXT aContext)
The Escape/Unescape routines use HTML-entity-reference-style encoding to handle characters which are:...
#define TO_UTF8(wxstring)
Convert a wxString to a UTF8 encoded C string for all wxWidgets build modes.
Definition: string_utils.h:391
@ CTX_LINE
Definition: string_utils.h:59