KiCad PCB EDA Suite
Loading...
Searching...
No Matches
dialog_export_netlist.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) 2013-2017 Jean-Pierre Charras, [email protected]
5 * Copyright (C) 2013 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, 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/* Functions relative to the dialog creating the netlist for Pcbnew. The dialog is a notebook
27 * with 7 fixed netlist formats:
28 * Pcbnew
29 * ORCADPCB2
30 * Allegro
31 * CADSTAR
32 * Pads
33 * SPICE
34 * SPICE model
35 * and up to CUSTOMPANEL_COUNTMAX user programmable formats. These external converters are
36 * referred to as plugins, but they are really just external binaries.
37 */
38
39#include <pgm_base.h>
40#include <kiface_base.h>
41#include <string_utils.h>
42#include <gestfich.h>
44#include <sch_edit_frame.h>
47#include <invoke_sch_dialog.h>
49#include <paths.h>
51
52#include <eeschema_id.h>
53#include <wx/checkbox.h>
54#include <wx/filedlg.h>
55#include <wx/msgdlg.h>
56#include <wx/regex.h>
57#include <wx/txtstrm.h>
58
59#include <thread>
60
61
62#define CUSTOMPANEL_COUNTMAX 8 // Max number of netlist plugins
63
64/*
65 * PANEL_NETLIST_INDEX values are used as index in m_PanelNetType[]
66 */
68{
69 PANELPCBNEW = 0, /* Handle Netlist format Pcbnew */
70 PANELORCADPCB2, /* Handle Netlist format OracdPcb2 */
71 PANELALLEGRO, /* Handle Netlist format Allegro */
72 PANELCADSTAR, /* Handle Netlist format CadStar */
73 PANELPADS, /* Handle Netlist format PADS */
74 PANELSPICE, /* Handle Netlist format Spice */
75 PANELSPICEMODEL, /* Handle Netlist format Spice Model (subcircuit) */
77
78 /* First auxiliary panel (custom netlists). Subsequent ones use PANELCUSTOMBASE+1,
79 * PANELCUSTOMBASE+2, etc., up to PANELCUSTOMBASE+CUSTOMPANEL_COUNTMAX-1 */
81};
82
83
84/* wxPanels for creating the NoteBook pages for each netlist format: */
85class EXPORT_NETLIST_PAGE : public wxPanel
86{
87public:
97 EXPORT_NETLIST_PAGE( wxNotebook* aParent, const wxString& aTitle, NETLIST_TYPE_ID aIdNetType, bool aCustom );
99
103 const wxString GetPageNetFmtName() { return m_pageNetFmtName; }
104
105 bool IsCustom() const { return m_custom; }
106
107public:
109
110 // opt to reformat passive component values (e.g. 1M -> 1Meg):
111 wxCheckBox* m_CurSheetAsRoot;
112 wxCheckBox* m_SaveAllVoltages;
113 wxCheckBox* m_SaveAllCurrents;
115 wxCheckBox* m_SaveAllEvents;
118 wxTextCtrl* m_TitleStringCtrl;
119 wxBoxSizer* m_LeftBoxSizer;
120 wxBoxSizer* m_RightBoxSizer;
122 wxBoxSizer* m_LowBoxSizer;
123
124private:
127};
128
129
131{
132public:
134
135 const wxString GetGeneratorTitle() { return m_textCtrlName->GetValue(); }
136 const wxString GetGeneratorTCommandLine() { return m_textCtrlCommand->GetValue(); }
137
138 bool TransferDataFromWindow() override;
139
140private:
144 void OnBrowseGenerators( wxCommandEvent& event ) override;
145
147};
148
149
150/* Event id for notebook page buttons: */
160
161
162EXPORT_NETLIST_PAGE::EXPORT_NETLIST_PAGE( wxNotebook* aParent, const wxString& aTitle,
163 NETLIST_TYPE_ID aIdNetType, bool aCustom ) :
164 wxPanel( aParent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ),
165 m_IdNetType( aIdNetType ),
166 m_CurSheetAsRoot( nullptr ),
167 m_SaveAllVoltages( nullptr ),
168 m_SaveAllCurrents( nullptr ),
169 m_SaveAllDissipations( nullptr ),
170 m_SaveAllEvents( nullptr ),
171 m_RunExternalSpiceCommand( nullptr ),
172 m_CommandStringCtrl( nullptr ),
173 m_TitleStringCtrl( nullptr ),
174 m_pageNetFmtName( aTitle ),
175 m_custom( aCustom )
176{
177 aParent->AddPage( this, aTitle, false );
178
179 wxBoxSizer* MainBoxSizer = new wxBoxSizer( wxVERTICAL );
180 SetSizer( MainBoxSizer );
181 wxBoxSizer* UpperBoxSizer = new wxBoxSizer( wxHORIZONTAL );
182 m_LowBoxSizer = new wxBoxSizer( wxVERTICAL );
183 MainBoxSizer->Add( UpperBoxSizer, 0, wxEXPAND | wxALL, 5 );
184 MainBoxSizer->Add( m_LowBoxSizer, 0, wxEXPAND | wxALL, 5 );
185
186 m_LeftBoxSizer = new wxBoxSizer( wxVERTICAL );
187 m_RightBoxSizer = new wxBoxSizer( wxVERTICAL );
188 m_RightOptionsBoxSizer = new wxBoxSizer( wxVERTICAL );
189 UpperBoxSizer->Add( m_LeftBoxSizer, 0, wxEXPAND | wxALL, 5 );
190 UpperBoxSizer->Add( m_RightBoxSizer, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5 );
191 UpperBoxSizer->Add( m_RightOptionsBoxSizer, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5 );
192}
193
194
196 DIALOG_EXPORT_NETLIST( aEditFrame, aEditFrame )
197{
198}
199
200
202 JOB_EXPORT_SCH_NETLIST* aJob ) :
204 m_job( aJob )
205{
206 m_editFrame = aEditFrame;
207
208 // Initialize the array of netlist pages
210
211 // Add notebook pages:
212 EXPORT_NETLIST_PAGE* page = nullptr;
213 wxStaticText* label = nullptr;
214
215 page = new EXPORT_NETLIST_PAGE( m_NoteBook, wxT( "KiCad" ), NET_TYPE_PCBNEW, false );
216 label = new wxStaticText( page, wxID_ANY, _( "Export netlist in KiCad format" ) );
217 page->m_LeftBoxSizer->Add( label, 0, wxBOTTOM, 10 );
219
220 page = new EXPORT_NETLIST_PAGE( m_NoteBook, wxT( "OrcadPCB2" ), NET_TYPE_ORCADPCB2, false );
221 label = new wxStaticText( page, wxID_ANY, _( "Export netlist in OrcadPCB2 format" ) );
222 page->m_LeftBoxSizer->Add( label, 0, wxBOTTOM, 10 );
224
225 page = new EXPORT_NETLIST_PAGE( m_NoteBook, wxT( "Allegro" ), NET_TYPE_ALLEGRO, false );
226 label = new wxStaticText( page, wxID_ANY, _( "Export netlist in Allegro format" ) );
227 page->m_LeftBoxSizer->Add( label, 0, wxBOTTOM, 10 );
229
230 page = new EXPORT_NETLIST_PAGE( m_NoteBook, wxT( "PADS" ), NET_TYPE_PADS, false );
231 label = new wxStaticText( page, wxID_ANY, _( "Export netlist in PADS format" ) );
232 page->m_LeftBoxSizer->Add( label, 0, wxBOTTOM, 10 );
234
235 page = new EXPORT_NETLIST_PAGE( m_NoteBook, wxT( "CadStar" ), NET_TYPE_CADSTAR, false );
236 label = new wxStaticText( page, wxID_ANY, _( "Export netlist in CadStar format" ) );
237 page->m_LeftBoxSizer->Add( label, 0, wxBOTTOM, 10 );
239
242
243 if( !m_job )
244 {
245 m_outputPath->Hide();
248
249 SetupStandardButtons( { { wxID_OK, _( "Export Netlist" ) },
250 { wxID_CANCEL, _( "Close" ) } } );
251 }
252 else
253 {
254 SetTitle( m_job->GetSettingsDialogTitle() );
255
256 m_MessagesBox->Hide();
258
260
261 // custom netlist (external invokes, not supported)
262 for( int ii = 0; ii < DEFINED_NETLISTS_COUNT + CUSTOMPANEL_COUNTMAX; ++ii )
263 {
264 if( EXPORT_NETLIST_PAGE* candidate = m_PanelNetType[ii] )
265 {
266 if( candidate->GetPageNetFmtName() == JOB_EXPORT_SCH_NETLIST::GetFormatNameMap()[m_job->format] )
267 {
268 m_NoteBook->ChangeSelection( ii );
269 break;
270 }
271 }
272 }
273
274 m_buttonAddGenerator->Hide();
275 m_buttonDelGenerator->Hide();
276 }
277
278 // DIALOG_SHIM needs a unique hash_key because classname will be the same for both job and
279 // non-job versions.
280 m_hash_key = TO_UTF8( GetTitle() );
281
282 // Now all widgets have the size fixed, call FinishDialogSettings
284
286}
287
288
290{
291 EXPORT_NETLIST_PAGE* pg = new EXPORT_NETLIST_PAGE( m_NoteBook, wxT( "SPICE" ), NET_TYPE_SPICE, false );
292
293 wxStaticText* label = new wxStaticText( pg, wxID_ANY, _( "Export netlist in SPICE format" ) );
294 pg->m_LeftBoxSizer->Add( label, 0, wxBOTTOM, 10 );
295
296 pg->m_CurSheetAsRoot = new wxCheckBox( pg, ID_CUR_SHEET_AS_ROOT, _( "Use current sheet as root" ) );
297 pg->m_CurSheetAsRoot->SetToolTip( _( "Export netlist only for the current sheet" ) );
298 pg->m_LeftBoxSizer->Add( pg->m_CurSheetAsRoot, 0, wxGROW | wxBOTTOM | wxRIGHT, 5 );
299
300 pg->m_SaveAllVoltages = new wxCheckBox( pg, ID_SAVE_ALL_VOLTAGES, _( "Save all voltages" ) );
301 pg->m_SaveAllVoltages->SetToolTip( _( "Write a directive to save all voltages (.save all)" ) );
302 pg->m_LeftBoxSizer->Add( pg->m_SaveAllVoltages, 0, wxBOTTOM | wxRIGHT, 5 );
303
304 pg->m_SaveAllCurrents = new wxCheckBox( pg, ID_SAVE_ALL_CURRENTS, _( "Save all currents" ) );
305 pg->m_SaveAllCurrents->SetToolTip( _( "Write a directive to save all currents (.probe alli)" ) );
306 pg->m_LeftBoxSizer->Add( pg->m_SaveAllCurrents, 0, wxBOTTOM | wxRIGHT, 5 );
307
308 pg->m_SaveAllDissipations = new wxCheckBox( pg, ID_SAVE_ALL_DISSIPATIONS, _( "Save all power dissipations" ) );
309 pg->m_SaveAllDissipations->SetToolTip( _( "Write directives to save power dissipation of all items "
310 "(.probe p(<item>))" ) );
311 pg->m_LeftBoxSizer->Add( pg->m_SaveAllDissipations, 0, wxBOTTOM | wxRIGHT, 5 );
312
313 pg->m_SaveAllEvents = new wxCheckBox( pg, ID_SAVE_ALL_EVENTS, _( "Save all digital event data" ) );
314 pg->m_SaveAllEvents->SetToolTip( _( "If not set, write a directive to prevent the saving of digital event data "
315 "(esave none)" ) );
316 pg->m_LeftBoxSizer->Add( pg->m_SaveAllEvents, 0, wxBOTTOM | wxRIGHT, 5 );
317
318
319 pg->m_RunExternalSpiceCommand = new wxCheckBox( pg, ID_RUN_SIMULATOR, _( "Run external simulator command:" ) );
320 pg->m_RunExternalSpiceCommand->SetToolTip( _( "Enter the command line to run SPICE\n"
321 "Usually '<path to SPICE binary> \"%I\"'\n"
322 "%I will be replaced by the netlist filepath" ) );
323 pg->m_LowBoxSizer->Add( pg->m_RunExternalSpiceCommand, 0, wxEXPAND | wxLEFT | wxRIGHT | wxBOTTOM, 5 );
324
325 pg->m_CommandStringCtrl = new wxTextCtrl( pg, wxID_ANY, wxT( "spice \"%I\"" ) );
326
327 pg->m_CommandStringCtrl->SetInsertionPoint( 1 );
328 pg->m_LowBoxSizer->Add( pg->m_CommandStringCtrl, 0, wxEXPAND | wxLEFT | wxRIGHT | wxBOTTOM, 5 );
329
331}
332
333
335{
336 auto* pg = new EXPORT_NETLIST_PAGE( m_NoteBook, wxT( "SPICE Model" ), NET_TYPE_SPICE_MODEL, false );
337
338 wxStaticText* label = new wxStaticText( pg, wxID_ANY, _( "Export netlist as a SPICE .subckt model" ) );
339 pg->m_LeftBoxSizer->Add( label, 0, wxBOTTOM, 10 );
340
341 pg->m_CurSheetAsRoot = new wxCheckBox( pg, ID_CUR_SHEET_AS_ROOT, _( "Use current sheet as root" ) );
342 pg->m_CurSheetAsRoot->SetToolTip( _( "Export netlist only for the current sheet" ) );
343 pg->m_LeftBoxSizer->Add( pg->m_CurSheetAsRoot, 0, wxEXPAND | wxBOTTOM | wxRIGHT, 5 );
344
346}
347
348
350{
351 EXPORT_NETLIST_PAGE* currPage;
352 EESCHEMA_SETTINGS* cfg = dynamic_cast<EESCHEMA_SETTINGS*>( Kiface().KifaceSettings() );
353 wxCHECK( cfg, /* void */ );
354
355 for( size_t i = 0; i < CUSTOMPANEL_COUNTMAX && i < cfg->m_NetlistPanel.plugins.size(); i++ )
356 {
357 // pairs of (title, command) are stored
358 currPage = AddOneCustomPage( cfg->m_NetlistPanel.plugins[i].name,
359 cfg->m_NetlistPanel.plugins[i].command,
360 static_cast<NETLIST_TYPE_ID>( NET_TYPE_CUSTOM1 + i ) );
361
362 m_PanelNetType[PANELCUSTOMBASE + i] = currPage;
363 }
364}
365
366
368 const wxString& aCommandString,
369 NETLIST_TYPE_ID aNetTypeId )
370{
371 EXPORT_NETLIST_PAGE* pg = new EXPORT_NETLIST_PAGE( m_NoteBook, aTitle, aNetTypeId, true );
372
373 pg->m_LowBoxSizer->Add( new wxStaticText( pg, wxID_ANY, _( "Title:" ) ), 0,
374 wxEXPAND | wxLEFT | wxRIGHT | wxTOP, 5 );
375
376 pg->m_LowBoxSizer->AddSpacer( 2 );
377
378 pg->m_TitleStringCtrl = new wxTextCtrl( pg, wxID_ANY, aTitle );
379
380 pg->m_TitleStringCtrl->SetInsertionPoint( 1 );
381 pg->m_LowBoxSizer->Add( pg->m_TitleStringCtrl, 0, wxEXPAND | wxLEFT | wxRIGHT, 5 );
382
383 pg->m_LowBoxSizer->AddSpacer( 10 );
384
385 pg->m_LowBoxSizer->Add( new wxStaticText( pg, wxID_ANY, _( "Netlist command:" ) ), 0,
386 wxEXPAND | wxLEFT | wxRIGHT | wxTOP, 5 );
387
388 pg->m_LowBoxSizer->AddSpacer( 2 );
389
390 pg->m_CommandStringCtrl = new wxTextCtrl( pg, wxID_ANY, aCommandString );
391
392 pg->m_CommandStringCtrl->SetInsertionPoint( 1 );
393 pg->m_LowBoxSizer->Add( pg->m_CommandStringCtrl, 0, wxEXPAND | wxLEFT | wxRIGHT, 5 );
394
395 return pg;
396}
397
398
400{
402}
403
404
406{
407 wxFileName fn;
408 wxString fileWildcard;
409 wxString fileExt;
410 wxString title = _( "Save Netlist File" );
411
412 if( m_job )
413 {
414 for( const auto& [format, name] : JOB_EXPORT_SCH_NETLIST::GetFormatNameMap() )
415 {
416 if( name == m_PanelNetType[m_NoteBook->GetSelection()]->GetPageNetFmtName() )
417 {
418 m_job->format = format;
419 break;
420 }
421 }
422
424 m_job->m_spiceSaveAllVoltages = m_PanelNetType[ PANELSPICE ]->m_SaveAllVoltages->IsChecked();
425 m_job->m_spiceSaveAllCurrents = m_PanelNetType[ PANELSPICE ]->m_SaveAllCurrents->IsChecked();
426 m_job->m_spiceSaveAllDissipations = m_PanelNetType[ PANELSPICE ]->m_SaveAllDissipations->IsChecked();
427 m_job->m_spiceSaveAllEvents = m_PanelNetType[ PANELSPICE ]->m_SaveAllEvents->IsChecked();
428
429 return true;
430 }
431
432 EXPORT_NETLIST_PAGE* currPage;
433 currPage = (EXPORT_NETLIST_PAGE*) m_NoteBook->GetCurrentPage();
434
435 bool runExternalSpiceCommand = false;
436 unsigned netlist_opt = 0;
437
438 // Calculate the netlist filename
440 FilenamePrms( currPage->m_IdNetType, &fileExt, &fileWildcard );
441
442 // Set some parameters
443 switch( currPage->m_IdNetType )
444 {
445 case NET_TYPE_SPICE:
446 // Set spice netlist options:
448
449 if( currPage->m_SaveAllVoltages->GetValue() )
451
452 if( currPage->m_SaveAllCurrents->GetValue() )
454
455 if( currPage->m_SaveAllDissipations->GetValue() )
457
458 if( currPage->m_SaveAllEvents->GetValue() )
460
461 if( currPage->m_CurSheetAsRoot->GetValue() )
463
464 runExternalSpiceCommand = currPage->m_RunExternalSpiceCommand->GetValue();
465 break;
466
468 if( currPage->m_CurSheetAsRoot->GetValue() )
470
471 break;
472
473 case NET_TYPE_CADSTAR:
474 break;
475
476 case NET_TYPE_PCBNEW:
477 break;
478
480 break;
481
482 case NET_TYPE_ALLEGRO:
483 break;
484
485 case NET_TYPE_PADS:
486 break;
487
488 default: // custom, NET_TYPE_CUSTOM1 and greater
489 title.Printf( _( "%s Export" ), currPage->m_TitleStringCtrl->GetValue() );
490 break;
491 }
492
493 wxString fullpath;
494
495 if( runExternalSpiceCommand )
496 {
497 fn.SetExt( FILEEXT::SpiceFileExtension );
498 fullpath = fn.GetFullPath();
499 }
500 else
501 {
502 fn.SetExt( fileExt );
503
504 if( fn.GetPath().IsEmpty() )
505 fn.SetPath( wxPathOnly( Prj().GetProjectFullName() ) );
506
507 wxString fullname = fn.GetFullName();
508 wxString path = fn.GetPath();
509
510 // full name does not and should not include the path, per wx docs.
511 wxFileDialog dlg( this, title, path, fullname, fileWildcard, wxFD_SAVE );
512
513 if( dlg.ShowModal() == wxID_CANCEL )
514 return false;
515
516 fullpath = dlg.GetPath(); // directory + filename
517 }
518
520 REPORTER& reporter = m_MessagesBox->Reporter();
521
522 if( currPage->m_CommandStringCtrl )
523 m_editFrame->SetNetListerCommand( currPage->m_CommandStringCtrl->GetValue() );
524 else
525 m_editFrame->SetNetListerCommand( wxEmptyString );
526
527 if( !m_editFrame->ReadyToNetlist( _( "Exporting netlist requires a fully annotated schematic." ) ) )
528 return false;
529
530 m_editFrame->WriteNetListFile( currPage->m_IdNetType, fullpath, netlist_opt, &reporter );
531
532 if( runExternalSpiceCommand )
533 {
534 // Build the command line
535 wxString commandLine = m_PanelNetType[ PANELSPICE ]->m_CommandStringCtrl->GetValue();
536 commandLine.Replace( wxS( "%I" ), fullpath, true );
537 commandLine.Trim( true ).Trim( false );
538
539 if( !commandLine.IsEmpty() )
540 {
541 wxProcess* process = new wxProcess( GetEventHandler(), wxID_ANY );
542 process->Redirect();
543 wxExecute( commandLine, wxEXEC_ASYNC, process );
544
545 reporter.ReportHead( commandLine, RPT_SEVERITY_ACTION );
546 process->Activate();
547
548 std::this_thread::sleep_for( std::chrono::seconds( 1 ) ); // give the process time to start and output any data or errors
549
550 if( process->IsInputAvailable() )
551 {
552 wxInputStream* in = process->GetInputStream();
553 wxTextInputStream textstream( *in );
554
555 while( in->CanRead() )
556 {
557 wxString line = textstream.ReadLine();
558
559 if( !line.IsEmpty() )
560 reporter.Report( line, RPT_SEVERITY_INFO );
561 }
562 }
563
564 if( process->IsErrorAvailable() )
565 {
566 wxInputStream* err = process->GetErrorStream();
567 wxTextInputStream textstream( *err );
568
569 while( err->CanRead() )
570 {
571 wxString line = textstream.ReadLine();
572
573 if( !line.IsEmpty() )
574 {
575 if( line.EndsWith( wxS( "failed with error 2!" ) ) ) // ENOENT
576 {
577 reporter.Report( _( "external simulator not found" ), RPT_SEVERITY_ERROR );
578 reporter.Report( _( "Note: command line is usually: "
579 "<tt>&lt;path to SPICE binary&gt; \"%I\"</tt>" ),
581 }
582 else if( line.EndsWith( wxS( "failed with error 8!" ) ) ) // ENOEXEC
583 {
584 reporter.Report( _( "external simulator has the wrong format or "
585 "architecture" ), RPT_SEVERITY_ERROR );
586 }
587 else if( line.EndsWith( "failed with error 13!" ) ) // EACCES
588 {
589 reporter.Report( _( "permission denied" ), RPT_SEVERITY_ERROR );
590 }
591 else
592 {
593 reporter.Report( line, RPT_SEVERITY_ERROR );
594 }
595 }
596 }
597 }
598
599 process->CloseOutput();
600 process->Detach();
601
602 // Do not delete process, it will delete itself when it terminates
603 }
604 }
605
607
608 return !runExternalSpiceCommand;
609}
610
611
612bool DIALOG_EXPORT_NETLIST::FilenamePrms( NETLIST_TYPE_ID aType, wxString * aExt, wxString * aWildCard )
613{
614 wxString fileExt;
615 wxString fileWildcard;
616 bool ret = true;
617
618 switch( aType )
619 {
620 case NET_TYPE_SPICE:
622 fileWildcard = FILEEXT::SpiceNetlistFileWildcard();
623 break;
624
625 case NET_TYPE_CADSTAR:
628 break;
629
633 break;
634
635 case NET_TYPE_PCBNEW:
637 fileWildcard = FILEEXT::NetlistFileWildcard();
638 break;
639
640 case NET_TYPE_ALLEGRO:
643 break;
644
645 case NET_TYPE_PADS:
647 fileWildcard = FILEEXT::PADSNetlistFileWildcard();
648 break;
649
650
651 default: // custom, NET_TYPE_CUSTOM1 and greater
652 fileWildcard = FILEEXT::AllFilesWildcard();
653 ret = false;
654 }
655
656 if( aExt )
657 *aExt = fileExt;
658
659 if( aWildCard )
660 *aWildCard = fileWildcard;
661
662 return ret;
663}
664
665
667{
668 EESCHEMA_SETTINGS* cfg = dynamic_cast<EESCHEMA_SETTINGS*>( Kiface().KifaceSettings() );
669 wxCHECK( cfg, /* void */ );
670
671 cfg->m_NetlistPanel.plugins.clear();
672
673 // Update existing custom pages
674 for( int ii = PANELCUSTOMBASE; ii < PANELCUSTOMBASE + CUSTOMPANEL_COUNTMAX; ++ii )
675 {
676 if( EXPORT_NETLIST_PAGE* currPage = m_PanelNetType[ii] )
677 {
678 wxString title = currPage->m_TitleStringCtrl->GetValue();
679 wxString command = currPage->m_CommandStringCtrl->GetValue();
680
681 if( title.IsEmpty() || command.IsEmpty() )
682 continue;
683
684 cfg->m_NetlistPanel.plugins.emplace_back( title, wxEmptyString );
685 cfg->m_NetlistPanel.plugins.back().command = command;
686 }
687 }
688}
689
690
691void DIALOG_EXPORT_NETLIST::OnDelGenerator( wxCommandEvent& event )
692{
693 EXPORT_NETLIST_PAGE* currPage = (EXPORT_NETLIST_PAGE*) m_NoteBook->GetCurrentPage();
694
695 if( !currPage->IsCustom() )
696 return;
697
698 currPage->m_CommandStringCtrl->SetValue( wxEmptyString );
699 currPage->m_TitleStringCtrl->SetValue( wxEmptyString );
700
702
703 if( IsQuasiModal() )
705 else
706 EndDialog( NET_PLUGIN_CHANGE );
707}
708
709
710void DIALOG_EXPORT_NETLIST::OnAddGenerator( wxCommandEvent& event )
711{
713
714 if( dlg.ShowModal() != wxID_OK )
715 return;
716
717 wxString title = dlg.GetGeneratorTitle();
718 wxString cmd = dlg.GetGeneratorTCommandLine();
719
720 // Verify it does not exists
721 for( int ii = PANELCUSTOMBASE; ii < PANELCUSTOMBASE + CUSTOMPANEL_COUNTMAX; ++ii )
722 {
723 if( m_PanelNetType[ii] && m_PanelNetType[ii]->GetPageNetFmtName() == title )
724 {
725 wxMessageBox( _( "This plugin already exists." ) );
726 return;
727 }
728 }
729
730 // Find the first empty slot
731 int netTypeId = PANELCUSTOMBASE;
732
733 while( m_PanelNetType[netTypeId] )
734 {
735 netTypeId++;
736
737 if( netTypeId == PANELCUSTOMBASE + CUSTOMPANEL_COUNTMAX )
738 {
739 wxMessageBox( _( "Maximum number of plugins already added to dialog." ) );
740 return;
741 }
742 }
743
744 m_PanelNetType[netTypeId] = AddOneCustomPage( title, cmd, (NETLIST_TYPE_ID)netTypeId );
745
747
748 if( IsQuasiModal() )
750 else
751 EndDialog( NET_PLUGIN_CHANGE );
752}
753
754
757{
758 m_Parent = parent;
760
763}
764
765
767{
768 if( !wxDialog::TransferDataFromWindow() )
769 return false;
770
771 if( m_textCtrlName->GetValue() == wxEmptyString )
772 {
773 wxMessageBox( _( "You must provide a netlist generator title" ) );
774 return false;
775 }
776
777 return true;
778}
779
780
782{
783 wxString FullFileName, Path;
784
785#ifndef __WXMAC__
786 Path = Pgm().GetExecutablePath();
787#else
788 Path = PATHS::GetOSXKicadDataDir() + wxT( "/plugins" );
789#endif
790
791 FullFileName = wxFileSelector( _( "Generator File" ), Path, FullFileName, wxEmptyString,
792 wxFileSelectorDefaultWildcardStr, wxFD_OPEN, this );
793
794 if( FullFileName.IsEmpty() )
795 return;
796
797 // Creates a default command line, suitable for external tool xslproc or python, based on
798 // the plugin extension ("xsl" or "exe" or "py")
799 wxString cmdLine;
800 wxFileName fn( FullFileName );
801 wxString ext = fn.GetExt();
802
803 if( ext == wxT( "xsl" ) )
804 cmdLine.Printf( wxT( "xsltproc -o \"%%O\" \"%s\" \"%%I\"" ), FullFileName );
805 else if( ext == wxT( "exe" ) || ext.IsEmpty() )
806 cmdLine.Printf( wxT( "\"%s\" > \"%%O\" < \"%%I\"" ), FullFileName );
807 else if( ext == wxT( "py" ) || ext.IsEmpty() )
808 cmdLine.Printf( wxT( "python \"%s\" \"%%I\" \"%%O\"" ), FullFileName );
809 else
810 cmdLine.Printf( wxT( "\"%s\"" ), FullFileName );
811
812 m_textCtrlCommand->SetValue( cmdLine );
813
814 // We need a title for this panel
815 // Propose a default value if empty ( i.e. the short filename of the script)
816 if( m_textCtrlName->GetValue().IsEmpty() )
817 m_textCtrlName->SetValue( fn.GetName() );
818}
819
820
822{
823 EXPORT_NETLIST_PAGE* currPage = (EXPORT_NETLIST_PAGE*) m_NoteBook->GetCurrentPage();
824
825 if( currPage == nullptr )
826 return;
827
828 m_buttonDelGenerator->Enable( currPage->IsCustom() );
829}
830
831
833{
834 DIALOG_EXPORT_NETLIST dlg( aCaller );
835
836 int ret = dlg.ShowModal();
837 aCaller->SaveProjectLocalSettings();
838
839 return ret;
840}
const char * name
Definition: DXF_plotter.cpp:62
KIFACE_BASE & Kiface()
Global KIFACE_BASE "get" accessor.
Class DIALOG_EXPORT_NETLIST_BASE.
WX_HTML_REPORT_PANEL * m_MessagesBox
void OnDelGenerator(wxCommandEvent &event) override
Remove a panel relative to a netlist plugin.
void WriteCurrentNetlistSetup()
Write the current netlist options setup in the configuration.
EXPORT_NETLIST_PAGE * AddOneCustomPage(const wxString &aTitle, const wxString &aCommandString, NETLIST_TYPE_ID aNetTypeId)
bool TransferDataFromWindow() override
std::vector< EXPORT_NETLIST_PAGE * > m_PanelNetType
SCH_EDIT_FRAME * m_editFrame
JOB_EXPORT_SCH_NETLIST * m_job
void OnAddGenerator(wxCommandEvent &event) override
Add a new panel for a new netlist plugin.
void OnNetlistTypeSelection(wxNotebookEvent &event) override
bool FilenamePrms(NETLIST_TYPE_ID aType, wxString *aExt, wxString *aWildCard)
Return the filename extension and the wildcard string for this page or a void name if there is no def...
DIALOG_EXPORT_NETLIST(SCH_EDIT_FRAME *aEditFrame)
void SetupStandardButtons(std::map< int, wxString > aLabels={})
std::string m_hash_key
Definition: dialog_shim.h:236
bool IsQuasiModal() const
Definition: dialog_shim.h:86
void EndQuasiModal(int retCode)
void finishDialogSettings()
In all dialogs, we must call the same functions to fix minimal dlg size, the default position and per...
wxWindow * m_initialFocusTarget
Definition: dialog_shim.h:246
int ShowModal() override
virtual void ClearMsgPanel()
Clear all messages from the message panel.
PANEL_NETLIST m_NetlistPanel
const wxString GetPageNetFmtName()
~EXPORT_NETLIST_PAGE()=default
EXPORT_NETLIST_PAGE(wxNotebook *aParent, const wxString &aTitle, NETLIST_TYPE_ID aIdNetType, bool aCustom)
Create a setup page for one netlist format.
wxCheckBox * m_RunExternalSpiceCommand
static std::map< JOB_EXPORT_SCH_NETLIST::FORMAT, wxString > & GetFormatNameMap()
wxString GetSettingsDialogTitle() const override
void SetConfiguredOutputPath(const wxString &aPath)
Sets the configured output path for the job, this path is always saved to file.
Definition: job.cpp:153
wxString GetConfiguredOutputPath() const
Returns the configured output path for the job.
Definition: job.h:232
APP_SETTINGS_BASE * KifaceSettings() const
Definition: kiface_base.h:95
PROJECT & Prj() const
Return a reference to the PROJECT associated with this KIWAY.
Class NETLIST_DIALOG_ADD_GENERATOR_BASE.
NETLIST_DIALOG_ADD_GENERATOR(DIALOG_EXPORT_NETLIST *parent)
void OnBrowseGenerators(wxCommandEvent &event) override
Browse plugin files, and set m_CommandStringCtrl field.
virtual const wxString & GetExecutablePath() const
Definition: pgm_base.cpp:879
A pure virtual class used to derive REPORTER objects from.
Definition: reporter.h:73
virtual REPORTER & ReportHead(const wxString &aText, SEVERITY aSeverity=RPT_SEVERITY_UNDEFINED)
Places the report at the beginning of the list for objects that support ordering.
Definition: reporter.h:121
virtual REPORTER & Report(const wxString &aText, SEVERITY aSeverity=RPT_SEVERITY_UNDEFINED)
Report a string with a given severity.
Definition: reporter.h:102
wxString GetFileName() const
Helper to retrieve the filename from the root sheet screen.
Definition: schematic.cpp:350
Schematic editor (Eeschema) main window.
void SaveProjectLocalSettings() override
Save changes to the project settings to the project (.pro) file.
bool ReadyToNetlist(const wxString &aAnnotateMessage)
Check if we are ready to write a netlist file for the current schematic.
bool WriteNetListFile(int aFormat, const wxString &aFullFileName, unsigned aNetlistOptions, REPORTER *aReporter=nullptr)
Create a netlist file.
SCHEMATIC & Schematic() const
void SetNetListerCommand(const wxString &aCommand)
REPORTER & Reporter()
Return the reporter object that reports to this panel.
@ PANELSPICEMODEL
@ DEFINED_NETLISTS_COUNT
@ PANELORCADPCB2
@ PANELCUSTOMBASE
@ ID_RUN_SIMULATOR
@ ID_SAVE_ALL_VOLTAGES
@ ID_SAVE_ALL_CURRENTS
@ ID_CUR_SHEET_AS_ROOT
@ ID_SAVE_ALL_DISSIPATIONS
@ ID_CREATE_NETLIST
@ ID_SAVE_ALL_EVENTS
#define CUSTOMPANEL_COUNTMAX
int InvokeDialogNetList(SCH_EDIT_FRAME *aCaller)
#define _(s)
@ ID_END_EESCHEMA_ID_LIST
Definition: eeschema_id.h:71
static const std::string CadstarNetlistFileExtension
static const std::string NetlistFileExtension
static const std::string OrCadPcb2NetlistFileExtension
static const std::string SpiceFileExtension
static const std::string PADSNetlistFileExtension
static const std::string AllegroNetlistFileExtension
static wxString SpiceNetlistFileWildcard()
static wxString OrCadPcb2NetlistFileWildcard()
static wxString AllFilesWildcard()
static wxString AllegroNetlistFileWildcard()
static wxString CadstarNetlistFileWildcard()
static wxString PADSNetlistFileWildcard()
static wxString NetlistFileWildcard()
#define NET_PLUGIN_CHANGE
Create and shows DIALOG_EXPORT_NETLIST and returns whatever DIALOG_EXPORT_NETLIST::ShowModal() return...
NETLIST_TYPE_ID
netlist types
Definition: netlist.h:35
@ NET_TYPE_CADSTAR
Definition: netlist.h:40
@ NET_TYPE_ORCADPCB2
Definition: netlist.h:39
@ NET_TYPE_SPICE
Definition: netlist.h:41
@ NET_TYPE_ALLEGRO
Definition: netlist.h:43
@ NET_TYPE_SPICE_MODEL
Definition: netlist.h:42
@ NET_TYPE_PCBNEW
Definition: netlist.h:38
@ NET_TYPE_PADS
Definition: netlist.h:44
@ NET_TYPE_CUSTOM1
Definition: netlist.h:45
static PGM_BASE * process
Definition: pgm_base.cpp:899
PGM_BASE & Pgm()
The global program "get" accessor.
Definition: pgm_base.cpp:902
see class PGM_BASE
@ RPT_SEVERITY_ERROR
@ RPT_SEVERITY_INFO
@ RPT_SEVERITY_ACTION
#define TO_UTF8(wxstring)
Convert a wxString to a UTF8 encoded C string for all wxWidgets build modes.
Definition: string_utils.h:429
std::vector< NETLIST_PLUGIN_SETTINGS > plugins
Definition of file extensions used in Kicad.