KiCad PCB EDA Suite
dialog_exchange_modules.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 <dick@softplc.com>
6  * Copyright (C) 2013-2016 Wayne Stambaugh <stambaughw@verizon.net>
7  * Copyright (C) 1992-2017 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 <fctsys.h>
28 #include <class_drawpanel.h>
29 #include <class_draw_panel_gal.h>
30 #include <confirm.h>
31 #include <kicad_string.h>
32 #include <wxPcbStruct.h>
33 #include <macros.h>
34 #include <board_commit.h>
35 
36 #include <class_board.h>
37 #include <class_module.h>
38 #include <project.h>
39 
40 #include <pcbnew.h>
43 #include <kiway.h>
44 
45 
46 static bool RecreateCmpFile( BOARD * aBrd, const wxString& aFullCmpFileName );
47 
48 
50 
51 
53  DIALOG_EXCHANGE_MODULE_BASE( parent ), m_commit( parent )
54 {
55  m_parent = parent;
56  m_currentModule = Module;
57  init();
58  GetSizer()->Fit( this );
59  GetSizer()->SetSizeHints( this );
60  Center();
61 }
62 
63 
64 void DIALOG_EXCHANGE_MODULE::OnQuit( wxCommandEvent& event )
65 {
66  m_selectionMode = m_Selection->GetSelection();
67  Show( false );
68  EndQuasiModal( wxID_CANCEL );
69 }
70 
71 
73 {
74  SetFocus();
75 
76  m_CurrentFootprintFPID->AppendText( FROM_UTF8( m_currentModule->GetFPID().Format().c_str() ) );
77  m_NewFootprintFPID->AppendText( FROM_UTF8( m_currentModule->GetFPID().Format().c_str() ) );
78  m_CmpValue->AppendText( m_currentModule->GetValue() );
80  m_Selection->SetString( 0, wxString::Format(
81  _( "Change footprint of '%s'" ),
83  wxString fpname = m_CurrentFootprintFPID->GetValue().AfterLast( ':' );
84 
85  if( fpname.IsEmpty() ) // Happens for old fp names
86  fpname = m_CurrentFootprintFPID->GetValue();
87 
88  m_Selection->SetString( 1, wxString::Format(
89  _( "Change footprints '%s'" ),
90  GetChars( fpname.Left( 12 ) ) ) );
91 
92  m_Selection->SetSelection( m_selectionMode );
93 
94  // Enable/disable widgets:
95  wxCommandEvent event;
96  OnSelectionClicked( event );
97 }
98 
99 
100 void DIALOG_EXCHANGE_MODULE::OnOkClick( wxCommandEvent& event )
101 {
102  m_selectionMode = m_Selection->GetSelection();
103  bool result = false;
104 
105  switch( m_Selection->GetSelection() )
106  {
107  case 0:
108  result = changeCurrentFootprint();
109  break;
110 
111  case 1:
112  result = changeSameFootprints( false );
113  break;
114 
115  case 2:
116  result = changeSameFootprints( true );
117  break;
118 
119  case 3:
120  result = changeAllFootprints();
121  break;
122  }
123 
124  if( result )
125  {
127  m_parent->Compile_Ratsnest( NULL, true );
128 
129  m_parent->GetCanvas()->Refresh();
130  }
131 
132  m_commit.Push( wxT( "Changed footprint" ) );
133 }
134 
135 
136 void DIALOG_EXCHANGE_MODULE::OnSelectionClicked( wxCommandEvent& event )
137 {
138  bool enable = true;
139 
140  switch( m_Selection->GetSelection() )
141  {
142  case 0:
143  case 1:
144  case 2:
145  break;
146 
147  case 3:
148  enable = false;
149  break;
150  }
151 
152  m_NewFootprintFPID->Enable( enable );
153  m_Browsebutton->Enable( enable );
154 }
155 
156 
157 void DIALOG_EXCHANGE_MODULE::RebuildCmpList( wxCommandEvent& event )
158 {
159  wxFileName fn;
160  wxString msg;
161 
162  // Build the .cmp file name from the board name
163  fn = m_parent->GetBoard()->GetFileName();
164  fn.SetExt( ComponentFileExtension );
165 
166  if( RecreateCmpFile( m_parent->GetBoard(), fn.GetFullPath() ) )
167  {
168  msg.Printf( _( "File '%s' created\n" ),
169  GetChars( fn.GetFullPath() ) );
170  }
171  else
172  {
173  msg.Printf( _( "** Could not create file '%s' ***\n" ),
174  GetChars( fn.GetFullPath() ) );
175  }
176 
177  m_WinMessages->AppendText( msg );
178 }
179 
180 
182 {
183  wxString newmodulename = m_NewFootprintFPID->GetValue();
184 
185  if( newmodulename == wxEmptyString )
186  return false;
187 
188  return change_1_Module( m_currentModule, newmodulename, true );
189 }
190 
191 
193 {
194  wxString msg;
195  MODULE* Module;
196  MODULE* PtBack;
197  bool change = false;
198  wxString newmodulename = m_NewFootprintFPID->GetValue();
199  wxString value;
200  LIB_ID lib_reference;
201  bool check_module_value = false;
202  int ShowErr = 3; // Post 3 error messages max.
203 
204  if( m_parent->GetBoard()->m_Modules == NULL )
205  return false;
206 
207  if( newmodulename == wxEmptyString )
208  return false;
209 
210  lib_reference = m_currentModule->GetFPID();
211 
212  if( aUseValue )
213  {
214  check_module_value = true;
215  value = m_currentModule->GetValue();
216  msg.Printf( _( "Change footprint %s -> %s (for value = %s)?" ),
217  GetChars( FROM_UTF8( m_currentModule->GetFPID().Format().c_str() ) ),
218  GetChars( newmodulename ),
220  }
221  else
222  {
223  msg.Printf( _( "Change footprint %s -> %s ?" ),
224  GetChars( FROM_UTF8( lib_reference.Format().c_str() ) ),
225  GetChars( newmodulename ) );
226  }
227 
228  if( !IsOK( this, msg ) )
229  return false;
230 
231  /* The change is done from the last module because
232  * change_1_Module () modifies the last item in the list.
233  *
234  * note: for the first module in chain (the last here), Module->Back()
235  * points the board or is NULL
236  */
237  Module = m_parent->GetBoard()->m_Modules.GetLast();
238 
239  for( ; Module && ( Module->Type() == PCB_MODULE_T ); Module = PtBack )
240  {
241  PtBack = Module->Back();
242 
243  if( lib_reference != Module->GetFPID() )
244  continue;
245 
246  if( check_module_value )
247  {
248  if( value.CmpNoCase( Module->GetValue() ) != 0 )
249  continue;
250  }
251 
252  if( change_1_Module( Module, newmodulename, ShowErr ) )
253  change = true;
254  else if( ShowErr )
255  ShowErr--;
256  }
257 
258  return change;
259 }
260 
261 
263 {
264  MODULE* Module, * PtBack;
265  bool change = false;
266  int ShowErr = 3; // Post 3 error max.
267 
268  if( m_parent->GetBoard()->m_Modules == NULL )
269  return false;
270 
271  if( !IsOK( this, _( "Are you sure you want to change all footprints?" ) ) )
272  return false;
273 
274  /* The change is done from the last module because the function
275  * change_1_Module () modifies the last module in the list
276  *
277  * note: for the first module in chain (the last here), Module->Back()
278  * points the board or is NULL
279  */
280  Module = m_parent->GetBoard()->m_Modules.GetLast();
281 
282  for( ; Module && ( Module->Type() == PCB_MODULE_T ); Module = PtBack )
283  {
284  PtBack = Module->Back();
285 
286  if( change_1_Module( Module, Module->GetFPID(), ShowErr ) )
287  change = true;
288  else if( ShowErr )
289  ShowErr--;
290  }
291 
292  return change;
293 }
294 
295 
297  const LIB_ID& aNewFootprintFPID,
298  bool aShowError )
299 {
300  MODULE* newModule;
301  wxString line;
302 
303  if( aModule == NULL )
304  return false;
305 
306  wxBusyCursor dummy;
307 
308  // Copy parameters from the old module.
309  LIB_ID oldFootprintFPID = aModule->GetFPID();
310 
311  // Load module.
312  line.Printf( _( "Change footprint '%s' (from '%s') to '%s'" ),
313  GetChars( aModule->GetReference() ),
314  FROM_UTF8( oldFootprintFPID.Format() ),
315  FROM_UTF8( aNewFootprintFPID.Format() ) );
316  m_WinMessages->AppendText( line );
317 
318  newModule = m_parent->LoadFootprint( aNewFootprintFPID );
319 
320  if( newModule == NULL ) // New module not found, redraw the old one.
321  {
322  m_WinMessages->AppendText( wxT( " No\n" ) );
323  return false;
324  }
325 
326  m_parent->Exchange_Module( aModule, newModule, m_commit );
327 
328  if( aModule == m_currentModule )
329  m_currentModule = newModule;
330 
331  m_WinMessages->AppendText( wxT( " OK\n" ) );
332 
333  return true;
334 }
335 
336 
338  MODULE* aNewModule,
339  BOARD_COMMIT& aCommit )
340 {
341  aNewModule->SetParent( GetBoard() );
342 
343  /* place module without ratsnest refresh: this will be made later
344  * when all modules are on board */
345  PlaceModule( aNewModule, NULL, true );
346 
347  // Copy full placement and pad net names (when possible)
348  // but not local settings like clearances (use library values)
349  aOldModule->CopyNetlistSettings( aNewModule, false );
350 
351  // Copy reference and value
352  aNewModule->SetReference( aOldModule->GetReference() );
353  aNewModule->SetValue( aOldModule->GetValue() );
354 
355  // Compare the footprint name only, in case the nickname is empty or in case
356  // user moved the footprint to a new library. Chances are if footprint name is
357  // same then the footprint is very nearly the same and the two texts should
358  // be kept at same size, position, and rotation.
359  if( aNewModule->GetFPID().GetLibItemName() == aOldModule->GetFPID().GetLibItemName() )
360  {
361  aNewModule->Reference().SetEffects( aOldModule->Reference() );
362  aNewModule->Value().SetEffects( aOldModule->Value() );
363  }
364 
365  // Updating other parameters
366  aNewModule->SetTimeStamp( aOldModule->GetTimeStamp() );
367  aNewModule->SetPath( aOldModule->GetPath() );
368 
369  aCommit.Remove( aOldModule );
370  aCommit.Add( aNewModule );
371 
372  // @todo LEGACY should be unnecessary
373  GetBoard()->m_Status_Pcb = 0;
374  aNewModule->ClearFlags();
375 }
376 
377 
378 // Displays the list of available footprints in library name and select a footprint.
380 {
381  wxString newname;
382 
383  newname = m_parent->SelectFootprint( m_parent, wxEmptyString, wxEmptyString, wxEmptyString,
384  Prj().PcbFootprintLibs() );
385 
386  if( newname != wxEmptyString )
387  m_NewFootprintFPID->SetValue( newname );
388 }
389 
390 
392 {
393  wxString newname;
394 
396 
397  if( frame->ShowModal( &newname, this ) )
398  {
399  m_NewFootprintFPID->SetValue( newname );
400  }
401 
402  frame->Destroy();
403 }
404 
405 
406 void PCB_EDIT_FRAME::RecreateCmpFileFromBoard( wxCommandEvent& aEvent )
407 {
408  wxFileName fn;
409  MODULE* module = GetBoard()->m_Modules;
410  wxString msg;
411  wxString wildcard;
412 
413  if( module == NULL )
414  {
415  DisplayError( this, _( "No footprints!" ) );
416  return;
417  }
418 
419  // Build the .cmp file name from the board name
420  fn = GetBoard()->GetFileName();
421  fn.SetExt( ComponentFileExtension );
422  wildcard = wxGetTranslation( ComponentFileWildcard );
423 
424  wxString pro_dir = wxPathOnly( Prj().GetProjectFullName() );
425 
426  wxFileDialog dlg( this, _( "Save Footprint Association File" ), pro_dir,
427  fn.GetFullName(), wildcard,
428  wxFD_SAVE | wxFD_OVERWRITE_PROMPT );
429 
430  if( dlg.ShowModal() == wxID_CANCEL )
431  return;
432 
433  fn = dlg.GetPath();
434 
435  if( ! RecreateCmpFile( GetBoard(), fn.GetFullPath() ) )
436  {
437  msg.Printf( _( "Could not create file '%s'" ), GetChars(fn.GetFullPath() ) );
438  DisplayError( this, msg );
439  return;
440  }
441 }
442 
443 
444 bool RecreateCmpFile( BOARD * aBrd, const wxString& aFullCmpFileName )
445 {
446  FILE* cmpFile;
447 
448  cmpFile = wxFopen( aFullCmpFileName, wxT( "wt" ) );
449 
450  if( cmpFile == NULL )
451  return false;
452 
453  fprintf( cmpFile, "Cmp-Mod V01 Created by PcbNew date = %s\n", TO_UTF8( DateAndTime() ) );
454 
455  MODULE* module = aBrd->m_Modules;
456  for( ; module != NULL; module = module->Next() )
457  {
458  fprintf( cmpFile, "\nBeginCmp\n" );
459  fprintf( cmpFile, "TimeStamp = %8.8lX\n", (unsigned long)module->GetTimeStamp() );
460  fprintf( cmpFile, "Path = %s\n", TO_UTF8( module->GetPath() ) );
461  fprintf( cmpFile, "Reference = %s;\n",
462  !module->GetReference().IsEmpty() ?
463  TO_UTF8( module->GetReference() ) : "[NoRef]" );
464  fprintf( cmpFile, "ValeurCmp = %s;\n",
465  !module->GetValue().IsEmpty() ?
466  TO_UTF8( module->GetValue() ) : "[NoVal]" );
467  fprintf( cmpFile, "IdModule = %s;\n", module->GetFPID().Format().c_str() );
468  fprintf( cmpFile, "EndCmp\n" );
469  }
470 
471  fprintf( cmpFile, "\nEndListe\n" );
472  fclose( cmpFile );
473 
474  return true;
475 }
KICAD_T Type() const
Function Type()
Definition: base_struct.h:198
void RecreateCmpFileFromBoard(wxCommandEvent &aEvent)
Function RecreateBOMFileFromBoard Recreates a .cmp file from the current loaded board this is the sam...
Class KIWAY_PLAYER is a wxFrame capable of the OpenProjectFiles function, meaning it can load a porti...
Definition: kiway_player.h:111
bool IsElementVisible(GAL_LAYER_ID LAYER_aPCB) const
Function IsElementVisible tests whether a given element category is visible.
TEXTE_MODULE & Reference()
Definition: class_module.h:463
KIWAY & Kiway() const
Function Kiway returns a reference to the KIWAY that this object has an opportunity to participate in...
Definition: kiway_player.h:60
static wxString FROM_UTF8(const char *cstring)
function FROM_UTF8 converts a UTF8 encoded C string to a wxString for all wxWidgets build modes...
Definition: macros.h:53
virtual void Refresh(bool eraseBackground=true, const wxRect *rect=NULL) override
Definition: draw_panel.cpp:326
This file is part of the common library.
EDA_DRAW_PANEL * GetCanvas()
Definition: draw_frame.h:299
void ViewAndSelectFootprint(wxCommandEvent &event) override
void Exchange_Module(MODULE *aOldModule, MODULE *aNewModule, BOARD_COMMIT &aCommit)
Function Exchange_Module Replaces OldModule by NewModule, using OldModule settings: position...
COMMIT & Add(EDA_ITEM *aItem)
Adds a new item to the model
Definition: commit.h:78
void OnOkClick(wxCommandEvent &event) override
Class BOARD to handle a board.
MODULE * Next() const
Definition: class_module.h:100
void OnQuit(wxCommandEvent &event) override
BOARD * GetBoard() const
const wxString & GetValue() const
Function GetValue.
Definition: class_module.h:447
bool changeSameFootprints(bool aUseValue)
Class LIB_ID.
Definition: lib_id.h:56
virtual void Push(const wxString &aMessage=wxT("A commit"), bool aCreateUndoEntry=true) override
Executes the changes.
static bool RecreateCmpFile(BOARD *aBrd, const wxString &aFullCmpFileName)
Class DIALOG_EXCHANGE_MODULE_BASE.
void SetTimeStamp(time_t aNewTimeStamp)
Definition: base_struct.h:203
This file contains miscellaneous commonly used macros and functions.
void PlaceModule(MODULE *aModule, wxDC *aDC, bool aDoNotRecreateRatsnest=false)
Function PlaceModule places aModule at the current cursor position and updates module coordinates wit...
Definition: modules.cpp:352
const LIB_ID & GetFPID() const
Definition: class_module.h:164
void OnSelectionClicked(wxCommandEvent &event) override
#define TO_UTF8(wxstring)
Macro TO_UTF8 converts a wxString to a UTF8 encoded C string for all wxWidgets build modes...
Definition: macros.h:47
PROJECT & Prj() const
Function Prj returns a reference to the PROJECT "associated with" this KIWAY.
class MODULE, a footprint
Definition: typeinfo.h:101
VTBL_ENTRY KIWAY_PLAYER * Player(FRAME_T aFrameType, bool doCreate=true, KIWAY_PLAYER *aParent=NULL)
Function Player returns the KIWAY_PLAYER* given a FRAME_T.
Definition: kiway.cpp:302
T * GetLast() const
Function GetLast returns the last T* in the list without removing it, or NULL if the list is empty...
Definition: dlist.h:170
void SetParent(EDA_ITEM *aParent)
Definition: base_struct.h:213
const wxString & GetFileName() const
Definition: class_board.h:234
TEXTE_MODULE & Value()
read/write accessors:
Definition: class_module.h:462
const UTF8 & GetLibItemName() const
Function GetLibItemName.
Definition: lib_id.h:129
The common library.
void SetReference(const wxString &aReference)
Function SetReference.
Definition: class_module.h:429
COMMIT & Remove(EDA_ITEM *aItem)
Removes a new item from the model
Definition: commit.h:90
MODULE * Back() const
Definition: class_module.h:101
bool Show(bool show) override
time_t GetTimeStamp() const
Definition: base_struct.h:204
void Compile_Ratsnest(wxDC *aDC, bool aDisplayStatus)
Function Compile_Ratsnest Create the entire board ratsnest.
Definition: ratsnest.cpp:57
void EndQuasiModal(int retCode)
bool change_1_Module(MODULE *aModule, const LIB_ID &aNewFootprintFPID, bool eShowError)
static const wxChar * GetChars(const wxString &s)
Function GetChars returns a wxChar* to the actual wxChar* data within a wxString, and is helpful for ...
Definition: macros.h:92
DIALOG_EXCHANGE_MODULE(PCB_EDIT_FRAME *aParent, MODULE *aModule)
MODULE * LoadFootprint(const LIB_ID &aFootprintId)
Function LoadFootprint attempts to load aFootprintId from the footprint library table.
Definition: loadcmp.cpp:316
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, CPTREE &aTree)
Function Format outputs a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
Definition: ptree.cpp:205
static LIB_PART * dummy()
Used when a LIB_PART is not found in library to draw a dummy shape This component is a 400 mils squar...
Class BOARD holds information pertinent to a Pcbnew printed circuit board.
Definition: class_board.h:169
const wxString & GetReference() const
Function GetReference.
Definition: class_module.h:419
const wxString ComponentFileExtension
DLIST< MODULE > m_Modules
Definition: class_board.h:245
void SetValue(const wxString &aValue)
Function SetValue.
Definition: class_module.h:456
UTF8 Format() const
Function Format.
Definition: lib_id.cpp:263
bool Destroy() override
Our version of Destroy() which is virtual from wxWidgets.
void ClearFlags(STATUS_FLAGS aMask=EDA_ITEM_ALL_FLAGS)
Definition: base_struct.h:254
void SetEffects(const TEXTE_MODULE &aSrc)
Function SetEffects sets the text effects from another instance.
void CopyNetlistSettings(MODULE *aModule, bool aCopyLocalSettings)
Function CopyNetlistSettings copies the netlist settings to aModule.
const wxString ComponentFileWildcard
Module description (excepted pads)
const wxString & GetPath() const
Definition: class_module.h:173
void DisplayError(wxWindow *parent, const wxString &text, int displaytime)
Function DisplayError displays an error or warning message box with aMessage.
Definition: confirm.cpp:69
bool IsOK(wxWindow *aParent, const wxString &aMessage)
Function IsOK displays a yes/no dialog with aMessage and returns the user response.
Definition: confirm.cpp:111
VTBL_ENTRY bool ShowModal(wxString *aResult=NULL, wxWindow *aResultantFocusWindow=NULL)
Function ShowModal puts up this wxFrame as if it were a modal dialog, with all other instantiated wxF...
void SetPath(const wxString &aPath)
Definition: class_module.h:174
void BrowseAndSelectFootprint(wxCommandEvent &event) override
wxString DateAndTime()
Function DateAndTime.
Definition: string.cpp:229
wxString SelectFootprint(EDA_DRAW_FRAME *aWindow, const wxString &aLibraryName, const wxString &aMask, const wxString &aKeyWord, FP_LIB_TABLE *aTable)
Function SelectFootprint displays a list of modules found in all libraries or a given library...
Definition: loadcmp.cpp:353
int m_Status_Pcb
Flags used in ratsnest calculation and update.
Definition: class_board.h:237
void RebuildCmpList(wxCommandEvent &event) override