X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/9a83f860948059b0273b5cc6d9e43fadad3ebfca..8d9eee83203dfc7177cd8639c14a5c809085698d:/samples/exec/exec.cpp?ds=sidebyside diff --git a/samples/exec/exec.cpp b/samples/exec/exec.cpp index ab63144a8e..fd5de1003c 100644 --- a/samples/exec/exec.cpp +++ b/samples/exec/exec.cpp @@ -43,6 +43,8 @@ #include "wx/choicdlg.h" #include "wx/button.h" + #include "wx/checkbox.h" + #include "wx/stattext.h" #include "wx/textctrl.h" #include "wx/listbox.h" @@ -106,7 +108,6 @@ public: void OnEndBusyCursor(wxCommandEvent& event); void OnSyncExec(wxCommandEvent& event); - void OnSyncNoEventsExec(wxCommandEvent& event); void OnAsyncExec(wxCommandEvent& event); void OnShell(wxCommandEvent& event); void OnExecWithRedirect(wxCommandEvent& event); @@ -139,6 +140,8 @@ private: const wxArrayString& output, const wxString& title); + int GetExecFlags() const; + void DoAsyncExec(const wxString& cmd); void AddAsyncProcess(MyProcess *process) { m_allAsync.push_back(process); } @@ -311,7 +314,6 @@ enum Exec_BeginBusyCursor, Exec_EndBusyCursor, Exec_SyncExec = 200, - Exec_SyncNoEventsExec, Exec_AsyncExec, Exec_Shell, Exec_POpen, @@ -322,6 +324,9 @@ enum Exec_DDERequest, Exec_Redirect, Exec_Pipe, + Exec_Flags_HideConsole, + Exec_Flags_ShowConsole, + Exec_Flags_NoEvents, Exec_About = wxID_ABOUT, // control ids @@ -348,7 +353,6 @@ BEGIN_EVENT_TABLE(MyFrame, wxFrame) EVT_MENU(Exec_EndBusyCursor, MyFrame::OnEndBusyCursor) EVT_MENU(Exec_SyncExec, MyFrame::OnSyncExec) - EVT_MENU(Exec_SyncNoEventsExec, MyFrame::OnSyncNoEventsExec) EVT_MENU(Exec_AsyncExec, MyFrame::OnAsyncExec) EVT_MENU(Exec_Shell, MyFrame::OnShell) EVT_MENU(Exec_Redirect, MyFrame::OnExecWithRedirect) @@ -411,9 +415,8 @@ bool MyApp::OnInit() MyFrame *frame = new MyFrame(wxT("Exec wxWidgets sample"), wxDefaultPosition, wxSize(500, 140)); - // Show it and tell the application that it's our main window + // Show it frame->Show(true); - SetTopWindow(frame); // success: wxApp::OnRun() will be called which will enter the main message // loop and the application will run. If we returned false here, the @@ -456,11 +459,17 @@ MyFrame::MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size) menuFile->AppendSeparator(); menuFile->Append(Exec_Quit, wxT("E&xit\tAlt-X"), wxT("Quit this program")); + wxMenu *flagsMenu = new wxMenu; + flagsMenu->AppendCheckItem(Exec_Flags_HideConsole, "Always &hide console"); + flagsMenu->AppendCheckItem(Exec_Flags_ShowConsole, "Always &show console"); + flagsMenu->AppendCheckItem(Exec_Flags_NoEvents, "Disable &events", + "This flag is valid for sync execution only"); + wxMenu *execMenu = new wxMenu; + execMenu->AppendSubMenu(flagsMenu, "Execution flags"); + execMenu->AppendSeparator(); execMenu->Append(Exec_SyncExec, wxT("Sync &execution...\tCtrl-E"), wxT("Launch a program and return when it terminates")); - execMenu->Append(Exec_SyncNoEventsExec, wxT("Sync execution and &block...\tCtrl-B"), - wxT("Launch a program and block until it terminates")); execMenu->Append(Exec_AsyncExec, wxT("&Async execution...\tCtrl-A"), wxT("Launch a program and return immediately")); execMenu->Append(Exec_Shell, wxT("Execute &shell command...\tCtrl-S"), @@ -487,7 +496,7 @@ MyFrame::MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size) #endif wxMenu *helpMenu = new wxMenu(wxEmptyString, wxMENU_TEAROFF); - helpMenu->Append(Exec_About, wxT("&About...\tF1"), wxT("Show about dialog")); + helpMenu->Append(Exec_About, wxT("&About\tF1"), wxT("Show about dialog")); // now append the freshly created menu to the menu bar... wxMenuBar *menuBar = new wxMenuBar(); @@ -502,7 +511,7 @@ MyFrame::MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size) m_lbox = new wxListBox(this, wxID_ANY); wxFont font(12, wxFONTFAMILY_TELETYPE, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL); - if ( font.Ok() ) + if ( font.IsOk() ) m_lbox->SetFont(font); #if wxUSE_STATUSBAR @@ -571,6 +580,8 @@ void MyFrame::OnKill(wxCommandEvent& WXUNUSED(event)) return; } + m_pidLast = pid; + static const wxString signalNames[] = { wxT("Just test (SIGNONE)"), @@ -591,9 +602,11 @@ void MyFrame::OnKill(wxCommandEvent& WXUNUSED(event)) wxT("Terminate (SIGTERM)"), }; + static int s_sigLast = wxSIGNONE; int sig = wxGetSingleChoiceIndex(wxT("How to kill the process?"), wxT("Exec question"), WXSIZEOF(signalNames), signalNames, + s_sigLast, this); switch ( sig ) { @@ -624,8 +637,11 @@ void MyFrame::OnKill(wxCommandEvent& WXUNUSED(event)) break; } - if ( sig == 0 ) + s_sigLast = sig; + + if ( sig == wxSIGNONE ) { + // This simply calls Kill(wxSIGNONE) but using it is more convenient. if ( wxProcess::Exists(pid) ) { wxLogStatus(wxT("Process %ld is running."), pid); @@ -659,14 +675,171 @@ void MyFrame::OnKill(wxCommandEvent& WXUNUSED(event)) } } +// ---------------------------------------------------------------------------- +// execution options dialog +// ---------------------------------------------------------------------------- + +enum ExecQueryDialogID +{ + TEXT_EXECUTABLE, + TEXT_CWD, + TEXT_ENVIRONMENT +}; + +class ExecQueryDialog : public wxDialog +{ +public: + ExecQueryDialog(const wxString& cmd); + + wxString GetExecutable() const + { + return m_executable->GetValue(); + } + + wxString GetWorkDir() const + { + return m_useCWD->GetValue() ? m_cwdtext->GetValue() : wxString(); + } + + void GetEnvironment(wxEnvVariableHashMap& env); + +private: + void OnUpdateWorkingDirectoryUI(wxUpdateUIEvent& event) + { + event.Enable(m_useCWD->GetValue()); + } + + void OnUpdateEnvironmentUI(wxUpdateUIEvent& event) + { + event.Enable(m_useEnv->GetValue()); + } + + wxTextCtrl* m_executable; + wxTextCtrl* m_cwdtext; + wxTextCtrl* m_envtext; + wxCheckBox* m_useCWD; + wxCheckBox* m_useEnv; + + DECLARE_EVENT_TABLE() +}; + +BEGIN_EVENT_TABLE(ExecQueryDialog, wxDialog) + EVT_UPDATE_UI(TEXT_CWD, ExecQueryDialog::OnUpdateWorkingDirectoryUI) + EVT_UPDATE_UI(TEXT_ENVIRONMENT, ExecQueryDialog::OnUpdateEnvironmentUI) +END_EVENT_TABLE() + +ExecQueryDialog::ExecQueryDialog(const wxString& cmd) + : wxDialog(NULL, wxID_ANY, DIALOG_TITLE, + wxDefaultPosition, wxDefaultSize, + wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER) +{ + wxSizer* globalSizer = new wxBoxSizer(wxVERTICAL); + + m_executable = new wxTextCtrl(this, TEXT_EXECUTABLE, wxString()); + m_cwdtext = new wxTextCtrl(this, TEXT_CWD, wxString()); + m_envtext = new wxTextCtrl(this, TEXT_ENVIRONMENT, wxString(), + wxDefaultPosition, wxSize(300, 200), + wxTE_MULTILINE|wxHSCROLL); + + const wxSizerFlags flagsExpand = wxSizerFlags().Expand().Border(); + globalSizer->Add(new wxStaticText(this, wxID_ANY, "Enter the command: "), + flagsExpand); + globalSizer->Add(m_executable, flagsExpand); + + m_useCWD = new wxCheckBox(this, wxID_ANY, "Working directory: "); + globalSizer->Add(m_useCWD, flagsExpand); + globalSizer->Add(m_cwdtext, flagsExpand); + + m_useEnv = new wxCheckBox(this, wxID_ANY, "Environment: "); + globalSizer->Add(m_useEnv, flagsExpand); + globalSizer->Add(m_envtext, wxSizerFlags(flagsExpand).Proportion(1)); + + globalSizer->Add(CreateStdDialogButtonSizer(wxOK|wxCANCEL), flagsExpand); + SetSizerAndFit(globalSizer); + + + m_executable->SetValue(cmd); + m_cwdtext->SetValue(wxGetCwd()); + wxEnvVariableHashMap env; + if ( wxGetEnvMap(&env) ) + { + for ( wxEnvVariableHashMap::iterator it = env.begin(); + it != env.end(); + ++it ) + { + m_envtext->AppendText(it->first + '=' + it->second + '\n'); + } + } + m_useCWD->SetValue(false); + m_useEnv->SetValue(false); +} + +void ExecQueryDialog::GetEnvironment(wxEnvVariableHashMap& env) +{ + env.clear(); + if ( m_useEnv->GetValue() ) + { + wxString name, + value; + + const int nb = m_envtext->GetNumberOfLines(); + for ( int l = 0; l < nb; l++ ) + { + const wxString line = m_envtext->GetLineText(l).Trim(); + + if ( !line.empty() ) + { + name = line.BeforeFirst('=', &value); + if ( name.empty() ) + { + wxLogWarning("Skipping invalid environment line \"%s\".", line); + continue; + } + + env[name] = value; + } + } + } +} + +static bool QueryExec(wxString& cmd, wxExecuteEnv& env) +{ + ExecQueryDialog dialog(cmd); + + if ( dialog.ShowModal() != wxID_OK ) + return false; + + cmd = dialog.GetExecutable(); + env.cwd = dialog.GetWorkDir(); + dialog.GetEnvironment(env.env); + + return true; +} + // ---------------------------------------------------------------------------- // event handlers: exec menu // ---------------------------------------------------------------------------- +int MyFrame::GetExecFlags() const +{ + wxMenuBar* const mbar = GetMenuBar(); + + int flags = 0; + + if ( mbar->IsChecked(Exec_Flags_HideConsole) ) + flags |= wxEXEC_HIDE_CONSOLE; + if ( mbar->IsChecked(Exec_Flags_ShowConsole) ) + flags |= wxEXEC_SHOW_CONSOLE; + if ( mbar->IsChecked(Exec_Flags_NoEvents) ) + flags |= wxEXEC_NOEVENTS; + + return flags; +} + void MyFrame::DoAsyncExec(const wxString& cmd) { MyProcess * const process = new MyProcess(this, cmd); - m_pidLast = wxExecute(cmd, wxEXEC_ASYNC, process); + m_pidLast = wxExecute(cmd, wxEXEC_ASYNC | GetExecFlags(), process); if ( !m_pidLast ) { wxLogError(wxT("Execution of '%s' failed."), cmd.c_str()); @@ -687,35 +860,14 @@ void MyFrame::DoAsyncExec(const wxString& cmd) void MyFrame::OnSyncExec(wxCommandEvent& WXUNUSED(event)) { - wxString cmd = wxGetTextFromUser(wxT("Enter the command: "), - DIALOG_TITLE, - m_cmdLast); - - if ( !cmd ) - return; - - wxLogStatus( wxT("'%s' is running please wait..."), cmd.c_str() ); - - int code = wxExecute(cmd, wxEXEC_SYNC); - - wxLogStatus(wxT("Process '%s' terminated with exit code %d."), - cmd.c_str(), code); - - m_cmdLast = cmd; -} - -void MyFrame::OnSyncNoEventsExec(wxCommandEvent& WXUNUSED(event)) -{ - wxString cmd = wxGetTextFromUser(wxT("Enter the command: "), - DIALOG_TITLE, - m_cmdLast); - - if ( !cmd ) + wxString cmd; + wxExecuteEnv env; + if ( !QueryExec(cmd, env) ) return; wxLogStatus( wxT("'%s' is running please wait..."), cmd.c_str() ); - int code = wxExecute(cmd, wxEXEC_BLOCK); + int code = wxExecute(cmd, wxEXEC_SYNC | GetExecFlags(), NULL, &env); wxLogStatus(wxT("Process '%s' terminated with exit code %d."), cmd.c_str(), code); @@ -1323,8 +1475,8 @@ void MyPipeFrame::DoGetFromStream(wxTextCtrl *text, wxInputStream& in) { while ( in.CanRead() ) { - wxChar buffer[4096]; - buffer[in.Read(buffer, WXSIZEOF(buffer) - 1).LastRead()] = wxT('\0'); + char buffer[4096]; + buffer[in.Read(buffer, WXSIZEOF(buffer) - 1).LastRead()] = '\0'; text->AppendText(buffer); } @@ -1370,8 +1522,7 @@ void MyPipeFrame::OnProcessTerm(wxProcessEvent& WXUNUSED(event)) { DoGet(); - delete m_process; - m_process = NULL; + wxDELETE(m_process); wxLogWarning(wxT("The other process has terminated, closing"));