KiCad PCB EDA Suite
backanno.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) 2015 Jean-Pierre Charras, jp.charras at wanadoo.fr
5  * Copyright (C) 2008-2016 Wayne Stambaugh <stambaughw@verizon.net>
6  * Copyright (C) 2004-2016 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 
31 #include <fctsys.h>
32 #include <confirm.h>
33 #include <kicad_string.h>
34 #include <gestfich.h>
35 #include <kiface_i.h>
36 #include <schframe.h>
37 #include <build_version.h>
39 
40 #include <general.h>
41 #include <sch_sheet_path.h>
42 #include <sch_component.h>
43 #include <sch_reference_list.h>
44 
45 #include <dsnlexer.h>
46 #include <ptree.h>
47 #include <boost/property_tree/ptree.hpp>
48 #include <wx/choicdlg.h>
49 
50 
51 void SCH_EDIT_FRAME::backAnnotateFootprints( const std::string& aChangedSetOfReferences )
52  throw( IO_ERROR, boost::bad_pointer )
53 {
54  // Build a flat list of components in schematic:
55  SCH_REFERENCE_LIST refs;
56  SCH_SHEET_LIST sheets( g_RootSheet );
57  bool isChanged = false;
58 
59  sheets.GetComponents( Prj().SchLibs(), refs, false );
60 
61  DSNLEXER lexer( aChangedSetOfReferences, FROM_UTF8( __func__ ) );
62  PTREE doc;
63 
64  try
65  {
66  Scan( &doc, &lexer );
67 
68 #if defined(DEBUG) && 0
70  Format( &sf, 0, 0, doc );
71  printf( "%s: '%s'\n", __func__, sf.GetString().c_str() );
72 #endif
73 
74  CPTREE& back_anno = doc.get_child( "back_annotation" );
75  wxString footprint;
76 
77  for( PTREE::const_iterator ref = back_anno.begin(); ref != back_anno.end(); ++ref )
78  {
79  wxASSERT( ref->first == "ref" );
80 
81  wxString reference = (UTF8&) ref->second.front().first;
82 
83  // Ensure the "fpid" node contains a footprint name,
84  // and get it if exists
85  if( ref->second.get_child( "fpid" ).size() )
86  {
87  wxString tmp = (UTF8&) ref->second.get_child( "fpid" ).front().first;
88  footprint = tmp;
89  }
90  else
91  footprint.Empty();
92 
93  // DBG( printf( "%s: ref:%s fpid:%s\n", __func__, TO_UTF8( reference ), TO_UTF8( footprint ) ); )
94 
95  // Search the component in the flat list
96  for( unsigned ii = 0; ii < refs.GetCount(); ++ii )
97  {
98  if( reference == refs[ii].GetRef() )
99  {
100  // We have found a candidate.
101  // Note: it can be not unique (multiple parts per package)
102  // So we *do not* stop the search here
103  SCH_COMPONENT* component = refs[ii].GetComp();
104  SCH_FIELD* fpfield = component->GetField( FOOTPRINT );
105  const wxString& oldfp = fpfield->GetText();
106 
107  if( !oldfp && fpfield->IsVisible() )
108  {
109  fpfield->SetVisible( false );
110  }
111 
112  // DBG( printf("%s: ref:%s fpid:%s\n", __func__, TO_UTF8( refs[ii].GetRef() ), TO_UTF8( footprint ) );)
113  if( oldfp != footprint )
114  isChanged = true;
115 
116  fpfield->SetText( footprint );
117  }
118  }
119  }
120  }
121  catch( const PTREE_ERROR& ex )
122  {
123  // remap the exception to something the caller is likely to understand.
124  THROW_IO_ERROR( ex.what() );
125  }
126 
127  if( isChanged )
128  OnModify();
129 }
130 
131 
132 bool SCH_EDIT_FRAME::ProcessCmpToFootprintLinkFile( const wxString& aFullFilename,
133  bool aForceVisibilityState,
134  bool aVisibilityState )
135 {
136  // Build a flat list of components in schematic:
137  SCH_REFERENCE_LIST referencesList;
138  SCH_SHEET_LIST sheetList( g_RootSheet );
139 
140  sheetList.GetComponents( Prj().SchLibs(), referencesList, false );
141 
142  FILE* cmpFile = wxFopen( aFullFilename, wxT( "rt" ) );
143 
144  if( cmpFile == NULL )
145  return false;
146 
147  // cmpFileReader dtor will close cmpFile
148  FILE_LINE_READER cmpFileReader( cmpFile, aFullFilename );
149 
150  // Now, for each component found in file,
151  // replace footprint field value by the new value:
152  wxString reference;
153  wxString footprint;
154  wxString buffer;
155  wxString value;
156 
157  while( cmpFileReader.ReadLine() )
158  {
159  buffer = FROM_UTF8( cmpFileReader.Line() );
160 
161  if( !buffer.StartsWith( wxT( "BeginCmp" ) ) )
162  continue;
163 
164  // Begin component description.
165  reference.Empty();
166  footprint.Empty();
167 
168  while( cmpFileReader.ReadLine() )
169  {
170  buffer = FROM_UTF8( cmpFileReader.Line() );
171 
172  if( buffer.StartsWith( wxT( "EndCmp" ) ) )
173  break;
174 
175  // store string value, stored between '=' and ';' delimiters.
176  value = buffer.AfterFirst( '=' );
177  value = value.BeforeLast( ';' );
178  value.Trim(true);
179  value.Trim(false);
180 
181  if( buffer.StartsWith( wxT( "Reference" ) ) )
182  {
183  reference = value;
184  }
185  else if( buffer.StartsWith( wxT( "IdModule" ) ) )
186  {
187  footprint = value;
188  }
189  }
190 
191  // A block is read: initialize the footprint field of the corresponding component
192  // if the footprint name is not empty
193  if( reference.IsEmpty() )
194  continue;
195 
196  // Search the component in the flat list
197  for( unsigned ii = 0; ii < referencesList.GetCount(); ii++ )
198  {
199  if( reference == referencesList[ii].GetRef() )
200  {
201  // We have found a candidate.
202  // Note: it can be not unique (multiple units per part)
203  // So we *do not* stop the search here
204  SCH_COMPONENT* component = referencesList[ii].GetComp();
205  SCH_FIELD* fpfield = component->GetField( FOOTPRINT );
206 
207  fpfield->SetText( footprint );
208 
209  if( aForceVisibilityState )
210  {
211  component->GetField( FOOTPRINT )->SetVisible( aVisibilityState );
212  }
213  }
214  }
215  }
216 
217  return true;
218 }
219 
220 
222 {
223  wxString path = wxPathOnly( Prj().GetProjectFullName() );
224 
225  wxFileDialog dlg( this, _( "Load Component Footprint Link File" ),
226  path, wxEmptyString,
228  wxFD_OPEN | wxFD_FILE_MUST_EXIST );
229 
230  if( dlg.ShowModal() == wxID_CANCEL )
231  return false;
232 
233  wxString filename = dlg.GetPath();
234 
235  wxArrayString choices;
236  choices.Add( _( "Keep existing footprint field visibility" ) );
237  choices.Add( _( "Show all footprint fields" ) );
238  choices.Add( _( "Hide all footprint fields" ) );
239 
240  wxSingleChoiceDialog choiceDlg( this, _( "Select the footprint field visibility setting." ),
241  _( "Change Visibility" ), choices );
242 
243 
244  if( choiceDlg.ShowModal() == wxID_CANCEL )
245  return false;
246 
247  bool forceVisibility = (choiceDlg.GetSelection() != 0 );
248  bool visibilityState = (choiceDlg.GetSelection() == 1 );
249 
250  if( !ProcessCmpToFootprintLinkFile( filename, forceVisibility, visibilityState ) )
251  {
252  wxString msg = wxString::Format( _( "Failed to open component-footprint link file '%s'" ),
253  filename.GetData() );
254 
255  DisplayError( this, msg );
256  return false;
257  }
258 
259  OnModify();
260  return true;
261 }
Class UTF8 is an 8 bit std::string that is assuredly encoded in UTF8, and supplies special conversion...
Definition: utf8.h:53
Class SCH_SHEET_LIST.
Class SCH_FIELD instances are attached to a component and provide a place for the component's value...
Definition: sch_field.h:56
char * ReadLine() override
Function ReadLine reads a line of text into the buffer and increments the line number counter...
Definition: richio.cpp:196
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 LoadCmpToFootprintLinkFile()
Function ReadCmpToFootprintLinkFile Loads a .cmp file from CvPcb and update the footprin field of com...
Definition: backanno.cpp:221
This file is part of the common library TODO brief description.
This file is part of the common library.
void OnModify()
Function OnModify Must be called after a schematic change in order to set the "modify" flag of the cu...
Definition: schframe.cpp:761
void Scan(PTREE *aTree, DSNLEXER *aLexer)
Function Scan fills an empty PTREE with information from a KiCad s-expresion stream.
Definition: ptree.cpp:90
PROJECT & Prj()
Definition: kicad.cpp:293
const PTREE CPTREE
Definition: eagle_plugin.h:63
void SetVisible(bool aVisible)
Definition: eda_text.h:175
const wxString ComponentFileExtensionWildcard
Field Name Module PCB, i.e. "16DIP300".
Class SCH_REFERENCE_LIST is used to create a flattened list of components because in a complex hierar...
PROJECT & Prj() const
Function Prj returns a reference to the PROJECT "associated with" this KIWAY.
Class FILE_LINE_READER is a LINE_READER that reads from an open file.
Definition: richio.h:180
SCH_SHEET * g_RootSheet
Definition: eeschema.cpp:54
SCH_FIELD * GetField(int aFieldNdx) const
Function GetField returns a field.
char * Line() const
Function Line returns a pointer to the last line that was read in.
Definition: richio.h:139
const wxString & GetText() const
Function GetText returns the string associated with the text object.
Definition: eda_text.h:130
The common library.
void backAnnotateFootprints(const std::string &aChangedSetOfReferences)
Definition: backanno.cpp:51
const std::string & GetString()
Definition: richio.h:475
#define THROW_IO_ERROR(x)
Definition: utf8.cpp:60
boost::property_tree::ptree_error PTREE_ERROR
Definition: ptree.h:56
Definition the SCH_COMPONENT class for Eeschema.
boost::property_tree::ptree PTREE
Definition: eagle_plugin.h:62
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
bool IsVisible() const
Definition: eda_text.h:176
Class SCH_COMPONENT describes a real schematic component.
Definition: sch_component.h:68
void GetComponents(PART_LIBS *aLibs, SCH_REFERENCE_LIST &aReferences, bool aIncludePowerSymbols=true)
Function GetComponents adds a SCH_REFERENCE() object to aReferences for each component in the list of...
Definition of the SCH_SHEET_PATH and SCH_SHEET_LIST classes for Eeschema.
unsigned GetCount()
Function GetCount.
Class STRING_FORMATTER implements OUTPUTFORMATTER to a memory buffer.
Definition: richio.h:445
void DisplayError(wxWindow *parent, const wxString &text, int displaytime)
Function DisplayError displays an error or warning message box with aMessage.
Definition: confirm.cpp:69
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
Class DSNLEXER implements a lexical analyzer for the SPECCTRA DSN file format.
Definition: dsnlexer.h:79
virtual void SetText(const wxString &aText)
Definition: eda_text.h:141
bool ProcessCmpToFootprintLinkFile(const wxString &aFullFilename, bool aForceVisibilityState, bool aVisibilityState)
Function ProcessStuffFile gets footprint info from each line in the Stuff File by Ref Desg...
Definition: backanno.cpp:132