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 symbols 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 symbol 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_SYMBOL* symbol = refs[ ii ].GetSymbol();
87 
88  // For backwards-compatibility CvPcb currently updates all instances of a
89  // symbol (even though it lists these instances separately).
90  SCH_SHEET_PATH* sheetPath = nullptr; // &refs[ii].GetSheetPath();
91  wxString oldfp = refs[ii].GetFootprint();
92 
93  if( oldfp.IsEmpty() && symbol->GetField( FOOTPRINT_FIELD )->IsVisible() )
94  symbol->GetField( FOOTPRINT_FIELD )->SetVisible( false );
95 
96  if( oldfp != footprint )
97  {
98  isChanged = true;
99  symbol->SetFootprint( sheetPath, footprint );
100  }
101  }
102  }
103  }
104  }
105  catch( const PTREE_ERROR& ex )
106  {
107  // remap the exception to something the caller is likely to understand.
108  THROW_IO_ERROR( ex.what() );
109  }
110 
111  if( isChanged )
112  {
113  m_frame->SyncView();
114  m_frame->GetCanvas()->Refresh();
115  m_frame->OnModify();
116  }
117 }
118 
119 
120 bool SCH_EDITOR_CONTROL::processCmpToFootprintLinkFile( const wxString& aFullFilename,
121  bool aForceVisibilityState,
122  bool aVisibilityState )
123 {
124  // Build a flat list of symbols in schematic:
125  SCH_REFERENCE_LIST referencesList;
126  SCH_SHEET_LIST sheetList = m_frame->Schematic().GetSheets();
127 
128  sheetList.GetSymbols( referencesList, false );
129 
130  FILE* cmpFile = wxFopen( aFullFilename, wxT( "rt" ) );
131 
132  if( cmpFile == nullptr )
133  return false;
134 
135  // cmpFileReader dtor will close cmpFile
136  FILE_LINE_READER cmpFileReader( cmpFile, aFullFilename );
137 
138  // Now, for each symbol found in file,
139  // replace footprint field value by the new value:
140  wxString reference;
141  wxString footprint;
142  wxString buffer;
143  wxString value;
144 
145  while( cmpFileReader.ReadLine() )
146  {
147  buffer = FROM_UTF8( cmpFileReader.Line() );
148 
149  if( !buffer.StartsWith( wxT( "BeginCmp" ) ) )
150  continue;
151 
152  // Begin symbol description.
153  reference.Empty();
154  footprint.Empty();
155 
156  while( cmpFileReader.ReadLine() )
157  {
158  buffer = FROM_UTF8( cmpFileReader.Line() );
159 
160  if( buffer.StartsWith( wxT( "EndCmp" ) ) )
161  break;
162 
163  // store string value, stored between '=' and ';' delimiters.
164  value = buffer.AfterFirst( '=' );
165  value = value.BeforeLast( ';' );
166  value.Trim(true);
167  value.Trim(false);
168 
169  if( buffer.StartsWith( wxT( "Reference" ) ) )
170  reference = value;
171  else if( buffer.StartsWith( wxT( "IdModule" ) ) )
172  footprint = value;
173  }
174 
175  // A block is read: initialize the footprint field of the corresponding symbol
176  // if the footprint name is not empty
177  if( reference.IsEmpty() )
178  continue;
179 
180  // Search the symbol in the flat list
181  for( unsigned ii = 0; ii < referencesList.GetCount(); ii++ )
182  {
183  if( reference == referencesList[ii].GetRef() )
184  {
185  // We have found a candidate.
186  // Note: it can be not unique (multiple units per part)
187  // So we *do not* stop the search here
188  SCH_SYMBOL* symbol = referencesList[ ii ].GetSymbol();
189  SCH_SHEET_PATH* sheetPath = &referencesList[ii].GetSheetPath();
190 
191  symbol->SetFootprint( sheetPath, footprint );
192 
193  if( aForceVisibilityState )
194  symbol->GetField( FOOTPRINT_FIELD )->SetVisible( aVisibilityState );
195  }
196  }
197  }
198 
199  return true;
200 }
201 
202 
204 {
205  wxString path = wxPathOnly( m_frame->Prj().GetProjectFullName() );
206 
207  wxFileDialog dlg( m_frame, _( "Load Symbol Footprint Link File" ),
208  path, wxEmptyString,
210  wxFD_OPEN | wxFD_FILE_MUST_EXIST );
211 
212  if( dlg.ShowModal() == wxID_CANCEL )
213  return 0;
214 
215  wxString filename = dlg.GetPath();
216 
217  wxArrayString choices;
218  choices.Add( _( "Keep existing footprint field visibility" ) );
219  choices.Add( _( "Show all footprint fields" ) );
220  choices.Add( _( "Hide all footprint fields" ) );
221 
222  wxSingleChoiceDialog choiceDlg( m_frame, _( "Select the footprint field visibility setting." ),
223  _( "Change Visibility" ), choices );
224 
225  if( choiceDlg.ShowModal() == wxID_CANCEL )
226  return 0;
227 
228  bool forceVisibility = (choiceDlg.GetSelection() != 0 );
229  bool visibilityState = (choiceDlg.GetSelection() == 1 );
230 
231  if( !processCmpToFootprintLinkFile( filename, forceVisibility, visibilityState ) )
232  {
233  wxString msg = wxString::Format( _( "Failed to open symbol-footprint link file '%s'." ),
234  filename.GetData() );
235 
236  DisplayError( m_frame, msg );
237  return 0;
238  }
239 
240  m_frame->SyncView();
241  m_frame->GetCanvas()->Refresh();
242  m_frame->OnModify();
243  return 0;
244 }
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:214
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:666
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.
void Scan(PTREE *aTree, DSNLEXER *aLexer)
Fill an empty PTREE with information from a KiCad s-expression stream.
Definition: ptree.cpp:86
void SetFootprint(const SCH_SHEET_PATH *sheet, const wxString &aFootprint)
Definition: sch_symbol.cpp:636
Container to create a flattened list of symbols because in a complex hierarchy, a symbol can be used ...
virtual void SetVisible(bool aVisible)
Definition: eda_text.h:185
boost::property_tree::ptree PTREE
Definition: ptree.h:52
A LINE_READER that reads from an open file.
Definition: richio.h:172
const PTREE CPTREE
Definition: ptree.h:53
void SyncView()
Mark all items for refresh.
virtual bool IsVisible() const
Definition: eda_text.h:186
PROJECT & Prj() const
Return a reference to the PROJECT associated with this KIWAY.
wxString FootprintAssignmentFileWildcard()
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:152
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
#define _(s)
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:116
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
Schematic symbol object.
Definition: sch_symbol.h:78
virtual void Refresh(bool aEraseBackground=true, const wxRect *aRect=nullptr) override
Update the board display after modifying it by a python script (note: it is automatically called by a...
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
Field Name Module PCB, i.e. "16DIP300".