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