51#include <wx/checkbox.h>
52#include <wx/filedlg.h>
54#include <wx/process.h>
56#include <wx/txtstrm.h>
66std::vector<wxString> SplitCommandLine(
const wxString& aCommand )
68 std::vector<wxString> args;
70 bool inSingle =
false;
71 bool inDouble =
false;
72 bool argStarted =
false;
74 for( wxUniChar c : aCommand )
76 if( c ==
'"' && !inSingle )
83 if( c ==
'\'' && !inDouble )
90 if( ( c ==
' ' || c ==
'\t' || c ==
'\n' || c ==
'\r' ) && !inSingle && !inDouble )
92 if( argStarted || !current.IsEmpty() )
94 args.emplace_back( current );
106 if( argStarted || !current.IsEmpty() )
107 args.emplace_back( current );
114#define CUSTOMPANEL_COUNTMAX 8
217 wxPanel( aParent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ),
230 aParent->AddPage(
this, aTitle,
false );
232 wxBoxSizer* MainBoxSizer =
new wxBoxSizer( wxVERTICAL );
233 SetSizer( MainBoxSizer );
234 wxBoxSizer* UpperBoxSizer =
new wxBoxSizer( wxHORIZONTAL );
236 MainBoxSizer->Add( UpperBoxSizer, 0, wxEXPAND | wxALL, 5 );
243 UpperBoxSizer->Add(
m_RightBoxSizer, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5 );
266 wxStaticText* label =
nullptr;
269 label =
new wxStaticText( page, wxID_ANY,
_(
"Export netlist in KiCad format" ) );
274 label =
new wxStaticText( page, wxID_ANY,
_(
"Export netlist in OrcadPCB2 format" ) );
279 label =
new wxStaticText( page, wxID_ANY,
_(
"Export netlist in Allegro format" ) );
284 label =
new wxStaticText( page, wxID_ANY,
_(
"Export netlist in CadStar format" ) );
289 label =
new wxStaticText( page, wxID_ANY,
_(
"Export netlist in PADS format" ) );
303 { wxID_CANCEL,
_(
"Close" ) } } );
307 SetTitle(
m_job->GetSettingsDialogTitle() );
350 wxStaticText* label =
new wxStaticText( pg, wxID_ANY,
_(
"Export netlist in SPICE format" ) );
354 pg->
m_CurSheetAsRoot->SetToolTip(
_(
"Export netlist only for the current sheet" ) );
358 pg->
m_SaveAllVoltages->SetToolTip(
_(
"Write a directive to save all voltages (.save all)" ) );
362 pg->
m_SaveAllCurrents->SetToolTip(
_(
"Write a directive to save all currents (.probe alli)" ) );
367 "(.probe p(<item>))" ) );
371 pg->
m_SaveAllEvents->SetToolTip(
_(
"If not set, write a directive to prevent the saving of digital event data "
378 "Usually '<path to SPICE binary> \"%I\"'\n"
379 "%I will be replaced by the netlist filepath" ) );
395 wxStaticText* label =
new wxStaticText( pg, wxID_ANY,
_(
"Export netlist as a SPICE .subckt model" ) );
396 pg->m_LeftBoxSizer->Add( label, 0, wxBOTTOM, 10 );
399 pg->m_CurSheetAsRoot->SetToolTip(
_(
"Export netlist only for the current sheet" ) );
400 pg->m_LeftBoxSizer->Add( pg->m_CurSheetAsRoot, 0, wxEXPAND | wxBOTTOM | wxRIGHT, 5 );
425 const wxString& aCommandString,
430 pg->
m_LowBoxSizer->Add(
new wxStaticText( pg, wxID_ANY,
_(
"Title:" ) ), 0,
431 wxEXPAND | wxLEFT | wxRIGHT | wxTOP, 5 );
442 pg->
m_LowBoxSizer->Add(
new wxStaticText( pg, wxID_ANY,
_(
"Netlist command:" ) ), 0,
443 wxEXPAND | wxLEFT | wxRIGHT | wxTOP, 5 );
472 wxString fileWildcard;
474 wxString title =
_(
"Save Netlist File" );
482 m_job->format = format;
499 bool runExternalSpiceCommand =
false;
500 unsigned netlist_opt = 0;
559 if( runExternalSpiceCommand )
562 fullpath = fn.GetFullPath();
566 fn.SetExt( fileExt );
568 if( fn.GetPath().IsEmpty() )
569 fn.SetPath( wxPathOnly(
Prj().GetProjectFullName() ) );
571 wxString fullname = fn.GetFullName();
572 wxString
path = fn.GetPath();
575 wxFileDialog dlg(
this, title,
path, fullname, fileWildcard, wxFD_SAVE );
579 if( dlg.ShowModal() == wxID_CANCEL )
582 fullpath = dlg.GetPath();
593 if( !
m_editFrame->ReadyToNetlist(
_(
"Exporting netlist requires a fully annotated schematic." ) ) )
598 if( runExternalSpiceCommand )
602 commandLine.Replace( wxS(
"%I" ), fullpath,
true );
603 commandLine.Trim(
true ).Trim(
false );
605 if( !commandLine.IsEmpty() )
607 std::vector<wxString> argsStrings = SplitCommandLine( commandLine );
609 if( !argsStrings.empty() )
611 std::vector<const wxChar*> argv;
612 argv.reserve( argsStrings.size() + 1 );
614 for( wxString& arg : argsStrings )
615 argv.emplace_back( arg.wc_str() );
617 argv.emplace_back(
nullptr );
620 wxGetEnvMap( &env.env );
624 for(
const auto& [key, value] : envVars )
626 if( !value.GetValue().IsEmpty() )
627 env.env[key] = value.GetValue();
630 wxFileName netlistFile( fullpath );
632 if( !netlistFile.IsAbsolute() )
633 netlistFile.MakeAbsolute(
Prj().GetProjectPath() );
635 netlistFile.MakeAbsolute();
637 wxString cwd = netlistFile.GetPath();
644 wxProcess*
process =
new wxProcess( GetEventHandler(), wxID_ANY );
647 long pid = wxExecute( argv.data(), wxEXEC_ASYNC,
process, &env );
654 reporter.Report(
_(
"Note: command line is usually: "
655 "<tt><path to SPICE binary> \"%I\"</tt>" ),
663 std::this_thread::sleep_for( std::chrono::seconds( 1 ) );
665 if(
process->IsInputAvailable() )
667 wxInputStream* in =
process->GetInputStream();
668 wxTextInputStream textstream( *in );
670 while( in->CanRead() )
672 wxString line = textstream.ReadLine();
674 if( !line.IsEmpty() )
679 if(
process->IsErrorAvailable() )
681 wxInputStream* err =
process->GetErrorStream();
682 wxTextInputStream textstream( *err );
684 while( err->CanRead() )
686 wxString line = textstream.ReadLine();
688 if( !line.IsEmpty() )
690 if( line.EndsWith( wxS(
"failed with error 2!" ) ) )
693 reporter.Report(
_(
"Note: command line is usually: "
694 "<tt><path to SPICE binary> \"%I\"</tt>" ),
697 else if( line.EndsWith( wxS(
"failed with error 8!" ) ) )
699 reporter.Report(
_(
"external simulator has the wrong format or "
702 else if( line.EndsWith(
"failed with error 13!" ) )
725 return !runExternalSpiceCommand;
732 wxString fileWildcard;
781 *aWildCard = fileWildcard;
799 wxString title = currPage->m_TitleStringCtrl->GetValue();
800 wxString command = currPage->m_CommandStringCtrl->GetValue();
802 if( title.IsEmpty() )
846 wxMessageBox(
_(
"This plugin already exists." ) );
860 wxMessageBox(
_(
"Maximum number of plugins already added to dialog." ) );
886 if( !wxDialog::TransferDataFromWindow() )
891 wxMessageBox(
_(
"You must provide a netlist generator title" ) );
901 wxString FullFileName, Path;
906 Path = PATHS::GetOSXKicadDataDir() + wxT(
"/plugins" );
909 FullFileName = wxFileSelector(
_(
"Generator File" ), Path, FullFileName, wxEmptyString,
910 wxFileSelectorDefaultWildcardStr, wxFD_OPEN,
this );
912 if( FullFileName.IsEmpty() )
918 wxFileName fn( FullFileName );
919 wxString ext = fn.GetExt();
921 if( ext == wxT(
"xsl" ) )
922 cmdLine.Printf( wxT(
"xsltproc -o \"%%O\" \"%s\" \"%%I\"" ), FullFileName );
923 else if( ext == wxT(
"exe" ) || ext.IsEmpty() )
924 cmdLine.Printf( wxT(
"\"%s\" > \"%%O\" < \"%%I\"" ), FullFileName );
925 else if( ext == wxT(
"py" ) || ext.IsEmpty() )
926 cmdLine.Printf( wxT(
"python \"%s\" \"%%I\" \"%%O\"" ), FullFileName );
928 cmdLine.Printf( wxT(
"\"%s\"" ), FullFileName );
943 if( currPage ==
nullptr )
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
bool TransferDataToWindow() override
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={})
void EndDialogShim(int aReturnCode)
A mode agnostic way to close a dialog.
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.
Schematic editor (Eeschema) main window.
void SaveProjectLocalSettings() override
Save changes to the project settings to the project (.pro) file.
KIFACE_BASE & Kiface()
Global KIFACE_BASE "get" accessor.
@ 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 SpiceSubcircuitFileExtension
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()
static wxString SpiceSubcircuitFileWildcard()
#define TO_UTF8(wxstring)
Convert a wxString to a UTF8 encoded C string for all wxWidgets build modes.
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.
std::vector< NETLIST_PLUGIN_SETTINGS > plugins
IbisParser parser & reporter
Definition of file extensions used in Kicad.