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 <footprint.h>
29#include <pad.h>
31#include <string_utils.h>
32#include <kiway.h>
33#include <kiway_express.h>
34#include <macros.h>
35#include <pcb_edit_frame.h>
36#include <pcbnew_settings.h>
39
40
41#define ID_MATCH_FP_ALL 4200
42#define ID_MATCH_FP_SELECTED 4201
43#define ID_MATCH_FP_REF 4202
44#define ID_MATCH_FP_VAL 4203
45#define ID_MATCH_FP_ID 4204
46
47
52
53 // { update, change }
54bool g_removeExtraTextItems[2] = { false, false };
55bool g_resetTextItemLayers[2] = { false, true };
56bool g_resetTextItemEffects[2] = { false, true };
57bool g_resetFabricationAttrs[2] = { false, true };
58bool g_reset3DModels[2] = { true, true };
59
60
62 FOOTPRINT* aFootprint,
63 bool updateMode, bool selectedMode ) :
65 m_commit( aParent ),
66 m_parent( aParent ),
67 m_currentFootprint( aFootprint ),
68 m_updateMode( updateMode )
69{
70 if( !updateMode )
71 {
72 SetTitle( _( "Change Footprints" ) );
73 m_matchAll->SetLabel( _( "Change all footprints on board" ) );
74 m_matchSelected->SetLabel( _( "Change selected footprint(s)" ) );
75 m_matchSpecifiedRef->SetLabel( _( "Change footprints matching reference designator:" ) );
76 m_matchSpecifiedValue->SetLabel( _( "Change footprints matching value:" ) );
77 m_matchSpecifiedID->SetLabel( _( "Change footprints with library id:" ) );
78 m_resetTextItemLayers->SetLabel( _( "Update text layers and visibilities" ) );
79 m_resetTextItemEffects->SetLabel( _( "Update text sizes, styles and positions" ) );
80 m_resetFabricationAttrs->SetLabel( _( "Update fabrication attributes" ) );
81 m_reset3DModels->SetLabel( _( "Update 3D models" ) );
82 }
83
84#if 0 // translator hint
85 wxString x = _( "Update/reset strings: there are two cases these descriptions need to cover: "
86 "the user made overrides to a footprint on the PCB and wants to remove them, "
87 "or the user made changes to the library footprint and wants to propagate "
88 "them back to the PCB." );
89#endif
90
91 if( m_updateMode )
92 {
93 m_changeSizer->Show( false );
94 }
95 else
96 {
97 m_upperSizer->FindItem( m_matchAll )->Show( false );
98 m_newIDBrowseButton->SetBitmap( KiBitmapBundle( BITMAPS::small_library ) );
99 }
100
102 m_newID->AppendText( From_UTF8( m_currentFootprint->GetFPID().Format().c_str() ) );
103 else
104 m_upperSizer->FindItem( m_matchSelected )->Show( false );
105
106 // Use ChangeValue() instead of SetValue() so we don't generate events.
109
112
115
116 m_specifiedIDBrowseButton->SetBitmap( KiBitmapBundle( BITMAPS::small_library ) );
117
118 m_upperSizer->SetEmptyCellSize( wxSize( 0, 0 ) );
119 // The upper sizer has its content modified: re-layout it:
120 m_upperSizer->Layout();
121
122 // initialize match-mode
123 if( m_updateMode )
125 else
127
128 wxCommandEvent event;
129 event.SetEventObject( this );
130
131 switch( *m_matchMode )
132 {
133 case ID_MATCH_FP_ALL: OnMatchAllClicked( event ); break;
134 case ID_MATCH_FP_SELECTED: OnMatchSelectedClicked( event ); break;
135 case ID_MATCH_FP_REF: OnMatchRefClicked( event ); break;
136 case ID_MATCH_FP_VAL: OnMatchValueClicked( event ); break;
137 case ID_MATCH_FP_ID: OnMatchIDClicked( event ); break;
138 default: break;
139 }
140
145 m_reset3DModels->SetValue( g_reset3DModels[ m_updateMode ? 0 : 1 ] );
146
148 m_MessageWindow->SetFileName( Prj().GetProjectPath() + wxT( "report.txt" ) );
149
150 // DIALOG_SHIM needs a unique hash_key because classname is not sufficient
151 // because the update and change versions of this dialog have different controls.
152 m_hash_key = TO_UTF8( GetTitle() );
153
154 wxString okLabel = m_updateMode ? _( "Update" ) : _( "Change" );
155
156 SetupStandardButtons( { { wxID_OK, okLabel },
157 { wxID_CANCEL, _( "Close" ) } } );
158
159 // Now all widgets have the size fixed, call FinishDialogSettings
161}
162
163
165{
170 g_reset3DModels[ m_updateMode ? 0 : 1 ] = m_reset3DModels->GetValue();
171}
172
173
175{
176 LIB_ID specifiedID;
177
178 switch( *m_matchMode )
179 {
180 case ID_MATCH_FP_ALL:
181 return true;
183 return aFootprint == m_currentFootprint || aFootprint->IsSelected();
184 case ID_MATCH_FP_REF:
185 return WildCompareString( m_specifiedRef->GetValue(), aFootprint->GetReference(), false );
186 case ID_MATCH_FP_VAL:
187 return WildCompareString( m_specifiedValue->GetValue(), aFootprint->GetValue(), false );
188 case ID_MATCH_FP_ID:
189 specifiedID.Parse( m_specifiedID->GetValue() );
190 return aFootprint->GetFPID() == specifiedID;
191 default:
192 return false; // just to quiet compiler warnings....
193 }
194}
195
196
198{
199 switch( *m_matchMode )
200 {
201 case ID_MATCH_FP_ALL: return m_matchAll;
206 default: return nullptr;
207 }
208}
209
210
212{
213 wxRadioButton* rb_button = getRadioButtonForMode();
214
215 wxRadioButton* rb_butt_list[] =
216 {
222 nullptr // end of list
223 };
224
225 // Ensure the button state is ok. Only one button can be checked
226 // Change button state only if its state is incorrect, otherwise
227 // we have issues depending on the platform.
228 for( int ii = 0; rb_butt_list[ii]; ++ii )
229 {
230 bool state = rb_butt_list[ii] == rb_button;
231
232 if( rb_butt_list[ii]->GetValue() != state )
233 rb_butt_list[ii]->SetValue( state );
234 }
235}
236
237
239{
241
242 if( event.GetEventObject() == this )
244 else
245 m_matchAll->SetFocus();
246}
247
248
250{
252
253 if( event.GetEventObject() == this )
255 else
256 m_matchSelected->SetFocus();
257}
258
259
261{
263
264 if( event.GetEventObject() == this )
266 else if( event.GetEventObject() != m_specifiedRef )
267 m_specifiedRef->SetFocus();
268}
269
270
272{
274
275 if( event.GetEventObject() == this )
277 else if( event.GetEventObject() != m_specifiedValue )
278 m_specifiedValue->SetFocus();
279}
280
281
283{
285
286 if( event.GetEventObject() == this )
288 else if( event.GetEventObject() != m_specifiedID )
289 m_specifiedID->SetFocus();
290}
291
292
293void DIALOG_EXCHANGE_FOOTPRINTS::OnOKClicked( wxCommandEvent& event )
294{
295 wxBusyCursor dummy;
296
298 m_MessageWindow->Flush( false );
299
301
302 m_parent->Compile_Ratsnest( true );
304
305 m_MessageWindow->Flush( false );
306
307 m_commit.Push( wxT( "Changed footprint" ) );
308}
309
310
312{
313 LIB_ID newFPID;
314
315 if( m_parent->GetBoard()->Footprints().empty() )
316 return;
317
318 if( !m_updateMode )
319 {
320 newFPID.Parse( m_newID->GetValue() );
321
322 if( !newFPID.IsValid() )
323 return;
324 }
325
326 /*
327 * NB: the change is done from the last footprint because processFootprint() modifies the
328 * last item in the list.
329 */
330 for( auto it = m_parent->GetBoard()->Footprints().rbegin();
331 it != m_parent->GetBoard()->Footprints().rend(); it++ )
332 {
333 FOOTPRINT* footprint = *it;
334
335 if( !isMatch( footprint ) )
336 continue;
337
338 if( m_updateMode )
339 processFootprint( footprint, footprint->GetFPID() );
340 else
341 processFootprint( footprint, newFPID );
342 }
343}
344
345
347{
348 LIB_ID oldFPID = aFootprint->GetFPID();
349 wxString msg;
350
351 // Load new footprint.
352 if( m_updateMode )
353 {
354 msg.Printf( _( "Updated footprint %s (%s)" ) + wxS( ": " ),
355 aFootprint->GetReference(),
356 oldFPID.Format().c_str() );
357 }
358 else
359 {
360 msg.Printf( _( "Changed footprint %s from '%s' to '%s'" ) + wxS( ": " ),
361 aFootprint->GetReference(),
362 oldFPID.Format().c_str(),
363 aNewFPID.Format().c_str() );
364 }
365
366 FOOTPRINT* newFootprint = m_parent->LoadFootprint( aNewFPID );
367
368 if( !newFootprint )
369 {
370 msg += _( "*** library footprint not found ***" );
372 return;
373 }
374
375 bool updated = !m_updateMode || aFootprint->FootprintNeedsUpdate( newFootprint );
376
377 m_parent->ExchangeFootprint( aFootprint, newFootprint, m_commit,
378 m_removeExtraBox->GetValue(),
379 m_resetTextItemLayers->GetValue(),
380 m_resetTextItemEffects->GetValue(),
381 m_resetFabricationAttrs->GetValue(),
382 m_reset3DModels->GetValue(),
383 &updated );
384
385 // Update footprint field with the new FPID
386 newFootprint->Footprint().SetText( aNewFPID.Format() );
387
388 if( aFootprint == m_currentFootprint )
389 m_currentFootprint = newFootprint;
390
391 if( m_updateMode && !updated )
392 {
393 msg += _( ": (no changes)" );
395 }
396 else
397 {
398 msg += _( ": OK" );
400 }
401}
402
403
405{
406 wxString newname = m_newID->GetValue();
407
408 KIWAY_PLAYER* frame = Kiway().Player( FRAME_FOOTPRINT_CHOOSER, true, this );
409
411 {
412 /*
413 * Symbol netlist format:
414 * pinNumber pinName <tab> pinNumber pinName...
415 * fpFilter fpFilter...
416 */
417 wxString netlist;
418
419 wxArrayString pins;
420
421 for( const wxString& pad : m_currentFootprint->GetUniquePadNumbers() )
422 pins.push_back( pad + ' ' + wxEmptyString /* leave pinName empty */ );
423
424 if( !pins.IsEmpty() )
425 netlist << EscapeString( wxJoin( pins, '\t' ), CTX_LINE );
426
427 netlist << wxS( "\r" );
428
430
431 std::string payload( netlist.ToStdString() );
433 frame->KiwayMailIn( mail );
434 }
435
436 if( frame->ShowModal( &newname, this ) )
437 {
438 if( event.GetEventObject() == m_newIDBrowseButton )
439 m_newID->SetValue( newname );
440 else
441 m_specifiedID->SetValue( newname );
442 }
443
444 frame->Destroy();
445}
446
447
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:322
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:98
void SetupStandardButtons(std::map< int, wxString > aLabels={})
std::string m_hash_key
Definition: dialog_shim.h:206
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:183
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:1835
PCB_FIELD & Footprint()
Definition: footprint.h:626
bool FootprintNeedsUpdate(const FOOTPRINT *aLibFP, REPORTER *aReporter=nullptr)
Return true if a board footprint differs from the library version.
const LIB_ID & GetFPID() const
Definition: footprint.h:233
wxString GetFilters() const
Definition: footprint.h:258
const wxString & GetValue() const
Definition: footprint.h:610
const wxString & GetReference() const
Definition: footprint.h:588
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:67
virtual bool ShowModal(wxString *aResult=nullptr, wxWindow *aResultantFocusWindow=nullptr)
Show this wxFrame as if it were a modal dialog, with all other instantiated wxFrames disabled until t...
virtual void KiwayMailIn(KIWAY_EXPRESS &aEvent)
Receive KIWAY_EXPRESS messages from other players.
bool Destroy() override
Our version of Destroy() which is virtual from wxWidgets.
virtual KIWAY_PLAYER * Player(FRAME_T aFrameType, bool doCreate=true, wxTopLevelWindow *aParent=nullptr)
Return the KIWAY_PLAYER* given a FRAME_T.
Definition: kiway.cpp:406
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
void Compile_Ratsnest(bool aDisplayStatus)
Create the entire board ratsnest.
Definition: ratsnest.cpp:35
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 reset3DModels=true, bool *aUpdated=nullptr)
Replace aExisting footprint by aNew footprint using the Existing footprint settings (position,...
void SetBitmap(const wxBitmapBundle &aBmp)
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]
#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