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