53#include <wx/checkbox.h>
54#include <wx/filedlg.h>
56#include <wx/process.h>
58#include <wx/txtstrm.h>
67std::vector<wxString> SplitCommandLine(
const wxString& aCommand )
69 std::vector<wxString> args;
71 bool inSingle =
false;
72 bool inDouble =
false;
73 bool argStarted =
false;
75 for( wxUniChar c : aCommand )
77 if( c ==
'"' && !inSingle )
84 if( c ==
'\'' && !inDouble )
91 if( ( c ==
' ' || c ==
'\t' || c ==
'\n' || c ==
'\r' ) && !inSingle && !inDouble )
93 if( argStarted || !current.IsEmpty() )
95 args.emplace_back( current );
107 if( argStarted || !current.IsEmpty() )
108 args.emplace_back( current );
115#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() );
346 wxStaticText* label =
new wxStaticText( pg, wxID_ANY,
_(
"Export netlist in SPICE format" ) );
350 pg->
m_CurSheetAsRoot->SetToolTip(
_(
"Export netlist only for the current sheet" ) );
354 pg->
m_SaveAllVoltages->SetToolTip(
_(
"Write a directive to save all voltages (.save all)" ) );
358 pg->
m_SaveAllCurrents->SetToolTip(
_(
"Write a directive to save all currents (.probe alli)" ) );
363 "(.probe p(<item>))" ) );
367 pg->
m_SaveAllEvents->SetToolTip(
_(
"If not set, write a directive to prevent the saving of digital event data "
374 "Usually '<path to SPICE binary> \"%I\"'\n"
375 "%I will be replaced by the netlist filepath" ) );
391 wxStaticText* label =
new wxStaticText( pg, wxID_ANY,
_(
"Export netlist as a SPICE .subckt model" ) );
392 pg->m_LeftBoxSizer->Add( label, 0, wxBOTTOM, 10 );
395 pg->m_CurSheetAsRoot->SetToolTip(
_(
"Export netlist only for the current sheet" ) );
396 pg->m_LeftBoxSizer->Add( pg->m_CurSheetAsRoot, 0, wxEXPAND | wxBOTTOM | wxRIGHT, 5 );
421 const wxString& aCommandString,
426 pg->
m_LowBoxSizer->Add(
new wxStaticText( pg, wxID_ANY,
_(
"Title:" ) ), 0,
427 wxEXPAND | wxLEFT | wxRIGHT | wxTOP, 5 );
438 pg->
m_LowBoxSizer->Add(
new wxStaticText( pg, wxID_ANY,
_(
"Netlist command:" ) ), 0,
439 wxEXPAND | wxLEFT | wxRIGHT | wxTOP, 5 );
461 wxString fileWildcard;
463 wxString title =
_(
"Save Netlist File" );
471 m_job->format = format;
488 bool runExternalSpiceCommand =
false;
489 unsigned netlist_opt = 0;
548 if( runExternalSpiceCommand )
551 fullpath = fn.GetFullPath();
555 fn.SetExt( fileExt );
557 if( fn.GetPath().IsEmpty() )
558 fn.SetPath( wxPathOnly(
Prj().GetProjectFullName() ) );
560 wxString fullname = fn.GetFullName();
561 wxString
path = fn.GetPath();
564 wxFileDialog dlg(
this, title,
path, fullname, fileWildcard, wxFD_SAVE );
566 if( dlg.ShowModal() == wxID_CANCEL )
569 fullpath = dlg.GetPath();
580 if( !
m_editFrame->ReadyToNetlist(
_(
"Exporting netlist requires a fully annotated schematic." ) ) )
585 if( runExternalSpiceCommand )
589 commandLine.Replace( wxS(
"%I" ), fullpath,
true );
590 commandLine.Trim(
true ).Trim(
false );
592 if( !commandLine.IsEmpty() )
594 std::vector<wxString> argsStrings = SplitCommandLine( commandLine );
596 if( !argsStrings.empty() )
598 std::vector<const wxChar*> argv;
599 argv.reserve( argsStrings.size() + 1 );
601 for( wxString& arg : argsStrings )
602 argv.emplace_back( arg.wc_str() );
604 argv.emplace_back(
nullptr );
607 wxGetEnvMap( &env.env );
611 for(
const auto& [key, value] : envVars )
613 if( !value.GetValue().IsEmpty() )
614 env.env[key] = value.GetValue();
617 wxFileName netlistFile( fullpath );
619 if( !netlistFile.IsAbsolute() )
620 netlistFile.MakeAbsolute(
Prj().GetProjectPath() );
622 netlistFile.MakeAbsolute();
624 wxString cwd = netlistFile.GetPath();
631 wxProcess*
process =
new wxProcess( GetEventHandler(), wxID_ANY );
634 long pid = wxExecute( argv.data(), wxEXEC_ASYNC,
process, &env );
641 reporter.
Report(
_(
"Note: command line is usually: "
642 "<tt><path to SPICE binary> \"%I\"</tt>" ),
650 std::this_thread::sleep_for( std::chrono::seconds( 1 ) );
652 if(
process->IsInputAvailable() )
654 wxInputStream* in =
process->GetInputStream();
655 wxTextInputStream textstream( *in );
657 while( in->CanRead() )
659 wxString line = textstream.ReadLine();
661 if( !line.IsEmpty() )
666 if(
process->IsErrorAvailable() )
668 wxInputStream* err =
process->GetErrorStream();
669 wxTextInputStream textstream( *err );
671 while( err->CanRead() )
673 wxString line = textstream.ReadLine();
675 if( !line.IsEmpty() )
677 if( line.EndsWith( wxS(
"failed with error 2!" ) ) )
680 reporter.
Report(
_(
"Note: command line is usually: "
681 "<tt><path to SPICE binary> \"%I\"</tt>" ),
684 else if( line.EndsWith( wxS(
"failed with error 8!" ) ) )
686 reporter.
Report(
_(
"external simulator has the wrong format or "
689 else if( line.EndsWith(
"failed with error 13!" ) )
712 return !runExternalSpiceCommand;
719 wxString fileWildcard;
764 *aWildCard = fileWildcard;
782 wxString title = currPage->m_TitleStringCtrl->GetValue();
783 wxString command = currPage->m_CommandStringCtrl->GetValue();
785 if( title.IsEmpty() || command.IsEmpty() )
829 wxMessageBox(
_(
"This plugin already exists." ) );
843 wxMessageBox(
_(
"Maximum number of plugins already added to dialog." ) );
872 if( !wxDialog::TransferDataFromWindow() )
877 wxMessageBox(
_(
"You must provide a netlist generator title" ) );
887 wxString FullFileName, Path;
892 Path = PATHS::GetOSXKicadDataDir() + wxT(
"/plugins" );
895 FullFileName = wxFileSelector(
_(
"Generator File" ), Path, FullFileName, wxEmptyString,
896 wxFileSelectorDefaultWildcardStr, wxFD_OPEN,
this );
898 if( FullFileName.IsEmpty() )
904 wxFileName fn( FullFileName );
905 wxString ext = fn.GetExt();
907 if( ext == wxT(
"xsl" ) )
908 cmdLine.Printf( wxT(
"xsltproc -o \"%%O\" \"%s\" \"%%I\"" ), FullFileName );
909 else if( ext == wxT(
"exe" ) || ext.IsEmpty() )
910 cmdLine.Printf( wxT(
"\"%s\" > \"%%O\" < \"%%I\"" ), FullFileName );
911 else if( ext == wxT(
"py" ) || ext.IsEmpty() )
912 cmdLine.Printf( wxT(
"python \"%s\" \"%%I\" \"%%O\"" ), FullFileName );
914 cmdLine.Printf( wxT(
"\"%s\"" ), FullFileName );
929 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)
@ 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...
NETLIST_TYPE_ID
netlist types
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.