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) 2015 Jean-Pierre Charras, jean-pierre.charras
9  * Copyright (C) 2011-2016 Wayne Stambaugh <stambaughw@verizon.net>
10  * Copyright (C) 1992-2017 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 <reporter.h>
38 #include <html_messagebox.h>
39 
40 #include <cvpcb.h>
41 #include <cvpcb_mainframe.h>
42 #include <listview_classes.h>
45 
46 
47 void CVPCB_MAINFRAME::SetNewPkg( const wxString& aFootprintName )
48 {
49  COMPONENT* component;
50  bool hasFootprint = false;
51  int componentIndex;
52 
53  if( m_netlist.IsEmpty() )
54  return;
55 
56  // If no component is selected, select the first one
57  if( m_compListBox->GetFirstSelected() < 0 )
58  {
59  componentIndex = 0;
60  m_compListBox->SetSelection( componentIndex, true );
61  }
62 
63  // iterate over the selection
64  while( m_compListBox->GetFirstSelected() != -1 )
65  {
66  // Get the component for the current iteration
67  componentIndex = m_compListBox->GetFirstSelected();
68  component = m_netlist.GetComponent( componentIndex );
69 
70  if( component == NULL )
71  return;
72 
73  // Check to see if the component has already a footprint set.
74  hasFootprint = !component->GetFPID().empty();
75 
76  LIB_ID fpid;
77 
78  if( !aFootprintName.IsEmpty() )
79  {
80  wxCHECK_RET( fpid.Parse( TO_UTF8( aFootprintName ) ) < 0,
81  wxString::Format( wxT( "<%s> is not a valid LIB_ID." ),
82  GetChars( aFootprintName ) ) );
83  }
84 
85  component->SetFPID( fpid );
86 
87  // create the new component description
88  wxString description = wxString::Format( CMP_FORMAT, componentIndex + 1,
89  GetChars( component->GetReference() ),
90  GetChars( component->GetValue() ),
91  GetChars( FROM_UTF8( component->GetFPID().Format().c_str() ) ) );
92 
93  // If the component hasn't had a footprint associated with it
94  // it now has, so we decrement the count of components without
95  // a footprint assigned.
96  if( !hasFootprint )
98 
99  // Set the new description and deselect the processed component
100  m_compListBox->SetString( componentIndex, description );
101  m_compListBox->SetSelection( componentIndex, false );
102  }
103 
104  // Mark this "session" as modified
105  m_modified = true;
106 
107  // select the next component, if there is one
108  if( componentIndex < (m_compListBox->GetCount() - 1) )
109  componentIndex++;
110 
111  m_compListBox->SetSelection( componentIndex, true );
112 
113  // update the statusbar
114  DisplayStatus();
115 }
116 
117 
121 static int guessNickname( FP_LIB_TABLE* aTbl, LIB_ID* aFootprintId )
122 {
123  if( aFootprintId->GetLibNickname().size() )
124  return 0;
125 
126  wxString nick;
127  wxString fpname = FROM_UTF8( aFootprintId->GetLibItemName() );
128 
129  std::vector<wxString> nicks = aTbl->GetLogicalLibs();
130 
131  // Search each library going through libraries alphabetically.
132  for( unsigned libNdx = 0; libNdx<nicks.size(); ++libNdx )
133  {
134  wxArrayString fpnames = aTbl->FootprintEnumerate( nicks[libNdx] );
135 
136  for( unsigned nameNdx = 0; nameNdx<fpnames.size(); ++nameNdx )
137  {
138  if( fpname == fpnames[nameNdx] )
139  {
140  if( !nick )
141  nick = nicks[libNdx];
142  else
143  return 2; // duplicate, the guess would not be certain
144  }
145  }
146  }
147 
148  if( nick.size() )
149  {
150  aFootprintId->SetLibNickname( TO_UTF8( nick ) );
151  return 0;
152  }
153 
154  return 1;
155 }
156 
157 
158 bool CVPCB_MAINFRAME::ReadNetListAndLinkFiles( const std::string& aNetlist )
159 {
160  wxString msg;
161  bool hasMissingNicks = false;
162 
163  ReadSchematicNetlist( aNetlist );
164 
165  if( m_compListBox == NULL )
166  return false;
167 
168  LoadProjectFile();
170 
173 
174  m_compListBox->Clear();
176 
178  {
179  for( unsigned i = 0; i < m_netlist.GetCount(); i++ )
180  {
181  COMPONENT* component = m_netlist.GetComponent( i );
182 
183  if( component->GetFPID().empty() )
184  continue;
185 
186  if( component->GetFPID().IsLegacy() )
187  hasMissingNicks = true;
188  }
189  }
190 
191  // Check if footprint links were generated before the footprint library table was implemented.
192  if( hasMissingNicks )
193  {
194  msg = _(
195  "Some of the assigned footprints are legacy entries (are missing lib nicknames). "
196  "Would you like CvPcb to attempt to convert them to the new required LIB_ID format? "
197  "(If you answer no, then these assignments will be cleared out and you will "
198  "have to re-assign these footprints yourself.)"
199  );
200 
201  if( IsOK( this, msg ) )
202  {
203  msg.Clear();
204 
205  try
206  {
207  for( unsigned i = 0; i < m_netlist.GetCount(); i++ )
208  {
209  COMPONENT* component = m_netlist.GetComponent( i );
210 
211  if( component->GetFPID().IsLegacy() )
212  {
213  // get this first here, it's possibly obsoleted if we get it too soon.
214  FP_LIB_TABLE* tbl = Prj().PcbFootprintLibs( Kiway() );
215 
216  int guess = guessNickname( tbl, (LIB_ID*) &component->GetFPID() );
217 
218  switch( guess )
219  {
220  case 0:
221  DBG(printf("%s: guessed OK ref:%s fpid:%s\n", __func__,
222  TO_UTF8( component->GetReference() ), component->GetFPID().Format().c_str() );)
223  m_modified = true;
224  break;
225 
226  case 1:
227  msg += wxString::Format( _(
228  "Component '%s' footprint '%s' was <b>not found</b> in any library.\n" ),
229  GetChars( component->GetReference() ),
230  GetChars( FROM_UTF8( component->GetFPID().GetLibItemName() ) )
231  );
232  break;
233 
234  case 2:
235  msg += wxString::Format( _(
236  "Component '%s' footprint '%s' was found in <b>multiple</b> libraries.\n" ),
237  GetChars( component->GetReference() ),
238  GetChars( FROM_UTF8( component->GetFPID().GetLibItemName() ) )
239  );
240  break;
241  }
242  }
243  }
244  }
245  catch( const IO_ERROR& ioe )
246  {
247  msg = ioe.What();
248  msg += wxT( "\n\n" );
249  msg += _( "First check your footprint library table entries." );
250 
251  wxMessageBox( msg, _( "Problematic Footprint Library Tables" ) );
252  return false;
253  }
254 
255  if( msg.size() )
256  {
257  HTML_MESSAGE_BOX dlg( this, wxEmptyString );
258 
259  dlg.MessageSet( _( "The following errors occurred attempting to convert the "
260  "footprint assignments:\n\n" ) );
261  dlg.ListSet( msg );
262  dlg.MessageSet( _( "\nYou will need to reassign them manually if you want them "
263  "to be updated correctly the next time you import the "
264  "netlist in Pcbnew." ) );
265 
266 #if 1
267  dlg.ShowModal();
268 #else
269  dlg.Fit();
270  dlg.Show( true ); // modeless lets user watch while fixing the problems, but its not working.
271 #endif
272  }
273  }
274  else
275  {
276  // Clear the legacy footprint assignments.
277  for( unsigned i = 0; i < m_netlist.GetCount(); i++ )
278  {
279  COMPONENT* component = m_netlist.GetComponent( i );
280 
281  if( component->GetFPID().IsLegacy() )
282  {
283  component->SetFPID( LIB_ID() /* empty */ );
284  m_modified = true;
285  }
286  }
287  }
288  }
289 
290 
291  // Display a dialog to select footprint selection, if the netlist
292  // and the .cmp file give 2 different valid footprints
293  std::vector <int > m_indexes; // indexes of footprints in netlist
294 
295  for( unsigned ii = 0; ii < m_netlist.GetCount(); ii++ )
296  {
297  COMPONENT* component = m_netlist.GetComponent( ii );
298 
299  if( component->GetAltFPID().empty() )
300  continue;
301 
302  if( component->GetFPID().IsLegacy() || component->GetAltFPID().IsLegacy())
303  continue;
304 
305  m_indexes.push_back( ii );
306  }
307 
308  // If a n assignment conflict is found,
309  // open a dialog to chose between schematic assignment
310  // and .cmp file assignment:
311  if( m_indexes.size() > 0 )
312  {
314 
315  for( unsigned ii = 0; ii < m_indexes.size(); ii++ )
316  {
317  COMPONENT* component = m_netlist.GetComponent( m_indexes[ii] );
318 
319  wxString cmpfpid = FROM_UTF8( component->GetFPID().Format() );
320  wxString schfpid = FROM_UTF8( component->GetAltFPID().Format() );
321 
322  dlg.Add( component->GetReference(), schfpid, cmpfpid );
323  }
324 
325  if( dlg.ShowModal() == wxID_OK )
326  {
327 
328  // Update the fp selection:
329  for( unsigned ii = 0; ii < m_indexes.size(); ii++ )
330  {
331  COMPONENT* component = m_netlist.GetComponent( m_indexes[ii] );
332 
333  int choice = dlg.GetSelection( component->GetReference() );
334 
335  if( choice == 0 ) // the schematic (alt fpid) is chosen:
336  component->SetFPID( component->GetAltFPID() );
337  }
338  }
339  }
340 
341  // Populates the component list box:
342  for( unsigned i = 0; i < m_netlist.GetCount(); i++ )
343  {
344  COMPONENT* component = m_netlist.GetComponent( i );
345 
346  msg.Printf( CMP_FORMAT, m_compListBox->GetCount() + 1,
347  GetChars( component->GetReference() ),
348  GetChars( component->GetValue() ),
349  GetChars( FROM_UTF8( component->GetFPID().Format().c_str() ) ) );
350 
351  m_compListBox->AppendLine( msg );
352 
353  if( component->GetFPID().empty() )
354  {
356  continue;
357  }
358  }
359 
360  if( !m_netlist.IsEmpty() )
361  m_compListBox->SetSelection( 0, true );
362 
363  DisplayStatus();
364 
365  UpdateTitle();
366  return true;
367 }
368 
369 
371 {
372  STRING_FORMATTER sf;
373 
375 
377 
378  SetStatusText( _("Footprint association sent to Eeschema") );
379 }
bool empty() const
Function empty.
Definition: lib_id.h:199
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:164
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:153
CVPCB->SCH footprint stuffing at cvpcb termination.
Definition: mail_type.h:40
This file is part of the common library.
COMPONENTS_LISTBOX * m_compListBox
wxArrayString FootprintEnumerate(const wxString &aNickname)
Function FootprintEnumerate returns a list of footprint names contained within the library given by a...
bool IsLegacy() const
Function IsLegacy.
Definition: lib_id.h:185
void SetSelection(int index, bool State=true)
void SetNewPkg(const wxString &aFootprintName)
Function SetNewPkg links the footprint to the current selected component and selects the next compone...
void UpdateTitle()
Function UpdateTitle sets the main window title bar text.
int ReadSchematicNetlist(const std::string &aNetlist)
int Parse(const UTF8 &aId)
Function Parse.
Definition: lib_id.cpp:122
bool IsEmpty() const
Function IsEmpty()
Definition: pcb_netlist.h:235
Class LIB_ID.
Definition: lib_id.h:56
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.
void AppendLine(const wxString &text)
This file contains miscellaneous commonly used macros and functions.
const wxString & GetReference() const
Definition: pcb_netlist.h:149
const wxString & GetValue() 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
PROJECT & Prj() const
Function Prj returns a reference to the PROJECT "associated with" this KIWAY.
bool ReadNetListAndLinkFiles(const std::string &aNetlist)
Function ReadNetList reads the netlist (.net) file defined by #m_NetlistFileName. ...
const UTF8 & GetLibItemName() const
Function GetLibItemName.
Definition: lib_id.h:129
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.
The common library.
const std::string & GetString()
Definition: richio.h:475
void BuildFOOTPRINTS_LISTBOX()
Class HTML_MESSAGE_BOX.
void FormatBackAnnotation(OUTPUTFORMATTER *aOut)
Definition: pcb_netlist.h:346
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)
Function SetLibNickname.
Definition: lib_id.cpp:219
COMPONENT * GetComponent(unsigned aIndex)
Function GetComponent returns the COMPONENT at aIndex.
Definition: pcb_netlist.h:256
#define CMP_FORMAT
Definition: cvpcb.h:32
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
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
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
VTBL_ENTRY void ExpressMail(FRAME_T aDestination, MAIL_T aCommand, const std::string &aPayload, wxWindow *aSource=NULL)
Function ExpressMail send aPayload to aDestination from aSource.
Definition: kiway.cpp:387
void SetString(unsigned linecount, const wxString &text)
The common library.
UTF8 Format() const
Function Format.
Definition: lib_id.cpp:263
#define DBG(x)
Definition: fctsys.h:33
const UTF8 & GetLibNickname() const
Function GetLibNickname.
Definition: lib_id.h:108
void SaveFootprintAssociation()
Function SaveFootprintAssociation saves the edits that the user has done by sending them back to eesc...
unsigned GetCount() const
Function GetCount.
Definition: pcb_netlist.h:247
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:111
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()
Function GetLogicalLibs.