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, LIB_ID::ID_PCB ) < 0,
103  wxString::Format( _( "\"%s\" is not a valid LIB_ID." ), aFootprintName ) );
104  }
105 
106  component->SetFPID( fpid );
107 
108  // create the new component description
109  wxString description = wxString::Format( CMP_FORMAT, aIndex + 1,
110  GetChars( component->GetReference() ),
111  GetChars( component->GetValue() ),
112  GetChars( FROM_UTF8( component->GetFPID().Format().c_str() ) ) );
113 
114  // Set the new description and deselect the processed component
115  m_compListBox->SetString( aIndex, description );
116 
117  // Mark this "session" as modified
118  m_modified = true;
119 
120  // update the statusbar
121  DisplayStatus();
122 }
123 
124 
128 static int guessNickname( FP_LIB_TABLE* aTbl, LIB_ID* aFootprintId )
129 {
130  if( aFootprintId->GetLibNickname().size() )
131  return 0;
132 
133  wxString nick;
134  wxString fpname = aFootprintId->GetLibItemName();
135 
136  std::vector<wxString> nicks = aTbl->GetLogicalLibs();
137 
138  // Search each library going through libraries alphabetically.
139  for( unsigned libNdx = 0; libNdx<nicks.size(); ++libNdx )
140  {
141  wxArrayString fpnames;
142 
143  aTbl->FootprintEnumerate( fpnames, nicks[libNdx] );
144 
145  for( unsigned nameNdx = 0; nameNdx<fpnames.size(); ++nameNdx )
146  {
147  if( fpname == fpnames[nameNdx] )
148  {
149  if( !nick )
150  nick = nicks[libNdx];
151  else
152  return 2; // duplicate, the guess would not be certain
153  }
154  }
155  }
156 
157  if( nick.size() )
158  {
159  aFootprintId->SetLibNickname( nick );
160  return 0;
161  }
162 
163  return 1;
164 }
165 
166 
167 bool CVPCB_MAINFRAME::ReadNetListAndFpFiles( const std::string& aNetlist )
168 {
169  wxString msg;
170  bool hasMissingNicks = false;
171 
172  ReadSchematicNetlist( aNetlist );
173 
174  if( m_compListBox == NULL )
175  return false;
176 
177  LoadProjectFile();
178 
179  wxSafeYield();
180 
182 
185 
186  m_compListBox->Clear();
187 
189  {
190  for( unsigned i = 0; i < m_netlist.GetCount(); i++ )
191  {
192  COMPONENT* component = m_netlist.GetComponent( i );
193 
194  if( component->GetFPID().empty() )
195  continue;
196 
197  if( component->GetFPID().IsLegacy() )
198  hasMissingNicks = true;
199  }
200  }
201 
202  // Check if footprint links were generated before the footprint library table was implemented.
203  if( hasMissingNicks )
204  {
205  msg = _(
206  "Some of the assigned footprints are legacy entries (are missing lib nicknames). "
207  "Would you like CvPcb to attempt to convert them to the new required LIB_ID format? "
208  "(If you answer no, then these assignments will be cleared out and you will "
209  "have to re-assign these footprints yourself.)"
210  );
211 
212  if( IsOK( this, msg ) )
213  {
214  msg.Clear();
215 
216  try
217  {
218  for( unsigned i = 0; i < m_netlist.GetCount(); i++ )
219  {
220  COMPONENT* component = m_netlist.GetComponent( i );
221 
222  if( component->GetFPID().IsLegacy() )
223  {
224  // get this first here, it's possibly obsoleted if we get it too soon.
225  FP_LIB_TABLE* tbl = Prj().PcbFootprintLibs( Kiway() );
226 
227  int guess = guessNickname( tbl, (LIB_ID*) &component->GetFPID() );
228 
229  switch( guess )
230  {
231  case 0:
232  DBG(printf("%s: guessed OK ref:%s fpid:%s\n", __func__,
233  TO_UTF8( component->GetReference() ), component->GetFPID().Format().c_str() );)
234  m_modified = true;
235  break;
236 
237  case 1:
238  msg += wxString::Format( _(
239  "Component \"%s\" footprint \"%s\" was <b>not found</b> in any library.\n" ),
240  GetChars( component->GetReference() ),
241  GetChars( component->GetFPID().GetLibItemName() )
242  );
243  break;
244 
245  case 2:
246  msg += wxString::Format( _(
247  "Component \"%s\" footprint \"%s\" was found in <b>multiple</b> libraries.\n" ),
248  GetChars( component->GetReference() ),
249  GetChars( component->GetFPID().GetLibItemName() )
250  );
251  break;
252  }
253  }
254  }
255  }
256  catch( const IO_ERROR& ioe )
257  {
258  msg = ioe.What();
259  msg += wxT( "\n\n" );
260  msg += _( "First check your footprint library table entries." );
261 
262  wxMessageBox( msg, _( "Problematic Footprint Library Tables" ) );
263  return false;
264  }
265 
266  if( msg.size() )
267  {
268  HTML_MESSAGE_BOX dlg( this, wxEmptyString );
269 
270  dlg.MessageSet( _( "The following errors occurred attempting to convert the "
271  "footprint assignments:\n\n" ) );
272  dlg.ListSet( msg );
273  dlg.MessageSet( _( "\nYou will need to reassign them manually if you want them "
274  "to be updated correctly the next time you import the "
275  "netlist in Pcbnew." ) );
276 
277 #if 1
278  dlg.ShowModal();
279 #else
280  dlg.Fit();
281  dlg.Show( true ); // modeless lets user watch while fixing the problems, but its not working.
282 #endif
283  }
284  }
285  else
286  {
287  // Clear the legacy footprint assignments.
288  for( unsigned i = 0; i < m_netlist.GetCount(); i++ )
289  {
290  COMPONENT* component = m_netlist.GetComponent( i );
291 
292  if( component->GetFPID().IsLegacy() )
293  {
294  component->SetFPID( LIB_ID() /* empty */ );
295  m_modified = true;
296  }
297  }
298  }
299  }
300 
301 
302  // Display a dialog to select footprint selection, if the netlist
303  // and the .cmp file give 2 different valid footprints
304  std::vector <int > m_indexes; // indexes of footprints in netlist
305 
306  for( unsigned ii = 0; ii < m_netlist.GetCount(); ii++ )
307  {
308  COMPONENT* component = m_netlist.GetComponent( ii );
309 
310  if( component->GetAltFPID().empty() )
311  continue;
312 
313  if( component->GetFPID().IsLegacy() || component->GetAltFPID().IsLegacy())
314  continue;
315 
316  m_indexes.push_back( ii );
317  }
318 
319  // If a n assignment conflict is found,
320  // open a dialog to chose between schematic assignment
321  // and .cmp file assignment:
322  if( m_indexes.size() > 0 )
323  {
325 
326  for( unsigned ii = 0; ii < m_indexes.size(); ii++ )
327  {
328  COMPONENT* component = m_netlist.GetComponent( m_indexes[ii] );
329 
330  wxString cmpfpid = component->GetFPID().Format();
331  wxString schfpid = component->GetAltFPID().Format();
332 
333  dlg.Add( component->GetReference(), schfpid, cmpfpid );
334  }
335 
336  if( dlg.ShowModal() == wxID_OK )
337  {
338 
339  // Update the fp selection:
340  for( unsigned ii = 0; ii < m_indexes.size(); ii++ )
341  {
342  COMPONENT* component = m_netlist.GetComponent( m_indexes[ii] );
343 
344  int choice = dlg.GetSelection( component->GetReference() );
345 
346  if( choice == 0 ) // the schematic (alt fpid) is chosen:
347  component->SetFPID( component->GetAltFPID() );
348  }
349  }
350  }
351 
352  // Populates the component list box:
353  for( unsigned i = 0; i < m_netlist.GetCount(); i++ )
354  {
355  COMPONENT* component = m_netlist.GetComponent( i );
356 
357  msg.Printf( CMP_FORMAT, m_compListBox->GetCount() + 1,
358  GetChars( component->GetReference() ),
359  GetChars( component->GetValue() ),
360  GetChars( FROM_UTF8( component->GetFPID().Format().c_str() ) ) );
361 
362  m_compListBox->AppendLine( msg );
363  }
364 
365  if( !m_netlist.IsEmpty() )
366  m_compListBox->SetSelection( 0, true );
367 
368  DisplayStatus();
369 
370  return true;
371 }
372 
373 
374 bool CVPCB_MAINFRAME::SaveFootprintAssociation( bool doSaveSchematic )
375 {
376  STRING_FORMATTER sf;
377 
379 
381 
382  if( doSaveSchematic )
383  Kiway().ExpressMail( FRAME_SCH, MAIL_SCH_SAVE, std::string( "" ) );
384 
385  return true; // we can't tell if it was successful, so just assume the best
386 }
bool empty() const
Definition: lib_id.h:186
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:176
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.
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:114
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:193
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:237
#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:97
int Parse(const UTF8 &aId, LIB_ID_TYPE aType, bool aFix=false)
Parse LIB_ID with the information from aId.
Definition: lib_id.cpp:122
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:76
bool IsOK(wxWindow *aParent, const wxString &aMessage)
Function IsOK displays a yes/no dialog with aMessage and returns the user response.
Definition: confirm.cpp:295
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
std::vector< wxString > GetLogicalLibs()
Return the logical library names, all of them that are pertinent to a look up done on this LIB_TABLE...
bool SaveFootprintAssociation(bool doSaveSchematic)
Function SaveFootprintAssociation saves the edits that the user has done by sending them back to eesc...