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] );
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 
92 
93  wxSafeYield();
94 
96 
99 
100  m_compListBox->Clear();
101 
103  {
104  for( unsigned i = 0; i < m_netlist.GetCount(); i++ )
105  {
106  COMPONENT* component = m_netlist.GetComponent( i );
107 
108  if( component->GetFPID().empty() )
109  continue;
110 
111  if( component->GetFPID().IsLegacy() )
112  hasMissingNicks = true;
113  }
114  }
115 
116  // Check if footprint links were generated before the footprint library table was implemented.
117  if( hasMissingNicks )
118  {
119  msg = _(
120  "Some of the assigned footprints are legacy entries (are missing lib nicknames). "
121  "Would you like CvPcb to attempt to convert them to the new required LIB_ID format? "
122  "(If you answer no, then these assignments will be cleared out and you will "
123  "have to re-assign these footprints yourself.)"
124  );
125 
126  if( IsOK( this, msg ) )
127  {
128  msg.Clear();
129 
130  try
131  {
132  for( unsigned i = 0; i < m_netlist.GetCount(); i++ )
133  {
134  COMPONENT* component = m_netlist.GetComponent( i );
135 
136  if( component->GetFPID().IsLegacy() )
137  {
138  // get this first here, it's possibly obsoleted if we get it too soon.
139  FP_LIB_TABLE* tbl = Prj().PcbFootprintLibs( Kiway() );
140 
141  int guess = guessNickname( tbl, (LIB_ID*) &component->GetFPID() );
142 
143  switch( guess )
144  {
145  case 0:
146  DBG(printf("%s: guessed OK ref:%s fpid:%s\n", __func__,
147  TO_UTF8( component->GetReference() ), component->GetFPID().Format().c_str() );)
148  m_modified = true;
149  break;
150 
151  case 1:
152  msg += wxString::Format( _(
153  "Component \"%s\" footprint \"%s\" was <b>not found</b> in any library.\n" ),
154  GetChars( component->GetReference() ),
155  GetChars( component->GetFPID().GetLibItemName() )
156  );
157  break;
158 
159  case 2:
160  msg += wxString::Format( _(
161  "Component \"%s\" footprint \"%s\" was found in <b>multiple</b> libraries.\n" ),
162  GetChars( component->GetReference() ),
163  GetChars( component->GetFPID().GetLibItemName() )
164  );
165  break;
166  }
167  }
168  }
169  }
170  catch( const IO_ERROR& ioe )
171  {
172  msg = ioe.What();
173  msg += wxT( "\n\n" );
174  msg += _( "First check your footprint library table entries." );
175 
176  wxMessageBox( msg, _( "Problematic Footprint Library Tables" ) );
177  return false;
178  }
179 
180  if( msg.size() )
181  {
182  HTML_MESSAGE_BOX dlg( this, wxEmptyString );
183 
184  dlg.MessageSet( _( "The following errors occurred attempting to convert the "
185  "footprint assignments:\n\n" ) );
186  dlg.ListSet( msg );
187  dlg.MessageSet( _( "\nYou will need to reassign them manually if you want them "
188  "to be updated correctly the next time you import the "
189  "netlist in Pcbnew." ) );
190 
191 #if 1
192  dlg.ShowModal();
193 #else
194  dlg.Fit();
195  dlg.Show( true ); // modeless lets user watch while fixing the problems, but its not working.
196 #endif
197  }
198  }
199  else
200  {
201  // Clear the legacy footprint assignments.
202  for( unsigned i = 0; i < m_netlist.GetCount(); i++ )
203  {
204  COMPONENT* component = m_netlist.GetComponent( i );
205 
206  if( component->GetFPID().IsLegacy() )
207  {
208  component->SetFPID( LIB_ID() /* empty */ );
209  m_modified = true;
210  }
211  }
212  }
213  }
214 
215 
216  // Display a dialog to select footprint selection, if the netlist
217  // and the .cmp file give 2 different valid footprints
218  std::vector <int > m_indexes; // indexes of footprints in netlist
219 
220  for( unsigned ii = 0; ii < m_netlist.GetCount(); ii++ )
221  {
222  COMPONENT* component = m_netlist.GetComponent( ii );
223 
224  if( component->GetAltFPID().empty() )
225  continue;
226 
227  if( component->GetFPID().IsLegacy() || component->GetAltFPID().IsLegacy())
228  continue;
229 
230  m_indexes.push_back( ii );
231  }
232 
233  // If a n assignment conflict is found,
234  // open a dialog to chose between schematic assignment
235  // and .cmp file assignment:
236  if( m_indexes.size() > 0 )
237  {
239 
240  for( unsigned ii = 0; ii < m_indexes.size(); ii++ )
241  {
242  COMPONENT* component = m_netlist.GetComponent( m_indexes[ii] );
243 
244  wxString cmpfpid = component->GetFPID().Format();
245  wxString schfpid = component->GetAltFPID().Format();
246 
247  dlg.Add( component->GetReference(), schfpid, cmpfpid );
248  }
249 
250  if( dlg.ShowModal() == wxID_OK )
251  {
252 
253  // Update the fp selection:
254  for( unsigned ii = 0; ii < m_indexes.size(); ii++ )
255  {
256  COMPONENT* component = m_netlist.GetComponent( m_indexes[ii] );
257 
258  int choice = dlg.GetSelection( component->GetReference() );
259 
260  if( choice == 0 ) // the schematic (alt fpid) is chosen:
261  component->SetFPID( component->GetAltFPID() );
262  }
263  }
264  }
265 
266  // Populates the component list box:
267  for( unsigned i = 0; i < m_netlist.GetCount(); i++ )
268  {
269  COMPONENT* component = m_netlist.GetComponent( i );
270 
271  msg.Printf( CMP_FORMAT, m_compListBox->GetCount() + 1,
272  GetChars( component->GetReference() ),
273  GetChars( component->GetValue() ),
274  GetChars( FROM_UTF8( component->GetFPID().Format().c_str() ) ) );
275 
276  m_compListBox->AppendLine( msg );
277  }
278 
279  if( !m_netlist.IsEmpty() )
280  m_compListBox->SetSelection( 0, true );
281 
282  DisplayStatus();
283 
284  return true;
285 }
286 
287 
288 bool CVPCB_MAINFRAME::SaveFootprintAssociation( bool doSaveSchematic )
289 {
290  std::string payload;
291  STRING_FORMATTER sf;
292 
294 
295  payload = sf.GetString();
297 
298  if( doSaveSchematic )
299  {
300  payload = "";
301  Kiway().ExpressMail( FRAME_SCH, MAIL_SCH_SAVE, payload );
302 
303  if( payload == "success" )
304  SetStatusText( _( "Schematic saved" ), 1 );
305  }
306 
307  // Changes are saved, so reset the flag
308  m_modified = false;
309 
310  return true;
311 }
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:62
#define CMP_FORMAT
The print format to display a schematic component line.
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.
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:256
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:166
#define TO_UTF8(wxstring)
Macro TO_UTF8 converts a wxString to a UTF8 encoded C string for all wxWidgets build modes.
Definition: macros.h:48
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
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)
Function ListSet 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:151
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()
Class HTML_MESSAGE_BOX.
#define _(s)
void FormatBackAnnotation(OUTPUTFORMATTER *aOut)
Definition: pcb_netlist.h:355
void MessageSet(const wxString &message)
Function MessageSet adds a message (in bold) to message list.
UTF8 Format() const
Definition: lib_id.cpp:237
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
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:407
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:101
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
size_t i
Definition: json11.cpp:597
bool IsEmpty() const
Function IsEmpty()
Definition: pcb_netlist.h:244
const wxString & GetValue() const
Definition: pcb_netlist.h:153
#define DBG(x)
Definition: fctsys.h:33
bool IsLegacy() const
Definition: lib_id.h:176
void FootprintEnumerate(wxArrayString &aFootprintNames, const wxString &aNickname)
Return a list of footprint names contained within the library given by aNickname.
std::string::size_type size() const
Definition: utf8.h:115
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)
Display a yes/no dialog with aMessage and returns the user response.
Definition: confirm.cpp:294
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:50
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...