KiCad PCB EDA Suite
readwrite_dlgs.cpp
Go to the documentation of this file.
1 
5 /*
6  * This program source code file is part of KiCad, a free EDA CAD application.
7  *
8  * Copyright (C) 2018 Jean-Pierre Charras, jean-pierre.charras
9  * Copyright (C) 2011-2016 Wayne Stambaugh <stambaughw@verizon.net>
10  * Copyright (C) 1992-2018 KiCad Developers, see AUTHORS.txt for contributors.
11  *
12  * This program is free software; you can redistribute it and/or
13  * modify it under the terms of the GNU General Public License
14  * as published by the Free Software Foundation; either version 2
15  * of the License, or (at your option) any later version.
16  *
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20  * GNU General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License
23  * along with this program; if not, you may find one here:
24  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
25  * or you may search the http://www.gnu.org website for the version 2 license,
26  * or you may write to the Free Software Foundation, Inc.,
27  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
28  */
29 #include <fctsys.h>
30 #include <kiway.h>
31 #include <common.h>
32 #include <confirm.h>
33 #include <build_version.h>
34 #include <macros.h>
35 #include <lib_id.h>
36 #include <fp_lib_table.h>
37 #include <html_messagebox.h>
38 
39 #include <cvpcb.h>
40 #include <cvpcb_mainframe.h>
41 #include <listboxes.h>
43 
44 
45 void CVPCB_MAINFRAME::SetNewPkg( const wxString& aFootprintName )
46 {
47  COMPONENT* component;
48  int componentIndex;
49 
50  if( m_netlist.IsEmpty() )
51  return;
52 
53  // If no component is selected, select the first one
54  if( m_compListBox->GetFirstSelected() < 0 )
55  {
56  componentIndex = 0;
57  m_compListBox->SetSelection( componentIndex, true );
58  }
59 
60  // iterate over the selection
61  while( m_compListBox->GetFirstSelected() != -1 )
62  {
63  // Get the component for the current iteration
64  componentIndex = m_compListBox->GetFirstSelected();
65  component = m_netlist.GetComponent( componentIndex );
66 
67  if( component == NULL )
68  return;
69 
70  SetNewPkg( aFootprintName, componentIndex );
71 
72  m_compListBox->SetSelection( componentIndex, false );
73  }
74 
75  // select the next component, if there is one
76  if( componentIndex < (m_compListBox->GetCount() - 1) )
77  componentIndex++;
78 
79  m_compListBox->SetSelection( componentIndex, true );
80 
81  // update the statusbar
82  DisplayStatus();
83 }
84 
85 
86 void CVPCB_MAINFRAME::SetNewPkg( const wxString& aFootprintName, int aIndex )
87 {
88  COMPONENT* component;
89 
90  if( m_netlist.IsEmpty() )
91  return;
92 
93  component = m_netlist.GetComponent( aIndex );
94 
95  if( component == NULL )
96  return;
97 
98  LIB_ID fpid;
99 
100  if( !aFootprintName.IsEmpty() )
101  {
102  wxCHECK_RET( fpid.Parse( aFootprintName ) < 0,
103  wxString::Format( wxT( "\"%s\" is not a valid LIB_ID." ),
104  GetChars( aFootprintName ) ) );
105  }
106 
107  component->SetFPID( fpid );
108 
109  // create the new component description
110  wxString description = wxString::Format( CMP_FORMAT, aIndex + 1,
111  GetChars( component->GetReference() ),
112  GetChars( component->GetValue() ),
113  GetChars( FROM_UTF8( component->GetFPID().Format().c_str() ) ) );
114 
115  // Set the new description and deselect the processed component
116  m_compListBox->SetString( aIndex, description );
117 
118  // Mark this "session" as modified
119  m_modified = true;
120 
121  // update the statusbar
122  DisplayStatus();
123 }
124 
125 
129 static int guessNickname( FP_LIB_TABLE* aTbl, LIB_ID* aFootprintId )
130 {
131  if( aFootprintId->GetLibNickname().size() )
132  return 0;
133 
134  wxString nick;
135  wxString fpname = aFootprintId->GetLibItemName();
136 
137  std::vector<wxString> nicks = aTbl->GetLogicalLibs();
138 
139  // Search each library going through libraries alphabetically.
140  for( unsigned libNdx = 0; libNdx<nicks.size(); ++libNdx )
141  {
142  wxArrayString fpnames;
143 
144  aTbl->FootprintEnumerate( fpnames, nicks[libNdx] );
145 
146  for( unsigned nameNdx = 0; nameNdx<fpnames.size(); ++nameNdx )
147  {
148  if( fpname == fpnames[nameNdx] )
149  {
150  if( !nick )
151  nick = nicks[libNdx];
152  else
153  return 2; // duplicate, the guess would not be certain
154  }
155  }
156  }
157 
158  if( nick.size() )
159  {
160  aFootprintId->SetLibNickname( nick );
161  return 0;
162  }
163 
164  return 1;
165 }
166 
167 
168 bool CVPCB_MAINFRAME::ReadNetListAndFpFiles( const std::string& aNetlist )
169 {
170  wxString msg;
171  bool hasMissingNicks = false;
172 
173  ReadSchematicNetlist( aNetlist );
174 
175  if( m_compListBox == NULL )
176  return false;
177 
178  LoadProjectFile();
179 
180  wxSafeYield();
181 
183 
186 
187  m_compListBox->Clear();
188 
190  {
191  for( unsigned i = 0; i < m_netlist.GetCount(); i++ )
192  {
193  COMPONENT* component = m_netlist.GetComponent( i );
194 
195  if( component->GetFPID().empty() )
196  continue;
197 
198  if( component->GetFPID().IsLegacy() )
199  hasMissingNicks = true;
200  }
201  }
202 
203  // Check if footprint links were generated before the footprint library table was implemented.
204  if( hasMissingNicks )
205  {
206  msg = _(
207  "Some of the assigned footprints are legacy entries (are missing lib nicknames). "
208  "Would you like CvPcb to attempt to convert them to the new required LIB_ID format? "
209  "(If you answer no, then these assignments will be cleared out and you will "
210  "have to re-assign these footprints yourself.)"
211  );
212 
213  if( IsOK( this, msg ) )
214  {
215  msg.Clear();
216 
217  try
218  {
219  for( unsigned i = 0; i < m_netlist.GetCount(); i++ )
220  {
221  COMPONENT* component = m_netlist.GetComponent( i );
222 
223  if( component->GetFPID().IsLegacy() )
224  {
225  // get this first here, it's possibly obsoleted if we get it too soon.
226  FP_LIB_TABLE* tbl = Prj().PcbFootprintLibs( Kiway() );
227 
228  int guess = guessNickname( tbl, (LIB_ID*) &component->GetFPID() );
229 
230  switch( guess )
231  {
232  case 0:
233  DBG(printf("%s: guessed OK ref:%s fpid:%s\n", __func__,
234  TO_UTF8( component->GetReference() ), component->GetFPID().Format().c_str() );)
235  m_modified = true;
236  break;
237 
238  case 1:
239  msg += wxString::Format( _(
240  "Component \"%s\" footprint \"%s\" was <b>not found</b> in any library.\n" ),
241  GetChars( component->GetReference() ),
242  GetChars( component->GetFPID().GetLibItemName() )
243  );
244  break;
245 
246  case 2:
247  msg += wxString::Format( _(
248  "Component \"%s\" footprint \"%s\" was found in <b>multiple</b> libraries.\n" ),
249  GetChars( component->GetReference() ),
250  GetChars( component->GetFPID().GetLibItemName() )
251  );
252  break;
253  }
254  }
255  }
256  }
257  catch( const IO_ERROR& ioe )
258  {
259  msg = ioe.What();
260  msg += wxT( "\n\n" );
261  msg += _( "First check your footprint library table entries." );
262 
263  wxMessageBox( msg, _( "Problematic Footprint Library Tables" ) );
264  return false;
265  }
266 
267  if( msg.size() )
268  {
269  HTML_MESSAGE_BOX dlg( this, wxEmptyString );
270 
271  dlg.MessageSet( _( "The following errors occurred attempting to convert the "
272  "footprint assignments:\n\n" ) );
273  dlg.ListSet( msg );
274  dlg.MessageSet( _( "\nYou will need to reassign them manually if you want them "
275  "to be updated correctly the next time you import the "
276  "netlist in Pcbnew." ) );
277 
278 #if 1
279  dlg.ShowModal();
280 #else
281  dlg.Fit();
282  dlg.Show( true ); // modeless lets user watch while fixing the problems, but its not working.
283 #endif
284  }
285  }
286  else
287  {
288  // Clear the legacy footprint assignments.
289  for( unsigned i = 0; i < m_netlist.GetCount(); i++ )
290  {
291  COMPONENT* component = m_netlist.GetComponent( i );
292 
293  if( component->GetFPID().IsLegacy() )
294  {
295  component->SetFPID( LIB_ID() /* empty */ );
296  m_modified = true;
297  }
298  }
299  }
300  }
301 
302 
303  // Display a dialog to select footprint selection, if the netlist
304  // and the .cmp file give 2 different valid footprints
305  std::vector <int > m_indexes; // indexes of footprints in netlist
306 
307  for( unsigned ii = 0; ii < m_netlist.GetCount(); ii++ )
308  {
309  COMPONENT* component = m_netlist.GetComponent( ii );
310 
311  if( component->GetAltFPID().empty() )
312  continue;
313 
314  if( component->GetFPID().IsLegacy() || component->GetAltFPID().IsLegacy())
315  continue;
316 
317  m_indexes.push_back( ii );
318  }
319 
320  // If a n assignment conflict is found,
321  // open a dialog to chose between schematic assignment
322  // and .cmp file assignment:
323  if( m_indexes.size() > 0 )
324  {
326 
327  for( unsigned ii = 0; ii < m_indexes.size(); ii++ )
328  {
329  COMPONENT* component = m_netlist.GetComponent( m_indexes[ii] );
330 
331  wxString cmpfpid = component->GetFPID().Format();
332  wxString schfpid = component->GetAltFPID().Format();
333 
334  dlg.Add( component->GetReference(), schfpid, cmpfpid );
335  }
336 
337  if( dlg.ShowModal() == wxID_OK )
338  {
339 
340  // Update the fp selection:
341  for( unsigned ii = 0; ii < m_indexes.size(); ii++ )
342  {
343  COMPONENT* component = m_netlist.GetComponent( m_indexes[ii] );
344 
345  int choice = dlg.GetSelection( component->GetReference() );
346 
347  if( choice == 0 ) // the schematic (alt fpid) is chosen:
348  component->SetFPID( component->GetAltFPID() );
349  }
350  }
351  }
352 
353  // Populates the component list box:
354  for( unsigned i = 0; i < m_netlist.GetCount(); i++ )
355  {
356  COMPONENT* component = m_netlist.GetComponent( i );
357 
358  msg.Printf( CMP_FORMAT, m_compListBox->GetCount() + 1,
359  GetChars( component->GetReference() ),
360  GetChars( component->GetValue() ),
361  GetChars( FROM_UTF8( component->GetFPID().Format().c_str() ) ) );
362 
363  m_compListBox->AppendLine( msg );
364  }
365 
366  if( !m_netlist.IsEmpty() )
367  m_compListBox->SetSelection( 0, true );
368 
369  DisplayStatus();
370 
371  return true;
372 }
373 
374 
375 void CVPCB_MAINFRAME::SaveFootprintAssociation( bool doSaveSchematic )
376 {
377  STRING_FORMATTER sf;
378 
380 
382 
383  if( doSaveSchematic )
384  Kiway().ExpressMail( FRAME_SCH, MAIL_SCH_SAVE, std::string( "" ) );
385 }
bool empty() const
Definition: lib_id.h:190
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
const LIB_ID & GetFPID() const
Definition: pcb_netlist.h:166
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
bool AnyFootprintsLinked() const
Function AnyFootprintsLinked.
void SetFPID(const LIB_ID &aFPID)
Definition: pcb_netlist.h:155
CVPCB->SCH footprint stuffing.
Definition: mail_type.h:40
This file is part of the common library.
COMPONENTS_LISTBOX * m_compListBox
bool IsLegacy() const
Definition: lib_id.h:180
void SetSelection(int index, bool State=true)
void SetNewPkg(const wxString &aFootprintName)
Function SetNewPkg set the footprint name for all selected components in component list and selects t...
int ReadSchematicNetlist(const std::string &aNetlist)
Function ReadSchematicNetlist read the netlist (.net) file built on the fly by Eeschema.
int Parse(const UTF8 &aId)
Parse LIB_ID with the information from aId.
Definition: lib_id.cpp:122
std::string::size_type size() const
Definition: utf8.h:115
bool IsEmpty() const
Function IsEmpty()
Definition: pcb_netlist.h:244
A logical library item identifier and consists of various portions much like a URI.
Definition: lib_id.h:51
bool LoadFootprintFiles()
Function LoadFootprintFiles reads the list of footprint (*.mod files) and generate the list of footpr...
static int guessNickname(FP_LIB_TABLE *aTbl, LIB_ID *aFootprintId)
Return true if the resultant LIB_ID has a certain nickname.
CVPCB->SCH save the schematic.
Definition: mail_type.h:41
void AppendLine(const wxString &text)
This file contains miscellaneous commonly used macros and functions.
VTBL_ENTRY void ExpressMail(FRAME_T aDestination, MAIL_T aCommand, std::string aPayload, wxWindow *aSource=NULL)
Function ExpressMail send aPayload to aDestination from aSource.
Definition: kiway.cpp:386
const wxString & GetReference() const
Definition: pcb_netlist.h:151
#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
const wxString & GetValue() const
Definition: pcb_netlist.h:153
PROJECT & Prj() const
Function Prj returns a reference to the PROJECT "associated with" this KIWAY.
const UTF8 & GetLibItemName() const
Definition: lib_id.h:118
void Add(const wxString &aRef, const wxString &aFpSchName, const wxString &aFpCmpName)
Add a line to the selection list.
void ListSet(const wxString &aList)
Function ListSet Add a list of items.
Subclass of DIALOG_DISPLAY_HTML_TEXT_BASE, which is generated by wxFormBuilder.
const std::string & GetString()
Definition: richio.h:475
void BuildFOOTPRINTS_LISTBOX()
Class HTML_MESSAGE_BOX.
void FormatBackAnnotation(OUTPUTFORMATTER *aOut)
Definition: pcb_netlist.h:355
void MessageSet(const wxString &message)
Function MessageSet adds a message (in bold) to message list.
bool Show(bool show) override
Class COMPONENT is used to store components and all of their related information found in a netlist...
Definition: pcb_netlist.h:83
VTBL_ENTRY FP_LIB_TABLE * PcbFootprintLibs(KIWAY &aKiway)
Return the table of footprint libraries.
int SetLibNickname(const UTF8 &aNickname)
Override the logical library name portion of the LIB_ID to aNickname.
Definition: lib_id.cpp:219
COMPONENT * GetComponent(unsigned aIndex)
Function GetComponent returns the COMPONENT at aIndex.
Definition: pcb_netlist.h:265
#define CMP_FORMAT
Definition: cvpcb.h:30
const LIB_ID & GetAltFPID() const
Definition: pcb_netlist.h:168
virtual const wxString What() const
A composite of Problem() and Where()
Definition: exceptions.cpp:33
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
bool ReadNetListAndFpFiles(const std::string &aNetlist)
Function ReadNetListAndFpFiles loads the netlist file built on the fly by Eeschema and loads footprin...
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
const char * c_str() const
Definition: utf8.h:107
size_t i
Definition: json11.cpp:597
void SetString(unsigned linecount, const wxString &text)
The common library.
UTF8 Format() const
Definition: lib_id.cpp:263
#define DBG(x)
Definition: fctsys.h:33
void FootprintEnumerate(wxArrayString &aFootprintNames, const wxString &aNickname)
Return a list of footprint names contained within the library given by aNickname. ...
const UTF8 & GetLibNickname() const
Return the logical library name portion of a LIB_ID.
Definition: lib_id.h:101
unsigned GetCount() const
Function GetCount.
Definition: pcb_netlist.h:256
Class STRING_FORMATTER implements OUTPUTFORMATTER to a memory buffer.
Definition: richio.h:445
Struct IO_ERROR is a class used to hold an error message and may be used when throwing exceptions con...
Definition: ki_exception.h:47
bool IsOK(wxWindow *aParent, const wxString &aMessage)
Function IsOK displays a yes/no dialog with aMessage and returns the user response.
Definition: confirm.cpp:233
void DisplayStatus()
Function DisplayStatus updates the information displayed on the status bar at bottom of the main fram...
void LoadProjectFile()
Function LoadProjectFile reads the CvPcb configuration parameter from the project (...
Definition: cfg.cpp:59
void SaveFootprintAssociation(bool doSaveSchematic)
Function SaveFootprintAssociation saves the edits that the user has done by sending them back to eesc...
std::vector< wxString > GetLogicalLibs()
Return the logical library names, all of them that are pertinent to a look up done on this LIB_TABLE...