From: Nicolas Boichat Date: Fri, 30 Apr 2004 23:01:03 +0000 (+0000) Subject: - wxbRestorePanel : Added "Cancel" button to cancel restore at all state of restore... X-Git-Tag: Release-1.34.3~67 X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=38adff07fd2983856d6fd35114249c1c4ef68ccc;p=bacula%2Fbacula - wxbRestorePanel : Added "Cancel" button to cancel restore at all state of restore process. - wxbMainFrame : Added "Send" button - wxbRestorePanel (first configure) : Changed defaults values when Job Name changes - wxbRestorePanel (first configure) : corrected problem when bad parameters are chosen - wxbRestorePanel : Checking more carefully which job we just have run - wxbRestorePanel : Using wxStopWatch instead of GetTicks to manage timeouts. git-svn-id: https://bacula.svn.sourceforge.net/svnroot/bacula/trunk@1333 91ce42f0-d328-0410-95d8-f526ca767f89 --- diff --git a/bacula/src/wx-console/CHANGELOG b/bacula/src/wx-console/CHANGELOG index f1812cab72..c7e4eca3f6 100644 --- a/bacula/src/wx-console/CHANGELOG +++ b/bacula/src/wx-console/CHANGELOG @@ -1,4 +1,17 @@ 30-04-2004 : + - wxbRestorePanel : Added "Cancel" button to cancel restore at + all state of restore process. + - wxbMainFrame : Added "Send" button + - wxbRestorePanel (first configure) : Changed defaults values when + Job Name changes + - wxbRestorePanel (first configure) : corrected problem when bad + parameters are chosen + - wxbRestorePanel : Checking more carefully which job we just have run + - wxbRestorePanel : Using wxStopWatch instead of GetTicks to manage + timeouts. + - wxbMainFrame : Added "Command: " in front of the command window + so that the user knows he can type into the command line + (thanks to Kern) - wxbMainFrame : Fixed 100% CPU usage in GTK : added buffering when receiving data to print to the console (thanks to Phil) - wxbRestorePanel : Fixed 100% CPU usage in GTK : added sleeps between diff --git a/bacula/src/wx-console/TODO b/bacula/src/wx-console/TODO index 0465ad0879..22d419336b 100644 --- a/bacula/src/wx-console/TODO +++ b/bacula/src/wx-console/TODO @@ -1,35 +1,25 @@ FEATURES -------- -wxbMainFrame : Add some text in front of the command window such as - "Command: " so that the user knows he can type into the - command line - wxbRestorePanel : Reconsider start button's labels. -wxbRestorePanel : Implement cancel button when first configuring - -wxbRestorePanel : Change defaults values when Job Name changes (first configure) - wxbRestorePanel : Add titles to configuration panel -general : Show nice messages boxes when errors occurs. - -wxbMainFrame : set focus to type control when clicking on console +wxbRestorePanel : When cancelling, check for commands results -wxbRestorePanel : Add a Cancel Restore button - (may need to implement BNET_BREAK to break current command) +general : Show nice messages boxes when errors occurs. general : Allow the user to quit however the state is (kill thread if necessary) -general : correct segmentation fault when exiting - -wxbRestorePanel : Check more carefully which job we just have run - (an elegant solution would need director modification). +general : correct segmentation faults when exiting [postponed to July:] -global : create a general class which keeps clients, filesets, pools... list. +wxbRestorePanel : Add a way to cancel restore when building tree (needs director modifications) + +wxbMainFrame : set focus to type control when clicking on console + +global : create a general class which keeps clients, jobs, filesets, pools... list. wxbMainFrame : use more often status text @@ -54,7 +44,7 @@ wxbRestorePanel : Is there any way to add a width adjustment handle between the tree view window and the file view window so that the width of the tree view can be changed? -general : Implement reconnecting +general : Implement dis/reconnecting wxbRestorePanel : Use ".default job=RestoreFiles" to get defaults parameters when changing a restore parameter fails. @@ -91,6 +81,9 @@ wxbRestorePanel : The + only appears when one selects a directory, wxbRestorePanel : Add a timeout when waiting for commands results +wxbRestorePanel : Be sure of which job we just have run (not suppositions + as I'm doing now) : needs director modification. + bacula-dir : correct director to handle correctly + marked status (In fact there is a bug in the director : If you mark a directory (not a file), and then unmark it, its parents keep the "+" status.) diff --git a/bacula/src/wx-console/wxbmainframe.cpp b/bacula/src/wx-console/wxbmainframe.cpp index 0b595f105a..4a6623495d 100644 --- a/bacula/src/wx-console/wxbmainframe.cpp +++ b/bacula/src/wx-console/wxbmainframe.cpp @@ -33,6 +33,8 @@ #include +#include + // ---------------------------------------------------------------------------- // event tables and other macros for wxWindows // ---------------------------------------------------------------------------- @@ -52,7 +54,8 @@ enum // (where it is special and put into the "Apple" menu) Minimal_About = wxID_ABOUT, TypeText = 2, - Thread = 3 + SendButton = 3, + Thread = 4 }; /* @@ -71,6 +74,7 @@ BEGIN_EVENT_TABLE(wxbMainFrame, wxFrame) EVT_MENU(Minimal_Quit, wxbMainFrame::OnQuit) EVT_MENU(Minimal_About, wxbMainFrame::OnAbout) EVT_TEXT_ENTER(TypeText, wxbMainFrame::OnEnter) + EVT_BUTTON(SendButton, wxbMainFrame::OnEnter) EVT_CUSTOM(wxbTHREAD_EVENT, Thread, wxbMainFrame::OnPrint) END_EVENT_TABLE() @@ -199,10 +203,8 @@ wxbMainFrame::wxbMainFrame(const wxString& title, const wxPoint& pos, const wxSi SetMenuBar(menuBar); #endif // wxUSE_MENUS -#if wxUSE_STATUSBAR CreateStatusBar(1); SetStatusText(wxString("Welcome to bacula wx-console ") << VERSION << " (" << BDATE << ")!\n"); -#endif // wxUSE_STATUSBAR wxPanel* global = new wxPanel(this, -1); @@ -216,14 +218,23 @@ wxbMainFrame::wxbMainFrame(const wxString& title, const wxPoint& pos, const wxSi consoleCtrl = new wxTextCtrl(consolePanel,-1,"",wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE | wxTE_READONLY | wxTE_RICH); consoleCtrl->SetDefaultStyle(wxTextAttr(*wxBLACK, wxNullColour, wxFont(10, wxMODERN, wxNORMAL, wxNORMAL))); - typeCtrl = new wxTextCtrl(consolePanel,TypeText,"",wxDefaultPosition,wxSize(200,20), wxTE_PROCESS_ENTER); - wxFlexGridSizer *consoleSizer = new wxFlexGridSizer(2, 1, 0, 0); consoleSizer->AddGrowableCol(0); consoleSizer->AddGrowableRow(0); + typeCtrl = new wxTextCtrl(consolePanel,TypeText,"",wxDefaultPosition,wxSize(200,20), wxTE_PROCESS_ENTER); + sendButton = new wxButton(consolePanel, SendButton, "Send"); + + wxFlexGridSizer *typeSizer = new wxFlexGridSizer(1, 3, 0, 0); + typeSizer->AddGrowableCol(1); + typeSizer->AddGrowableRow(0); + + typeSizer->Add(new wxStaticText(consolePanel, -1, "Command: "), 0, wxALIGN_CENTER | wxALL, 0); + typeSizer->Add(typeCtrl, 1, wxEXPAND | wxALL, 0); + typeSizer->Add(sendButton, 1, wxEXPAND | wxLEFT, 5); + consoleSizer->Add(consoleCtrl, 1, wxEXPAND | wxALL, 0); - consoleSizer->Add(typeCtrl, 0, wxEXPAND | wxALL, 0); + consoleSizer->Add(typeSizer, 0, wxEXPAND | wxALL, 0); consolePanel->SetAutoLayout( TRUE ); consolePanel->SetSizer( consoleSizer ); @@ -418,6 +429,8 @@ void wxbMainFrame::Print(wxString str, int status) } if (status == CS_DEBUG) { + consoleCtrl->AppendText(consoleBuffer); + consoleBuffer = ""; consoleCtrl->SetDefaultStyle(wxTextAttr(wxColour(0, 128, 0))); } else { diff --git a/bacula/src/wx-console/wxbmainframe.h b/bacula/src/wx-console/wxbmainframe.h index a054c3eb02..6016b26c9e 100644 --- a/bacula/src/wx-console/wxbmainframe.h +++ b/bacula/src/wx-console/wxbmainframe.h @@ -131,8 +131,9 @@ private: ~wxbMainFrame(); wxNotebook *notebook; /* main notebook */ - wxTextCtrl *typeCtrl; /* wxTextCtrl for console user input */ wxTextCtrl *consoleCtrl; /* wxTextCtrl containing graphical console */ + wxTextCtrl *typeCtrl; /* wxTextCtrl for console user input */ + wxButton *sendButton; /* wxButton used to send data */ wxbPanel **panels; /* panels array, contained in the notebook */ wxbDataParsers parsers; /* Data parsers, which need to receive director informations */ diff --git a/bacula/src/wx-console/wxbrestorepanel.cpp b/bacula/src/wx-console/wxbrestorepanel.cpp index e221c966cb..1a4f12a8fe 100644 --- a/bacula/src/wx-console/wxbrestorepanel.cpp +++ b/bacula/src/wx-console/wxbrestorepanel.cpp @@ -52,6 +52,8 @@ Select parameter to modify (1-11): #include #include +#include + #include "unmarked.xpm" #include "marked.xpm" #include "partmarked.xpm" @@ -162,24 +164,26 @@ int wxbTreeItemData::GetMarkedStatus(wxString file) { enum { RestoreStart = 1, - TreeCtrl = 2, - ListCtrl = 3, - ConfigOk = 4, - ConfigApply = 5, - ConfigCancel = 6, - ConfigWhere = 7, - ConfigReplace = 8, - ConfigWhen = 9, - ConfigPriority = 10, - ConfigClient = 11, - ConfigFileset = 12, - ConfigStorage = 13, - ConfigJobName = 14, - ConfigPool = 15 + RestoreCancel = 2, + TreeCtrl = 3, + ListCtrl = 4, + ConfigOk = 5, + ConfigApply = 6, + ConfigCancel = 7, + ConfigWhere = 8, + ConfigReplace = 9, + ConfigWhen = 10, + ConfigPriority = 11, + ConfigClient = 12, + ConfigFileset = 13, + ConfigStorage = 14, + ConfigJobName = 15, + ConfigPool = 16 }; BEGIN_EVENT_TABLE(wxbRestorePanel, wxPanel) EVT_BUTTON(RestoreStart, wxbRestorePanel::OnStart) + EVT_BUTTON(RestoreCancel, wxbRestorePanel::OnCancel) EVT_TREE_SEL_CHANGING(TreeCtrl, wxbRestorePanel::OnTreeChanging) EVT_TREE_SEL_CHANGED(TreeCtrl, wxbRestorePanel::OnTreeChanged) @@ -223,10 +227,16 @@ wxbRestorePanel::wxbRestorePanel(wxWindow* parent): wxbPanel(parent) { mainSizer->AddGrowableCol(0); mainSizer->AddGrowableRow(1); - wxBoxSizer *firstSizer = new wxBoxSizer(wxHORIZONTAL); + wxFlexGridSizer *firstSizer = new wxFlexGridSizer(1, 2, 10, 10); + + firstSizer->AddGrowableCol(0); + firstSizer->AddGrowableRow(0); start = new wxButton(this, RestoreStart, "Enter restore mode", wxDefaultPosition, wxSize(150, 30)); - firstSizer->Add(start, 1, wxALIGN_CENTER_HORIZONTAL | wxALIGN_CENTER_VERTICAL, 10); + firstSizer->Add(start, 0, wxALIGN_CENTER_HORIZONTAL | wxALIGN_CENTER_VERTICAL, 10); + + cancel = new wxButton(this, RestoreCancel, "Cancel restore", wxDefaultPosition, wxSize(150, 30)); + firstSizer->Add(cancel, 0, wxALIGN_CENTER_HORIZONTAL | wxALIGN_RIGHT, 10); wxString elist[1]; @@ -236,7 +246,7 @@ wxbRestorePanel::wxbRestorePanel(wxWindow* parent): wxbPanel(parent) { jobChoice = new wxChoice(this, -1, wxDefaultPosition, wxSize(150, 30), 0, elist); firstSizer->Add(jobChoice, 1, wxALIGN_CENTER_HORIZONTAL | wxALIGN_CENTER_VERTICAL, 10);*/ - mainSizer->Add(firstSizer, 1, wxALIGN_CENTER_HORIZONTAL | wxALIGN_CENTER_VERTICAL, 10); + mainSizer->Add(firstSizer, 1, wxEXPAND, 10); treelistPanel = new wxbTreeListPanel(this); @@ -298,7 +308,7 @@ wxbRestorePanel::wxbRestorePanel(wxWindow* parent): wxbPanel(parent) { config->Add(new wxbConfigParam("Storage", ConfigStorage, choice, 0, elist)); config->Add(new wxbConfigParam("Before", ConfigWhen, choice, 0, elist)); - configPanel = new wxbConfigPanel(this, config, RestoreStart, ConfigCancel, -1); + configPanel = new wxbConfigPanel(this, config, RestoreStart, RestoreCancel, -1); configPanel->Show(true); configPanel->Enable(false); @@ -343,6 +353,8 @@ wxbRestorePanel::wxbRestorePanel(wxWindow* parent): wxbPanel(parent) { SetCursor(*wxSTANDARD_CURSOR); markWhenListingDone = false; + + cancelled = 0; } /* @@ -379,7 +391,7 @@ void wxbRestorePanel::EnablePanel(bool enable) { void wxbRestorePanel::CmdStart() { unsigned int i; if (status == activable) { - wxbMainFrame::GetInstance()->SetStatusText("Getting clients and filesets list."); + wxbMainFrame::GetInstance()->SetStatusText("Getting parameters list."); wxbDataTokenizer* dt = WaitForEnd(".clients\n", true, false); wxString str; @@ -400,6 +412,11 @@ void wxbRestorePanel::CmdStart() { delete dt; + if (cancelled) { + cancelled = 2; + return; + } + dt = WaitForEnd(".filesets\n", true, false); configPanel->ClearRowChoices("Fileset"); @@ -419,6 +436,11 @@ void wxbRestorePanel::CmdStart() { delete dt; + if (cancelled) { + cancelled = 2; + return; + } + dt = WaitForEnd(".storage\n", true, false); configPanel->ClearRowChoices("Storage"); @@ -438,6 +460,11 @@ void wxbRestorePanel::CmdStart() { delete dt; + if (cancelled) { + cancelled = 2; + return; + } + dt = WaitForEnd(".jobs\n", true, false); configPanel->ClearRowChoices("Job Name"); @@ -457,6 +484,11 @@ void wxbRestorePanel::CmdStart() { delete dt; + if (cancelled) { + cancelled = 2; + return; + } + dt = WaitForEnd(".pools\n", true, false); configPanel->ClearRowChoices("Pool"); @@ -473,50 +505,17 @@ void wxbRestorePanel::CmdStart() { } delete dt; - - dt = WaitForEnd(wxString(".defaults job=") + configPanel->GetRowString("Job Name") + "\n", true, false); - /* job=RestoreFiles - * pool=Default - * messages=Standard - * client=*** - * storage=File - * where=/tmp/bacula-restores - * level=0 - * type=Restore - * fileset=Full Set */ - wxString name; - int j; - - for (i = 0; i < dt->GetCount(); i++) { - str = (*dt)[i]; - if ((j = str.Find('=')) > -1) { - name = str.Mid(0, j); - if (name == "pool") { - configPanel->SetRowString("Pool", str.Mid(j+1)); - } - else if (name == "client") { - configPanel->SetRowString("Client", str.Mid(j+1)); - } - else if (name == "storage") { - configPanel->SetRowString("Storage", str.Mid(j+1)); - } - else if (name == "fileset") { - configPanel->SetRowString("Fileset", str.Mid(j+1)); - } - } + if (cancelled) { + cancelled = 2; + return; } - - delete dt; SetStatus(entered); - - configPanel->Enable(false); - configPanel->SetRowSelection("Client", 0); - CmdListJobs(); - configPanel->Enable(true); - - wxbMainFrame::GetInstance()->SetStatusText("Please select a client and a date at which the files you'll select were backed up."); + + UpdateFirstConfig(); + + wxbMainFrame::GetInstance()->SetStatusText("Please configure your restore parameters."); } else if (status == entered) { /* if (clientChoice->GetStringSelection().Length() < 1) { @@ -529,6 +528,8 @@ void wxbRestorePanel::CmdStart() { }*/ wxbMainFrame::GetInstance()->SetStatusText("Building restore tree..."); + SetStatus(choosing); + WaitForPrompt(wxString("restore") << " client=\"" << configPanel->GetRowString("Client") << "\" fileset=\"" << configPanel->GetRowString("Fileset") << @@ -544,11 +545,33 @@ void wxbRestorePanel::CmdStart() { } delete pp;*/ + wxbTableParser* tableparser = new wxbTableParser(); wxbDataTokenizer* dt = new wxbDataTokenizer(true); - wxbTableParser* tableparser = CreateAndWaitForParser(wxString() << configPanel->GetRowString("Before") << "\n"); + + wxbMainFrame::GetInstance()->Send(wxString() << configPanel->GetRowString("Before") << "\n"); + + while (!tableparser->hasFinished() && !dt->hasFinished()) { + wxTheApp->Yield(true); + ::wxUsleep(100); + } + + wxString str; + + if (dt->hasFinished() && !tableparser->hasFinished()) { + str = ""; + if (dt->GetCount() > 1) { + str = (*dt)[dt->GetCount()-2]; + str.RemoveLast(); + } + wxbMainFrame::GetInstance()->SetStatusText(wxString("Error while starting restore: ") << str); + delete dt; + delete tableparser; + SetStatus(finished); + return; + } + int tot = 0; long l; - wxString str; for (i = 0; i < tableparser->size(); i++) { str = (*tableparser)[i][2]; @@ -557,7 +580,7 @@ void wxbRestorePanel::CmdStart() { tot += l; } } - + gauge->SetValue(0); gauge->SetRange(tot); @@ -574,8 +597,7 @@ void wxbRestorePanel::CmdStart() { while (!dt->hasFinished()) { newdate = wxDateTime::Now(); - if ( ( (1000*(newdate.GetTicks()-base.GetTicks())) + - (newdate.GetMillisecond()-base.GetMillisecond()) ) > 10 ) { + if (newdate.Subtract(base).GetMilliseconds() > 10 ) { base = newdate; for (; lastindex < dt->GetCount(); lastindex++) { if (((*dt)[lastindex].Find("Building directory tree for JobId ") == 0) && @@ -614,7 +636,7 @@ void wxbRestorePanel::CmdStart() { << "-" << willdo << "]", CS_DEBUG);*/ } wxTheApp->Yield(true); - ::wxUsleep(100); + ::wxUsleep(1); } gauge->SetValue(tot); @@ -622,9 +644,14 @@ void wxbRestorePanel::CmdStart() { gauge->SetValue(0); delete dt; - + delete tableparser; + + if (cancelled) { + cancelled = 2; + return; + } + WaitForEnd("unmark *\n"); - SetStatus(choosing); wxTreeItemId root = tree->AddRoot(configPanel->GetRowString("Client"), -1, -1, new wxbTreeItemData("/", configPanel->GetRowString("Client"), 0)); tree->Refresh(); UpdateTreeItem(root, true); @@ -632,8 +659,6 @@ void wxbRestorePanel::CmdStart() { tree->Expand(root); } else if (status == choosing) { - SetStatus(configuring); - EnableConfig(false); totfilemessages = 0; @@ -644,6 +669,8 @@ void wxbRestorePanel::CmdStart() { dt = new wxbDataTokenizer(true); WaitForPrompt("done\n"); + SetStatus(configuring); + for (i = 0; i < dt->GetCount(); i++) { if ((j = (*dt)[i].Find(" files selected to be restored.")) > -1) { (*dt)[i].Mid(0, j).ToLong(&totfilemessages); @@ -660,7 +687,7 @@ void wxbRestorePanel::CmdStart() { wxString("Please configure your restore (") << totfilemessages << " files selected to be restored)..."); - UpdateConfig(dt); + UpdateSecondConfig(dt); delete dt; @@ -675,6 +702,8 @@ void wxbRestorePanel::CmdStart() { } } else if (status == configuring) { + cancel->Enable(false); + jobid = ""; EnableConfig(false); wxbMainFrame::GetInstance()->SetStatusText("Restoring, please wait..."); @@ -687,15 +716,78 @@ void wxbRestorePanel::CmdStart() { gauge->SetValue(0); gauge->SetRange(totfilemessages); + wxDateTime currenttime; + + dt = WaitForEnd("time\n", true); + wxStringTokenizer ttkz((*dt)[0], " ", wxTOKEN_STRTOK); + if ((currenttime.ParseDate(ttkz.GetNextToken()) == NULL) || // Date + (currenttime.ParseTime(ttkz.GetNextToken()) == NULL)) { // Time + currenttime.SetYear(1990); // If parsing fails, set currenttime to a dummy date + } + else { + currenttime -= wxTimeSpan::Seconds(30); //Adding a 30" tolerance + } + delete dt; + + wxDateTime scheduledtime; + wxStringTokenizer stkz(restorePanel->GetRowString("When"), " ", wxTOKEN_STRTOK); + + if ((scheduledtime.ParseDate(stkz.GetNextToken()) == NULL) || // Date + (scheduledtime.ParseTime(stkz.GetNextToken()) == NULL)) { // Time + scheduledtime.SetYear(2090); // If parsing fails, set scheduledtime to a dummy date + } + + if (scheduledtime.Subtract(currenttime).IsLongerThan(wxTimeSpan::Seconds(150))) { + wxbMainFrame::GetInstance()->Print("Restore is scheduled in more than two minutes, wx-console will not wait for its completion.\n", CS_DEBUG); + wxbMainFrame::GetInstance()->SetStatusText("Restore is scheduled in more than two minutes, wx-console will not wait for its completion."); + SetStatus(finished); + return; + } + wxString cmd = "list jobid="; - wxbTableParser* tableparser = CreateAndWaitForParser("list jobs\n"); - /* TODO (#1#): Check more carefully which job we just have run. */ - cmd << (*tableparser)[tableparser->size()-1][0] << "\n"; + wxString jobname = restorePanel->GetRowString("Job Name"); - delete tableparser; + wxStopWatch sw; - filemessages = 0; + wxbTableParser* tableparser; + + while (true) { + tableparser = CreateAndWaitForParser("list jobs\n"); + + wxDateTime jobtime; + + if (jobname == (*tableparser)[tableparser->size()-1][1]) { + wxStringTokenizer jtkz((*tableparser)[tableparser->size()-1][2], " ", wxTOKEN_STRTOK); + if ((jobtime.ParseDate(jtkz.GetNextToken()) != NULL) && // Date + (jobtime.ParseTime(jtkz.GetNextToken()) != NULL)) { // Time + if (jobtime.IsLaterThan(currenttime)) { + jobid = (*tableparser)[tableparser->size()-1][0]; + cmd << jobid << "\n"; + delete tableparser; + cancel->Enable(true); + break; + } + } + } + + delete tableparser; + + wxStopWatch sw2; + while (sw2.Time() < 2000) { + wxTheApp->Yield(true); + ::wxUsleep(100); + } + if (sw.Time() > 60000) { + wxbMainFrame::GetInstance()->Print("The restore job has not been created within one minute, wx-console will not wait for its completion anymore.\n", CS_DEBUG); + wxbMainFrame::GetInstance()->SetStatusText("The restore job has not been created within one minute, wx-console will not wait for its completion anymore."); + SetStatus(finished); + cancel->Enable(true); + return; + } + } + + long filemessages = 0; while (true) { tableparser = CreateAndWaitForParser(cmd); @@ -738,8 +830,8 @@ void wxbRestorePanel::CmdStart() { wxbMainFrame::GetInstance()->SetStatusText(wxString("Restoring, please wait (") << filemessages << " of " << totfilemessages << " files done)..."); - time_t start = wxDateTime::Now().GetTicks(); - while (((wxDateTime::Now().GetTicks())-start) < 10) { + wxStopWatch sw2; + while (sw2.Time() < 10000) { wxTheApp->Yield(true); ::wxUsleep(100); } @@ -762,6 +854,53 @@ void wxbRestorePanel::CmdStart() { } } +/* The cancel button has been clicked */ +void wxbRestorePanel::CmdCancel() { + cancelled = 1; + + if (status == restoring) { + int n = 0; + if (jobid != "") { + wxbMainFrame::GetInstance()->Send(wxString("cancel job=") << jobid << "\n"); + } + cancel->Enable(true); + return; + } + + wxStopWatch sw; + while ((working) && (cancelled != 2)) { + wxTheApp->Yield(true); + ::wxUsleep(100); + if (sw.Time() > 30000) { /* 30 seconds timeout */ + if (status == choosing) { + wxbMainFrame::GetInstance()->Send("quit\n"); + } + else if (status == configuring) { + wxbMainFrame::GetInstance()->Send("no\n"); + } + else if (status == restoring) { + + } + SetStatus(finished); + ::wxUsleep(1000); + return; + } + } + + switch (status) { + case choosing: + wxbMainFrame::GetInstance()->Send("quit\n"); + break; + case configuring: + wxbMainFrame::GetInstance()->Send("no\n"); + break; + default: + break; + } + ::wxUsleep(1000); + SetStatus(finished); +} + /* Apply configuration changes */ /* 1: Level (not appropriate) @@ -790,6 +929,10 @@ void wxbRestorePanel::CmdConfigApply() { bool failed = false; while (cfgUpdated > 0) { + if (cancelled) { + cancelled = 2; + return; + } wxString def; //String to send if can't use our data if ((cfgUpdated >> ConfigWhere) & 1) { WaitForPrompt("mod\n"); /* TODO: check results */ @@ -886,7 +1029,7 @@ void wxbRestorePanel::CmdConfigApply() { failed = true; } } - UpdateConfig(dt); /* TODO: Check result */ + UpdateSecondConfig(dt); /* TODO: Check result */ EnableConfig(true); @@ -918,7 +1061,7 @@ void wxbRestorePanel::CmdListJobs() { wxDateTime datetime; const char* chr; if ( ( (chr = datetime.ParseDate(str.GetData()) ) != NULL ) && ( datetime.ParseTime(++chr) != NULL ) ) { - datetime = datetime.GetTicks() + 1; + datetime += wxTimeSpan::Seconds(1); //wxbMainFrame::GetInstance()->Print(wxString("-") << datetime.Format("%Y-%m-%d %H:%M:%S"), CS_DEBUG); configPanel->AddRowChoice("Before", datetime.Format("%Y-%m-%d %H:%M:%S")); } @@ -1381,8 +1524,60 @@ void wxbRestorePanel::RefreshTree(wxTreeItemId item) { }*/ } +/* Update first config, adapting settings to the job name selected */ +void wxbRestorePanel::UpdateFirstConfig() { + configPanel->Enable(false); + wxbDataTokenizer* dt = WaitForEnd(wxString(".defaults job=") + configPanel->GetRowString("Job Name") + "\n", true, false); + /* job=RestoreFiles + * pool=Default + * messages=Standard + * client=*** + * storage=File + * where=/tmp/bacula-restores + * level=0 + * type=Restore + * fileset=Full Set */ + + wxString name, str; + unsigned int i; + int j; + wxString client; + bool dolistjobs = false; + + for (i = 0; i < dt->GetCount(); i++) { + str = (*dt)[i]; + if ((j = str.Find('=')) > -1) { + name = str.Mid(0, j); + if (name == "pool") { + configPanel->SetRowString("Pool", str.Mid(j+1)); + } + else if (name == "client") { + str = str.Mid(j+1); + if ((str != configPanel->GetRowString("Client")) || (configPanel->GetRowString("Before") == "")) { + configPanel->SetRowString("Client", str); + dolistjobs = true; + } + } + else if (name == "storage") { + configPanel->SetRowString("Storage", str.Mid(j+1)); + } + else if (name == "fileset") { + configPanel->SetRowString("Fileset", str.Mid(j+1)); + } + } + } + + delete dt; + + if (dolistjobs) { + //wxTheApp->Yield(false); + CmdListJobs(); + } + configPanel->Enable(true); +} + /* - * Update config. + * Update second config. * * Run Restore job * JobName: RestoreFiles @@ -1397,7 +1592,7 @@ void wxbRestorePanel::RefreshTree(wxTreeItemId item) { * OK to run? (yes/mod/no): * */ -bool wxbRestorePanel::UpdateConfig(wxbDataTokenizer* dt) { +bool wxbRestorePanel::UpdateSecondConfig(wxbDataTokenizer* dt) { unsigned int i; for (i = 0; i < dt->GetCount(); i++) { if ((*dt)[i].Find("Run Restore job") == 0) @@ -1466,7 +1661,9 @@ void wxbRestorePanel::SetStatus(status_enum newstatus) { tree->Enable(false); list->Enable(false); gauge->Enable(false); + cancel->Enable(false); cfgUpdated = 0; + cancelled = 0; break; case finished: centerSizer->Remove(configPanel); @@ -1486,12 +1683,14 @@ void wxbRestorePanel::SetStatus(status_enum newstatus) { wxbMainFrame::GetInstance()->EnablePanels(); newstatus = activable; case activable: + cancelled = 0; start->SetLabel("Enter restore mode"); start->Enable(true); configPanel->Enable(false); tree->Enable(false); list->Enable(false); gauge->Enable(false); + cancel->Enable(false); cfgUpdated = 0; break; case entered: @@ -1502,6 +1701,7 @@ void wxbRestorePanel::SetStatus(status_enum newstatus) { configPanel->Enable(true); tree->Enable(false); list->Enable(false); + cancel->Enable(true); cfgUpdated = 0; break; case listing: @@ -1563,8 +1763,11 @@ void wxbRestorePanel::EnableConfig(bool enable) { Event handling ----------------------------------------------------------------------------*/ -void wxbRestorePanel::OnClientChoiceChanged(wxCommandEvent& event) { - +void wxbRestorePanel::OnCancel(wxEvent& WXUNUSED(event)) { + cancel->Enable(false); + SetCursor(*wxHOURGLASS_CURSOR); + CmdCancel(); + SetCursor(*wxSTANDARD_CURSOR); } void wxbRestorePanel::OnStart(wxEvent& WXUNUSED(event)) { @@ -1686,7 +1889,17 @@ void wxbRestorePanel::OnListActivated(wxListEvent& event) { void wxbRestorePanel::OnConfigUpdated(wxCommandEvent& event) { if (status == entered) { - if (event.GetId() == ConfigClient) { + if (event.GetId() == ConfigJobName) { + if (working) { + return; + } + SetCursor(*wxHOURGLASS_CURSOR); + working = true; + UpdateFirstConfig(); + working = false; + SetCursor(*wxSTANDARD_CURSOR); + } + else if (event.GetId() == ConfigClient) { if (working) { return; } diff --git a/bacula/src/wx-console/wxbrestorepanel.h b/bacula/src/wx-console/wxbrestorepanel.h index 1f285cd66e..015a6d4cee 100644 --- a/bacula/src/wx-console/wxbrestorepanel.h +++ b/bacula/src/wx-console/wxbrestorepanel.h @@ -60,6 +60,9 @@ class wxbRestorePanel : public wxbPanel /* The main button has been clicked */ void CmdStart(); + /* The cancel button has been clicked */ + void CmdCancel(); + /* Apply configuration changes */ void CmdConfigApply(); @@ -76,10 +79,11 @@ class wxbRestorePanel : public wxbPanel void CmdMark(wxTreeItemId treeitem, long listitem); /* General functions and variables */ - bool ended; /* The last command send has finished */ + //bool ended; /* The last command send has finished */ - long filemessages; /* When restoring, number of files restored */ + //long filemessages; /* When restoring, number of files restored */ long totfilemessages; /* When restoring, number of files to be restored */ + wxString jobid; /* Parse a table in tableParser */ wxbTableParser* CreateAndWaitForParser(wxString cmd); @@ -112,8 +116,11 @@ class wxbRestorePanel : public wxbPanel /* Refresh a tree item, and all its children. */ void RefreshTree(wxTreeItemId item); - /* Update config */ - bool UpdateConfig(wxbDataTokenizer* dt); + /* Update first config, adapting settings to the job name selected */ + void UpdateFirstConfig(); + + /* Update second config */ + bool UpdateSecondConfig(wxbDataTokenizer* dt); /* Status related */ enum status_enum @@ -130,6 +137,12 @@ class wxbRestorePanel : public wxbPanel status_enum status; + /* Cancelled status : + * - 0 - !cancelled + * - 1 - will be cancelled + * - 2 - has been cancelled */ + int cancelled; + /* Set current status by enabling/disabling components */ void SetStatus(status_enum newstatus); @@ -143,13 +156,13 @@ class wxbRestorePanel : public wxbPanel /* Event handling */ void OnStart(wxEvent& WXUNUSED(event)); + void OnCancel(wxEvent& WXUNUSED(event)); void OnTreeChanging(wxTreeEvent& event); void OnTreeExpanding(wxTreeEvent& event); void OnTreeChanged(wxTreeEvent& event); void OnTreeMarked(wxbTreeMarkedEvent& event); void OnListMarked(wxbListMarkedEvent& event); void OnListActivated(wxListEvent& event); - void OnClientChoiceChanged(wxCommandEvent& event); void OnConfigUpdated(wxCommandEvent& event); void OnConfigOk(wxEvent& WXUNUSED(event)); void OnConfigApply(wxEvent& WXUNUSED(event)); @@ -164,6 +177,7 @@ class wxbRestorePanel : public wxbPanel wxImageList* imagelist; //image list for tree and list wxButton* start; + wxButton* cancel; wxbTreeCtrl* tree; wxbListCtrl* list; wxGauge* gauge;