54#include <wx/checkbox.h>
55#include <wx/filedlg.h>
57#include <wx/process.h>
59#include <wx/txtstrm.h>
68std::vector<wxString> SplitCommandLine(
const wxString& aCommand )
70 std::vector<wxString> args;
72 bool inSingle =
false;
73 bool inDouble =
false;
74 bool argStarted =
false;
76 for( wxUniChar c : aCommand )
78 if( c ==
'"' && !inSingle )
85 if( c ==
'\'' && !inDouble )
92 if( ( c ==
' ' || c ==
'\t' || c ==
'\n' || c ==
'\r' ) && !inSingle && !inDouble )
94 if( argStarted || !current.IsEmpty() )
96 args.emplace_back( current );
108 if( argStarted || !current.IsEmpty() )
109 args.emplace_back( current );
116#define CUSTOMPANEL_COUNTMAX 8
218 wxPanel( aParent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ),
231 aParent->AddPage(
this, aTitle,
false );
233 wxBoxSizer* MainBoxSizer =
new wxBoxSizer( wxVERTICAL );
234 SetSizer( MainBoxSizer );
235 wxBoxSizer* UpperBoxSizer =
new wxBoxSizer( wxHORIZONTAL );
237 MainBoxSizer->Add( UpperBoxSizer, 0, wxEXPAND | wxALL, 5 );
244 UpperBoxSizer->Add(
m_RightBoxSizer, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5 );
267 wxStaticText* label =
nullptr;
270 label =
new wxStaticText( page, wxID_ANY,
_(
"Export netlist in KiCad format" ) );
275 label =
new wxStaticText( page, wxID_ANY,
_(
"Export netlist in OrcadPCB2 format" ) );
280 label =
new wxStaticText( page, wxID_ANY,
_(
"Export netlist in Allegro format" ) );
285 label =
new wxStaticText( page, wxID_ANY,
_(
"Export netlist in CadStar format" ) );
290 label =
new wxStaticText( page, wxID_ANY,
_(
"Export netlist in PADS format" ) );
304 { wxID_CANCEL,
_(
"Close" ) } } );
308 SetTitle(
m_job->GetSettingsDialogTitle() );
347 wxStaticText* label =
new wxStaticText( pg, wxID_ANY,
_(
"Export netlist in SPICE format" ) );
351 pg->
m_CurSheetAsRoot->SetToolTip(
_(
"Export netlist only for the current sheet" ) );
355 pg->
m_SaveAllVoltages->SetToolTip(
_(
"Write a directive to save all voltages (.save all)" ) );
359 pg->
m_SaveAllCurrents->SetToolTip(
_(
"Write a directive to save all currents (.probe alli)" ) );
364 "(.probe p(<item>))" ) );
368 pg->
m_SaveAllEvents->SetToolTip(
_(
"If not set, write a directive to prevent the saving of digital event data "
375 "Usually '<path to SPICE binary> \"%I\"'\n"
376 "%I will be replaced by the netlist filepath" ) );
392 wxStaticText* label =
new wxStaticText( pg, wxID_ANY,
_(
"Export netlist as a SPICE .subckt model" ) );
393 pg->m_LeftBoxSizer->Add( label, 0, wxBOTTOM, 10 );
396 pg->m_CurSheetAsRoot->SetToolTip(
_(
"Export netlist only for the current sheet" ) );
397 pg->m_LeftBoxSizer->Add( pg->m_CurSheetAsRoot, 0, wxEXPAND | wxBOTTOM | wxRIGHT, 5 );
422 const wxString& aCommandString,
427 pg->
m_LowBoxSizer->Add(
new wxStaticText( pg, wxID_ANY,
_(
"Title:" ) ), 0,
428 wxEXPAND | wxLEFT | wxRIGHT | wxTOP, 5 );
439 pg->
m_LowBoxSizer->Add(
new wxStaticText( pg, wxID_ANY,
_(
"Netlist command:" ) ), 0,
440 wxEXPAND | wxLEFT | wxRIGHT | wxTOP, 5 );
462 wxString fileWildcard;
464 wxString title =
_(
"Save Netlist File" );
472 m_job->format = format;
489 bool runExternalSpiceCommand =
false;
490 unsigned netlist_opt = 0;
549 if( runExternalSpiceCommand )
552 fullpath = fn.GetFullPath();
556 fn.SetExt( fileExt );
558 if( fn.GetPath().IsEmpty() )
559 fn.SetPath( wxPathOnly(
Prj().GetProjectFullName() ) );
561 wxString fullname = fn.GetFullName();
562 wxString
path = fn.GetPath();
565 wxFileDialog dlg(
this, title,
path, fullname, fileWildcard, wxFD_SAVE );
569 if( dlg.ShowModal() == wxID_CANCEL )
572 fullpath = dlg.GetPath();
583 if( !
m_editFrame->ReadyToNetlist(
_(
"Exporting netlist requires a fully annotated schematic." ) ) )
588 if( runExternalSpiceCommand )
592 commandLine.Replace( wxS(
"%I" ), fullpath,
true );
593 commandLine.Trim(
true ).Trim(
false );
595 if( !commandLine.IsEmpty() )
597 std::vector<wxString> argsStrings = SplitCommandLine( commandLine );
599 if( !argsStrings.empty() )
601 std::vector<const wxChar*> argv;
602 argv.reserve( argsStrings.size() + 1 );
604 for( wxString& arg : argsStrings )
605 argv.emplace_back( arg.wc_str() );
607 argv.emplace_back(
nullptr );
610 wxGetEnvMap( &env.env );
614 for(
const auto& [key, value] : envVars )
616 if( !value.GetValue().IsEmpty() )
617 env.env[key] = value.GetValue();
620 wxFileName netlistFile( fullpath );
622 if( !netlistFile.IsAbsolute() )
623 netlistFile.MakeAbsolute(
Prj().GetProjectPath() );
625 netlistFile.MakeAbsolute();
627 wxString cwd = netlistFile.GetPath();
634 wxProcess*
process =
new wxProcess( GetEventHandler(), wxID_ANY );
637 long pid = wxExecute( argv.data(), wxEXEC_ASYNC,
process, &env );
644 reporter.
Report(
_(
"Note: command line is usually: "
645 "<tt><path to SPICE binary> \"%I\"</tt>" ),
653 std::this_thread::sleep_for( std::chrono::seconds( 1 ) );
655 if(
process->IsInputAvailable() )
657 wxInputStream* in =
process->GetInputStream();
658 wxTextInputStream textstream( *in );
660 while( in->CanRead() )
662 wxString line = textstream.ReadLine();
664 if( !line.IsEmpty() )
669 if(
process->IsErrorAvailable() )
671 wxInputStream* err =
process->GetErrorStream();
672 wxTextInputStream textstream( *err );
674 while( err->CanRead() )
676 wxString line = textstream.ReadLine();
678 if( !line.IsEmpty() )
680 if( line.EndsWith( wxS(
"failed with error 2!" ) ) )
683 reporter.
Report(
_(
"Note: command line is usually: "
684 "<tt><path to SPICE binary> \"%I\"</tt>" ),
687 else if( line.EndsWith( wxS(
"failed with error 8!" ) ) )
689 reporter.
Report(
_(
"external simulator has the wrong format or "
692 else if( line.EndsWith(
"failed with error 13!" ) )
715 return !runExternalSpiceCommand;
722 wxString fileWildcard;
767 *aWildCard = fileWildcard;
785 wxString title = currPage->m_TitleStringCtrl->GetValue();
786 wxString command = currPage->m_CommandStringCtrl->GetValue();
788 if( title.IsEmpty() || command.IsEmpty() )
832 wxMessageBox(
_(
"This plugin already exists." ) );
846 wxMessageBox(
_(
"Maximum number of plugins already added to dialog." ) );
875 if( !wxDialog::TransferDataFromWindow() )
880 wxMessageBox(
_(
"You must provide a netlist generator title" ) );
890 wxString FullFileName, Path;
895 Path = PATHS::GetOSXKicadDataDir() + wxT(
"/plugins" );
898 FullFileName = wxFileSelector(
_(
"Generator File" ), Path, FullFileName, wxEmptyString,
899 wxFileSelectorDefaultWildcardStr, wxFD_OPEN,
this );
901 if( FullFileName.IsEmpty() )
907 wxFileName fn( FullFileName );
908 wxString ext = fn.GetExt();
910 if( ext == wxT(
"xsl" ) )
911 cmdLine.Printf( wxT(
"xsltproc -o \"%%O\" \"%s\" \"%%I\"" ), FullFileName );
912 else if( ext == wxT(
"exe" ) || ext.IsEmpty() )
913 cmdLine.Printf( wxT(
"\"%s\" > \"%%O\" < \"%%I\"" ), FullFileName );
914 else if( ext == wxT(
"py" ) || ext.IsEmpty() )
915 cmdLine.Printf( wxT(
"python \"%s\" \"%%I\" \"%%O\"" ), FullFileName );
917 cmdLine.Printf( wxT(
"\"%s\"" ), FullFileName );
932 if( currPage ==
nullptr )
KIFACE_BASE & Kiface()
Global KIFACE_BASE "get" accessor.
wxStaticText * m_staticTextOutputPath
DIALOG_EXPORT_NETLIST_BASE(wxWindow *parent, wxWindowID id=wxID_ANY, const wxString &title=_("Export Netlist"), const wxPoint &pos=wxDefaultPosition, const wxSize &size=wxSize(-1,-1), long style=wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER)
wxButton * m_buttonDelGenerator
WX_HTML_REPORT_PANEL * m_MessagesBox
wxTextCtrl * m_outputPath
wxButton * m_buttonAddGenerator
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)
void InstallPageSpiceModel()
bool TransferDataFromWindow() override
std::vector< EXPORT_NETLIST_PAGE * > m_PanelNetType
void InstallCustomPages()
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 updateGeneratorButtons()
void SetupStandardButtons(std::map< int, wxString > aLabels={})
bool IsQuasiModal() const
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
PANEL_NETLIST m_NetlistPanel
const wxString GetPageNetFmtName()
NETLIST_TYPE_ID m_IdNetType
wxCheckBox * m_SaveAllVoltages
wxString m_pageNetFmtName
wxBoxSizer * m_RightBoxSizer
wxCheckBox * m_CurSheetAsRoot
wxBoxSizer * m_LeftBoxSizer
~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
wxCheckBox * m_SaveAllEvents
wxCheckBox * m_SaveAllCurrents
wxTextCtrl * m_CommandStringCtrl
wxBoxSizer * m_RightOptionsBoxSizer
wxCheckBox * m_SaveAllDissipations
wxTextCtrl * m_TitleStringCtrl
wxBoxSizer * m_LowBoxSizer
static std::map< JOB_EXPORT_SCH_NETLIST::FORMAT, wxString > & GetFormatNameMap()
APP_SETTINGS_BASE * KifaceSettings() const
PROJECT & Prj() const
Return a reference to the PROJECT associated with this KIWAY.
NETLIST_DIALOG_ADD_GENERATOR_BASE(wxWindow *parent, wxWindowID id=wxID_ANY, const wxString &title=_("Add Script-based Netlist Exporter"), const wxPoint &pos=wxDefaultPosition, const wxSize &size=wxSize(-1,-1), long style=wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER)
wxTextCtrl * m_textCtrlCommand
wxTextCtrl * m_textCtrlName
const wxString GetGeneratorTCommandLine()
DIALOG_EXPORT_NETLIST * m_Parent
NETLIST_DIALOG_ADD_GENERATOR(DIALOG_EXPORT_NETLIST *parent)
const wxString GetGeneratorTitle()
void OnBrowseGenerators(wxCommandEvent &event) override
Browse plugin files, and set m_CommandStringCtrl field.
bool TransferDataFromWindow() override
@ OPTION_SAVE_ALL_CURRENTS
@ OPTION_SAVE_ALL_VOLTAGES
@ OPTION_SAVE_ALL_DISSIPATIONS
@ OPTION_CUR_SHEET_AS_ROOT
virtual ENV_VAR_MAP & GetLocalEnvVariables() const
virtual const wxString & GetExecutablePath() const
virtual const wxString GetProjectPath() const
Return the full path of the project.
A pure virtual class used to derive REPORTER objects from.
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.
virtual REPORTER & Report(const wxString &aText, SEVERITY aSeverity=RPT_SEVERITY_UNDEFINED)
Report a string with a given severity.
Schematic editor (Eeschema) main window.
void SaveProjectLocalSettings() override
Save changes to the project settings to the project (.pro) file.
@ ID_SAVE_ALL_DISSIPATIONS
#define CUSTOMPANEL_COUNTMAX
int InvokeDialogNetList(SCH_EDIT_FRAME *aCaller)
NETLIST_TYPE_ID
netlist types
@ ID_END_EESCHEMA_ID_LIST
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()
std::map< wxString, ENV_VAR_ITEM > ENV_VAR_MAP
#define NET_PLUGIN_CHANGE
Create and shows DIALOG_EXPORT_NETLIST and returns whatever DIALOG_EXPORT_NETLIST::ShowModal() return...
static PGM_BASE * process
PGM_BASE & Pgm()
The global program "get" accessor.
#define TO_UTF8(wxstring)
Convert a wxString to a UTF8 encoded C string for all wxWidgets build modes.
std::vector< NETLIST_PLUGIN_SETTINGS > plugins
Definition of file extensions used in Kicad.