KiCad PCB EDA Suite
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 (C) 1992-2022 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 4 fixed netlist formats:
28 * Pcbnew
29 * ORCADPCB2
30 * CADSTAR
31 * SPICE
32 * and up to CUSTOMPANEL_COUNTMAX user programmable formats. These external converters are
33 * referred to as plugins, but they are really just external binaries.
34 */
35
36#include <pgm_base.h>
37#include <kiface_base.h>
38#include <gestfich.h>
40#include <sch_edit_frame.h>
41#include <netlist.h>
44#include <invoke_sch_dialog.h>
46#include <eeschema_settings.h>
47#include <schematic.h>
48#include <paths.h>
49
50#include <eeschema_id.h>
51#include <wx/checkbox.h>
52#include <wx/filedlg.h>
53#include <wx/msgdlg.h>
54#include <wx/regex.h>
55
56
57
58#define CUSTOMPANEL_COUNTMAX 8 // Max number of netlist plugins
59
60
61/* panel (notebook page) identifiers */
63 PANELPCBNEW = 0, /* Handle Netlist format Pcbnew */
64 PANELORCADPCB2, /* Handle Netlist format OracdPcb2 */
65 PANELCADSTAR, /* Handle Netlist format CadStar */
66 PANELSPICE, /* Handle Netlist format Spice */
67 PANELSPICEMODEL, /* Handle Netlist format Spice Model (subcircuit) */
68 PANELCUSTOMBASE /* First auxiliary panel (custom netlists).
69 * others use PANELCUSTOMBASE+1, PANELCUSTOMBASE+2.. */
70};
71
72
73/* wxPanels for creating the NoteBook pages for each netlist format: */
74class EXPORT_NETLIST_PAGE : public wxPanel
75{
76
77public:
87 EXPORT_NETLIST_PAGE( wxNotebook* aParent, const wxString& aTitle,
88 NETLIST_TYPE_ID aIdNetType, bool aCustom );
90
94 const wxString GetPageNetFmtName() { return m_pageNetFmtName; }
95
97 // opt to reformat passive component values (e.g. 1M -> 1Meg):
98 wxCheckBox* m_CurSheetAsRoot;
99 wxCheckBox* m_SaveAllVoltages;
100 wxCheckBox* m_SaveAllCurrents;
104 wxTextCtrl* m_TitleStringCtrl;
105 wxBoxSizer* m_LeftBoxSizer;
106 wxBoxSizer* m_RightBoxSizer;
108 wxBoxSizer* m_LowBoxSizer;
109
110 bool IsCustom() const { return m_custom; }
111
112private:
114
116};
117
118
119/* Dialog frame for creating netlists */
121{
122public:
125
126private:
127 void InstallCustomPages();
128 EXPORT_NETLIST_PAGE* AddOneCustomPage( const wxString& aTitle, const wxString& aCommandString,
129 NETLIST_TYPE_ID aNetTypeId );
130 void InstallPageSpice();
132
133 bool TransferDataFromWindow() override;
134 bool NetlistUpdateOpt();
135
137
138 // Called when changing the notebook page (and therefore the current netlist format)
139 void OnNetlistTypeSelection( wxNotebookEvent& event ) override;
140
144 void OnAddGenerator( wxCommandEvent& event ) override;
145
149 void OnDelGenerator( wxCommandEvent& event ) override;
150
155
165 bool FilenamePrms( NETLIST_TYPE_ID aType, wxString* aExt, wxString* aWildCard );
166
167public:
170};
171
172
174{
175public:
177
178 const wxString GetGeneratorTitle() { return m_textCtrlName->GetValue(); }
179 const wxString GetGeneratorTCommandLine() { return m_textCtrlCommand->GetValue(); }
180
181 bool TransferDataFromWindow() override;
182
183private:
184 /*
185 * Browse plugin files, and set m_CommandStringCtrl field
186 */
187 void OnBrowseGenerators( wxCommandEvent& event ) override;
188
190};
191
192
193/* Event id for notebook page buttons: */
202
203
204EXPORT_NETLIST_PAGE::EXPORT_NETLIST_PAGE( wxNotebook* aParent, const wxString& aTitle,
205 NETLIST_TYPE_ID aIdNetType, bool aCustom ) :
206 wxPanel( aParent, -1, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL )
207{
208 m_IdNetType = aIdNetType;
209 m_pageNetFmtName = aTitle;
210 m_CommandStringCtrl = nullptr;
211 m_CurSheetAsRoot = nullptr;
212 m_TitleStringCtrl = nullptr;
213 m_SaveAllVoltages = nullptr;
214 m_SaveAllCurrents = nullptr;
215 m_SaveAllDissipations = nullptr;
217 m_custom = aCustom;
218
219 aParent->AddPage( this, aTitle, false );
220
221 wxBoxSizer* MainBoxSizer = new wxBoxSizer( wxVERTICAL );
222 SetSizer( MainBoxSizer );
223 wxBoxSizer* UpperBoxSizer = new wxBoxSizer( wxHORIZONTAL );
224 m_LowBoxSizer = new wxBoxSizer( wxVERTICAL );
225 MainBoxSizer->Add( UpperBoxSizer, 0, wxGROW | wxALL, 5 );
226 MainBoxSizer->Add( m_LowBoxSizer, 0, wxGROW | wxALL, 5 );
227
228 m_LeftBoxSizer = new wxBoxSizer( wxVERTICAL );
229 m_RightBoxSizer = new wxBoxSizer( wxVERTICAL );
230 m_RightOptionsBoxSizer = new wxBoxSizer( wxVERTICAL );
231 UpperBoxSizer->Add( m_LeftBoxSizer, 0, wxGROW | wxALL, 5 );
232 UpperBoxSizer->Add( m_RightBoxSizer, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5 );
233 UpperBoxSizer->Add( m_RightOptionsBoxSizer, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5 );
234}
235
236
239{
240 m_Parent = parent;
241
243
244 for( EXPORT_NETLIST_PAGE*& page : m_PanelNetType )
245 page = nullptr;
246
247 // Add notebook pages:
249 NET_TYPE_PCBNEW, false );
250
252 NET_TYPE_ORCADPCB2, false );
253
255 NET_TYPE_CADSTAR, false );
256
260
261 SetupStandardButtons( { { wxID_OK, _( "Export Netlist" ) },
262 { wxID_CANCEL, _( "Close" ) } } );
263
264 for( int ii = 0; (ii < 4 + CUSTOMPANEL_COUNTMAX) && m_PanelNetType[ii]; ++ii )
265 {
266 if( m_PanelNetType[ii]->GetPageNetFmtName() == settings.m_NetFormatName )
267 {
268 m_NoteBook->ChangeSelection( ii );
269 break;
270 }
271 }
272
273 // Now all widgets have the size fixed, call FinishDialogSettings
275
277}
278
279
281{
283 new EXPORT_NETLIST_PAGE( m_NoteBook, wxT( "Spice" ), NET_TYPE_SPICE, false );
284
286
287 page->m_CurSheetAsRoot = new wxCheckBox( page, ID_CUR_SHEET_AS_ROOT,
288 _( "Use current sheet as root" ) );
289 page->m_CurSheetAsRoot->SetToolTip( _( "Export netlist only for the current sheet" ) );
290 page->m_CurSheetAsRoot->SetValue( settings.m_SpiceCurSheetAsRoot );
291 page->m_LeftBoxSizer->Add( page->m_CurSheetAsRoot, 0, wxGROW | wxBOTTOM | wxRIGHT, 5 );
292
293 page->m_SaveAllVoltages = new wxCheckBox( page, ID_SAVE_ALL_VOLTAGES,
294 _( "Save all voltages" ) );
295 page->m_SaveAllVoltages->SetToolTip( _( "Write a directive to save all voltages (.save all)" ) );
296 page->m_SaveAllVoltages->SetValue( settings.m_SpiceSaveAllVoltages );
297 page->m_LeftBoxSizer->Add( page->m_SaveAllVoltages, 0, wxBOTTOM | wxRIGHT, 5 );
298
299 page->m_SaveAllCurrents = new wxCheckBox( page, ID_SAVE_ALL_CURRENTS,
300 _( "Save all currents" ) );
301 page->m_SaveAllCurrents->SetToolTip( _( "Write a directive to save all currents (.probe alli)" ) );
302 page->m_SaveAllCurrents->SetValue( settings.m_SpiceSaveAllCurrents );
303 page->m_LeftBoxSizer->Add( page->m_SaveAllCurrents, 0, wxBOTTOM | wxRIGHT, 5 );
304
305 page->m_SaveAllDissipations = new wxCheckBox( page, ID_SAVE_ALL_DISSIPATIONS,
306 _( "Save all power dissipations" ) );
307 page->m_SaveAllDissipations->SetToolTip( _( "Write directives to save power dissipation of all items (.probe p(<item>))" ) );
308 page->m_SaveAllDissipations->SetValue( settings.m_SpiceSaveAllDissipations );
309 page->m_LeftBoxSizer->Add( page->m_SaveAllDissipations, 0, wxBOTTOM | wxRIGHT, 5 );
310
311
312 page->m_RunExternalSpiceCommand = new wxCheckBox( page, ID_RUN_SIMULATOR,
313 _( "Run external simulator command:" ) );
314 wxString simulatorCommand = settings.m_SpiceCommandString;
315 page->m_RunExternalSpiceCommand->SetToolTip( _( "Enter the command line to run SPICE\n"
316 "Usually '<path to SPICE binary> \"%I\"'\n"
317 "%I will be replaced by the netlist filepath" ) );
318 page->m_LowBoxSizer->Add( page->m_RunExternalSpiceCommand, 0,
319 wxGROW | wxLEFT | wxRIGHT | wxBOTTOM, 5 );
320
321 page->m_CommandStringCtrl = new wxTextCtrl( page, -1, simulatorCommand,
322 wxDefaultPosition, wxDefaultSize );
323
324 page->m_CommandStringCtrl->SetInsertionPoint( 1 );
325 page->m_LowBoxSizer->Add( page->m_CommandStringCtrl, 0,
326 wxGROW | wxLEFT | wxRIGHT | wxBOTTOM, 5 );
327}
328
329
331{
333 new EXPORT_NETLIST_PAGE( m_NoteBook, wxT( "Spice Model" ), NET_TYPE_SPICE_MODEL, false );
334
336
337 page->m_CurSheetAsRoot = new wxCheckBox( page, ID_CUR_SHEET_AS_ROOT,
338 _( "Use current sheet as root" ) );
339 page->m_CurSheetAsRoot->SetToolTip( _( "Export netlist only for the current sheet" ) );
340 page->m_CurSheetAsRoot->SetValue( settings.m_SpiceModelCurSheetAsRoot );
341 page->m_LeftBoxSizer->Add( page->m_CurSheetAsRoot, 0, wxGROW | wxBOTTOM | wxRIGHT, 5 );
342}
343
344
346{
347 EXPORT_NETLIST_PAGE* currPage;
348 EESCHEMA_SETTINGS* cfg = dynamic_cast<EESCHEMA_SETTINGS*>( Kiface().KifaceSettings() );
349 wxASSERT( cfg );
350
351 if( cfg )
352 {
353 for( size_t i = 0; i < CUSTOMPANEL_COUNTMAX && i < cfg->m_NetlistPanel.plugins.size(); i++ )
354 {
355 // pairs of (title, command) are stored
356 wxString title = cfg->m_NetlistPanel.plugins[i].name;
357
358 if( i >= cfg->m_NetlistPanel.plugins.size() )
359 break; // No more panel to install
360
361 wxString command = cfg->m_NetlistPanel.plugins[i].command;
362
363 currPage = AddOneCustomPage( title, command,
364 static_cast<NETLIST_TYPE_ID>( NET_TYPE_CUSTOM1 + i ) );
365
366 m_PanelNetType[PANELCUSTOMBASE + i] = currPage;
367 }
368 }
369}
370
371
373 const wxString& aCommandString,
374 NETLIST_TYPE_ID aNetTypeId )
375{
376 EXPORT_NETLIST_PAGE* currPage = new EXPORT_NETLIST_PAGE( m_NoteBook, aTitle, aNetTypeId, true );
377
378 currPage->m_LowBoxSizer->Add( new wxStaticText( currPage, -1, _( "Title:" ) ), 0,
379 wxGROW | wxLEFT | wxRIGHT | wxTOP, 5 );
380
381 currPage->m_TitleStringCtrl = new wxTextCtrl( currPage, -1, aTitle,
382 wxDefaultPosition, wxDefaultSize );
383
384 currPage->m_TitleStringCtrl->SetInsertionPoint( 1 );
385 currPage->m_LowBoxSizer->Add( currPage->m_TitleStringCtrl, 0,
386 wxGROW | wxTOP | wxLEFT | wxRIGHT | wxBOTTOM, 5 );
387
388 currPage->m_LowBoxSizer->Add( new wxStaticText( currPage, -1, _( "Netlist command:" ) ), 0,
389 wxGROW | wxLEFT | wxRIGHT | wxTOP, 5 );
390
391 currPage->m_CommandStringCtrl = new wxTextCtrl( currPage, -1, aCommandString,
392 wxDefaultPosition, wxDefaultSize );
393
394 currPage->m_CommandStringCtrl->SetInsertionPoint( 1 );
395 currPage->m_LowBoxSizer->Add( currPage->m_CommandStringCtrl, 0,
396 wxGROW | wxTOP | wxLEFT | wxRIGHT | wxBOTTOM, 5 );
397
398 return currPage;
399}
400
401
403{
405}
406
407
409{
410 bool changed = false;
411
412 bool saveAllVoltages = m_PanelNetType[ PANELSPICE ]->m_SaveAllVoltages->IsChecked();
413 bool saveAllCurrents = m_PanelNetType[ PANELSPICE ]->m_SaveAllCurrents->IsChecked();
414 bool saveAllDissipations = m_PanelNetType[ PANELSPICE ]->m_SaveAllDissipations->IsChecked();
415 wxString spiceCmdString = m_PanelNetType[ PANELSPICE ]->m_CommandStringCtrl->GetValue();
416 bool curSheetAsRoot = m_PanelNetType[ PANELSPICE ]->m_CurSheetAsRoot->GetValue();
417 bool spiceModelCurSheetAsRoot = m_PanelNetType[ PANELSPICEMODEL ]->m_CurSheetAsRoot->GetValue();
418
420 wxString netFormatName = m_PanelNetType[m_NoteBook->GetSelection()]->GetPageNetFmtName();
421
422 changed |= ( settings.m_SpiceSaveAllVoltages != saveAllVoltages );
423 changed |= ( settings.m_SpiceSaveAllCurrents != saveAllCurrents );
424 changed |= ( settings.m_SpiceSaveAllDissipations != saveAllDissipations );
425 changed |= ( settings.m_SpiceCommandString != spiceCmdString );
426 changed |= ( settings.m_SpiceCurSheetAsRoot != curSheetAsRoot );
427 changed |= ( settings.m_SpiceModelCurSheetAsRoot != spiceModelCurSheetAsRoot );
428 changed |= ( settings.m_NetFormatName != netFormatName );
429
430 settings.m_SpiceSaveAllVoltages = saveAllVoltages;
431 settings.m_SpiceSaveAllCurrents = saveAllCurrents;
432 settings.m_SpiceSaveAllDissipations = saveAllDissipations;
433 settings.m_SpiceCommandString = spiceCmdString;
434 settings.m_SpiceCurSheetAsRoot = curSheetAsRoot;
435 settings.m_SpiceModelCurSheetAsRoot = spiceModelCurSheetAsRoot;
436 settings.m_NetFormatName = netFormatName;
437
438 return changed;
439}
440
441
443{
444 wxFileName fn;
445 wxString fileWildcard;
446 wxString fileExt;
447 wxString title = _( "Save Netlist File" );
448
449 if( NetlistUpdateOpt() )
451
452 EXPORT_NETLIST_PAGE* currPage;
453 currPage = (EXPORT_NETLIST_PAGE*) m_NoteBook->GetCurrentPage();
454
455 bool runExternalSpiceCommand = false;
456 unsigned netlist_opt = 0;
457
458 // Calculate the netlist filename
460 FilenamePrms( currPage->m_IdNetType, &fileExt, &fileWildcard );
461
462 // Set some parameters
463 switch( currPage->m_IdNetType )
464 {
465 case NET_TYPE_SPICE:
466 // Set spice netlist options:
468
469 if( currPage->m_SaveAllVoltages->GetValue() )
471
472 if( currPage->m_SaveAllCurrents->GetValue() )
474
475 if( currPage->m_SaveAllDissipations->GetValue() )
477
478 if( currPage->m_CurSheetAsRoot->GetValue() )
480
481 runExternalSpiceCommand = currPage->m_RunExternalSpiceCommand->GetValue();
482 break;
483
485 if( currPage->m_CurSheetAsRoot->GetValue() )
487
488 break;
489
490 case NET_TYPE_CADSTAR:
491 break;
492
493 case NET_TYPE_PCBNEW:
494 break;
495
497 break;
498
499 default: // custom, NET_TYPE_CUSTOM1 and greater
500 {
501 title.Printf( _( "%s Export" ), currPage->m_TitleStringCtrl->GetValue() );
502 break;
503 }
504 }
505
506 wxString fullpath;
507
508 if( runExternalSpiceCommand )
509 {
510 fn.SetExt( SpiceFileExtension );
511 fullpath = fn.GetFullPath();
512 }
513 else
514 {
515 fn.SetExt( fileExt );
516
517 if( fn.GetPath().IsEmpty() )
518 fn.SetPath( wxPathOnly( Prj().GetProjectFullName() ) );
519
520 wxString fullname = fn.GetFullName();
521 wxString path = fn.GetPath();
522
523 // full name does not and should not include the path, per wx docs.
524 wxFileDialog dlg( this, title, path, fullname, fileWildcard, wxFD_SAVE );
525
526 if( dlg.ShowModal() == wxID_CANCEL )
527 return false;
528
529 fullpath = dlg.GetPath(); // directory + filename
530 }
531
533 REPORTER& reporter = m_MessagesBox->Reporter();
534
535 if( currPage->m_CommandStringCtrl )
536 m_Parent->SetNetListerCommand( currPage->m_CommandStringCtrl->GetValue() );
537 else
538 m_Parent->SetNetListerCommand( wxEmptyString );
539
540 if( !m_Parent->ReadyToNetlist( _( "Exporting netlist requires a fully annotated schematic." ) ) )
541 return false;
542
543 m_Parent->WriteNetListFile( currPage->m_IdNetType, fullpath, netlist_opt, &reporter );
544
545 if( runExternalSpiceCommand )
546 {
547 // Build the command line
548 wxString commandLine = m_Parent->Schematic().Settings().m_SpiceCommandString;
549 commandLine.Replace( wxS( "%I" ), fullpath, true );
550 commandLine.Trim( true ).Trim( false );
551
552 if( !commandLine.IsEmpty() )
553 {
554 wxArrayString output;
555 wxArrayString errors;
556 wxExecute( commandLine, output, errors, wxEXEC_ASYNC );
557
558 reporter.ReportHead( commandLine, RPT_SEVERITY_ACTION );
559
560 if( output.GetCount() )
561 {
562 for( unsigned ii = 0; ii < output.GetCount(); ii++ )
563 reporter.Report( output[ii], RPT_SEVERITY_INFO );
564 }
565
566 if( errors.GetCount() )
567 {
568 for( unsigned ii = 0; ii < errors.GetCount(); ii++ )
569 {
570 // wxExecute returns -1 for all error conditions, so we've no choice but
571 // to scrape the stderr messages for the error code(s).
572
573 if( errors[ii].EndsWith( wxS( "failed with error 2!" ) ) ) // ENOENT
574 {
575 reporter.Report( _( "external simulator not found" ), RPT_SEVERITY_ERROR );
576 reporter.Report( _( "Note: command line is usually: "
577 "<tt>&lt;path to SPICE binary&gt; \"%I\"</tt>" ),
579 }
580 else if( errors[ii].EndsWith( wxS( "failed with error 8!" ) ) ) // ENOEXEC
581 {
582 reporter.Report( _( "external simulator has the wrong format or "
583 "architecture" ), RPT_SEVERITY_ERROR );
584 }
585 else if( errors[ii].EndsWith( "failed with error 13!" ) ) // EACCES
586 {
587 reporter.Report( _( "permission denied" ), RPT_SEVERITY_ERROR );
588 }
589 else
590 {
591 reporter.Report( errors[ii], RPT_SEVERITY_ERROR );
592 }
593 }
594 }
595 }
596 }
597
599
600 return !runExternalSpiceCommand;
601}
602
603
604bool DIALOG_EXPORT_NETLIST::FilenamePrms( NETLIST_TYPE_ID aType, wxString * aExt, wxString * aWildCard )
605{
606 wxString fileExt;
607 wxString fileWildcard;
608 bool ret = true;
609
610 switch( aType )
611 {
612 case NET_TYPE_SPICE:
613 fileExt = SpiceFileExtension;
614 fileWildcard = SpiceNetlistFileWildcard();
615 break;
616
617 case NET_TYPE_CADSTAR:
619 fileWildcard = CadstarNetlistFileWildcard();
620 break;
621
624 fileWildcard = OrCadPcb2NetlistFileWildcard();
625 break;
626
627 case NET_TYPE_PCBNEW:
628 fileExt = NetlistFileExtension;
629 fileWildcard = NetlistFileWildcard();
630 break;
631
632 default: // custom, NET_TYPE_CUSTOM1 and greater
633 fileWildcard = AllFilesWildcard();
634 ret = false;
635 }
636
637 if( aExt )
638 *aExt = fileExt;
639
640 if( aWildCard )
641 *aWildCard = fileWildcard;
642
643 return ret;
644}
645
646
648{
649 if( NetlistUpdateOpt() )
651
652 EESCHEMA_SETTINGS* cfg = dynamic_cast<EESCHEMA_SETTINGS*>( Kiface().KifaceSettings() );
653 wxASSERT( cfg );
654
655 if( !cfg )
656 return;
657
658 cfg->m_NetlistPanel.plugins.clear();
659
660 // Update existing custom pages
661 for( int ii = 0; ii < CUSTOMPANEL_COUNTMAX; ii++ )
662 {
664
665 if( currPage == nullptr )
666 break;
667
668 wxString title = currPage->m_TitleStringCtrl->GetValue();
669 wxString command = currPage->m_CommandStringCtrl->GetValue();
670
671 if( title.IsEmpty() || command.IsEmpty() )
672 continue;
673
674 cfg->m_NetlistPanel.plugins.emplace_back( title, wxEmptyString );
675 cfg->m_NetlistPanel.plugins.back().command = command;
676 }
677}
678
679
680void DIALOG_EXPORT_NETLIST::OnDelGenerator( wxCommandEvent& event )
681{
682 EXPORT_NETLIST_PAGE* currPage = (EXPORT_NETLIST_PAGE*) m_NoteBook->GetCurrentPage();
683
684 if( !currPage->IsCustom() )
685 return;
686
687 currPage->m_CommandStringCtrl->SetValue( wxEmptyString );
688 currPage->m_TitleStringCtrl->SetValue( wxEmptyString );
689
691
692 if( IsQuasiModal() )
694 else
695 EndDialog( NET_PLUGIN_CHANGE );
696}
697
698
699void DIALOG_EXPORT_NETLIST::OnAddGenerator( wxCommandEvent& event )
700{
702
703 if( dlg.ShowModal() != wxID_OK )
704 return;
705
706 // Creates a new custom plugin page
707 wxString title = dlg.GetGeneratorTitle();
708
709 // Verify it does not exists
710 int netTypeId = PANELCUSTOMBASE; // the first not used type id
711 EXPORT_NETLIST_PAGE* currPage;
712
713 for( int ii = 0; ii < CUSTOMPANEL_COUNTMAX; ii++ )
714 {
715 netTypeId = PANELCUSTOMBASE + ii;
716 currPage = m_PanelNetType[ii + PANELCUSTOMBASE];
717
718 if( currPage == nullptr )
719 break;
720
721 if( currPage->GetPageNetFmtName() == title )
722 {
723 wxMessageBox( _("This plugin already exists.") );
724 return;
725 }
726 }
727
728 wxString cmd = dlg.GetGeneratorTCommandLine();
729 currPage = AddOneCustomPage( title,cmd, (NETLIST_TYPE_ID)netTypeId );
730 m_PanelNetType[netTypeId] = currPage;
732
733 if( IsQuasiModal() )
735 else
736 EndDialog( NET_PLUGIN_CHANGE );
737}
738
739
742{
743 m_Parent = parent;
745 GetSizer()->SetSizeHints( this );
746}
747
748
750{
751 if( !wxDialog::TransferDataFromWindow() )
752 return false;
753
754 if( m_textCtrlCommand->GetValue() == wxEmptyString )
755 {
756 wxMessageBox( _( "You must provide a netlist generator command string" ) );
757 return false;
758 }
759
760 if( m_textCtrlName->GetValue() == wxEmptyString )
761 {
762 wxMessageBox( _( "You must provide a netlist generator title" ) );
763 return false;
764 }
765
766 return true;
767}
768
769
771{
772 wxString FullFileName, Path;
773
774#ifndef __WXMAC__
775 Path = Pgm().GetExecutablePath();
776#else
777 Path = PATHS::GetOSXKicadDataDir() + wxT( "/plugins" );
778#endif
779
780 FullFileName = wxFileSelector( _( "Generator File" ), Path, FullFileName,
781 wxEmptyString, wxFileSelectorDefaultWildcardStr,
782 wxFD_OPEN, this );
783
784 if( FullFileName.IsEmpty() )
785 return;
786
787 // Creates a default command line, suitable for external tool xslproc or python, based on
788 // the plugin extension ("xsl" or "exe" or "py")
789 wxString cmdLine;
790 wxFileName fn( FullFileName );
791 wxString ext = fn.GetExt();
792
793 if( ext == wxT( "xsl" ) )
794 cmdLine.Printf( wxT( "xsltproc -o \"%%O\" \"%s\" \"%%I\"" ), FullFileName );
795 else if( ext == wxT( "exe" ) || ext.IsEmpty() )
796 cmdLine.Printf( wxT( "\"%s\" > \"%%O\" < \"%%I\"" ), FullFileName );
797 else if( ext == wxT( "py" ) || ext.IsEmpty() )
798 cmdLine.Printf( wxT( "python \"%s\" \"%%I\" \"%%O\"" ), FullFileName );
799 else
800 cmdLine.Printf( wxT( "\"%s\"" ), FullFileName );
801
802 m_textCtrlCommand->SetValue( cmdLine );
803
804 // We need a title for this panel
805 // Propose a default value if empty ( i.e. the short filename of the script)
806 if( m_textCtrlName->GetValue().IsEmpty() )
807 m_textCtrlName->SetValue( fn.GetName() );
808}
809
810
812{
813 EXPORT_NETLIST_PAGE* currPage = (EXPORT_NETLIST_PAGE*) m_NoteBook->GetCurrentPage();
814
815 if( currPage == nullptr )
816 return;
817
818 m_buttonDelGenerator->Enable( currPage->IsCustom() );
819}
820
821
823{
824 DIALOG_EXPORT_NETLIST dlg( aCaller );
825
826 int ret = dlg.ShowModal();
827 aCaller->SaveProjectLocalSettings();
828
829 return ret;
830}
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
EXPORT_NETLIST_PAGE * m_PanelNetType[5+CUSTOMPANEL_COUNTMAX]
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 *parent)
void SetupStandardButtons(std::map< int, wxString > aLabels={})
bool IsQuasiModal() const
Definition: dialog_shim.h:106
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...
virtual void ClearMsgPanel()
Clear all messages from the message panel.
PANEL_NETLIST m_NetlistPanel
const wxString GetPageNetFmtName()
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
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
A pure virtual class used to derive REPORTER objects from.
Definition: reporter.h:71
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:108
virtual REPORTER & Report(const wxString &aText, SEVERITY aSeverity=RPT_SEVERITY_UNDEFINED)=0
Report a string with a given severity.
These settings were stored in SCH_BASE_FRAME previously.
wxString GetFileName() const override
Helper to retrieve the filename from the root sheet screen.
Definition: schematic.cpp:199
SCHEMATIC_SETTINGS & Settings() const
Definition: schematic.cpp:205
Schematic editor (Eeschema) main window.
void OnModify() override
Must be called after a schematic change in order to set the "modify" flag and update other data struc...
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)
@ ID_RUN_SIMULATOR
@ ID_SAVE_ALL_VOLTAGES
@ ID_SAVE_ALL_CURRENTS
@ ID_CUR_SHEET_AS_ROOT
@ ID_SAVE_ALL_DISSIPATIONS
@ ID_CREATE_NETLIST
@ PANELSPICEMODEL
@ PANELORCADPCB2
@ PANELCUSTOMBASE
#define CUSTOMPANEL_COUNTMAX
int InvokeDialogNetList(SCH_EDIT_FRAME *aCaller)
#define _(s)
@ ID_END_EESCHEMA_ID_LIST
Definition: eeschema_id.h:83
const std::string SpiceFileExtension
const std::string CadstarNetlistFileExtension
const std::string NetlistFileExtension
const std::string OrCadPcb2NetlistFileExtension
wxString NetlistFileWildcard()
wxString OrCadPcb2NetlistFileWildcard()
wxString CadstarNetlistFileWildcard()
wxString AllFilesWildcard()
wxString SpiceNetlistFileWildcard()
#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_SPICE_MODEL
Definition: netlist.h:42
@ NET_TYPE_PCBNEW
Definition: netlist.h:38
@ NET_TYPE_CUSTOM1
Definition: netlist.h:43
see class PGM_BASE
@ RPT_SEVERITY_ERROR
@ RPT_SEVERITY_INFO
@ RPT_SEVERITY_ACTION
KIWAY Kiway & Pgm(), KFCTL_STANDALONE
The global Program "get" accessor.
Definition: single_top.cpp:111
std::vector< NETLIST_PLUGIN_SETTINGS > plugins
Definition of file extensions used in Kicad.