KiCad PCB EDA Suite
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-2018 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_commit.h>
29#include <board.h>
30#include <footprint.h>
31#include <pad.h>
33#include <string_utils.h>
34#include <kiway.h>
35#include <macros.h>
36#include <pcb_edit_frame.h>
37#include <pcbnew_settings.h>
38#include <project.h>
40
41
42#define ID_MATCH_FP_ALL 4200
43#define ID_MATCH_FP_SELECTED 4201
44#define ID_MATCH_FP_REF 4202
45#define ID_MATCH_FP_VAL 4203
46#define ID_MATCH_FP_ID 4204
47
48
53
54 // { update, change }
55bool g_removeExtraTextItems[2] = { false, false };
56bool g_resetTextItemLayers[2] = { false, true };
57bool g_resetTextItemEffects[2] = { false, true };
58bool g_resetFabricationAttrs[2] = { false, true };
59bool g_reset3DModels[2] = { true, true };
60
61
63 FOOTPRINT* aFootprint,
64 bool updateMode, bool selectedMode ) :
66 m_commit( aParent ),
67 m_parent( aParent ),
68 m_currentFootprint( aFootprint ),
69 m_updateMode( updateMode )
70{
71 if( !updateMode )
72 {
73 SetTitle( _( "Change Footprints" ) );
74 m_matchAll->SetLabel( _( "Change all footprints on board" ) );
75 m_matchSelected->SetLabel( _( "Change selected footprint(s)" ) );
76 m_matchSpecifiedRef->SetLabel( _( "Change footprints matching reference designator:" ) );
77 m_matchSpecifiedValue->SetLabel( _( "Change footprints matching value:" ) );
78 m_matchSpecifiedID->SetLabel( _( "Change footprints with library id:" ) );
79 m_resetTextItemLayers->SetLabel( _( "Update text layers and visibilities" ) );
80 m_resetTextItemEffects->SetLabel( _( "Update text sizes, styles and positions" ) );
81 m_resetFabricationAttrs->SetLabel( _( "Update fabrication attributes" ) );
82 m_reset3DModels->SetLabel( _( "Update 3D models" ) );
83 }
84
85#if 0 // translator hint
86 wxString x = _( "Update/reset strings: there are two cases these descriptions need to cover: "
87 "the user made overrides to a footprint on the PCB and wants to remove them, "
88 "or the user made changes to the library footprint and wants to propagate "
89 "them back to the PCB." );
90#endif
91
92 if( m_updateMode )
93 {
94 m_changeSizer->Show( false );
95 }
96 else
97 {
98 m_upperSizer->FindItem( m_matchAll )->Show( false );
100 }
101
103 {
104 m_newID->AppendText( FROM_UTF8( m_currentFootprint->GetFPID().Format().c_str() ) );
105 }
106 else
107 m_upperSizer->FindItem( m_matchSelected )->Show( false );
108
109 // Use ChangeValue() instead of SetValue() so we don't generate events.
112
115
118
120
121 m_upperSizer->SetEmptyCellSize( wxSize( 0, 0 ) );
122 // The upper sizer has its content modified: re-layout it:
123 m_upperSizer->Layout();
124
125 // initialize match-mode
126 if( m_updateMode )
128 else
130
131 wxCommandEvent event;
132 event.SetEventObject( this );
133
134 switch( *m_matchMode )
135 {
136 case ID_MATCH_FP_ALL: OnMatchAllClicked( event ); break;
137 case ID_MATCH_FP_SELECTED: OnMatchSelectedClicked( event ); break;
138 case ID_MATCH_FP_REF: OnMatchRefClicked( event ); break;
139 case ID_MATCH_FP_VAL: OnMatchValueClicked( event ); break;
140 case ID_MATCH_FP_ID: OnMatchIDClicked( event ); break;
141 default: break;
142 }
143
148 m_reset3DModels->SetValue( g_reset3DModels[ m_updateMode ? 0 : 1 ] );
149
151 m_MessageWindow->SetFileName( Prj().GetProjectPath() + wxT( "report.txt" ) );
152
153 // DIALOG_SHIM needs a unique hash_key because classname is not sufficient
154 // because the update and change versions of this dialog have different controls.
155 m_hash_key = TO_UTF8( GetTitle() );
156
157 wxString okLabel = m_updateMode ? _( "Update" ) : _( "Change" );
158
159 SetupStandardButtons( { { wxID_OK, okLabel },
160 { wxID_CANCEL, _( "Close" ) } } );
161
162 // Now all widgets have the size fixed, call FinishDialogSettings
164}
165
166
168{
173 g_reset3DModels[ m_updateMode ? 0 : 1 ] = m_reset3DModels->GetValue();
174}
175
176
178{
179 LIB_ID specifiedID;
180
181 switch( *m_matchMode )
182 {
183 case ID_MATCH_FP_ALL:
184 return true;
186 return aFootprint == m_currentFootprint || aFootprint->IsSelected();
187 case ID_MATCH_FP_REF:
188 return WildCompareString( m_specifiedRef->GetValue(), aFootprint->GetReference(), false );
189 case ID_MATCH_FP_VAL:
190 return WildCompareString( m_specifiedValue->GetValue(), aFootprint->GetValue(), false );
191 case ID_MATCH_FP_ID:
192 specifiedID.Parse( m_specifiedID->GetValue() );
193 return aFootprint->GetFPID() == specifiedID;
194 default:
195 return false; // just to quiet compiler warnings....
196 }
197}
198
199
201{
202 switch( *m_matchMode )
203 {
204 case ID_MATCH_FP_ALL: return m_matchAll;
209 default: return nullptr;
210 }
211}
212
213
215{
216 wxRadioButton* rb_button = getRadioButtonForMode();
217
218 wxRadioButton* rb_butt_list[] =
219 {
225 nullptr // end of list
226 };
227
228 // Ensure the button state is ok. Only one button can be checked
229 // Change button state only if its state is incorrect, otherwise
230 // we have issues depending on the platform.
231 for( int ii = 0; rb_butt_list[ii]; ++ii )
232 {
233 bool state = rb_butt_list[ii] == rb_button;
234
235 if( rb_butt_list[ii]->GetValue() != state )
236 rb_butt_list[ii]->SetValue( state );
237 }
238}
239
240
242{
244
245 if( event.GetEventObject() == this )
247 else
248 m_matchAll->SetFocus();
249}
250
251
253{
255
256 if( event.GetEventObject() == this )
258 else
259 m_matchSelected->SetFocus();
260}
261
262
264{
266
267 if( event.GetEventObject() == this )
269 else if( event.GetEventObject() != m_specifiedRef )
270 m_specifiedRef->SetFocus();
271}
272
273
275{
277
278 if( event.GetEventObject() == this )
280 else if( event.GetEventObject() != m_specifiedValue )
281 m_specifiedValue->SetFocus();
282}
283
284
286{
288
289 if( event.GetEventObject() == this )
291 else if( event.GetEventObject() != m_specifiedID )
292 m_specifiedID->SetFocus();
293}
294
295
296void DIALOG_EXCHANGE_FOOTPRINTS::OnOKClicked( wxCommandEvent& event )
297{
298 wxBusyCursor dummy;
299
301 m_MessageWindow->Flush( false );
302
304
305 m_parent->Compile_Ratsnest( true );
307
308 m_MessageWindow->Flush( false );
309
310 m_commit.Push( wxT( "Changed footprint" ) );
311}
312
313
315{
316 LIB_ID newFPID;
317
318 if( m_parent->GetBoard()->Footprints().empty() )
319 return;
320
321 if( !m_updateMode )
322 {
323 newFPID.Parse( m_newID->GetValue() );
324
325 if( !newFPID.IsValid() )
326 return;
327 }
328
329 /*
330 * NB: the change is done from the last footprint because processFootprint() modifies the
331 * last item in the list.
332 */
333 for( auto it = m_parent->GetBoard()->Footprints().rbegin();
334 it != m_parent->GetBoard()->Footprints().rend(); it++ )
335 {
336 FOOTPRINT* footprint = *it;
337
338 if( !isMatch( footprint ) )
339 continue;
340
341 if( m_updateMode )
342 processFootprint( footprint, footprint->GetFPID() );
343 else
344 processFootprint( footprint, newFPID );
345 }
346}
347
348
350{
351 LIB_ID oldFPID = aFootprint->GetFPID();
352 wxString msg;
353
354 // Load new footprint.
355 if( m_updateMode )
356 {
357 msg.Printf( _( "Updated footprint %s (%s)" ) + wxS( ": " ),
358 aFootprint->GetReference(),
359 oldFPID.Format().c_str() );
360 }
361 else
362 {
363 msg.Printf( _( "Changed footprint %s from '%s' to '%s'" ) + wxS( ": " ),
364 aFootprint->GetReference(),
365 oldFPID.Format().c_str(),
366 aNewFPID.Format().c_str() );
367 }
368
369 FOOTPRINT* newFootprint = m_parent->LoadFootprint( aNewFPID );
370
371 if( !newFootprint )
372 {
373 msg += _( "*** library footprint not found ***" );
375 return;
376 }
377
378 bool updated = !m_updateMode || aFootprint->FootprintNeedsUpdate( newFootprint );
379
380 m_parent->ExchangeFootprint( aFootprint, newFootprint, m_commit,
381 m_removeExtraBox->GetValue(),
382 m_resetTextItemLayers->GetValue(),
383 m_resetTextItemEffects->GetValue(),
384 m_resetFabricationAttrs->GetValue(),
385 m_reset3DModels->GetValue(),
386 &updated );
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 return;
403}
404
405
407{
408 wxString newname = m_newID->GetValue();
409
411
412 if( frame->ShowModal( &newname, this ) )
413 {
414 if( event.GetEventObject() == m_newIDBrowseButton )
415 m_newID->SetValue( newname );
416 else
417 m_specifiedID->SetValue( newname );
418 }
419
420 frame->Destroy();
421}
422
423
wxBitmap KiBitmap(BITMAPS aBitmap, int aHeightTag)
Construct a wxBitmap from an image identifier Returns the image from the active theme if the image ha...
Definition: bitmap.cpp:105
@ small_library
virtual void Push(const wxString &aMessage=wxT("A commit"), int aCommitFlags=0) override
Revert the commit by restoring the modified items state.
FOOTPRINTS & Footprints()
Definition: board.h:307
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:97
void SetupStandardButtons(std::map< int, wxString > aLabels={})
std::string m_hash_key
Definition: dialog_shim.h:203
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
Update the board display after modifying it by a python script (note: it is automatically called by a...
bool IsSelected() const
Definition: eda_item.h:106
bool FootprintNeedsUpdate(const FOOTPRINT *aLibFootprint)
Return true if a board footprint differs from the library version.
const LIB_ID & GetFPID() const
Definition: footprint.h:212
const wxString & GetValue() const
Definition: footprint.h:547
const wxString & GetReference() const
Definition: footprint.h:519
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:53
A wxFrame capable of the OpenProjectFiles function, meaning it can load a portion of a KiCad project.
Definition: kiway_player.h:66
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...
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:394
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:50
bool IsValid() const
Check if this LID_ID is valid.
Definition: lib_id.h:172
UTF8 Format() const
Definition: lib_id.cpp:117
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,...
const char * c_str() const
Definition: utf8.h:102
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_VIEWER_MODAL
Definition: frame_type.h:43
This file contains miscellaneous commonly used macros and functions.
#define TO_UTF8(wxstring)
Convert a wxString to a UTF8 encoded C string for all wxWidgets build modes.
Definition: macros.h:96
static wxString FROM_UTF8(const char *cstring)
Convert a UTF8 encoded C string to a wxString for all wxWidgets build modes.
Definition: macros.h:110
@ 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.