KiCad PCB EDA Suite
assign_footprints.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-2021 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 <kicad_string.h>
28 #include <kiface_i.h>
29 #include <sch_edit_frame.h>
31 #include <sch_sheet_path.h>
32 #include <sch_symbol.h>
33 #include <sch_reference_list.h>
34 #include <schematic.h>
35 #include <dsnlexer.h>
36 #include <ptree.h>
37 #include <boost/property_tree/ptree.hpp>
39 
40 #include <wx/choicdlg.h>
41 #include <wx/filedlg.h>
42 
43 
44 void SCH_EDITOR_CONTROL::AssignFootprints( const std::string& aChangedSetOfReferences )
45 {
46  // Build a flat list of components in schematic:
47  SCH_REFERENCE_LIST refs;
49  bool isChanged = false;
50 
51  sheets.GetSymbols( refs, false );
52 
53  DSNLEXER lexer( aChangedSetOfReferences, FROM_UTF8( __func__ ) );
54  PTREE doc;
55 
56  try
57  {
58  Scan( &doc, &lexer );
59 
60  CPTREE& back_anno = doc.get_child( "cvpcb_netlist" );
61  wxString footprint;
62 
63  for( PTREE::const_iterator ref = back_anno.begin(); ref != back_anno.end(); ++ref )
64  {
65  wxASSERT( ref->first == "ref" );
66 
67  wxString reference = (UTF8&) ref->second.front().first;
68 
69  // Ensure the "fpid" node contains a footprint name, and get it if exists
70  if( ref->second.get_child( "fpid" ).size() )
71  {
72  wxString tmp = (UTF8&) ref->second.get_child( "fpid" ).front().first;
73  footprint = tmp;
74  }
75  else
76  footprint.Empty();
77 
78  // Search the component in the flat list
79  for( unsigned ii = 0; ii < refs.GetCount(); ++ii )
80  {
81  if( reference == refs[ii].GetRef() )
82  {
83  // We have found a candidate.
84  // Note: it can be not unique (multiple parts per package)
85  // So we *do not* stop the search here
86  SCH_COMPONENT* component = refs[ ii ].GetSymbol();
87  // For backwards-compatibility CvPcb currently updates all instances of a
88  // component (even though it lists these instances separately).
89  SCH_SHEET_PATH* sheetPath = nullptr; // &refs[ii].GetSheetPath();
90  wxString oldfp = refs[ii].GetFootprint();
91 
92  if( oldfp.IsEmpty() && component->GetField( FOOTPRINT_FIELD )->IsVisible() )
93  component->GetField( FOOTPRINT_FIELD )->SetVisible( false );
94 
95  if( oldfp != footprint )
96  {
97  isChanged = true;
98  component->SetFootprint( sheetPath, footprint );
99  }
100  }
101  }
102  }
103  }
104  catch( const PTREE_ERROR& ex )
105  {
106  // remap the exception to something the caller is likely to understand.
107  THROW_IO_ERROR( ex.what() );
108  }
109 
110  if( isChanged )
111  {
112  m_frame->SyncView();
113  m_frame->GetCanvas()->Refresh();
114  m_frame->OnModify();
115  }
116 }
117 
118 
119 bool SCH_EDITOR_CONTROL::processCmpToFootprintLinkFile( const wxString& aFullFilename,
120  bool aForceVisibilityState,
121  bool aVisibilityState )
122 {
123  // Build a flat list of components in schematic:
124  SCH_REFERENCE_LIST referencesList;
125  SCH_SHEET_LIST sheetList = m_frame->Schematic().GetSheets();
126 
127  sheetList.GetSymbols( referencesList, false );
128 
129  FILE* cmpFile = wxFopen( aFullFilename, wxT( "rt" ) );
130 
131  if( cmpFile == NULL )
132  return false;
133 
134  // cmpFileReader dtor will close cmpFile
135  FILE_LINE_READER cmpFileReader( cmpFile, aFullFilename );
136 
137  // Now, for each component found in file,
138  // replace footprint field value by the new value:
139  wxString reference;
140  wxString footprint;
141  wxString buffer;
142  wxString value;
143 
144  while( cmpFileReader.ReadLine() )
145  {
146  buffer = FROM_UTF8( cmpFileReader.Line() );
147 
148  if( !buffer.StartsWith( wxT( "BeginCmp" ) ) )
149  continue;
150 
151  // Begin component description.
152  reference.Empty();
153  footprint.Empty();
154 
155  while( cmpFileReader.ReadLine() )
156  {
157  buffer = FROM_UTF8( cmpFileReader.Line() );
158 
159  if( buffer.StartsWith( wxT( "EndCmp" ) ) )
160  break;
161 
162  // store string value, stored between '=' and ';' delimiters.
163  value = buffer.AfterFirst( '=' );
164  value = value.BeforeLast( ';' );
165  value.Trim(true);
166  value.Trim(false);
167 
168  if( buffer.StartsWith( wxT( "Reference" ) ) )
169  reference = value;
170  else if( buffer.StartsWith( wxT( "IdModule" ) ) )
171  footprint = value;
172  }
173 
174  // A block is read: initialize the footprint field of the corresponding component
175  // if the footprint name is not empty
176  if( reference.IsEmpty() )
177  continue;
178 
179  // Search the component in the flat list
180  for( unsigned ii = 0; ii < referencesList.GetCount(); ii++ )
181  {
182  if( reference == referencesList[ii].GetRef() )
183  {
184  // We have found a candidate.
185  // Note: it can be not unique (multiple units per part)
186  // So we *do not* stop the search here
187  SCH_COMPONENT* symbol = referencesList[ ii ].GetSymbol();
188  SCH_SHEET_PATH* sheetPath = &referencesList[ii].GetSheetPath();
189 
190  symbol->SetFootprint( sheetPath, footprint );
191 
192  if( aForceVisibilityState )
193  symbol->GetField( FOOTPRINT_FIELD )->SetVisible( aVisibilityState );
194  }
195  }
196  }
197 
198  return true;
199 }
200 
201 
203 {
204  wxString path = wxPathOnly( m_frame->Prj().GetProjectFullName() );
205 
206  wxFileDialog dlg( m_frame, _( "Load Symbol Footprint Link File" ),
207  path, wxEmptyString,
209  wxFD_OPEN | wxFD_FILE_MUST_EXIST );
210 
211  if( dlg.ShowModal() == wxID_CANCEL )
212  return 0;
213 
214  wxString filename = dlg.GetPath();
215 
216  wxArrayString choices;
217  choices.Add( _( "Keep existing footprint field visibility" ) );
218  choices.Add( _( "Show all footprint fields" ) );
219  choices.Add( _( "Hide all footprint fields" ) );
220 
221  wxSingleChoiceDialog choiceDlg( m_frame, _( "Select the footprint field visibility setting." ),
222  _( "Change Visibility" ), choices );
223 
224  if( choiceDlg.ShowModal() == wxID_CANCEL )
225  return 0;
226 
227  bool forceVisibility = (choiceDlg.GetSelection() != 0 );
228  bool visibilityState = (choiceDlg.GetSelection() == 1 );
229 
230  if( !processCmpToFootprintLinkFile( filename, forceVisibility, visibilityState ) )
231  {
232  wxString msg = wxString::Format( _( "Failed to open component-footprint link file \"%s\"" ),
233  filename.GetData() );
234 
235  DisplayError( m_frame, msg );
236  return 0;
237  }
238 
239  m_frame->SyncView();
240  m_frame->GetCanvas()->Refresh();
241  m_frame->OnModify();
242  return 0;
243 }
void DisplayError(wxWindow *aParent, const wxString &aText, int aDisplayTime)
Display an error or warning message box with aMessage.
Definition: confirm.cpp:252
An 8 bit string that is assuredly encoded in UTF8, and supplies special conversion support to and fro...
Definition: utf8.h:70
A container for handling SCH_SHEET_PATH objects in a flattened hierarchy.
char * ReadLine() override
Read a line of text into the buffer and increments the line number counter.
Definition: richio.cpp:198
char * Line() const
Return a pointer to the last line that was read in.
Definition: richio.h:117
static wxString FROM_UTF8(const char *cstring)
Convert a UTF8 encoded C string to a wxString for all wxWidgets build modes.
Definition: macros.h:110
SCH_FIELD * GetField(MANDATORY_FIELD_T aFieldType)
Return a mandatory field in this symbol.
Definition: sch_symbol.cpp:665
void GetSymbols(SCH_REFERENCE_LIST &aReferences, bool aIncludePowerSymbols=true, bool aForceIncludeOrphanSymbols=false) const
Add a SCH_REFERENCE object to aReferences for each symbol in the list of sheets.
This file is part of the common library.
wxString ComponentFileWildcard()
void Scan(PTREE *aTree, DSNLEXER *aLexer)
Fill an empty PTREE with information from a KiCad s-expression stream.
Definition: ptree.cpp:86
bool IsVisible() const
Definition: eda_text.h:193
void SetVisible(bool aVisible)
Definition: eda_text.h:192
Container to create a flattened list of symbols because in a complex hierarchy, a symbol can be used ...
boost::property_tree::ptree PTREE
Definition: ptree.h:52
A LINE_READER that reads from an open file.
Definition: richio.h:172
#define NULL
const PTREE CPTREE
Definition: ptree.h:53
void SyncView()
Mark all items for refresh.
PROJECT & Prj() const
Return 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.
Generic, UI-independent tool event.
Definition: tool_event.h:173
bool processCmpToFootprintLinkFile(const wxString &aFullFilename, bool aForceVisibilityState, bool aVisibilityState)
Read the footprint info from each line in the stuff file by reference designator.
SCHEMATIC & Schematic() const
Definition of file extensions used in Kicad.
int ImportFPAssignments(const TOOL_EVENT &aEvent)
size_t GetCount() const
Handle access to a stack of flattened SCH_SHEET objects by way of a path for creating a flattened sch...
boost::property_tree::ptree_error PTREE_ERROR
Definition: ptree.h:54
virtual const wxString GetProjectFullName() const
Return the full path and name of the project.
Definition: project.cpp:117
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...
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, const CPTREE &aTree)
Output a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
Definition: ptree.cpp:200
SCH_SHEET_LIST GetSheets() const override
Builds and returns an updated schematic hierarchy TODO: can this be cached?
Definition: schematic.h:87
#define _(s)
Definition: 3d_actions.cpp:33
Schematic symbol object.
Definition: sch_symbol.h:78
void AssignFootprints(const std::string &aChangedSetOfReferences)
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.
#define THROW_IO_ERROR(msg)
Definition: ki_exception.h:38
Implement a lexical analyzer for the SPECCTRA DSN file format.
Definition: dsnlexer.h:78
void SetFootprint(const SCH_SHEET_PATH *sheet, const wxString &aFootprint)
Definition: sch_symbol.cpp:635
Field Name Module PCB, i.e. "16DIP300".