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 (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#include <wx/txtstrm.h>
56
57#include <thread>
58
59
60#define CUSTOMPANEL_COUNTMAX 8 // Max number of netlist plugins
61
62
63/* panel (notebook page) identifiers
64 * if modified, fix also the DEFINED_NETLISTS_COUNT value
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 PANELSPICE, /* Handle Netlist format Spice */
74 PANELSPICEMODEL, /* Handle Netlist format Spice Model (subcircuit) */
75 PANELCUSTOMBASE /* First auxiliary panel (custom netlists).
76 * others use PANELCUSTOMBASE+1, PANELCUSTOMBASE+2.. */
77};
78
79// The count of panels for internally defined netlist formats
80// (the max count of panel is DEFINED_NETLISTS_COUNT+CUSTOMPANEL_COUNTMAX)
81#define DEFINED_NETLISTS_COUNT 6
82
83/* wxPanels for creating the NoteBook pages for each netlist format: */
84class EXPORT_NETLIST_PAGE : public wxPanel
85{
86
87public:
97 EXPORT_NETLIST_PAGE( wxNotebook* aParent, const wxString& aTitle,
98 NETLIST_TYPE_ID aIdNetType, bool aCustom );
100
104 const wxString GetPageNetFmtName() { return m_pageNetFmtName; }
105
107 // opt to reformat passive component values (e.g. 1M -> 1Meg):
108 wxCheckBox* m_CurSheetAsRoot;
109 wxCheckBox* m_SaveAllVoltages;
110 wxCheckBox* m_SaveAllCurrents;
114 wxTextCtrl* m_TitleStringCtrl;
115 wxBoxSizer* m_LeftBoxSizer;
116 wxBoxSizer* m_RightBoxSizer;
118 wxBoxSizer* m_LowBoxSizer;
119
120 bool IsCustom() const { return m_custom; }
121
122private:
124
126};
127
128
129/* Dialog frame for creating netlists */
131{
132public:
135
136private:
137 void InstallCustomPages();
138 EXPORT_NETLIST_PAGE* AddOneCustomPage( const wxString& aTitle, const wxString& aCommandString,
139 NETLIST_TYPE_ID aNetTypeId );
140 void InstallPageSpice();
142
143 bool TransferDataFromWindow() override;
144 bool NetlistUpdateOpt();
145
147
148 // Called when changing the notebook page (and therefore the current netlist format)
149 void OnNetlistTypeSelection( wxNotebookEvent& event ) override;
150
154 void OnAddGenerator( wxCommandEvent& event ) override;
155
159 void OnDelGenerator( wxCommandEvent& event ) override;
160
165
175 bool FilenamePrms( NETLIST_TYPE_ID aType, wxString* aExt, wxString* aWildCard );
176
177public:
180};
181
182
184{
185public:
187
188 const wxString GetGeneratorTitle() { return m_textCtrlName->GetValue(); }
189 const wxString GetGeneratorTCommandLine() { return m_textCtrlCommand->GetValue(); }
190
191 bool TransferDataFromWindow() override;
192
193private:
194 /*
195 * Browse plugin files, and set m_CommandStringCtrl field
196 */
197 void OnBrowseGenerators( wxCommandEvent& event ) override;
198
200};
201
202
203/* Event id for notebook page buttons: */
212
213
214EXPORT_NETLIST_PAGE::EXPORT_NETLIST_PAGE( wxNotebook* aParent, const wxString& aTitle,
215 NETLIST_TYPE_ID aIdNetType, bool aCustom ) :
216 wxPanel( aParent, -1, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL )
217{
218 m_IdNetType = aIdNetType;
219 m_pageNetFmtName = aTitle;
220 m_CommandStringCtrl = nullptr;
221 m_CurSheetAsRoot = nullptr;
222 m_TitleStringCtrl = nullptr;
223 m_SaveAllVoltages = nullptr;
224 m_SaveAllCurrents = nullptr;
225 m_SaveAllDissipations = nullptr;
227 m_custom = aCustom;
228
229 aParent->AddPage( this, aTitle, false );
230
231 wxBoxSizer* MainBoxSizer = new wxBoxSizer( wxVERTICAL );
232 SetSizer( MainBoxSizer );
233 wxBoxSizer* UpperBoxSizer = new wxBoxSizer( wxHORIZONTAL );
234 m_LowBoxSizer = new wxBoxSizer( wxVERTICAL );
235 MainBoxSizer->Add( UpperBoxSizer, 0, wxGROW | wxALL, 5 );
236 MainBoxSizer->Add( m_LowBoxSizer, 0, wxGROW | wxALL, 5 );
237
238 m_LeftBoxSizer = new wxBoxSizer( wxVERTICAL );
239 m_RightBoxSizer = new wxBoxSizer( wxVERTICAL );
240 m_RightOptionsBoxSizer = new wxBoxSizer( wxVERTICAL );
241 UpperBoxSizer->Add( m_LeftBoxSizer, 0, wxGROW | wxALL, 5 );
242 UpperBoxSizer->Add( m_RightBoxSizer, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5 );
243 UpperBoxSizer->Add( m_RightOptionsBoxSizer, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5 );
244}
245
246
249{
250 m_Parent = parent;
251
253
254 for( EXPORT_NETLIST_PAGE*& page : m_PanelNetType )
255 page = nullptr;
256
257 // Add notebook pages:
259 new EXPORT_NETLIST_PAGE( m_NoteBook, wxT( "KiCad" ), NET_TYPE_PCBNEW, false );
260
262 new EXPORT_NETLIST_PAGE( m_NoteBook, wxT( "OrcadPCB2" ), NET_TYPE_ORCADPCB2, false );
263
265 new EXPORT_NETLIST_PAGE( m_NoteBook, wxT( "Allegro" ), NET_TYPE_ALLEGRO, false );
266
268 new EXPORT_NETLIST_PAGE( m_NoteBook, wxT( "CadStar" ), NET_TYPE_CADSTAR, false );
269
273
274 SetupStandardButtons( { { wxID_OK, _( "Export Netlist" ) },
275 { wxID_CANCEL, _( "Close" ) } } );
276
277 for( int ii = 0; (ii < 4 + CUSTOMPANEL_COUNTMAX) && m_PanelNetType[ii]; ++ii )
278 {
279 if( m_PanelNetType[ii]->GetPageNetFmtName() == settings.m_NetFormatName )
280 {
281 m_NoteBook->ChangeSelection( ii );
282 break;
283 }
284 }
285
286 // Now all widgets have the size fixed, call FinishDialogSettings
288
290}
291
292
294{
296 new EXPORT_NETLIST_PAGE( m_NoteBook, wxT( "Spice" ), NET_TYPE_SPICE, false );
297
299
300 page->m_CurSheetAsRoot = new wxCheckBox( page, ID_CUR_SHEET_AS_ROOT,
301 _( "Use current sheet as root" ) );
302 page->m_CurSheetAsRoot->SetToolTip( _( "Export netlist only for the current sheet" ) );
303 page->m_CurSheetAsRoot->SetValue( settings.m_SpiceCurSheetAsRoot );
304 page->m_LeftBoxSizer->Add( page->m_CurSheetAsRoot, 0, wxGROW | wxBOTTOM | wxRIGHT, 5 );
305
306 page->m_SaveAllVoltages = new wxCheckBox( page, ID_SAVE_ALL_VOLTAGES,
307 _( "Save all voltages" ) );
308 page->m_SaveAllVoltages->SetToolTip( _( "Write a directive to save all voltages (.save all)" ) );
309 page->m_SaveAllVoltages->SetValue( settings.m_SpiceSaveAllVoltages );
310 page->m_LeftBoxSizer->Add( page->m_SaveAllVoltages, 0, wxBOTTOM | wxRIGHT, 5 );
311
312 page->m_SaveAllCurrents = new wxCheckBox( page, ID_SAVE_ALL_CURRENTS,
313 _( "Save all currents" ) );
314 page->m_SaveAllCurrents->SetToolTip( _( "Write a directive to save all currents (.probe alli)" ) );
315 page->m_SaveAllCurrents->SetValue( settings.m_SpiceSaveAllCurrents );
316 page->m_LeftBoxSizer->Add( page->m_SaveAllCurrents, 0, wxBOTTOM | wxRIGHT, 5 );
317
318 page->m_SaveAllDissipations = new wxCheckBox( page, ID_SAVE_ALL_DISSIPATIONS,
319 _( "Save all power dissipations" ) );
320 page->m_SaveAllDissipations->SetToolTip( _( "Write directives to save power dissipation of all items (.probe p(<item>))" ) );
321 page->m_SaveAllDissipations->SetValue( settings.m_SpiceSaveAllDissipations );
322 page->m_LeftBoxSizer->Add( page->m_SaveAllDissipations, 0, wxBOTTOM | wxRIGHT, 5 );
323
324
325 page->m_RunExternalSpiceCommand = new wxCheckBox( page, ID_RUN_SIMULATOR,
326 _( "Run external simulator command:" ) );
327 wxString simulatorCommand = settings.m_SpiceCommandString;
328 page->m_RunExternalSpiceCommand->SetToolTip( _( "Enter the command line to run SPICE\n"
329 "Usually '<path to SPICE binary> \"%I\"'\n"
330 "%I will be replaced by the netlist filepath" ) );
331 page->m_LowBoxSizer->Add( page->m_RunExternalSpiceCommand, 0,
332 wxGROW | wxLEFT | wxRIGHT | wxBOTTOM, 5 );
333
334 page->m_CommandStringCtrl = new wxTextCtrl( page, -1, simulatorCommand,
335 wxDefaultPosition, wxDefaultSize );
336
337 page->m_CommandStringCtrl->SetInsertionPoint( 1 );
338 page->m_LowBoxSizer->Add( page->m_CommandStringCtrl, 0,
339 wxGROW | wxLEFT | wxRIGHT | wxBOTTOM, 5 );
340}
341
342
344{
346 new EXPORT_NETLIST_PAGE( m_NoteBook, wxT( "Spice Model" ), NET_TYPE_SPICE_MODEL, false );
347
349
350 page->m_CurSheetAsRoot = new wxCheckBox( page, ID_CUR_SHEET_AS_ROOT,
351 _( "Use current sheet as root" ) );
352 page->m_CurSheetAsRoot->SetToolTip( _( "Export netlist only for the current sheet" ) );
353 page->m_CurSheetAsRoot->SetValue( settings.m_SpiceModelCurSheetAsRoot );
354 page->m_LeftBoxSizer->Add( page->m_CurSheetAsRoot, 0, wxGROW | wxBOTTOM | wxRIGHT, 5 );
355}
356
357
359{
360 EXPORT_NETLIST_PAGE* currPage;
361 EESCHEMA_SETTINGS* cfg = dynamic_cast<EESCHEMA_SETTINGS*>( Kiface().KifaceSettings() );
362 wxASSERT( cfg );
363
364 if( cfg )
365 {
366 for( size_t i = 0; i < CUSTOMPANEL_COUNTMAX && i < cfg->m_NetlistPanel.plugins.size(); i++ )
367 {
368 // pairs of (title, command) are stored
369 wxString title = cfg->m_NetlistPanel.plugins[i].name;
370
371 if( i >= cfg->m_NetlistPanel.plugins.size() )
372 break; // No more panel to install
373
374 wxString command = cfg->m_NetlistPanel.plugins[i].command;
375
376 currPage = AddOneCustomPage( title, command,
377 static_cast<NETLIST_TYPE_ID>( NET_TYPE_CUSTOM1 + i ) );
378
379 m_PanelNetType[PANELCUSTOMBASE + i] = currPage;
380 }
381 }
382}
383
384
386 const wxString& aCommandString,
387 NETLIST_TYPE_ID aNetTypeId )
388{
389 EXPORT_NETLIST_PAGE* currPage = new EXPORT_NETLIST_PAGE( m_NoteBook, aTitle, aNetTypeId, true );
390
391 currPage->m_LowBoxSizer->Add( new wxStaticText( currPage, -1, _( "Title:" ) ), 0,
392 wxGROW | wxLEFT | wxRIGHT | wxTOP, 5 );
393
394 currPage->m_TitleStringCtrl = new wxTextCtrl( currPage, -1, aTitle,
395 wxDefaultPosition, wxDefaultSize );
396
397 currPage->m_TitleStringCtrl->SetInsertionPoint( 1 );
398 currPage->m_LowBoxSizer->Add( currPage->m_TitleStringCtrl, 0,
399 wxGROW | wxTOP | wxLEFT | wxRIGHT | wxBOTTOM, 5 );
400
401 currPage->m_LowBoxSizer->Add( new wxStaticText( currPage, -1, _( "Netlist command:" ) ), 0,
402 wxGROW | wxLEFT | wxRIGHT | wxTOP, 5 );
403
404 currPage->m_CommandStringCtrl = new wxTextCtrl( currPage, -1, aCommandString,
405 wxDefaultPosition, wxDefaultSize );
406
407 currPage->m_CommandStringCtrl->SetInsertionPoint( 1 );
408 currPage->m_LowBoxSizer->Add( currPage->m_CommandStringCtrl, 0,
409 wxGROW | wxTOP | wxLEFT | wxRIGHT | wxBOTTOM, 5 );
410
411 return currPage;
412}
413
414
416{
418}
419
420
422{
423 bool changed = false;
424
425 bool saveAllVoltages = m_PanelNetType[ PANELSPICE ]->m_SaveAllVoltages->IsChecked();
426 bool saveAllCurrents = m_PanelNetType[ PANELSPICE ]->m_SaveAllCurrents->IsChecked();
427 bool saveAllDissipations = m_PanelNetType[ PANELSPICE ]->m_SaveAllDissipations->IsChecked();
428 wxString spiceCmdString = m_PanelNetType[ PANELSPICE ]->m_CommandStringCtrl->GetValue();
429 bool curSheetAsRoot = m_PanelNetType[ PANELSPICE ]->m_CurSheetAsRoot->GetValue();
430 bool spiceModelCurSheetAsRoot = m_PanelNetType[ PANELSPICEMODEL ]->m_CurSheetAsRoot->GetValue();
431
433 wxString netFormatName = m_PanelNetType[m_NoteBook->GetSelection()]->GetPageNetFmtName();
434
435 changed |= ( settings.m_SpiceSaveAllVoltages != saveAllVoltages );
436 changed |= ( settings.m_SpiceSaveAllCurrents != saveAllCurrents );
437 changed |= ( settings.m_SpiceSaveAllDissipations != saveAllDissipations );
438 changed |= ( settings.m_SpiceCommandString != spiceCmdString );
439 changed |= ( settings.m_SpiceCurSheetAsRoot != curSheetAsRoot );
440 changed |= ( settings.m_SpiceModelCurSheetAsRoot != spiceModelCurSheetAsRoot );
441 changed |= ( settings.m_NetFormatName != netFormatName );
442
443 settings.m_SpiceSaveAllVoltages = saveAllVoltages;
444 settings.m_SpiceSaveAllCurrents = saveAllCurrents;
445 settings.m_SpiceSaveAllDissipations = saveAllDissipations;
446 settings.m_SpiceCommandString = spiceCmdString;
447 settings.m_SpiceCurSheetAsRoot = curSheetAsRoot;
448 settings.m_SpiceModelCurSheetAsRoot = spiceModelCurSheetAsRoot;
449 settings.m_NetFormatName = netFormatName;
450
451 return changed;
452}
453
454
456{
457 wxFileName fn;
458 wxString fileWildcard;
459 wxString fileExt;
460 wxString title = _( "Save Netlist File" );
461
462 if( NetlistUpdateOpt() )
464
465 EXPORT_NETLIST_PAGE* currPage;
466 currPage = (EXPORT_NETLIST_PAGE*) m_NoteBook->GetCurrentPage();
467
468 bool runExternalSpiceCommand = false;
469 unsigned netlist_opt = 0;
470
471 // Calculate the netlist filename
473 FilenamePrms( currPage->m_IdNetType, &fileExt, &fileWildcard );
474
475 // Set some parameters
476 switch( currPage->m_IdNetType )
477 {
478 case NET_TYPE_SPICE:
479 // Set spice netlist options:
481
482 if( currPage->m_SaveAllVoltages->GetValue() )
484
485 if( currPage->m_SaveAllCurrents->GetValue() )
487
488 if( currPage->m_SaveAllDissipations->GetValue() )
490
491 if( currPage->m_CurSheetAsRoot->GetValue() )
493
494 runExternalSpiceCommand = currPage->m_RunExternalSpiceCommand->GetValue();
495 break;
496
498 if( currPage->m_CurSheetAsRoot->GetValue() )
500
501 break;
502
503 case NET_TYPE_CADSTAR:
504 break;
505
506 case NET_TYPE_PCBNEW:
507 break;
508
510 break;
511
512 case NET_TYPE_ALLEGRO:
513 break;
514
515 default: // custom, NET_TYPE_CUSTOM1 and greater
516 {
517 title.Printf( _( "%s Export" ), currPage->m_TitleStringCtrl->GetValue() );
518 break;
519 }
520 }
521
522 wxString fullpath;
523
524 if( runExternalSpiceCommand )
525 {
526 fn.SetExt( SpiceFileExtension );
527 fullpath = fn.GetFullPath();
528 }
529 else
530 {
531 fn.SetExt( fileExt );
532
533 if( fn.GetPath().IsEmpty() )
534 fn.SetPath( wxPathOnly( Prj().GetProjectFullName() ) );
535
536 wxString fullname = fn.GetFullName();
537 wxString path = fn.GetPath();
538
539 // full name does not and should not include the path, per wx docs.
540 wxFileDialog dlg( this, title, path, fullname, fileWildcard, wxFD_SAVE );
541
542 if( dlg.ShowModal() == wxID_CANCEL )
543 return false;
544
545 fullpath = dlg.GetPath(); // directory + filename
546 }
547
549 REPORTER& reporter = m_MessagesBox->Reporter();
550
551 if( currPage->m_CommandStringCtrl )
552 m_Parent->SetNetListerCommand( currPage->m_CommandStringCtrl->GetValue() );
553 else
554 m_Parent->SetNetListerCommand( wxEmptyString );
555
556 if( !m_Parent->ReadyToNetlist( _( "Exporting netlist requires a fully annotated schematic." ) ) )
557 return false;
558
559 m_Parent->WriteNetListFile( currPage->m_IdNetType, fullpath, netlist_opt, &reporter );
560
561 if( runExternalSpiceCommand )
562 {
563 // Build the command line
564 wxString commandLine = m_Parent->Schematic().Settings().m_SpiceCommandString;
565 commandLine.Replace( wxS( "%I" ), fullpath, true );
566 commandLine.Trim( true ).Trim( false );
567
568 if( !commandLine.IsEmpty() )
569 {
570 wxProcess* process = new wxProcess( GetEventHandler(), wxID_ANY );
571 process->Redirect();
572 wxExecute( commandLine, wxEXEC_ASYNC, process );
573
574 reporter.ReportHead( commandLine, RPT_SEVERITY_ACTION );
575 process->Activate();
576
577 std::this_thread::sleep_for( std::chrono::seconds( 1 ) ); // give the process time to start and output any data or errors
578
579 if( process->IsInputAvailable() )
580 {
581 wxInputStream* in = process->GetInputStream();
582 wxTextInputStream textstream( *in );
583
584 while( in->CanRead() )
585 {
586 wxString line = textstream.ReadLine();
587
588 if( !line.IsEmpty() )
589 reporter.Report( line, RPT_SEVERITY_INFO );
590 }
591 }
592
593 if( process->IsErrorAvailable() )
594 {
595 wxInputStream* err = process->GetErrorStream();
596 wxTextInputStream textstream( *err );
597
598 while( err->CanRead() )
599 {
600 wxString line = textstream.ReadLine();
601
602 if( !line.IsEmpty() )
603 {
604 if( line.EndsWith( wxS( "failed with error 2!" ) ) ) // ENOENT
605 {
606 reporter.Report( _( "external simulator not found" ), RPT_SEVERITY_ERROR );
607 reporter.Report( _( "Note: command line is usually: "
608 "<tt>&lt;path to SPICE binary&gt; \"%I\"</tt>" ),
610 }
611 else if( line.EndsWith( wxS( "failed with error 8!" ) ) ) // ENOEXEC
612 {
613 reporter.Report( _( "external simulator has the wrong format or "
614 "architecture" ), RPT_SEVERITY_ERROR );
615 }
616 else if( line.EndsWith( "failed with error 13!" ) ) // EACCES
617 {
618 reporter.Report( _( "permission denied" ), RPT_SEVERITY_ERROR );
619 }
620 else
621 {
622 reporter.Report( line, RPT_SEVERITY_ERROR );
623 }
624 }
625 }
626 }
627
628 process->CloseOutput();
629 process->Detach();
630
631 // Do not delete process, it will delete itself when it terminates
632 }
633 }
634
636
637 return !runExternalSpiceCommand;
638}
639
640
641bool DIALOG_EXPORT_NETLIST::FilenamePrms( NETLIST_TYPE_ID aType, wxString * aExt, wxString * aWildCard )
642{
643 wxString fileExt;
644 wxString fileWildcard;
645 bool ret = true;
646
647 switch( aType )
648 {
649 case NET_TYPE_SPICE:
650 fileExt = SpiceFileExtension;
651 fileWildcard = SpiceNetlistFileWildcard();
652 break;
653
654 case NET_TYPE_CADSTAR:
656 fileWildcard = CadstarNetlistFileWildcard();
657 break;
658
661 fileWildcard = OrCadPcb2NetlistFileWildcard();
662 break;
663
664 case NET_TYPE_PCBNEW:
665 fileExt = NetlistFileExtension;
666 fileWildcard = NetlistFileWildcard();
667 break;
668
669 case NET_TYPE_ALLEGRO:
671 fileWildcard = AllegroNetlistFileWildcard();
672 break;
673
674 default: // custom, NET_TYPE_CUSTOM1 and greater
675 fileWildcard = AllFilesWildcard();
676 ret = false;
677 }
678
679 if( aExt )
680 *aExt = fileExt;
681
682 if( aWildCard )
683 *aWildCard = fileWildcard;
684
685 return ret;
686}
687
688
690{
691 if( NetlistUpdateOpt() )
693
694 EESCHEMA_SETTINGS* cfg = dynamic_cast<EESCHEMA_SETTINGS*>( Kiface().KifaceSettings() );
695 wxASSERT( cfg );
696
697 if( !cfg )
698 return;
699
700 cfg->m_NetlistPanel.plugins.clear();
701
702 // Update existing custom pages
703 for( int ii = 0; ii < CUSTOMPANEL_COUNTMAX; ii++ )
704 {
706
707 if( currPage == nullptr )
708 break;
709
710 wxString title = currPage->m_TitleStringCtrl->GetValue();
711 wxString command = currPage->m_CommandStringCtrl->GetValue();
712
713 if( title.IsEmpty() || command.IsEmpty() )
714 continue;
715
716 cfg->m_NetlistPanel.plugins.emplace_back( title, wxEmptyString );
717 cfg->m_NetlistPanel.plugins.back().command = command;
718 }
719}
720
721
722void DIALOG_EXPORT_NETLIST::OnDelGenerator( wxCommandEvent& event )
723{
724 EXPORT_NETLIST_PAGE* currPage = (EXPORT_NETLIST_PAGE*) m_NoteBook->GetCurrentPage();
725
726 if( !currPage->IsCustom() )
727 return;
728
729 currPage->m_CommandStringCtrl->SetValue( wxEmptyString );
730 currPage->m_TitleStringCtrl->SetValue( wxEmptyString );
731
733
734 if( IsQuasiModal() )
736 else
737 EndDialog( NET_PLUGIN_CHANGE );
738}
739
740
741void DIALOG_EXPORT_NETLIST::OnAddGenerator( wxCommandEvent& event )
742{
744
745 if( dlg.ShowModal() != wxID_OK )
746 return;
747
748 // Creates a new custom plugin page
749 wxString title = dlg.GetGeneratorTitle();
750
751 // Verify it does not exists
752 int netTypeId = PANELCUSTOMBASE; // the first not used type id
753 EXPORT_NETLIST_PAGE* currPage;
754
755 for( int ii = 0; ii < CUSTOMPANEL_COUNTMAX; ii++ )
756 {
757 netTypeId = PANELCUSTOMBASE + ii;
758 currPage = m_PanelNetType[ii + PANELCUSTOMBASE];
759
760 if( currPage == nullptr )
761 break;
762
763 if( currPage->GetPageNetFmtName() == title )
764 {
765 wxMessageBox( _("This plugin already exists.") );
766 return;
767 }
768 }
769
770 wxString cmd = dlg.GetGeneratorTCommandLine();
771 currPage = AddOneCustomPage( title,cmd, (NETLIST_TYPE_ID)netTypeId );
772 m_PanelNetType[netTypeId] = currPage;
774
775 if( IsQuasiModal() )
777 else
778 EndDialog( NET_PLUGIN_CHANGE );
779}
780
781
784{
785 m_Parent = parent;
787 GetSizer()->SetSizeHints( this );
788}
789
790
792{
793 if( !wxDialog::TransferDataFromWindow() )
794 return false;
795
796 if( m_textCtrlCommand->GetValue() == wxEmptyString )
797 {
798 wxMessageBox( _( "You must provide a netlist generator command string" ) );
799 return false;
800 }
801
802 if( m_textCtrlName->GetValue() == wxEmptyString )
803 {
804 wxMessageBox( _( "You must provide a netlist generator title" ) );
805 return false;
806 }
807
808 return true;
809}
810
811
813{
814 wxString FullFileName, Path;
815
816#ifndef __WXMAC__
817 Path = Pgm().GetExecutablePath();
818#else
819 Path = PATHS::GetOSXKicadDataDir() + wxT( "/plugins" );
820#endif
821
822 FullFileName = wxFileSelector( _( "Generator File" ), Path, FullFileName,
823 wxEmptyString, wxFileSelectorDefaultWildcardStr,
824 wxFD_OPEN, this );
825
826 if( FullFileName.IsEmpty() )
827 return;
828
829 // Creates a default command line, suitable for external tool xslproc or python, based on
830 // the plugin extension ("xsl" or "exe" or "py")
831 wxString cmdLine;
832 wxFileName fn( FullFileName );
833 wxString ext = fn.GetExt();
834
835 if( ext == wxT( "xsl" ) )
836 cmdLine.Printf( wxT( "xsltproc -o \"%%O\" \"%s\" \"%%I\"" ), FullFileName );
837 else if( ext == wxT( "exe" ) || ext.IsEmpty() )
838 cmdLine.Printf( wxT( "\"%s\" > \"%%O\" < \"%%I\"" ), FullFileName );
839 else if( ext == wxT( "py" ) || ext.IsEmpty() )
840 cmdLine.Printf( wxT( "python \"%s\" \"%%I\" \"%%O\"" ), FullFileName );
841 else
842 cmdLine.Printf( wxT( "\"%s\"" ), FullFileName );
843
844 m_textCtrlCommand->SetValue( cmdLine );
845
846 // We need a title for this panel
847 // Propose a default value if empty ( i.e. the short filename of the script)
848 if( m_textCtrlName->GetValue().IsEmpty() )
849 m_textCtrlName->SetValue( fn.GetName() );
850}
851
852
854{
855 EXPORT_NETLIST_PAGE* currPage = (EXPORT_NETLIST_PAGE*) m_NoteBook->GetCurrentPage();
856
857 if( currPage == nullptr )
858 return;
859
860 m_buttonDelGenerator->Enable( currPage->IsCustom() );
861}
862
863
865{
866 DIALOG_EXPORT_NETLIST dlg( aCaller );
867
868 int ret = dlg.ShowModal();
869 aCaller->SaveProjectLocalSettings();
870
871 return ret;
872}
static PGM_BASE * process
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
void OnAddGenerator(wxCommandEvent &event) override
Add a new panel for a new netlist plugin.
void OnNetlistTypeSelection(wxNotebookEvent &event) override
EXPORT_NETLIST_PAGE * m_PanelNetType[DEFINED_NETLISTS_COUNT+CUSTOMPANEL_COUNTMAX]
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:281
SCHEMATIC_SETTINGS & Settings() const
Definition: schematic.cpp:287
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)
@ PANELSPICEMODEL
@ 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
#define DEFINED_NETLISTS_COUNT
#define CUSTOMPANEL_COUNTMAX
int InvokeDialogNetList(SCH_EDIT_FRAME *aCaller)
#define _(s)
@ ID_END_EESCHEMA_ID_LIST
Definition: eeschema_id.h:71
const std::string SpiceFileExtension
const std::string CadstarNetlistFileExtension
const std::string NetlistFileExtension
const std::string OrCadPcb2NetlistFileExtension
const std::string AllegroNetlistFileExtension
wxString NetlistFileWildcard()
wxString OrCadPcb2NetlistFileWildcard()
wxString CadstarNetlistFileWildcard()
wxString AllFilesWildcard()
wxString SpiceNetlistFileWildcard()
wxString AllegroNetlistFileWildcard()
#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_CUSTOM1
Definition: netlist.h:44
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:119
std::vector< NETLIST_PLUGIN_SETTINGS > plugins
Definition of file extensions used in Kicad.