1 /*
2 * This program source code file is part of KiCad, a free EDA CAD application.
3 *
4 * Copyright (C) 1992-2021 KiCad Developers, see AUTHORS.txt for contributors.
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, you may find one here:
18 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
19 * or you may search the http://www.gnu.org website for the version 2 license,
20 * or you may write to the Free Software Foundation, Inc.,
21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
22 */
23
24 #include <project.h>
25 #include <kiface_base.h>
26 #include <confirm.h>
27 #include <pcb_edit_frame.h>
28 #include <pcbnew_settings.h>
29 #include <reporter.h>
30 #include <bitmaps.h>
31 #include <tool/tool_manager.h>
32 #include <tools/pcb_actions.h>
33 #include <connectivity/connectivity_data.h>
34 #include <wildcards_and_files_ext.h>
35 #include <netlist_reader/pcb_netlist.h>
36 #include <netlist_reader/board_netlist_updater.h>
37 #include <project/project_file.h> // LAST_PATH_TYPE
38
39 #include <dialog_netlist.h>
40
41 #include <wx_html_report_panel.h>
42 #include <wx/filedlg.h>
43
44
InstallNetlistFrame()45 void PCB_EDIT_FRAME::InstallNetlistFrame()
46 {
47 wxString netlistName = GetLastPath( LAST_PATH_NETLIST );
48
49 DIALOG_NETLIST dlg( this, netlistName );
50
51 dlg.ShowModal();
52
53 SetLastPath( LAST_PATH_NETLIST, netlistName );
54 }
55
56 bool DIALOG_NETLIST::m_matchByUUID = false;
57
58
DIALOG_NETLIST(PCB_EDIT_FRAME * aParent,wxString & aNetlistFullFilename)59 DIALOG_NETLIST::DIALOG_NETLIST( PCB_EDIT_FRAME* aParent, wxString& aNetlistFullFilename )
60 : DIALOG_NETLIST_BASE( aParent ),
61 m_parent( aParent ),
62 m_netlistPath( aNetlistFullFilename ),
63 m_initialized( false ),
64 m_runDragCommand( false )
65 {
66 m_NetlistFilenameCtrl->SetValue( m_netlistPath );
67 m_browseButton->SetBitmap( KiBitmap( BITMAPS::small_folder ) );
68
69 auto cfg = m_parent->GetPcbNewSettings();
70
71 m_cbUpdateFootprints->SetValue( cfg->m_NetlistDialog.update_footprints );
72 m_cbDeleteShortingTracks->SetValue( cfg->m_NetlistDialog.delete_shorting_tracks );
73 m_cbDeleteExtraFootprints->SetValue( cfg->m_NetlistDialog.delete_extra_footprints );
74
75 m_matchByTimestamp->SetSelection( m_matchByUUID ? 0 : 1 );
76
77 m_MessageWindow->SetLabel( _("Changes To Be Applied") );
78 m_MessageWindow->SetVisibleSeverities( cfg->m_NetlistDialog.report_filter );
79 m_MessageWindow->SetFileName( Prj().GetProjectPath() + wxT( "report.txt" ) );
80
81 // We use a sdbSizer to get platform-dependent ordering of the action buttons, but
82 // that requires us to correct the button labels here.
83 m_sdbSizer1OK->SetLabel( _( "Update PCB" ) );
84 m_sdbSizer1Cancel->SetLabel( _( "Close" ) );
85 m_buttonsSizer->Layout();
86
87 m_sdbSizer1OK->SetDefault();
88 finishDialogSettings();
89
90 m_initialized = true;
91 loadNetlist( true );
92 }
93
~DIALOG_NETLIST()94 DIALOG_NETLIST::~DIALOG_NETLIST()
95 {
96 m_matchByUUID = m_matchByTimestamp->GetSelection() == 0;
97
98 PCBNEW_SETTINGS* cfg = m_parent->GetPcbNewSettings();
99
100 cfg->m_NetlistDialog.report_filter = m_MessageWindow->GetVisibleSeverities();
101 cfg->m_NetlistDialog.update_footprints = m_cbUpdateFootprints->GetValue();
102 cfg->m_NetlistDialog.delete_shorting_tracks = m_cbDeleteShortingTracks->GetValue();
103 cfg->m_NetlistDialog.delete_extra_footprints = m_cbDeleteExtraFootprints->GetValue();
104
105 if( m_runDragCommand )
106 {
107 KIGFX::VIEW_CONTROLS* controls = m_parent->GetCanvas()->GetViewControls();
108 controls->SetCursorPosition( controls->GetMousePosition() );
109 m_parent->GetToolManager()->RunAction( PCB_ACTIONS::move, true );
110 }
111 }
112
113
OnOpenNetlistClick(wxCommandEvent & event)114 void DIALOG_NETLIST::OnOpenNetlistClick( wxCommandEvent& event )
115 {
116 wxString dirPath = wxFileName( Prj().GetProjectFullName() ).GetPath();
117
118 wxString filename = m_parent->GetLastPath( LAST_PATH_NETLIST );
119
120 if( !filename.IsEmpty() )
121 {
122 wxFileName fn = filename;
123 dirPath = fn.GetPath();
124 filename = fn.GetFullName();
125 }
126
127 wxFileDialog FilesDialog( this, _( "Select Netlist" ), dirPath, filename,
128 NetlistFileWildcard(), wxFD_DEFAULT_STYLE | wxFD_FILE_MUST_EXIST );
129
130 if( FilesDialog.ShowModal() != wxID_OK )
131 return;
132
133 m_NetlistFilenameCtrl->SetValue( FilesDialog.GetPath() );
134 onFilenameChanged();
135 }
136
OnUpdatePCB(wxCommandEvent & event)137 void DIALOG_NETLIST::OnUpdatePCB( wxCommandEvent& event )
138 {
139 wxFileName fn = m_NetlistFilenameCtrl->GetValue();
140
141 if( !fn.IsOk() )
142 {
143 wxMessageBox( _( "Please choose a valid netlist file." ) );
144 return;
145 }
146
147 if( !fn.FileExists() )
148 {
149 wxMessageBox( _( "The netlist file does not exist." ) );
150 return;
151 }
152
153 m_MessageWindow->SetLabel( _( "Changes Applied to PCB" ) );
154 loadNetlist( false );
155
156 m_sdbSizer1Cancel->SetDefault();
157 }
158
159
OnFilenameKillFocus(wxFocusEvent & event)160 void DIALOG_NETLIST::OnFilenameKillFocus( wxFocusEvent& event )
161 {
162 onFilenameChanged();
163 event.Skip();
164 }
165
166
onFilenameChanged()167 void DIALOG_NETLIST::onFilenameChanged()
168 {
169 if( m_initialized )
170 {
171 wxFileName fn = m_NetlistFilenameCtrl->GetValue();
172
173 if( fn.IsOk() )
174 {
175 if( fn.FileExists() )
176 {
177 m_netlistPath = m_NetlistFilenameCtrl->GetValue();
178 loadNetlist( true );
179 }
180 else
181 {
182 m_MessageWindow->Clear();
183 REPORTER& reporter = m_MessageWindow->Reporter();
184 reporter.Report( _( "The netlist file does not exist." ), RPT_SEVERITY_ERROR );
185 }
186 }
187 }
188 }
189
190
OnMatchChanged(wxCommandEvent & event)191 void DIALOG_NETLIST::OnMatchChanged( wxCommandEvent& event )
192 {
193 if( m_initialized )
194 loadNetlist( true );
195 }
196
197
OnOptionChanged(wxCommandEvent & event)198 void DIALOG_NETLIST::OnOptionChanged( wxCommandEvent& event )
199 {
200 if( m_initialized )
201 loadNetlist( true );
202 }
203
204
loadNetlist(bool aDryRun)205 void DIALOG_NETLIST::loadNetlist( bool aDryRun )
206 {
207 wxString netlistFileName = m_NetlistFilenameCtrl->GetValue();
208 wxFileName fn = netlistFileName;
209
210 if( !fn.IsOk() || !fn.FileExists() )
211 return;
212
213 m_MessageWindow->Clear();
214 REPORTER& reporter = m_MessageWindow->Reporter();
215
216 wxBusyCursor busy;
217
218 wxString msg;
219 msg.Printf( _( "Reading netlist file '%s'.\n" ), netlistFileName );
220 reporter.ReportHead( msg, RPT_SEVERITY_INFO );
221
222 if( m_matchByTimestamp->GetSelection() == 1 )
223 msg = _( "Using reference designators to match symbols and footprints.\n" );
224 else
225 msg = _( "Using tstamps (unique IDs) to match symbols and footprints.\n" );
226
227 reporter.ReportHead( msg, RPT_SEVERITY_INFO );
228 m_MessageWindow->SetLazyUpdate( true ); // Use lazy update to speed the creation of the report
229 // (the window is not updated for each message)
230 m_matchByUUID = m_matchByTimestamp->GetSelection() == 0;
231
232 NETLIST netlist;
233
234 netlist.SetFindByTimeStamp( m_matchByUUID );
235 netlist.SetReplaceFootprints( m_cbUpdateFootprints->GetValue() );
236
237 if( !m_parent->ReadNetlistFromFile( netlistFileName, netlist, reporter ) )
238 return;
239
240 BOARD_NETLIST_UPDATER updater( m_parent, m_parent->GetBoard() );
241 updater.SetReporter ( &reporter );
242 updater.SetIsDryRun( aDryRun );
243 updater.SetLookupByTimestamp( m_matchByUUID );
244 updater.SetDeleteUnusedFootprints( m_cbDeleteExtraFootprints->GetValue());
245 updater.SetReplaceFootprints( m_cbUpdateFootprints->GetValue() );
246 updater.UpdateNetlist( netlist );
247
248 // The creation of the report was made without window update: the full page must be displayed
249 m_MessageWindow->Flush( true );
250
251 if( aDryRun )
252 return;
253
254 m_parent->OnNetlistChanged( updater, &m_runDragCommand );
255 }
256
257
258