KiCad PCB EDA Suite
readwrite_dlgs.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) 2018 Jean-Pierre Charras, jean-pierre.charras
5  * Copyright (C) 2011-2016 Wayne Stambaugh <stambaughw@verizon.net>
6  * Copyright (C) 1992-2018 KiCad Developers, see AUTHORS.txt for contributors.
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License
10  * as published by the Free Software Foundation; either version 2
11  * of the License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, you may find one here:
20  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
21  * or you may search the http://www.gnu.org website for the version 2 license,
22  * or you may write to the Free Software Foundation, Inc.,
23  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
24  */
25 
26 #include <confirm.h>
27 #include <fctsys.h>
28 #include <fp_lib_table.h>
29 #include <html_messagebox.h>
30 #include <kiway.h>
31 #include <lib_id.h>
32 #include <macros.h>
33 
34 #include <cvpcb_mainframe.h>
35 #include <listboxes.h>
37 
38 
42 static int guessNickname( FP_LIB_TABLE* aTbl, LIB_ID* aFootprintId )
43 {
44  if( aFootprintId->GetLibNickname().size() )
45  return 0;
46 
47  wxString nick;
48  wxString fpname = aFootprintId->GetLibItemName();
49 
50  std::vector<wxString> nicks = aTbl->GetLogicalLibs();
51 
52  // Search each library going through libraries alphabetically.
53  for( unsigned libNdx = 0; libNdx<nicks.size(); ++libNdx )
54  {
55  wxArrayString fpnames;
56 
57  aTbl->FootprintEnumerate( fpnames, nicks[libNdx], true );
58 
59  for( unsigned nameNdx = 0; nameNdx<fpnames.size(); ++nameNdx )
60  {
61  if( fpname == fpnames[nameNdx] )
62  {
63  if( !nick )
64  nick = nicks[libNdx];
65  else
66  return 2; // duplicate, the guess would not be certain
67  }
68  }
69  }
70 
71  if( nick.size() )
72  {
73  aFootprintId->SetLibNickname( nick );
74  return 0;
75  }
76 
77  return 1;
78 }
79 
80 
81 bool CVPCB_MAINFRAME::ReadNetListAndFpFiles( const std::string& aNetlist )
82 {
83  wxString msg;
84  bool hasMissingNicks = false;
85 
86  ReadSchematicNetlist( aNetlist );
87 
88  if( m_compListBox == NULL )
89  return false;
90 
91  wxSafeYield();
92 
94 
97 
99 
101  {
102  for( unsigned i = 0; i < m_netlist.GetCount(); i++ )
103  {
104  COMPONENT* component = m_netlist.GetComponent( i );
105 
106  if( component->GetFPID().empty() )
107  continue;
108 
109  if( component->GetFPID().IsLegacy() )
110  hasMissingNicks = true;
111  }
112  }
113 
114  // Check if footprint links were generated before the footprint library table was implemented.
115  if( hasMissingNicks )
116  {
117  msg = _(
118  "Some of the assigned footprints are legacy entries (are missing lib nicknames). "
119  "Would you like CvPcb to attempt to convert them to the new required LIB_ID format? "
120  "(If you answer no, then these assignments will be cleared out and you will "
121  "have to re-assign these footprints yourself.)"
122  );
123 
124  if( IsOK( this, msg ) )
125  {
126  msg.Clear();
127 
128  try
129  {
130  for( unsigned i = 0; i < m_netlist.GetCount(); i++ )
131  {
132  COMPONENT* component = m_netlist.GetComponent( i );
133 
134  if( component->GetFPID().IsLegacy() )
135  {
136  // get this first here, it's possibly obsoleted if we get it too soon.
137  FP_LIB_TABLE* tbl = Prj().PcbFootprintLibs( Kiway() );
138 
139  int guess = guessNickname( tbl, (LIB_ID*) &component->GetFPID() );
140 
141  switch( guess )
142  {
143  case 0:
144  DBG(printf("%s: guessed OK ref:%s fpid:%s\n", __func__,
145  TO_UTF8( component->GetReference() ), component->GetFPID().Format().c_str() );)
146  m_modified = true;
147  break;
148 
149  case 1:
150  msg += wxString::Format( _(
151  "Component \"%s\" footprint \"%s\" was <b>not found</b> in any library.\n" ),
152  GetChars( component->GetReference() ),
153  GetChars( component->GetFPID().GetLibItemName() )
154  );
155  break;
156 
157  case 2:
158  msg += wxString::Format( _(
159  "Component \"%s\" footprint \"%s\" was found in <b>multiple</b> libraries.\n" ),
160  GetChars( component->GetReference() ),
161  GetChars( component->GetFPID().GetLibItemName() )
162  );
163  break;
164  }
165  }
166  }
167  }
168  catch( const IO_ERROR& ioe )
169  {
170  msg = ioe.What();
171  msg += wxT( "\n\n" );
172  msg += _( "First check your footprint library table entries." );
173 
174  wxMessageBox( msg, _( "Problematic Footprint Library Tables" ) );
175  return false;
176  }
177 
178  if( msg.size() )
179  {
180  HTML_MESSAGE_BOX dlg( this, wxEmptyString );
181 
182  dlg.MessageSet( _( "The following errors occurred attempting to convert the "
183  "footprint assignments:\n\n" ) );
184  dlg.ListSet( msg );
185  dlg.MessageSet( _( "\nYou will need to reassign them manually if you want them "
186  "to be updated correctly the next time you import the "
187  "netlist in Pcbnew." ) );
188 
189 #if 1
190  dlg.ShowModal();
191 #else
192  dlg.Fit();
193  dlg.Show( true ); // modeless lets user watch while fixing the problems, but its not working.
194 #endif
195  }
196  }
197  else
198  {
199  // Clear the legacy footprint assignments.
200  for( unsigned i = 0; i < m_netlist.GetCount(); i++ )
201  {
202  COMPONENT* component = m_netlist.GetComponent( i );
203 
204  if( component->GetFPID().IsLegacy() )
205  {
206  component->SetFPID( LIB_ID() /* empty */ );
207  m_modified = true;
208  }
209  }
210  }
211  }
212 
213 
214  // Display a dialog to select footprint selection, if the netlist
215  // and the .cmp file give 2 different valid footprints
216  std::vector <int > m_indexes; // indexes of footprints in netlist
217 
218  for( unsigned ii = 0; ii < m_netlist.GetCount(); ii++ )
219  {
220  COMPONENT* component = m_netlist.GetComponent( ii );
221 
222  if( component->GetAltFPID().empty() )
223  continue;
224 
225  if( component->GetFPID().IsLegacy() || component->GetAltFPID().IsLegacy())
226  continue;
227 
228  m_indexes.push_back( ii );
229  }
230 
231  // If a n assignment conflict is found,
232  // open a dialog to chose between schematic assignment
233  // and .cmp file assignment:
234  if( m_indexes.size() > 0 )
235  {
237 
238  for( unsigned ii = 0; ii < m_indexes.size(); ii++ )
239  {
240  COMPONENT* component = m_netlist.GetComponent( m_indexes[ii] );
241 
242  wxString cmpfpid = component->GetFPID().Format();
243  wxString schfpid = component->GetAltFPID().Format();
244 
245  dlg.Add( component->GetReference(), schfpid, cmpfpid );
246  }
247 
248  if( dlg.ShowModal() == wxID_OK )
249  {
250 
251  // Update the fp selection:
252  for( unsigned ii = 0; ii < m_indexes.size(); ii++ )
253  {
254  COMPONENT* component = m_netlist.GetComponent( m_indexes[ii] );
255 
256  int choice = dlg.GetSelection( component->GetReference() );
257 
258  if( choice == 0 ) // the schematic (alt fpid) is chosen:
259  component->SetFPID( component->GetAltFPID() );
260  }
261  }
262  }
263 
264  // Populates the component list box:
265  for( unsigned i = 0; i < m_netlist.GetCount(); i++ )
266  {
267  COMPONENT* component = m_netlist.GetComponent( i );
268 
269  msg.Printf( CMP_FORMAT, m_compListBox->GetCount() + 1,
270  GetChars( component->GetReference() ),
271  GetChars( component->GetValue() ),
272  GetChars( FROM_UTF8( component->GetFPID().Format().c_str() ) ) );
273 
274  m_compListBox->AppendLine( msg );
275  }
276 
277  if( !m_netlist.IsEmpty() )
278  m_compListBox->SetSelection( 0, true );
279 
280  DisplayStatus();
281 
282  return true;
283 }
284 
285 
286 bool CVPCB_MAINFRAME::SaveFootprintAssociation( bool doSaveSchematic )
287 {
288  std::string payload;
289  STRING_FORMATTER sf;
290 
292 
293  payload = sf.GetString();
295 
296  if( doSaveSchematic )
297  {
298  payload = "";
299  Kiway().ExpressMail( FRAME_SCH, MAIL_SCH_SAVE, payload );
300 
301  if( payload == "success" )
302  SetStatusText( _( "Schematic saved" ), 1 );
303  }
304 
305  // Changes are saved, so reset the flag
306  m_modified = false;
307 
308  return true;
309 }
const UTF8 & GetLibItemName() const
Definition: lib_id.h:114
KIWAY & Kiway() const
Function Kiway returns a reference to the KIWAY that this object has an opportunity to participate in...
Definition: kiway_holder.h:56
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:114
#define CMP_FORMAT
The print format to display a schematic component line.
void SetFPID(const LIB_ID &aFPID)
Definition: pcb_netlist.h:153
CVPCB->SCH footprint stuffing.
Definition: mail_type.h:40
This file is part of the common library.
bool AnyFootprintsLinked() const
Function AnyFootprintsLinked.
COMPONENTS_LISTBOX * m_compListBox
void SetSelection(int index, bool State=true)
int ReadSchematicNetlist(const std::string &aNetlist)
Function ReadSchematicNetlist read the netlist (.net) file built on the fly by Eeschema.
unsigned GetCount() const
Function GetCount.
Definition: pcb_netlist.h:254
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
bool empty() const
Definition: lib_id.h:186
void AppendLine(const wxString &text)
This file contains miscellaneous commonly used macros and functions.
const char * c_str() const
Definition: utf8.h:107
const LIB_ID & GetFPID() const
Definition: pcb_netlist.h:164
void FootprintEnumerate(wxArrayString &aFootprintNames, const wxString &aNickname, bool aBestEfforts)
Return a list of footprint names contained within the library given by aNickname.
#define NULL
const LIB_ID & GetAltFPID() const
Definition: pcb_netlist.h:166
virtual const wxString What() const
A composite of Problem() and Where()
Definition: exceptions.cpp:33
PROJECT & Prj() const
Function Prj returns a reference to the PROJECT "associated with" this KIWAY.
void Add(const wxString &aRef, const wxString &aFpSchName, const wxString &aFpCmpName)
Add a line to the selection list.
void ListSet(const wxString &aList)
Add a list of items.
Subclass of DIALOG_DISPLAY_HTML_TEXT_BASE, which is generated by wxFormBuilder.
const wxString & GetReference() const
Definition: pcb_netlist.h:149
void SetStatusText(const wxString &aText, int aNumber=0) override
const UTF8 & GetLibNickname() const
Return the logical library name portion of a LIB_ID.
Definition: lib_id.h:97
const std::string & GetString()
Definition: richio.h:475
void BuildFOOTPRINTS_LISTBOX()
HTML_MESSAGE_BOX.
void FormatBackAnnotation(OUTPUTFORMATTER *aOut)
Definition: pcb_netlist.h:353
void MessageSet(const wxString &message)
Add a message (in bold) to message list.
UTF8 Format() const
Definition: lib_id.cpp:237
bool Show(bool show) override
COMPONENT is used to store components and all of their related information found in a netlist.
Definition: pcb_netlist.h:80
VTBL_ENTRY FP_LIB_TABLE * PcbFootprintLibs(KIWAY &aKiway)
Return the table of footprint libraries.
Definition: project.cpp:284
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:263
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:428
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:153
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
#define _(s)
Definition: 3d_actions.cpp:33
#define TO_UTF8(wxstring)
bool IsEmpty() const
Function IsEmpty()
Definition: pcb_netlist.h:242
const wxString & GetValue() const
Definition: pcb_netlist.h:151
#define DBG(x)
Definition: fctsys.h:33
bool IsLegacy() const
Definition: lib_id.h:176
std::string::size_type size() const
Definition: utf8.h:115
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)
Display a yes/no dialog with aMessage and returns the user response.
Definition: confirm.cpp:283
void DisplayStatus()
Function DisplayStatus updates the information displayed on the status bar at bottom of the main fram...
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...