KiCad PCB EDA Suite
Loading...
Searching...
No Matches
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 The 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, see <https://www.gnu.org/licenses/>.
20 */
21
22#include <confirm.h>
23#include <string_utils.h>
24#include <kiface_base.h>
25#include <sch_edit_frame.h>
27#include <sch_commit.h>
28#include <sch_sheet_path.h>
29#include <sch_symbol.h>
30#include <sch_reference_list.h>
31#include <schematic.h>
32#include <dsnlexer.h>
33#include <ptree.h>
34#include <boost/property_tree/ptree.hpp>
36
37#include <wx/choicdlg.h>
38#include <wx/filedlg.h>
39#include <kiplatform/ui.h>
40
41
42void SCH_EDITOR_CONTROL::AssignFootprints( const std::string& aChangedSetOfReferences )
43{
44 // Build a flat list of symbols in schematic:
46 SCH_COMMIT commit( m_frame );
47 bool isChanged = false;
48
49 m_frame->Schematic().Hierarchy().GetSymbols( refs, SYMBOL_FILTER_NON_POWER );
50
51 DSNLEXER lexer( aChangedSetOfReferences, From_UTF8( __func__ ) );
52 PTREE doc;
53
54 try
55 {
56 Scan( &doc, &lexer );
57
58 CPTREE& back_anno = doc.get_child( "cvpcb_netlist" );
59 wxString footprint;
60
61 for( PTREE::const_iterator ref = back_anno.begin(); ref != back_anno.end(); ++ref )
62 {
63 wxASSERT( ref->first == "ref" );
64
65 wxString reference = UTF8( ref->second.front().first );
66
67 // Ensure the "fpid" node contains a footprint name, and get it if exists
68 if( ref->second.get_child( "fpid" ).size() )
69 {
70 wxString tmp = UTF8( ref->second.get_child( "fpid" ).front().first );
71 footprint = tmp;
72 }
73 else
74 footprint.Empty();
75
76 // Search the symbol in the flat list
77 for( unsigned ii = 0; ii < refs.GetCount(); ++ii )
78 {
79 if( reference == refs[ii].GetRef() )
80 {
81 // We have found a candidate.
82 // Note: it can be not unique (multiple parts per package)
83 // So we *do not* stop the search here
84 SCH_SYMBOL* symbol = refs[ ii ].GetSymbol();
85
86 // For backwards-compatibility CvPcb currently updates all instances of a
87 // symbol (even though it lists these instances separately).
88 wxString oldfp = refs[ii].GetFootprint();
89 SCH_FIELD* footprintField = symbol->GetField( FIELD_T::FOOTPRINT );
90
91 if( oldfp.IsEmpty() && footprintField->IsVisible() )
92 footprintField->SetVisible( false );
93
94 if( oldfp != footprint )
95 {
96 isChanged = true;
97 SCH_SCREEN* screen = refs[ii].GetSheetPath().LastScreen();
98
99 commit.Modify( symbol, screen, RECURSE_MODE::NO_RECURSE );
100 footprintField->SetText( footprint );
101 }
102 }
103 }
104 }
105 }
106 catch( const PTREE_ERROR& ex )
107 {
108 // remap the exception to something the caller is likely to understand.
109 THROW_IO_ERROR( ex.what() );
110 }
111
112 if( isChanged )
113 {
114 m_frame->SyncView();
115 commit.Push( wxS( "Assign Footprints" ) );
116 }
117}
118
119
120bool 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 m_frame->Schematic().Hierarchy().GetSymbols( referencesList, SYMBOL_FILTER_NON_POWER );
127
128 FILE* cmpFile = wxFopen( aFullFilename, wxT( "rt" ) );
129
130 if( cmpFile == nullptr )
131 return false;
132
133 // cmpFileReader dtor will close cmpFile
134 FILE_LINE_READER cmpFileReader( cmpFile, aFullFilename );
135
136 // Now, for each symbol found in file,
137 // replace footprint field value by the new value:
138 wxString reference;
139 wxString footprint;
140 wxString buffer;
141 wxString value;
142
143 while( cmpFileReader.ReadLine() )
144 {
145 buffer = From_UTF8( cmpFileReader.Line() );
146
147 if( !buffer.StartsWith( wxT( "BeginCmp" ) ) )
148 continue;
149
150 // Begin symbol description.
151 reference.Empty();
152 footprint.Empty();
153
154 while( cmpFileReader.ReadLine() )
155 {
156 buffer = From_UTF8( cmpFileReader.Line() );
157
158 if( buffer.StartsWith( wxT( "EndCmp" ) ) )
159 break;
160
161 // store string value, stored between '=' and ';' delimiters.
162 value = buffer.AfterFirst( '=' );
163 value = value.BeforeLast( ';' );
164 value.Trim(true);
165 value.Trim(false);
166
167 if( buffer.StartsWith( wxT( "Reference" ) ) )
168 reference = value;
169 else if( buffer.StartsWith( wxT( "IdModule" ) ) )
170 footprint = value;
171 }
172
173 // A block is read: initialize the footprint field of the corresponding symbol
174 // if the footprint name is not empty
175 if( reference.IsEmpty() )
176 continue;
177
178 // Search the symbol in the flat list
179 for( unsigned ii = 0; ii < referencesList.GetCount(); ii++ )
180 {
181 if( reference == referencesList[ii].GetRef() )
182 {
183 // We have found a candidate.
184 // Note: it can be not unique (multiple units per part)
185 // So we *do not* stop the search here
186 SCH_SYMBOL* symbol = referencesList[ ii ].GetSymbol();
187
188 symbol->SetFootprintFieldText( footprint );
189
190 if( aForceVisibilityState )
191 symbol->GetField( FIELD_T::FOOTPRINT )->SetVisible( aVisibilityState );
192 }
193 }
194 }
195
196 return true;
197}
198
199
201{
202 wxString path = wxPathOnly( m_frame->Prj().GetProjectFullName() );
203
204 wxFileDialog dlg( m_frame, _( "Load Symbol Footprint Link File" ),
205 path, wxEmptyString,
207 wxFD_OPEN | wxFD_FILE_MUST_EXIST );
208
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 symbol-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}
COMMIT & Modify(EDA_ITEM *aItem, BASE_SCREEN *aScreen=nullptr, RECURSE_MODE aRecurse=RECURSE_MODE::NO_RECURSE)
Modify a given item in the model.
Definition commit.h:102
Implement a lexical analyzer for the SPECCTRA DSN file format.
Definition dsnlexer.h:75
virtual bool IsVisible() const
Definition eda_text.h:208
virtual void SetVisible(bool aVisible)
Definition eda_text.cpp:381
A LINE_READER that reads from an open file.
Definition richio.h:154
char * ReadLine() override
Read a line of text into the buffer and increments the line number counter.
Definition richio.cpp:208
char * Line() const
Return a pointer to the last line that was read in.
Definition richio.h:98
virtual void Push(const wxString &aMessage=wxT("A commit"), int aCommitFlags=0) override
Execute the changes.
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 SetText(const wxString &aText) override
Container to create a flattened list of symbols because in a complex hierarchy, a symbol can be used ...
Schematic symbol object.
Definition sch_symbol.h:69
void SetFootprintFieldText(const wxString &aFootprint)
SCH_FIELD * GetField(FIELD_T aFieldType)
Return a mandatory field in this symbol.
Generic, UI-independent tool event.
Definition tool_event.h:167
An 8 bit string that is assuredly encoded in UTF8, and supplies special conversion support to and fro...
Definition utf8.h:67
void DisplayError(wxWindow *aParent, const wxString &aText)
Display an error or warning message box with aMessage.
Definition confirm.cpp:192
This file is part of the common library.
#define _(s)
@ NO_RECURSE
Definition eda_item.h:50
static wxString FootprintAssignmentFileWildcard()
#define THROW_IO_ERROR(msg)
macro which captures the "call site" values of FILE_, __FUNCTION & LINE
void AllowNetworkFileSystems(wxDialog *aDialog)
Configure a file dialog to show network and virtual file systems.
Definition wxgtk/ui.cpp:448
void Scan(PTREE *aTree, DSNLEXER *aLexer)
Fill an empty PTREE with information from a KiCad s-expression stream.
Definition ptree.cpp:80
const PTREE CPTREE
Definition ptree.h:49
boost::property_tree::ptree_error PTREE_ERROR
Definition ptree.h:50
boost::property_tree::ptree PTREE
Definition ptree.h:48
Definition of the SCH_SHEET_PATH and SCH_SHEET_LIST classes for Eeschema.
@ SYMBOL_FILTER_NON_POWER
wxString From_UTF8(const char *cstring)
@ FOOTPRINT
Field Name Module PCB, i.e. "16DIP300".
std::string path
Definition of file extensions used in Kicad.