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-2020 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  m_modified = true;
145  break;
146 
147  case 1:
148  msg += wxString::Format( _(
149  "Component \"%s\" footprint \"%s\" was <b>not found</b> in any library.\n" ),
150  GetChars( component->GetReference() ),
151  GetChars( component->GetFPID().GetLibItemName() )
152  );
153  break;
154 
155  case 2:
156  msg += wxString::Format( _(
157  "Component \"%s\" footprint \"%s\" was found in <b>multiple</b> libraries.\n" ),
158  GetChars( component->GetReference() ),
159  GetChars( component->GetFPID().GetLibItemName() )
160  );
161  break;
162  }
163  }
164  }
165  }
166  catch( const IO_ERROR& ioe )
167  {
168  msg = ioe.What();
169  msg += wxT( "\n\n" );
170  msg += _( "First check your footprint library table entries." );
171 
172  wxMessageBox( msg, _( "Problematic Footprint Library Tables" ) );
173  return false;
174  }
175 
176  if( msg.size() )
177  {
178  HTML_MESSAGE_BOX dlg( this, wxEmptyString );
179 
180  dlg.MessageSet( _( "The following errors occurred attempting to convert the "
181  "footprint assignments:\n\n" ) );
182  dlg.ListSet( msg );
183  dlg.MessageSet( _( "\nYou will need to reassign them manually if you want them "
184  "to be updated correctly the next time you import the "
185  "netlist in Pcbnew." ) );
186 
187 #if 1
188  dlg.ShowModal();
189 #else
190  dlg.Fit();
191  dlg.Show( true ); // modeless lets user watch while fixing the problems, but its not working.
192 #endif
193  }
194  }
195  else
196  {
197  // Clear the legacy footprint assignments.
198  for( unsigned i = 0; i < m_netlist.GetCount(); i++ )
199  {
200  COMPONENT* component = m_netlist.GetComponent( i );
201 
202  if( component->GetFPID().IsLegacy() )
203  {
204  component->SetFPID( LIB_ID() /* empty */ );
205  m_modified = true;
206  }
207  }
208  }
209  }
210 
211 
212  // Display a dialog to select footprint selection, if the netlist
213  // and the .cmp file give 2 different valid footprints
214  std::vector <int > m_indexes; // indexes of footprints in netlist
215 
216  for( unsigned ii = 0; ii < m_netlist.GetCount(); ii++ )
217  {
218  COMPONENT* component = m_netlist.GetComponent( ii );
219 
220  if( component->GetAltFPID().empty() )
221  continue;
222 
223  if( component->GetFPID().IsLegacy() || component->GetAltFPID().IsLegacy())
224  continue;
225 
226  m_indexes.push_back( ii );
227  }
228 
229  // If a n assignment conflict is found,
230  // open a dialog to chose between schematic assignment
231  // and .cmp file assignment:
232  if( m_indexes.size() > 0 )
233  {
235 
236  for( unsigned ii = 0; ii < m_indexes.size(); ii++ )
237  {
238  COMPONENT* component = m_netlist.GetComponent( m_indexes[ii] );
239 
240  wxString cmpfpid = component->GetFPID().Format();
241  wxString schfpid = component->GetAltFPID().Format();
242 
243  dlg.Add( component->GetReference(), schfpid, cmpfpid );
244  }
245 
246  if( dlg.ShowModal() == wxID_OK )
247  {
248 
249  // Update the fp selection:
250  for( unsigned ii = 0; ii < m_indexes.size(); ii++ )
251  {
252  COMPONENT* component = m_netlist.GetComponent( m_indexes[ii] );
253 
254  int choice = dlg.GetSelection( component->GetReference() );
255 
256  if( choice == 0 ) // the schematic (alt fpid) is chosen:
257  component->SetFPID( component->GetAltFPID() );
258  }
259  }
260  }
261 
262  // Populates the component list box:
263  for( unsigned i = 0; i < m_netlist.GetCount(); i++ )
264  {
265  COMPONENT* component = m_netlist.GetComponent( i );
266 
267  msg.Printf( CMP_FORMAT, m_compListBox->GetCount() + 1,
268  GetChars( component->GetReference() ),
269  GetChars( component->GetValue() ),
270  GetChars( FROM_UTF8( component->GetFPID().Format().c_str() ) ) );
271 
272  m_compListBox->AppendLine( msg );
273  }
274 
275  if( !m_netlist.IsEmpty() )
276  m_compListBox->SetSelection( 0, true );
277 
278  DisplayStatus();
279 
280  return true;
281 }
282 
283 
284 bool CVPCB_MAINFRAME::SaveFootprintAssociation( bool doSaveSchematic )
285 {
286  std::string payload;
287  STRING_FORMATTER sf;
288 
290 
291  payload = sf.GetString();
293 
294  if( doSaveSchematic )
295  {
296  payload = "";
297  Kiway().ExpressMail( FRAME_SCH, MAIL_SCH_SAVE, payload );
298 
299  if( payload == "success" )
300  SetStatusText( _( "Schematic saved" ), 1 );
301  }
302 
303  // Changes are saved, so reset the flag
304  m_modified = false;
305 
306  return true;
307 }
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:156
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:224
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.
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:157
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:160
virtual const wxString What() const
A composite of Problem() and Where()
Definition: exceptions.cpp:29
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.
const wxString & GetReference() const
Definition: pcb_netlist.h:147
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:287
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:286
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:233
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:437
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:201
#define _(s)
Definition: 3d_actions.cpp:33
bool IsEmpty() const
Function IsEmpty()
Definition: pcb_netlist.h:212
const wxString & GetValue() const
Definition: pcb_netlist.h:148
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...