55#include <wx/checkbox.h>
56#include <wx/filedlg.h>
58#include <wx/process.h>
60#include <wx/txtstrm.h>
70std::vector<wxString> SplitCommandLine(
const wxString& aCommand )
72 std::vector<wxString> args;
74 bool inSingle =
false;
75 bool inDouble =
false;
76 bool argStarted =
false;
78 for( wxUniChar c : aCommand )
80 if( c ==
'"' && !inSingle )
87 if( c ==
'\'' && !inDouble )
94 if( ( c ==
' ' || c ==
'\t' || c ==
'\n' || c ==
'\r' ) && !inSingle && !inDouble )
96 if( argStarted || !current.IsEmpty() )
98 args.emplace_back( current );
110 if( argStarted || !current.IsEmpty() )
111 args.emplace_back( current );
118#define CUSTOMPANEL_COUNTMAX 8
220 wxPanel( aParent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ),
233 aParent->AddPage(
this, aTitle,
false );
235 wxBoxSizer* MainBoxSizer =
new wxBoxSizer( wxVERTICAL );
236 SetSizer( MainBoxSizer );
237 wxBoxSizer* UpperBoxSizer =
new wxBoxSizer( wxHORIZONTAL );
239 MainBoxSizer->Add( UpperBoxSizer, 0, wxEXPAND | wxALL, 5 );
246 UpperBoxSizer->Add(
m_RightBoxSizer, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5 );
269 wxStaticText* label =
nullptr;
272 label =
new wxStaticText( page, wxID_ANY,
_(
"Export netlist in KiCad format" ) );
277 label =
new wxStaticText( page, wxID_ANY,
_(
"Export netlist in OrcadPCB2 format" ) );
282 label =
new wxStaticText( page, wxID_ANY,
_(
"Export netlist in Allegro format" ) );
287 label =
new wxStaticText( page, wxID_ANY,
_(
"Export netlist in CadStar format" ) );
292 label =
new wxStaticText( page, wxID_ANY,
_(
"Export netlist in PADS format" ) );
306 { wxID_CANCEL,
_(
"Close" ) } } );
310 SetTitle(
m_job->GetSettingsDialogTitle() );
349 wxStaticText* label =
new wxStaticText( pg, wxID_ANY,
_(
"Export netlist in SPICE format" ) );
353 pg->
m_CurSheetAsRoot->SetToolTip(
_(
"Export netlist only for the current sheet" ) );
357 pg->
m_SaveAllVoltages->SetToolTip(
_(
"Write a directive to save all voltages (.save all)" ) );
361 pg->
m_SaveAllCurrents->SetToolTip(
_(
"Write a directive to save all currents (.probe alli)" ) );
366 "(.probe p(<item>))" ) );
370 pg->
m_SaveAllEvents->SetToolTip(
_(
"If not set, write a directive to prevent the saving of digital event data "
377 "Usually '<path to SPICE binary> \"%I\"'\n"
378 "%I will be replaced by the netlist filepath" ) );
394 wxStaticText* label =
new wxStaticText( pg, wxID_ANY,
_(
"Export netlist as a SPICE .subckt model" ) );
395 pg->m_LeftBoxSizer->Add( label, 0, wxBOTTOM, 10 );
398 pg->m_CurSheetAsRoot->SetToolTip(
_(
"Export netlist only for the current sheet" ) );
399 pg->m_LeftBoxSizer->Add( pg->m_CurSheetAsRoot, 0, wxEXPAND | wxBOTTOM | wxRIGHT, 5 );
424 const wxString& aCommandString,
429 pg->
m_LowBoxSizer->Add(
new wxStaticText( pg, wxID_ANY,
_(
"Title:" ) ), 0,
430 wxEXPAND | wxLEFT | wxRIGHT | wxTOP, 5 );
441 pg->
m_LowBoxSizer->Add(
new wxStaticText( pg, wxID_ANY,
_(
"Netlist command:" ) ), 0,
442 wxEXPAND | wxLEFT | wxRIGHT | wxTOP, 5 );
464 wxString fileWildcard;
466 wxString title =
_(
"Save Netlist File" );
474 m_job->format = format;
491 bool runExternalSpiceCommand =
false;
492 unsigned netlist_opt = 0;
551 if( runExternalSpiceCommand )
554 fullpath = fn.GetFullPath();
558 fn.SetExt( fileExt );
560 if( fn.GetPath().IsEmpty() )
561 fn.SetPath( wxPathOnly(
Prj().GetProjectFullName() ) );
563 wxString fullname = fn.GetFullName();
564 wxString
path = fn.GetPath();
567 wxFileDialog dlg(
this, title,
path, fullname, fileWildcard, wxFD_SAVE );
571 if( dlg.ShowModal() == wxID_CANCEL )
574 fullpath = dlg.GetPath();
585 if( !
m_editFrame->ReadyToNetlist(
_(
"Exporting netlist requires a fully annotated schematic." ) ) )
590 if( runExternalSpiceCommand )
594 commandLine.Replace( wxS(
"%I" ), fullpath,
true );
595 commandLine.Trim(
true ).Trim(
false );
597 if( !commandLine.IsEmpty() )
599 std::vector<wxString> argsStrings = SplitCommandLine( commandLine );
601 if( !argsStrings.empty() )
603 std::vector<const wxChar*> argv;
604 argv.reserve( argsStrings.size() + 1 );
606 for( wxString& arg : argsStrings )
607 argv.emplace_back( arg.wc_str() );
609 argv.emplace_back(
nullptr );
612 wxGetEnvMap( &env.env );
616 for(
const auto& [key, value] : envVars )
618 if( !value.GetValue().IsEmpty() )
619 env.env[key] = value.GetValue();
622 wxFileName netlistFile( fullpath );
624 if( !netlistFile.IsAbsolute() )
625 netlistFile.MakeAbsolute(
Prj().GetProjectPath() );
627 netlistFile.MakeAbsolute();
629 wxString cwd = netlistFile.GetPath();
636 wxProcess*
process =
new wxProcess( GetEventHandler(), wxID_ANY );
639 long pid = wxExecute( argv.data(), wxEXEC_ASYNC,
process, &env );
646 reporter.
Report(
_(
"Note: command line is usually: "
647 "<tt><path to SPICE binary> \"%I\"</tt>" ),
655 std::this_thread::sleep_for( std::chrono::seconds( 1 ) );
657 if(
process->IsInputAvailable() )
659 wxInputStream* in =
process->GetInputStream();
660 wxTextInputStream textstream( *in );
662 while( in->CanRead() )
664 wxString line = textstream.ReadLine();
666 if( !line.IsEmpty() )
671 if(
process->IsErrorAvailable() )
673 wxInputStream* err =
process->GetErrorStream();
674 wxTextInputStream textstream( *err );
676 while( err->CanRead() )
678 wxString line = textstream.ReadLine();
680 if( !line.IsEmpty() )
682 if( line.EndsWith( wxS(
"failed with error 2!" ) ) )
685 reporter.
Report(
_(
"Note: command line is usually: "
686 "<tt><path to SPICE binary> \"%I\"</tt>" ),
689 else if( line.EndsWith( wxS(
"failed with error 8!" ) ) )
691 reporter.
Report(
_(
"external simulator has the wrong format or "
694 else if( line.EndsWith(
"failed with error 13!" ) )
717 return !runExternalSpiceCommand;
724 wxString fileWildcard;
769 *aWildCard = fileWildcard;
787 wxString title = currPage->m_TitleStringCtrl->GetValue();
788 wxString command = currPage->m_CommandStringCtrl->GetValue();
790 if( title.IsEmpty() || command.IsEmpty() )
834 wxMessageBox(
_(
"This plugin already exists." ) );
848 wxMessageBox(
_(
"Maximum number of plugins already added to dialog." ) );
877 if( !wxDialog::TransferDataFromWindow() )
882 wxMessageBox(
_(
"You must provide a netlist generator title" ) );
892 wxString FullFileName, Path;
897 Path = PATHS::GetOSXKicadDataDir() + wxT(
"/plugins" );
900 FullFileName = wxFileSelector(
_(
"Generator File" ), Path, FullFileName, wxEmptyString,
901 wxFileSelectorDefaultWildcardStr, wxFD_OPEN,
this );
903 if( FullFileName.IsEmpty() )
909 wxFileName fn( FullFileName );
910 wxString ext = fn.GetExt();
912 if( ext == wxT(
"xsl" ) )
913 cmdLine.Printf( wxT(
"xsltproc -o \"%%O\" \"%s\" \"%%I\"" ), FullFileName );
914 else if( ext == wxT(
"exe" ) || ext.IsEmpty() )
915 cmdLine.Printf( wxT(
"\"%s\" > \"%%O\" < \"%%I\"" ), FullFileName );
916 else if( ext == wxT(
"py" ) || ext.IsEmpty() )
917 cmdLine.Printf( wxT(
"python \"%s\" \"%%I\" \"%%O\"" ), FullFileName );
919 cmdLine.Printf( wxT(
"\"%s\"" ), FullFileName );
934 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.