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 The 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 if( aFootprint == m_currentFootprint )
396 m_currentFootprint = newFootprint;
397
398 if( newFootprint )
399 m_newFootprints.push_back( newFootprint );
400
401 if( m_updateMode && !updated )
402 {
403 msg += _( ": (no changes)" );
405 }
406 else
407 {
408 msg += _( ": OK" );
410 }
411}
412
413
415{
416 wxString newname = m_newID->GetValue();
417
418 if( KIWAY_PLAYER* frame = Kiway().Player( FRAME_FOOTPRINT_CHOOSER, true, this ) )
419 {
421 {
422 /*
423 * Symbol netlist format:
424 * pinNumber pinName <tab> pinNumber pinName...
425 * fpFilter fpFilter...
426 */
427 wxString netlist;
428
429 wxArrayString pins;
430
431 for( const wxString& pad : m_currentFootprint->GetUniquePadNumbers() )
432 pins.push_back( pad + ' ' + wxEmptyString /* leave pinName empty */ );
433
434 if( !pins.IsEmpty() )
435 netlist << EscapeString( wxJoin( pins, '\t' ), CTX_LINE );
436
437 netlist << wxS( "\r" );
438
440
441 std::string payload( netlist.ToStdString() );
443 frame->KiwayMailIn( mail );
444 }
445
446 if( frame->ShowModal( &newname, this ) )
447 {
448 if( event.GetEventObject() == m_newIDBrowseButton )
449 m_newID->SetValue( newname );
450 else
451 m_specifiedID->SetValue( newname );
452 }
453
454 frame->Destroy();
455 }
456}
457
458
wxBitmapBundle KiBitmapBundle(BITMAPS aBitmap)
Definition: bitmap.cpp:110
virtual void Push(const wxString &aMessage=wxEmptyString, int aCommitFlags=0) override
Execute the changes.
const FOOTPRINTS & Footprints() const
Definition: board.h:336
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:230
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:110
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:1963
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:246
wxString GetFilters() const
Definition: footprint.h:270
const wxString & GetValue() const
Definition: footprint.h:642
const wxString & GetReference() const
Definition: footprint.h:620
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()
Clears the report panel.
void SetLazyUpdate(bool aLazyUpdate)
Set the lazy update.
void SetFileName(const wxString &aReportFileName)
Set the report full file name to the string.
void Report(const wxString &aText, SEVERITY aSeverity, REPORTER::LOCATION aLocation=REPORTER::LOC_BODY)
Report the string.
void Flush(bool aSort=false)
Force updating the HTML page, after the report is built in lazy mode If aSort = true,...
#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:398
@ CTX_LINE
Definition: string_utils.h:59