3 * wxbPanel for restoring files
5 * Nicolas Boichat, April-May 2004
9 Copyright (C) 2004 Kern Sibbald and John Walker
11 This program is free software; you can redistribute it and/or
12 modify it under the terms of the GNU General Public License
13 as published by the Free Software Foundation; either version 2
14 of the License, or (at your option) any later version.
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
21 You should have received a copy of the GNU General Public License
22 along with this program; if not, write to the Free Software
23 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
25 /* Note concerning "done" output (modifiable marked with +)
27 +JobName: RestoreFiles
28 Bootstrap: /var/lib/bacula/restore.bsr
29 +Where: /tmp/bacula-restores
34 +When: 2004-04-18 01:18:56
36 OK to run? (yes/mod/no):mod
38 1: Level (not appropriate)
39 2: Storage (automatic ?)
42 5: Client (yes : "The defined Client resources are:\n\t1: velours-fd\n\t2: tom-fd\nSelect Client (File daemon) resource (1-2):")
43 6: When (yes : "Please enter desired start time as YYYY-MM-DD HH:MM:SS (return for now):")
44 7: Priority (yes : "Enter new Priority: (positive integer)")
46 9: Where (yes : "Please enter path prefix for restore (/ for none):")
47 10: Replace (yes : "Replace:\n 1: always\n 2: ifnewer\n 3: ifolder\n 4: never\n
48 Select replace option (1-4):")
50 Select parameter to modify (1-11):
53 #include "wxbrestorepanel.h"
55 #include "wxbmainframe.h"
59 #include <wx/choice.h>
60 #include <wx/datetime.h>
64 #include "unmarked.xpm"
66 #include "partmarked.xpm"
68 /* A macro named Yield is defined under MinGW */
72 * Class which is stored in the tree and in the list to keep informations
75 class wxbTreeItemData : public wxTreeItemData {
77 wxbTreeItemData(wxString path, wxString name, int marked, long listid = -1);
78 wxbTreeItemData(wxString path, wxString name, wxString marked, long listid = -1);
84 void SetMarked(int marked);
85 void SetMarked(wxString marked);
89 static int GetMarkedStatus(wxString file);
91 wxString* path; /* Full path */
92 wxString* name; /* File name */
93 int marked; /* 0 - Not Marked, 1 - Marked, 2 - Some file under is marked */
94 long listid; /* list ID : >-1 if this data is in the list (and/or on the tree) */
97 wxbTreeItemData::wxbTreeItemData(wxString path, wxString name, int marked, long listid): wxTreeItemData() {
98 this->path = new wxString(path);
99 this->name = new wxString(name);
100 this->marked = marked;
101 this->listid = listid;
104 wxbTreeItemData::wxbTreeItemData(wxString path, wxString name, wxString marked, long listid): wxTreeItemData() {
105 this->path = new wxString(path);
106 this->name = new wxString(name);
108 this->listid = listid;
111 wxbTreeItemData::~wxbTreeItemData() {
116 int wxbTreeItemData::GetMarked() {
120 void wxbTreeItemData::SetMarked(wxString marked) {
124 else if (marked == "+") {
132 void wxbTreeItemData::SetMarked(int marked) {
133 this->marked = marked;
136 long wxbTreeItemData::GetListId() {
140 wxString wxbTreeItemData::GetPath() {
144 wxString wxbTreeItemData::GetName() {
148 /*wxbTreeItemData* wxbTreeItemData::GetChild(wxString dirname) {
149 int marked = GetMarkedStatus(dirname);
150 return new wxbTreeItemData(path + (marked ? dirname.Mid(1) : dirname), marked);
153 int wxbTreeItemData::GetMarkedStatus(wxString file) {
154 if (file.Length() == 0)
157 switch (file.GetChar(0)) {
167 // ----------------------------------------------------------------------------
168 // event tables and other macros for wxWindows
169 // ----------------------------------------------------------------------------
197 BEGIN_EVENT_TABLE(wxbRestorePanel, wxPanel)
198 EVT_BUTTON(RestoreStart, wxbRestorePanel::OnStart)
199 EVT_BUTTON(RestoreCancel, wxbRestorePanel::OnCancel)
201 EVT_TREE_SEL_CHANGING(TreeCtrl, wxbRestorePanel::OnTreeChanging)
202 EVT_TREE_SEL_CHANGED(TreeCtrl, wxbRestorePanel::OnTreeChanged)
203 EVT_TREE_ITEM_EXPANDING(TreeCtrl, wxbRestorePanel::OnTreeExpanding)
204 EVT_TREE_MARKED_EVENT(TreeCtrl, wxbRestorePanel::OnTreeMarked)
205 EVT_BUTTON(TreeAdd, wxbRestorePanel::OnTreeAdd)
206 EVT_BUTTON(TreeRemove, wxbRestorePanel::OnTreeRemove)
207 EVT_BUTTON(TreeRefresh, wxbRestorePanel::OnTreeRefresh)
209 EVT_LIST_ITEM_ACTIVATED(ListCtrl, wxbRestorePanel::OnListActivated)
210 EVT_LIST_MARKED_EVENT(ListCtrl, wxbRestorePanel::OnListMarked)
211 EVT_LIST_ITEM_SELECTED(ListCtrl, wxbRestorePanel::OnListChanged)
212 EVT_LIST_ITEM_DESELECTED(ListCtrl, wxbRestorePanel::OnListChanged)
213 EVT_BUTTON(ListAdd, wxbRestorePanel::OnListAdd)
214 EVT_BUTTON(ListRemove, wxbRestorePanel::OnListRemove)
215 EVT_BUTTON(ListRefresh, wxbRestorePanel::OnListRefresh)
217 EVT_TEXT(ConfigWhere, wxbRestorePanel::OnConfigUpdated)
218 EVT_TEXT(ConfigWhen, wxbRestorePanel::OnConfigUpdated)
219 EVT_TEXT(ConfigPriority, wxbRestorePanel::OnConfigUpdated)
220 EVT_CHOICE(ConfigWhen, wxbRestorePanel::OnConfigUpdated)
221 EVT_CHOICE(ConfigReplace, wxbRestorePanel::OnConfigUpdated)
222 EVT_CHOICE(ConfigClient, wxbRestorePanel::OnConfigUpdated)
223 EVT_CHOICE(ConfigFileset, wxbRestorePanel::OnConfigUpdated)
224 EVT_CHOICE(ConfigStorage, wxbRestorePanel::OnConfigUpdated)
225 EVT_CHOICE(ConfigJobName, wxbRestorePanel::OnConfigUpdated)
226 EVT_CHOICE(ConfigPool, wxbRestorePanel::OnConfigUpdated)
228 EVT_BUTTON(ConfigOk, wxbRestorePanel::OnConfigOk)
229 EVT_BUTTON(ConfigApply, wxbRestorePanel::OnConfigApply)
230 EVT_BUTTON(ConfigCancel, wxbRestorePanel::OnConfigCancel)
234 * wxbRestorePanel constructor
236 wxbRestorePanel::wxbRestorePanel(wxWindow* parent): wxbPanel(parent) {
237 imagelist = new wxImageList(16, 16, TRUE, 3);
238 imagelist->Add(wxIcon(unmarked_xpm));
239 imagelist->Add(wxIcon(marked_xpm));
240 imagelist->Add(wxIcon(partmarked_xpm));
242 wxFlexGridSizer* mainSizer = new wxFlexGridSizer(3, 1, 10, 10);
243 mainSizer->AddGrowableCol(0);
244 mainSizer->AddGrowableRow(1);
246 wxFlexGridSizer *firstSizer = new wxFlexGridSizer(1, 2, 10, 10);
248 firstSizer->AddGrowableCol(0);
249 firstSizer->AddGrowableRow(0);
251 start = new wxButton(this, RestoreStart, "Enter restore mode", wxDefaultPosition, wxSize(150, 30));
252 firstSizer->Add(start, 0, wxALIGN_CENTER_HORIZONTAL | wxALIGN_CENTER_VERTICAL, 10);
254 cancel = new wxButton(this, RestoreCancel, "Cancel restore", wxDefaultPosition, wxSize(150, 30));
255 firstSizer->Add(cancel, 0, wxALIGN_CENTER_HORIZONTAL | wxALIGN_RIGHT, 10);
259 /* clientChoice = new wxChoice(this, ClientChoice, wxDefaultPosition, wxSize(150, 30), 0, elist);
260 firstSizer->Add(clientChoice, 1, wxALIGN_CENTER_HORIZONTAL | wxALIGN_CENTER_VERTICAL, 10);
262 jobChoice = new wxChoice(this, -1, wxDefaultPosition, wxSize(150, 30), 0, elist);
263 firstSizer->Add(jobChoice, 1, wxALIGN_CENTER_HORIZONTAL | wxALIGN_CENTER_VERTICAL, 10);*/
265 mainSizer->Add(firstSizer, 1, wxEXPAND, 10);
267 treelistPanel = new wxSplitterWindow(this);
269 wxPanel* treePanel = new wxPanel(treelistPanel);
270 wxFlexGridSizer *treeSizer = new wxFlexGridSizer(2, 1, 0, 0);
271 treeSizer->AddGrowableCol(0);
272 treeSizer->AddGrowableRow(0);
274 tree = new wxbTreeCtrl(treePanel, this, TreeCtrl, wxDefaultPosition, wxSize(200,50));
275 tree->SetImageList(imagelist);
277 treeSizer->Add(tree, 1, wxEXPAND, 0);
279 wxBoxSizer *treeCtrlSizer = new wxBoxSizer(wxHORIZONTAL);
280 treeadd = new wxButton(treePanel, TreeAdd, "Add", wxDefaultPosition, wxSize(60, 25));
281 treeCtrlSizer->Add(treeadd, 0, wxLEFT | wxRIGHT, 3);
282 treeremove = new wxButton(treePanel, TreeRemove, "Remove", wxDefaultPosition, wxSize(60, 25));
283 treeCtrlSizer->Add(treeremove, 0, wxLEFT | wxRIGHT, 3);
284 treerefresh = new wxButton(treePanel, TreeRefresh, "Refresh", wxDefaultPosition, wxSize(60, 25));
285 treeCtrlSizer->Add(treerefresh, 0, wxLEFT | wxRIGHT, 3);
287 treeSizer->Add(treeCtrlSizer, 1, wxALIGN_CENTER_HORIZONTAL, 0);
289 treePanel->SetSizer(treeSizer);
291 wxPanel* listPanel = new wxPanel(treelistPanel);
292 wxFlexGridSizer *listSizer = new wxFlexGridSizer(2, 1, 0, 0);
293 listSizer->AddGrowableCol(0);
294 listSizer->AddGrowableRow(0);
296 list = new wxbListCtrl(listPanel, this, ListCtrl, wxDefaultPosition, wxSize(200,50));
297 //treelistSizer->Add(list, 1, wxEXPAND, 10);
299 list->SetImageList(imagelist, wxIMAGE_LIST_SMALL);
302 info.SetMask(wxLIST_MASK_TEXT | wxLIST_MASK_FORMAT);
304 info.SetAlign(wxLIST_FORMAT_CENTER);
305 list->InsertColumn(0, info);
307 info.SetText("Filename");
308 info.SetAlign(wxLIST_FORMAT_LEFT);
309 list->InsertColumn(1, info);
311 info.SetText("Size");
312 info.SetAlign(wxLIST_FORMAT_RIGHT);
313 list->InsertColumn(2, info);
315 info.SetText("Date");
316 info.SetAlign(wxLIST_FORMAT_LEFT);
317 list->InsertColumn(3, info);
319 info.SetText("Perm.");
320 info.SetAlign(wxLIST_FORMAT_LEFT);
321 list->InsertColumn(4, info);
323 info.SetText("User");
324 info.SetAlign(wxLIST_FORMAT_RIGHT);
325 list->InsertColumn(5, info);
327 info.SetText("Group");
328 info.SetAlign(wxLIST_FORMAT_RIGHT);
329 list->InsertColumn(6, info);
331 listSizer->Add(list, 1, wxEXPAND, 0);
333 wxBoxSizer *listCtrlSizer = new wxBoxSizer(wxHORIZONTAL);
334 listadd = new wxButton(listPanel, ListAdd, "Add", wxDefaultPosition, wxSize(60, 25));
335 listCtrlSizer->Add(listadd, 0, wxLEFT | wxRIGHT, 5);
336 listremove = new wxButton(listPanel, ListRemove, "Remove", wxDefaultPosition, wxSize(60, 25));
337 listCtrlSizer->Add(listremove, 0, wxLEFT | wxRIGHT, 5);
338 listrefresh = new wxButton(listPanel, ListRefresh, "Refresh", wxDefaultPosition, wxSize(60, 25));
339 listCtrlSizer->Add(listrefresh, 0, wxLEFT | wxRIGHT, 5);
341 listSizer->Add(listCtrlSizer, 1, wxALIGN_CENTER_HORIZONTAL, 0);
343 listPanel->SetSizer(listSizer);
345 treelistPanel->SplitVertically(treePanel, listPanel, 210);
347 treelistPanel->SetMinimumPaneSize(210);
349 treelistPanel->Show(false);
351 wxbConfig* config = new wxbConfig();
352 config->Add(new wxbConfigParam("Job Name", ConfigJobName, choice, 0, elist));
353 config->Add(new wxbConfigParam("Client", ConfigClient, choice, 0, elist));
354 config->Add(new wxbConfigParam("Fileset", ConfigFileset, choice, 0, elist));
355 config->Add(new wxbConfigParam("Pool", ConfigPool, choice, 0, elist));
356 config->Add(new wxbConfigParam("Storage", ConfigStorage, choice, 0, elist));
357 config->Add(new wxbConfigParam("Before", ConfigWhen, choice, 0, elist));
359 configPanel = new wxbConfigPanel(this, config, "Please configure parameters concerning files to restore :", RestoreStart, RestoreCancel, -1);
361 configPanel->Show(true);
362 configPanel->Enable(false);
364 config = new wxbConfig();
365 config->Add(new wxbConfigParam("Job Name", -1, text, ""));
366 config->Add(new wxbConfigParam("Bootstrap", -1, text, ""));
367 config->Add(new wxbConfigParam("Where", ConfigWhere, modifiableText, ""));
368 wxString erlist[] = {"always", "if newer", "if older", "never"};
369 config->Add(new wxbConfigParam("Replace", ConfigReplace, choice, 4, erlist));
370 config->Add(new wxbConfigParam("Fileset", ConfigFileset, choice, 0, erlist));
371 config->Add(new wxbConfigParam("Client", ConfigClient, choice, 0, erlist));
372 config->Add(new wxbConfigParam("Storage", ConfigStorage, choice, 0, erlist));
373 config->Add(new wxbConfigParam("When", ConfigWhen, modifiableText, ""));
374 config->Add(new wxbConfigParam("Priority", ConfigPriority, modifiableText, ""));
376 restorePanel = new wxbConfigPanel(this, config, "Please configure parameters concerning files restoration :", ConfigOk, ConfigCancel, ConfigApply);
378 restorePanel->Show(false);
380 centerSizer = new wxBoxSizer(wxHORIZONTAL);
381 //centerSizer->Add(treelistPanel, 1, wxEXPAND | wxADJUST_MINSIZE);
383 mainSizer->Add(centerSizer, 1, wxEXPAND, 10);
385 gauge = new wxGauge(this, -1, 1, wxDefaultPosition, wxSize(200,20));
387 mainSizer->Add(gauge, 1, wxEXPAND, 5);
389 gauge->Enable(false);
392 mainSizer->SetSizeHints(this);
396 for (int i = 0; i < 7; i++) {
397 list->SetColumnWidth(i, 70);
401 SetCursor(*wxSTANDARD_CURSOR);
403 markWhenListingDone = false;
409 * wxbRestorePanel destructor
411 wxbRestorePanel::~wxbRestorePanel() {
415 /*----------------------------------------------------------------------------
416 wxbPanel overloadings
417 ----------------------------------------------------------------------------*/
419 wxString wxbRestorePanel::GetTitle() {
423 void wxbRestorePanel::EnablePanel(bool enable) {
425 if (status == disabled) {
426 SetStatus(activable);
434 /*----------------------------------------------------------------------------
435 Commands called by events handler
436 ----------------------------------------------------------------------------*/
438 /* The main button has been clicked */
439 void wxbRestorePanel::CmdStart() {
441 if (status == activable) {
442 wxbMainFrame::GetInstance()->SetStatusText("Getting parameters list.");
443 wxbDataTokenizer* dt = WaitForEnd(".clients\n", true, false);
446 configPanel->ClearRowChoices("Client");
447 restorePanel->ClearRowChoices("Client");
449 if (dt->GetCount() == 0) {
450 wxbMainFrame::GetInstance()->SetStatusText("Error : no clients returned by the director.");
454 for (i = 0; i < dt->GetCount(); i++) {
457 configPanel->AddRowChoice("Client", str);
458 restorePanel->AddRowChoice("Client", str);
468 dt = WaitForEnd(".filesets\n", true, false);
470 configPanel->ClearRowChoices("Fileset");
471 restorePanel->ClearRowChoices("Fileset");
473 if (dt->GetCount() == 0) {
474 wxbMainFrame::GetInstance()->SetStatusText("Error : no filesets returned by the director.");
478 for (i = 0; i < dt->GetCount(); i++) {
481 configPanel->AddRowChoice("Fileset", str);
482 restorePanel->AddRowChoice("Fileset", str);
492 dt = WaitForEnd(".storage\n", true, false);
494 configPanel->ClearRowChoices("Storage");
495 restorePanel->ClearRowChoices("Storage");
497 if (dt->GetCount() == 0) {
498 wxbMainFrame::GetInstance()->SetStatusText("Error : no storage returned by the director.");
502 for (i = 0; i < dt->GetCount(); i++) {
505 configPanel->AddRowChoice("Storage", str);
506 restorePanel->AddRowChoice("Storage", str);
516 dt = WaitForEnd(".jobs\n", true, false);
518 configPanel->ClearRowChoices("Job Name");
520 if (dt->GetCount() == 0) {
521 wxbMainFrame::GetInstance()->SetStatusText("Error : no jobs returned by the director.");
525 for (i = 0; i < dt->GetCount(); i++) {
528 configPanel->AddRowChoice("Job Name", str);
531 configPanel->SetRowString("Job Name", "RestoreFiles");
540 dt = WaitForEnd(".pools\n", true, false);
542 configPanel->ClearRowChoices("Pool");
544 if (dt->GetCount() == 0) {
545 wxbMainFrame::GetInstance()->SetStatusText("Error : no jobs returned by the director.");
549 for (i = 0; i < dt->GetCount(); i++) {
552 configPanel->AddRowChoice("Pool", str);
566 wxbMainFrame::GetInstance()->SetStatusText("Please configure your restore parameters.");
568 else if (status == entered) {
569 /* if (clientChoice->GetStringSelection().Length() < 1) {
570 wxbMainFrame::GetInstance()->SetStatusText("Please select a client.");
573 if (jobChoice->GetStringSelection().Length() < 1) {
574 wxbMainFrame::GetInstance()->SetStatusText("Please select a restore date.");
577 wxbMainFrame::GetInstance()->SetStatusText("Building restore tree...");
581 WaitForPrompt(wxString("restore") <<
582 " client=\"" << configPanel->GetRowString("Client") <<
583 "\" fileset=\"" << configPanel->GetRowString("Fileset") <<
584 "\" pool=\"" << configPanel->GetRowString("Pool") <<
585 "\" storage=\"" << configPanel->GetRowString("Storage") << "\"\n");
586 WaitForPrompt("6\n");
588 /*wxbPromptParser *pp = WaitForPrompt(wxString() << configPanel->GetRowString("Before") << "\n", true);
589 int client = pp->getChoices()->Index(configPanel->GetRowString("Client"));
590 if (client == wxNOT_FOUND) {
591 wxbMainFrame::GetInstance()->SetStatusText("Failed to find the selected client.");
596 wxbTableParser* tableparser = new wxbTableParser();
597 wxbDataTokenizer* dt = new wxbDataTokenizer(true);
599 wxbMainFrame::GetInstance()->Send(wxString() << configPanel->GetRowString("Before") << "\n");
601 while (!tableparser->hasFinished() && !dt->hasFinished()) {
602 wxTheApp->Yield(true);
608 if (dt->hasFinished() && !tableparser->hasFinished()) {
610 if (dt->GetCount() > 1) {
611 str = (*dt)[dt->GetCount()-2];
614 wxbMainFrame::GetInstance()->SetStatusText(wxString("Error while starting restore: ") << str);
624 for (i = 0; i < tableparser->GetCount(); i++) {
625 str = (*tableparser)[i][2];
626 str.Replace(",", "");
627 if (str.ToLong(&l)) {
633 gauge->SetRange(tot);
635 /*wxbMainFrame::GetInstance()->Print(
636 wxString("[") << tot << "]", CS_DEBUG);*/
638 wxDateTime base = wxDateTime::Now();
642 unsigned int lastindex = 0;
646 while (!dt->hasFinished()) {
647 newdate = wxDateTime::Now();
648 if (newdate.Subtract(base).GetMilliseconds() > 10 ) {
650 for (; lastindex < dt->GetCount(); lastindex++) {
651 if (((*dt)[lastindex].Find("Building directory tree for JobId ") == 0) &&
652 ((i = (*dt)[lastindex].Find(" ...")) > 0)) {
653 str = (*dt)[lastindex].Mid(34, i-34);
654 for (i = 0; i < tableparser->GetCount(); i++) {
655 if (str == (*tableparser)[i][0]) {
656 str = (*tableparser)[i][2];
657 str.Replace(",", "");
658 if (str.ToLong(&l)) {
661 var = (willdo-done)/3;
669 if (gauge->GetValue() <= done) {
670 gauge->SetValue(done);
674 else if (gauge->GetValue() >= willdo) {
675 gauge->SetValue(willdo);
680 gauge->SetValue(gauge->GetValue()+var);
682 /*wxbMainFrame::GetInstance()->Print(
683 wxString("[") << gauge->GetValue() << "/" << done
684 << "-" << willdo << "]", CS_DEBUG);*/
686 wxTheApp->Yield(true);
690 gauge->SetValue(tot);
691 wxTheApp->Yield(true);
702 WaitForEnd("unmark *\n");
703 wxTreeItemId root = tree->AddRoot(configPanel->GetRowString("Client"), -1, -1, new wxbTreeItemData("/", configPanel->GetRowString("Client"), 0));
704 currentTreeItem = root;
706 tree->SelectItem(root);
708 wxbMainFrame::GetInstance()->SetStatusText("Right click on a file or on a directory, or double-click on its mark to add it to the restore list.");
711 else if (status == choosing) {
715 wxbDataTokenizer* dt;
719 dt = new wxbDataTokenizer(true);
720 WaitForPrompt("done\n");
722 SetStatus(configuring);
724 for (i = 0; i < dt->GetCount(); i++) {
725 if ((j = (*dt)[i].Find(" files selected to be restored.")) > -1) {
726 (*dt)[i].Mid(0, j).ToLong(&totfilemessages);
730 if ((j = (*dt)[i].Find(" file selected to be restored.")) > -1) {
731 (*dt)[i].Mid(0, j).ToLong(&totfilemessages);
736 wxbMainFrame::GetInstance()->SetStatusText(
737 wxString("Please configure your restore (")
738 << totfilemessages << " files selected to be restored)...");
740 UpdateSecondConfig(dt);
745 restorePanel->EnableApply(false);
747 if (totfilemessages == 0) {
748 wxbMainFrame::GetInstance()->Print("Restore failed : no file selected.\n", CS_DEBUG);
749 wxbMainFrame::GetInstance()->SetStatusText("Restore failed : no file selected.");
754 else if (status == configuring) {
755 cancel->Enable(false);
759 wxbMainFrame::GetInstance()->SetStatusText("Restoring, please wait...");
761 wxbDataTokenizer* dt;
763 SetStatus(restoring);
767 gauge->SetRange(totfilemessages);
769 wxDateTime currenttime;
771 dt = WaitForEnd("time\n", true);
772 wxStringTokenizer ttkz((*dt)[0], " ", wxTOKEN_STRTOK);
773 if ((currenttime.ParseDate(ttkz.GetNextToken()) == NULL) || // Date
774 (currenttime.ParseTime(ttkz.GetNextToken()) == NULL)) { // Time
775 currenttime.SetYear(1990); // If parsing fails, set currenttime to a dummy date
778 currenttime -= wxTimeSpan::Seconds(30); //Adding a 30" tolerance
782 wxDateTime scheduledtime;
783 wxStringTokenizer stkz(restorePanel->GetRowString("When"), " ", wxTOKEN_STRTOK);
785 if ((scheduledtime.ParseDate(stkz.GetNextToken()) == NULL) || // Date
786 (scheduledtime.ParseTime(stkz.GetNextToken()) == NULL)) { // Time
787 scheduledtime.SetYear(2090); // If parsing fails, set scheduledtime to a dummy date
790 if (scheduledtime.Subtract(currenttime).IsLongerThan(wxTimeSpan::Seconds(150))) {
791 wxbMainFrame::GetInstance()->Print("Restore is scheduled in more than two minutes, wx-console will not wait for its completion.\n", CS_DEBUG);
792 wxbMainFrame::GetInstance()->SetStatusText("Restore is scheduled in more than two minutes, wx-console will not wait for its completion.");
797 wxString cmd = "list jobid=";
799 wxString jobname = restorePanel->GetRowString("Job Name");
803 wxbTableParser* tableparser;
806 tableparser = CreateAndWaitForParser("list jobs\n");
810 if (jobname == (*tableparser)[tableparser->GetCount()-1][1]) {
811 wxStringTokenizer jtkz((*tableparser)[tableparser->GetCount()-1][2], " ", wxTOKEN_STRTOK);
812 if ((jobtime.ParseDate(jtkz.GetNextToken()) != NULL) && // Date
813 (jobtime.ParseTime(jtkz.GetNextToken()) != NULL)) { // Time
814 if (jobtime.IsLaterThan(currenttime)) {
815 jobid = (*tableparser)[tableparser->GetCount()-1][0];
816 cmd << jobid << "\n";
818 cancel->Enable(true);
827 while (sw2.Time() < 2000) {
828 wxTheApp->Yield(true);
831 if (sw.Time() > 60000) {
832 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);
833 wxbMainFrame::GetInstance()->SetStatusText("The restore job has not been created within one minute, wx-console will not wait for its completion anymore.");
835 cancel->Enable(true);
840 long filemessages = 0;
843 tableparser = CreateAndWaitForParser(cmd);
844 if ((*tableparser)[0][7] != "C") {
849 dt = WaitForEnd("messages\n", true);
851 for (unsigned int i = 0; i < dt->GetCount(); i++) {
852 wxStringTokenizer tkz((*dt)[i], " ", wxTOKEN_STRTOK);
856 // Date Time name: perm ? user grp size date time
857 //04-Apr-2004 17:19 Tom-fd: -rwx------ 1 nicolas None 514967 2004-03-20 20:03:42 filename
859 if (datetime.ParseDate(tkz.GetNextToken()) != NULL) { // Date
860 if (datetime.ParseTime(tkz.GetNextToken()) != NULL) { // Time
861 if (tkz.GetNextToken().Last() == ':') { // name:
862 tkz.GetNextToken(); // perm
863 tkz.GetNextToken(); // ?
864 tkz.GetNextToken(); // user
865 tkz.GetNextToken(); // grp
866 tkz.GetNextToken(); // size
867 if (datetime.ParseDate(tkz.GetNextToken()) != NULL) { //date
868 if (datetime.ParseTime(tkz.GetNextToken()) != NULL) { //time
870 //wxbMainFrame::GetInstance()->Print(wxString("(") << filemessages << ")", CS_DEBUG);
871 gauge->SetValue(filemessages);
881 wxbMainFrame::GetInstance()->SetStatusText(wxString("Restoring, please wait (") << filemessages << " of " << totfilemessages << " files done)...");
884 while (sw2.Time() < 10000) {
885 wxTheApp->Yield(true);
890 WaitForEnd("messages\n");
892 gauge->SetValue(totfilemessages);
894 if ((*tableparser)[0][7] == "T") {
895 wxbMainFrame::GetInstance()->Print("Restore done successfully.\n", CS_DEBUG);
896 wxbMainFrame::GetInstance()->SetStatusText("Restore done successfully.");
899 wxbMainFrame::GetInstance()->Print("Restore failed, please look at messages.\n", CS_DEBUG);
900 wxbMainFrame::GetInstance()->SetStatusText("Restore failed, please look at messages in console.");
907 /* The cancel button has been clicked */
908 void wxbRestorePanel::CmdCancel() {
911 if (status == restoring) {
913 wxbMainFrame::GetInstance()->Send(wxString("cancel job=") << jobid << "\n");
915 cancel->Enable(true);
920 while ((working) && (cancelled != 2)) {
921 wxTheApp->Yield(true);
923 if (sw.Time() > 30000) { /* 30 seconds timeout */
924 if (status == choosing) {
925 wxbMainFrame::GetInstance()->Send("quit\n");
927 else if (status == configuring) {
928 wxbMainFrame::GetInstance()->Send("no\n");
930 else if (status == restoring) {
941 wxbMainFrame::GetInstance()->Send("quit\n");
944 wxbMainFrame::GetInstance()->Send("no\n");
953 /* Apply configuration changes */
955 /* 1: Level (not appropriate)
960 * 6: When (yes : "Please enter desired start time as YYYY-MM-DD HH:MM:SS (return for now):")
961 * 7: Priority (yes : "Enter new Priority: (positive integer)")
963 * 9: Where (yes : "Please enter path prefix for restore (/ for none):")
964 * 10: Replace (yes : "Replace:\n 1: always\n 2: ifnewer\n 3: ifolder\n 4: never\n
965 * Select replace option (1-4):")
969 void wxbRestorePanel::CmdConfigApply() {
970 if (cfgUpdated == 0) return;
972 wxbMainFrame::GetInstance()->SetStatusText("Applying restore configuration changes...");
976 wxbDataTokenizer* dt = NULL;
980 while (cfgUpdated > 0) {
985 wxString def; //String to send if can't use our data
986 if ((cfgUpdated >> ConfigWhere) & 1) {
987 WaitForPrompt("mod\n"); /* TODO: check results */
988 WaitForPrompt("9\n");
989 dt = new wxbDataTokenizer(true);
990 WaitForPrompt(restorePanel->GetRowString("Where") + "\n");
992 cfgUpdated = cfgUpdated & (~(1 << ConfigWhere));
994 else if ((cfgUpdated >> ConfigReplace) & 1) {
995 WaitForPrompt("mod\n"); /* TODO: check results */
996 WaitForPrompt("10\n");
997 dt = new wxbDataTokenizer(true);
998 WaitForPrompt(wxString() << (restorePanel->GetRowSelection("Replace")+1) << "\n");
1000 cfgUpdated = cfgUpdated & (~(1 << ConfigReplace));
1002 else if ((cfgUpdated >> ConfigWhen) & 1) {
1003 WaitForPrompt("mod\n"); /* TODO: check results */
1004 WaitForPrompt("6\n");
1005 dt = new wxbDataTokenizer(true);
1006 WaitForPrompt(restorePanel->GetRowString("When") + "\n");
1008 cfgUpdated = cfgUpdated & (~(1 << ConfigWhen));
1010 else if ((cfgUpdated >> ConfigPriority) & 1) {
1011 WaitForPrompt("mod\n"); /* TODO: check results */
1012 WaitForPrompt("7\n");
1013 dt = new wxbDataTokenizer(true);
1014 WaitForPrompt(restorePanel->GetRowString("Priority") + "\n");
1016 cfgUpdated = cfgUpdated & (~(1 << ConfigPriority));
1018 else if ((cfgUpdated >> ConfigClient) & 1) {
1019 WaitForPrompt("mod\n"); /* TODO: check results */
1020 wxbPromptParser *pp = WaitForPrompt("5\n", true);
1021 int client = pp->getChoices()->Index(restorePanel->GetRowString("Client"));
1022 if (client == wxNOT_FOUND) {
1023 wxbMainFrame::GetInstance()->SetStatusText("Failed to find the selected client.");
1028 dt = new wxbDataTokenizer(true);
1029 WaitForPrompt(wxString() << client << "\n");
1031 cfgUpdated = cfgUpdated & (~(1 << ConfigClient));
1033 else if ((cfgUpdated >> ConfigFileset) & 1) {
1034 WaitForPrompt("mod\n"); /* TODO: check results */
1035 wxbPromptParser *pp = WaitForPrompt("4\n", true);
1036 int fileset = pp->getChoices()->Index(restorePanel->GetRowString("Fileset"));
1037 if (fileset == wxNOT_FOUND) {
1038 wxbMainFrame::GetInstance()->SetStatusText("Failed to find the selected fileset.");
1043 dt = new wxbDataTokenizer(true);
1044 WaitForPrompt(wxString() << fileset << "\n");
1046 cfgUpdated = cfgUpdated & (~(1 << ConfigFileset));
1048 else if ((cfgUpdated >> ConfigStorage) & 1) {
1049 WaitForPrompt("mod\n"); /* TODO: check results */
1050 wxbPromptParser *pp = WaitForPrompt("2\n", true);
1051 int fileset = pp->getChoices()->Index(restorePanel->GetRowString("Storage"));
1052 if (fileset == wxNOT_FOUND) {
1053 wxbMainFrame::GetInstance()->SetStatusText("Failed to find the selected storage.");
1058 dt = new wxbDataTokenizer(true);
1059 WaitForPrompt(wxString() << fileset << "\n");
1061 cfgUpdated = cfgUpdated & (~(1 << ConfigFileset));
1069 for (i = 0; i < dt->GetCount(); i++) {
1070 if ((*dt)[i].Find("Run Restore job") == 0) {
1075 if (i == dt->GetCount()) {
1077 dt = WaitForEnd(def + "\n", true);
1081 UpdateSecondConfig(dt); /* TODO: Check result */
1086 wxbMainFrame::GetInstance()->SetStatusText("Restore configuration changes were applied.");
1092 /* Cancel restore */
1093 void wxbRestorePanel::CmdConfigCancel() {
1095 wxbMainFrame::GetInstance()->Print("Restore cancelled.\n", CS_DEBUG);
1096 wxbMainFrame::GetInstance()->SetStatusText("Restore cancelled.");
1097 SetStatus(finished);
1100 /* List jobs for a specified client */
1101 void wxbRestorePanel::CmdListJobs() {
1102 if (status == entered) {
1103 configPanel->ClearRowChoices("Before");
1104 WaitForPrompt("query\n");
1105 WaitForPrompt("6\n");
1106 wxbTableParser* tableparser = CreateAndWaitForParser(configPanel->GetRowString("Client") + "\n");
1108 for (int i = tableparser->GetCount()-1; i > -1; i--) {
1109 wxString str = (*tableparser)[i][3];
1110 wxDateTime datetime;
1112 if ( ( (chr = datetime.ParseDate(str.GetData()) ) != NULL ) && ( datetime.ParseTime(++chr) != NULL ) ) {
1113 datetime += wxTimeSpan::Seconds(1);
1114 //wxbMainFrame::GetInstance()->Print(wxString("-") << datetime.Format("%Y-%m-%d %H:%M:%S"), CS_DEBUG);
1115 configPanel->AddRowChoice("Before", datetime.Format("%Y-%m-%d %H:%M:%S"));
1118 jobChoice->Append("Invalid");
1124 configPanel->SetRowSelection("Before", 0);
1128 /* List files and directories for a specified tree item */
1129 void wxbRestorePanel::CmdList(wxTreeItemId item) {
1130 if (status == choosing) {
1131 list->DeleteAllItems();
1136 UpdateTreeItem(item, (tree->GetSelection() == item), false);
1138 if (list->GetItemCount() >= 1) {
1139 int firstwidth = list->GetSize().GetWidth();
1140 for (int i = 2; i < 7; i++) {
1141 list->SetColumnWidth(i, wxLIST_AUTOSIZE);
1142 firstwidth -= list->GetColumnWidth(i);
1145 list->SetColumnWidth(0, 18);
1147 list->SetColumnWidth(1, wxLIST_AUTOSIZE);
1148 if (list->GetColumnWidth(1) < firstwidth) {
1149 list->SetColumnWidth(1, firstwidth-25);
1155 /* Mark a treeitem (directory) or a listitem (file or directory) */
1156 void wxbRestorePanel::CmdMark(wxTreeItemId treeitem, long* listitems, int listsize, int state) {
1157 if (status == choosing) {
1158 wxbTreeItemData** itemdata;
1159 int itemdatasize = 0;
1160 if (listsize == 0) {
1161 itemdata = new wxbTreeItemData*[1];
1165 itemdata = new wxbTreeItemData*[listsize];
1166 itemdatasize = listsize;
1169 if (listitems != NULL) {
1170 for (int i = 0; i < listsize; i++) {
1171 itemdata[i] = (wxbTreeItemData*)list->GetItemData(listitems[i]);
1174 else if (treeitem.IsOk()) {
1175 itemdata[0] = (wxbTreeItemData*)tree->GetItemData(treeitem);
1182 if (itemdata[0] == NULL) { //Should never happen
1187 wxString dir = itemdata[0]->GetPath();
1191 if (dir.GetChar(dir.Length()-1) == '/') {
1195 int i = dir.Find('/', TRUE);
1200 else { /* first dir below root */
1201 file = dir.Mid(i+1);
1202 dir = dir.Mid(0, i+1);
1211 bool marked = false;
1212 bool unmarked = false;
1214 for (int i = 0; i < itemdatasize; i++) {
1215 switch(itemdata[i]->GetMarked()) {
1229 if (marked && unmarked)
1245 WaitForEnd(wxString("cd \"") << dir << "\"\n");
1246 WaitForEnd(wxString((state==1) ? "mark" : "unmark") << " \"" << file << "\"\n");
1248 /* TODO: Check commands results */
1250 /*if ((dir == "/") && (file == "*")) {
1251 itemdata->SetMarked((itemdata->GetMarked() == 1) ? 0 : 1);
1254 if (listitems == NULL) { /* tree item state changed */
1255 SetTreeItemState(treeitem, state);
1256 /*treeitem = tree->GetSelection();
1257 UpdateTree(treeitem, true);
1258 treeitem = tree->GetItemParent(treeitem);*/
1261 for (int i = 0; i < listsize; i++) {
1262 SetListItemState(listitems[i], state);
1264 /*UpdateTree(treeitem, (tree->GetSelection() == treeitem));
1265 treeitem = tree->GetItemParent(treeitem);*/
1268 /*while (treeitem.IsOk()) {
1269 WaitForList(treeitem, false);
1270 treeitem = tree->GetItemParent(treeitem);
1277 /*----------------------------------------------------------------------------
1279 ----------------------------------------------------------------------------*/
1281 /* Parse a table in tableParser */
1282 wxbTableParser* wxbRestorePanel::CreateAndWaitForParser(wxString cmd) {
1283 wxbTableParser* tableParser = new wxbTableParser();
1285 wxbMainFrame::GetInstance()->Send(cmd);
1287 //time_t base = wxDateTime::Now().GetTicks();
1288 while (!tableParser->hasFinished()) {
1289 //innerThread->Yield();
1290 wxTheApp->Yield(true);
1292 //if (base+15 < wxDateTime::Now().GetTicks()) break;
1297 /* Run a command, and waits until prompt result is fully received,
1298 * if keepresults is true, returns a valid pointer to a wxbPromptParser
1299 * containing the data. */
1300 wxbPromptParser* wxbRestorePanel::WaitForPrompt(wxString cmd, bool keepresults) {
1301 wxbPromptParser* promptParser = new wxbPromptParser();
1303 wxbMainFrame::GetInstance()->Send(cmd);
1305 //time_t base = wxDateTime::Now().GetTicks();
1306 while (!promptParser->hasFinished()) {
1307 //innerThread->Yield();
1308 wxTheApp->Yield(true);
1310 //if (base+15 < wxDateTime::Now().GetTicks()) break;
1314 return promptParser;
1317 delete promptParser;
1322 /* Run a command, and waits until result is fully received. */
1323 wxbDataTokenizer* wxbRestorePanel::WaitForEnd(wxString cmd, bool keepresults, bool linebyline) {
1324 wxbDataTokenizer* datatokenizer = new wxbDataTokenizer(linebyline);
1326 wxbMainFrame::GetInstance()->Send(cmd);
1328 //wxbMainFrame::GetInstance()->Print("(<WFE)", CS_DEBUG);
1330 //time_t base = wxDateTime::Now().GetTicks();
1331 while (!datatokenizer->hasFinished()) {
1332 //innerThread->Yield();
1333 wxTheApp->Yield(true);
1335 //if (base+15 < wxDateTime::Now().GetTicks()) break;
1338 //wxbMainFrame::GetInstance()->Print("(>WFE)", CS_DEBUG);
1341 return datatokenizer;
1344 delete datatokenizer;
1349 /* Run a dir command, and waits until result is fully received. */
1350 void wxbRestorePanel::UpdateTreeItem(wxTreeItemId item, bool updatelist, bool recurse) {
1351 // this->updatelist = updatelist;
1352 wxbDataTokenizer* dt;
1354 dt = WaitForEnd(wxString("cd \"") <<
1355 static_cast<wxbTreeItemData*>(tree->GetItemData(item))
1356 ->GetPath() << "\"\n", false);
1358 /* TODO: check command result */
1365 list->DeleteAllItems();
1366 dt = WaitForEnd("dir\n", true);
1370 for (unsigned int i = 0; i < dt->GetCount(); i++) {
1373 if (str.Find("cwd is:") == 0) { // Sometimes cd command result "infiltrate" into listings.
1379 wxString* file = ParseList(str);
1384 wxTreeItemId treeid;
1386 if (file[8].GetChar(file[8].Length()-1) == '/') {
1390 treeid = tree->GetFirstChild(item, cookie);
1392 bool updated = false;
1394 while (treeid.IsOk()) {
1395 itemStr = tree->GetItemText(treeid);
1396 if (file[8] == itemStr) {
1397 int stat = wxbTreeItemData::GetMarkedStatus(file[6]);
1398 if (static_cast<wxbTreeItemData*>(tree->GetItemData(treeid))->GetMarked() != stat) {
1399 tree->SetItemImage(treeid, stat, wxTreeItemIcon_Normal);
1400 tree->SetItemImage(treeid, stat, wxTreeItemIcon_Selected);
1401 static_cast<wxbTreeItemData*>(tree->GetItemData(treeid))->SetMarked(file[6]);
1403 if ((recurse) && (tree->IsExpanded(treeid))) {
1404 UpdateTreeItem(treeid, false, true);
1409 treeid = tree->GetNextChild(item, cookie);
1413 int img = wxbTreeItemData::GetMarkedStatus(file[6]);
1414 treeid = tree->AppendItem(item, file[8], img, img, new wxbTreeItemData(file[7], file[8], file[6]));
1419 long ind = list->InsertItem(list->GetItemCount(), wxbTreeItemData::GetMarkedStatus(file[6]));
1420 wxbTreeItemData* data = new wxbTreeItemData(file[7], file[8], file[6], ind);
1421 data->SetId(treeid);
1422 list->SetItemData(ind, (long)data);
1423 list->SetItem(ind, 1, file[8]); // filename
1424 list->SetItem(ind, 2, file[4]); //Size
1425 list->SetItem(ind, 3, file[5]); //date
1426 list->SetItem(ind, 4, file[0]); //perm
1427 list->SetItem(ind, 5, file[2]); //user
1428 list->SetItem(ind, 6, file[3]); //grp
1440 /* Parse dir command results. */
1441 wxString* wxbRestorePanel::ParseList(wxString line) {
1442 //drwx------ 11 1003 42949672 0 2001-07-30 16:45:14 *filename
1443 //+ 10 ++ 4++ 10 ++ 8 ++ 8 + + 19 + *+ ->
1444 //0 10 14 24 32 42 62
1446 if (line.Length() < 63)
1449 wxString* ret = new wxString[9];
1451 ret[0] = line.Mid(0, 10).Trim();
1452 ret[1] = line.Mid(10, 4).Trim();
1453 ret[2] = line.Mid(14, 10).Trim();
1454 ret[3] = line.Mid(24, 8).Trim();
1455 ret[4] = line.Mid(32, 8).Trim();
1456 ret[5] = line.Mid(42, 19).Trim();
1457 ret[6] = line.Mid(62, 1);
1458 ret[7] = line.Mid(63).Trim();
1460 if (ret[6] == " ") ret[6] = "";
1462 if (ret[7].GetChar(ret[7].Length()-1) == '/') {
1464 ret[8].RemoveLast();
1465 ret[8] = ret[7].Mid(ret[8].Find('/', true)+1);
1468 ret[8] = ret[7].Mid(ret[7].Find('/', true)+1);
1474 /* Sets a list item state, and update its parents and children if it is a directory */
1475 void wxbRestorePanel::SetListItemState(long listitem, int newstate) {
1476 wxbTreeItemData* itemdata = (wxbTreeItemData*)list->GetItemData(listitem);
1478 wxTreeItemId treeitem;
1480 itemdata->SetMarked(newstate);
1481 list->SetItemImage(listitem, newstate, 0); /* TODO: Find what these ints are for */
1482 list->SetItemImage(listitem, newstate, 1);
1484 if ((treeitem = itemdata->GetId()).IsOk()) {
1485 SetTreeItemState(treeitem, newstate);
1488 UpdateTreeItemState(tree->GetSelection());
1492 /* Sets a tree item state, and update its children, parents and list (if necessary) */
1493 void wxbRestorePanel::SetTreeItemState(wxTreeItemId item, int newstate) {
1495 wxTreeItemId currentChild = tree->GetFirstChild(item, cookie);
1497 wxbTreeItemData* itemdata;
1499 while (currentChild.IsOk()) {
1500 itemdata = (wxbTreeItemData*)tree->GetItemData(currentChild);
1501 int state = itemdata->GetMarked();
1503 if (state != newstate) {
1504 itemdata->SetMarked(newstate);
1505 tree->SetItemImage(currentChild, newstate, wxTreeItemIcon_Normal);
1506 tree->SetItemImage(currentChild, newstate, wxTreeItemIcon_Selected);
1509 currentChild = tree->GetNextChild(item, cookie);
1512 itemdata = (wxbTreeItemData*)tree->GetItemData(item);
1513 itemdata->SetMarked(newstate);
1514 tree->SetItemImage(item, newstate, wxTreeItemIcon_Normal);
1515 tree->SetItemImage(item, newstate, wxTreeItemIcon_Selected);
1518 if (tree->GetSelection() == item) {
1519 for (long i = 0; i < list->GetItemCount(); i++) {
1520 list->SetItemImage(i, newstate, 0); /* TODO: Find what these ints are for */
1521 list->SetItemImage(i, newstate, 1);
1525 UpdateTreeItemState(tree->GetItemParent(item));
1528 /* Update a tree item state, and its parents' state */
1529 void wxbRestorePanel::UpdateTreeItemState(wxTreeItemId item) {
1537 wxTreeItemId currentChild = tree->GetFirstChild(item, cookie);
1539 bool onechildmarked = false;
1540 bool onechildunmarked = false;
1542 while (currentChild.IsOk()) {
1543 state = ((wxbTreeItemData*)tree->GetItemData(currentChild))->GetMarked();
1546 onechildunmarked = true;
1549 onechildmarked = true;
1552 onechildmarked = true;
1553 onechildunmarked = true;
1557 if (onechildmarked && onechildunmarked) {
1561 currentChild = tree->GetNextChild(item, cookie);
1564 if (tree->GetSelection() == item) {
1565 for (long i = 0; i < list->GetItemCount(); i++) {
1566 state = ((wxbTreeItemData*)list->GetItemData(i))->GetMarked();
1570 onechildunmarked = true;
1573 onechildmarked = true;
1576 onechildmarked = true;
1577 onechildunmarked = true;
1581 if (onechildmarked && onechildunmarked) {
1589 if (onechildmarked && onechildunmarked) {
1592 else if (onechildmarked) {
1595 else if (onechildunmarked) {
1598 else { // no child, don't change anything
1599 UpdateTreeItemState(tree->GetItemParent(item));
1603 wxbTreeItemData* itemdata = (wxbTreeItemData*)tree->GetItemData(item);
1605 itemdata->SetMarked(state);
1606 tree->SetItemImage(item, state, wxTreeItemIcon_Normal);
1607 tree->SetItemImage(item, state, wxTreeItemIcon_Selected);
1609 UpdateTreeItemState(tree->GetItemParent(item));
1612 /* Refresh the whole tree. */
1613 void wxbRestorePanel::RefreshTree() {
1614 /* Save current selection */
1615 wxArrayString current;
1617 wxTreeItemId item = currentTreeItem;
1619 while ((item.IsOk()) && (item != tree->GetRootItem())) {
1620 current.Add(tree->GetItemText(item));
1621 item = tree->GetItemParent(item);
1624 /* Update the tree */
1625 UpdateTreeItem(tree->GetRootItem(), false, true);
1627 /* Reselect the former selected item */
1628 item = tree->GetRootItem();
1630 if (current.Count() == 0) {
1631 tree->SelectItem(item);
1637 for (int i = current.Count()-1; i >= 0; i--) {
1639 wxTreeItemId currentChild = tree->GetFirstChild(item, cookie);
1643 while (currentChild.IsOk()) {
1644 if (tree->GetItemText(currentChild) == current[i]) {
1645 item = currentChild;
1650 currentChild = tree->GetNextChild(item, cookie);
1656 UpdateTreeItem(item, true, false); /* Update the list */
1658 tree->SelectItem(item);
1661 void wxbRestorePanel::RefreshList() {
1662 if (currentTreeItem.IsOk()) {
1663 UpdateTreeItem(currentTreeItem, true, false); /* Update the list */
1667 /* Update first config, adapting settings to the job name selected */
1668 void wxbRestorePanel::UpdateFirstConfig() {
1669 configPanel->Enable(false);
1670 wxbDataTokenizer* dt = WaitForEnd(wxString(".defaults job=") + configPanel->GetRowString("Job Name") + "\n", true, false);
1676 * where=/tmp/bacula-restores
1679 * fileset=Full Set */
1685 bool dolistjobs = false;
1687 for (i = 0; i < dt->GetCount(); i++) {
1689 if ((j = str.Find('=')) > -1) {
1690 name = str.Mid(0, j);
1691 if (name == "pool") {
1692 configPanel->SetRowString("Pool", str.Mid(j+1));
1694 else if (name == "client") {
1696 if ((str != configPanel->GetRowString("Client")) || (configPanel->GetRowString("Before") == "")) {
1697 configPanel->SetRowString("Client", str);
1701 else if (name == "storage") {
1702 configPanel->SetRowString("Storage", str.Mid(j+1));
1704 else if (name == "fileset") {
1705 configPanel->SetRowString("Fileset", str.Mid(j+1));
1713 //wxTheApp->Yield(false);
1716 configPanel->Enable(true);
1720 * Update second config.
1723 * JobName: RestoreFiles
1724 * Bootstrap: /var/lib/bacula/restore.bsr
1725 * Where: /tmp/bacula-restores
1730 * When: 2004-04-18 01:18:56
1732 * OK to run? (yes/mod/no):
1735 bool wxbRestorePanel::UpdateSecondConfig(wxbDataTokenizer* dt) {
1737 for (i = 0; i < dt->GetCount(); i++) {
1738 if ((*dt)[i].Find("Run Restore job") == 0)
1742 if ((i + 10) > dt->GetCount()) {
1748 if ((k = (*dt)[++i].Find("JobName:")) != 0) return false;
1749 restorePanel->SetRowString("Job Name", (*dt)[i].Mid(10).Trim(false).RemoveLast());
1750 if ((k = (*dt)[++i].Find("Bootstrap:")) != 0) return false;
1751 restorePanel->SetRowString("Bootstrap", (*dt)[i].Mid(10).Trim(false).RemoveLast());
1752 if ((k = (*dt)[++i].Find("Where:")) != 0) return false;
1753 restorePanel->SetRowString("Where", (*dt)[i].Mid(10).Trim(false).RemoveLast());
1755 if ((k = (*dt)[++i].Find("Replace:")) != 0) return false;
1756 wxString str = (*dt)[i].Mid(10).Trim(false).RemoveLast();
1757 if (str == "always") restorePanel->SetRowSelection("Replace", 0);
1758 else if (str == "ifnewer") restorePanel->SetRowSelection("Replace", 1);
1759 else if (str == "ifolder") restorePanel->SetRowSelection("Replace", 2);
1760 else if (str == "never") restorePanel->SetRowSelection("Replace", 3);
1761 else restorePanel->SetRowSelection("Replace", 0);
1763 if ((k = (*dt)[++i].Find("FileSet:")) != 0) return false;
1764 restorePanel->SetRowString("Fileset", (*dt)[i].Mid(10).Trim(false).RemoveLast());
1765 if ((k = (*dt)[++i].Find("Client:")) != 0) return false;
1766 restorePanel->SetRowString("Client", (*dt)[i].Mid(10).Trim(false).RemoveLast());
1767 if ((k = (*dt)[++i].Find("Storage:")) != 0) return false;
1768 restorePanel->SetRowString("Storage", (*dt)[i].Mid(10).Trim(false).RemoveLast());
1769 if ((k = (*dt)[++i].Find("When:")) != 0) return false;
1770 restorePanel->SetRowString("When", (*dt)[i].Mid(10).Trim(false).RemoveLast());
1771 if ((k = (*dt)[++i].Find("Priority:")) != 0) return false;
1772 restorePanel->SetRowString("Priority", (*dt)[i].Mid(10).Trim(false).RemoveLast());
1775 restorePanel->Layout();
1780 /*----------------------------------------------------------------------------
1782 ----------------------------------------------------------------------------*/
1784 /* Set current status by enabling/disabling components */
1785 void wxbRestorePanel::SetStatus(status_enum newstatus) {
1786 switch (newstatus) {
1788 centerSizer->Remove(configPanel);
1789 centerSizer->Remove(restorePanel);
1790 centerSizer->Remove(treelistPanel);
1791 treelistPanel->Show(false);
1792 restorePanel->Show(false);
1793 centerSizer->Add(configPanel, 1, wxEXPAND);
1794 configPanel->Show(true);
1795 configPanel->Layout();
1796 centerSizer->Layout();
1798 start->SetLabel("Enter restore mode");
1799 start->Enable(false);
1800 configPanel->Enable(false);
1801 tree->Enable(false);
1802 list->Enable(false);
1803 gauge->Enable(false);
1804 cancel->Enable(false);
1809 centerSizer->Remove(configPanel);
1810 centerSizer->Remove(restorePanel);
1811 centerSizer->Remove(treelistPanel);
1812 treelistPanel->Show(false);
1813 restorePanel->Show(false);
1814 centerSizer->Add(configPanel, 1, wxEXPAND);
1815 configPanel->Show(true);
1816 configPanel->Layout();
1817 centerSizer->Layout();
1819 tree->DeleteAllItems();
1820 list->DeleteAllItems();
1821 configPanel->ClearRowChoices("Client");
1822 configPanel->ClearRowChoices("Before");
1823 wxbMainFrame::GetInstance()->EnablePanels();
1824 newstatus = activable;
1827 start->SetLabel("Enter restore mode");
1828 start->Enable(true);
1829 configPanel->Enable(false);
1830 tree->Enable(false);
1831 list->Enable(false);
1832 gauge->Enable(false);
1833 cancel->Enable(false);
1837 wxbMainFrame::GetInstance()->DisablePanels(this);
1839 start->Enable(false);
1840 //start->SetLabel("Choose files to restore");
1841 configPanel->Enable(true);
1842 tree->Enable(false);
1843 list->Enable(false);
1844 cancel->Enable(true);
1851 start->Enable(true);
1852 start->SetLabel("Restore");
1853 centerSizer->Remove(configPanel);
1854 configPanel->Show(false);
1855 centerSizer->Add(treelistPanel, 1, wxEXPAND);
1856 treelistPanel->Show(true);
1857 treelistPanel->Layout();
1858 centerSizer->Layout();
1863 SetCursor(*wxSTANDARD_CURSOR);
1866 start->Enable(false);
1867 configPanel->Enable(false);
1868 tree->Enable(false);
1869 list->Enable(false);
1870 centerSizer->Remove(treelistPanel);
1871 treelistPanel->Show(false);
1872 centerSizer->Add(restorePanel, 1, wxEXPAND);
1873 restorePanel->Show(true);
1874 restorePanel->Layout();
1875 centerSizer->Layout();
1877 restorePanel->EnableApply(false);
1880 start->SetLabel("Restoring...");
1881 gauge->Enable(true);
1883 start->Enable(false);
1884 configPanel->Enable(false);
1885 tree->Enable(false);
1886 list->Enable(false);
1887 SetCursor(*wxHOURGLASS_CURSOR);
1894 /*----------------------------------------------------------------------------
1896 ----------------------------------------------------------------------------*/
1898 void wxbRestorePanel::EnableConfig(bool enable) {
1899 restorePanel->Enable(enable);
1902 /*----------------------------------------------------------------------------
1904 ----------------------------------------------------------------------------*/
1906 void wxbRestorePanel::OnCancel(wxCommandEvent& WXUNUSED(event)) {
1907 cancel->Enable(false);
1908 SetCursor(*wxHOURGLASS_CURSOR);
1910 SetCursor(*wxSTANDARD_CURSOR);
1913 void wxbRestorePanel::OnStart(wxCommandEvent& WXUNUSED(event)) {
1917 SetCursor(*wxHOURGLASS_CURSOR);
1921 SetCursor(*wxSTANDARD_CURSOR);
1924 void wxbRestorePanel::OnTreeChanging(wxTreeEvent& event) {
1930 void wxbRestorePanel::OnTreeExpanding(wxTreeEvent& event) {
1936 //CmdList(event.GetItem());
1937 if (tree->GetSelection() != event.GetItem()) {
1938 tree->SelectItem(event.GetItem());
1943 void wxbRestorePanel::OnTreeChanged(wxTreeEvent& event) {
1947 if (currentTreeItem == event.GetItem()) {
1950 treeadd->Enable(false);
1951 treeremove->Enable(false);
1952 treerefresh->Enable(false);
1953 SetCursor(*wxHOURGLASS_CURSOR);
1954 markWhenListingDone = false;
1956 currentTreeItem = event.GetItem();
1957 CmdList(event.GetItem());
1958 if (markWhenListingDone) {
1959 CmdMark(event.GetItem(), NULL, 0);
1963 SetCursor(*wxSTANDARD_CURSOR);
1964 if (event.GetItem().IsOk()) {
1965 int status = ((wxbTreeItemData*)tree->GetItemData(event.GetItem()))->GetMarked();
1966 treeadd->Enable(status != 1);
1967 treeremove->Enable(status != 0);
1969 treerefresh->Enable(true);
1972 void wxbRestorePanel::OnTreeMarked(wxbTreeMarkedEvent& event) {
1973 csprint("Tree marked", CS_DEBUG);
1975 if (tree->GetSelection() == event.GetItem()) {
1976 markWhenListingDone = !markWhenListingDone;
1980 SetCursor(*wxHOURGLASS_CURSOR);
1982 CmdMark(event.GetItem(), NULL, 0);
1986 if (event.GetItem().IsOk()) {
1987 int status = ((wxbTreeItemData*)tree->GetItemData(event.GetItem()))->GetMarked();
1988 treeadd->Enable(status != 1);
1989 treeremove->Enable(status != 0);
1991 SetCursor(*wxSTANDARD_CURSOR);
1994 void wxbRestorePanel::OnTreeAdd(wxCommandEvent& event) {
1999 if (currentTreeItem.IsOk()) {
2000 SetCursor(*wxHOURGLASS_CURSOR);
2002 CmdMark(currentTreeItem, NULL, 0, 1);
2006 treeremove->Enable(1);
2007 SetCursor(*wxSTANDARD_CURSOR);
2011 void wxbRestorePanel::OnTreeRemove(wxCommandEvent& event) {
2016 if (currentTreeItem.IsOk()) {
2017 SetCursor(*wxHOURGLASS_CURSOR);
2019 CmdMark(currentTreeItem, NULL, 0, 0);
2023 treeremove->Enable(0);
2024 SetCursor(*wxSTANDARD_CURSOR);
2028 void wxbRestorePanel::OnTreeRefresh(wxCommandEvent& event) {
2036 void wxbRestorePanel::OnListMarked(wxbListMarkedEvent& event) {
2042 if (list->GetSelectedItemCount() == 0) {
2046 SetCursor(*wxHOURGLASS_CURSOR);
2049 long* items = new long[list->GetSelectedItemCount()];
2053 long item = list->GetNextItem(-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
2054 while (item != -1) {
2057 item = list->GetNextItem(item, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
2060 CmdMark(wxTreeItemId(), items, num);
2064 wxListEvent listevt;
2066 OnListChanged(listevt);
2071 SetCursor(*wxSTANDARD_CURSOR);
2074 void wxbRestorePanel::OnListActivated(wxListEvent& event) {
2079 SetCursor(*wxHOURGLASS_CURSOR);
2081 long item = event.GetIndex();
2082 // long item = list->GetNextItem(-1, wxLIST_NEXT_ALL, wxLIST_STATE_FOCUSED);
2084 wxbTreeItemData* itemdata = (wxbTreeItemData*)list->GetItemData(item);
2085 wxString name = itemdata->GetName();
2092 if (name.GetChar(name.Length()-1) == '/') {
2093 wxTreeItemId currentChild = tree->GetFirstChild(currentTreeItem, cookie);
2095 while (currentChild.IsOk()) {
2096 wxString name2 = tree->GetItemText(currentChild);
2097 if (name2 == name) {
2098 //tree->UnselectAll();
2100 SetCursor(*wxSTANDARD_CURSOR);
2101 tree->Expand(currentTreeItem);
2102 tree->SelectItem(currentChild);
2106 currentChild = tree->GetNextChild(currentTreeItem, cookie);
2111 SetCursor(*wxSTANDARD_CURSOR);
2114 void wxbRestorePanel::OnListChanged(wxListEvent& event) {
2115 listadd->Enable(false);
2116 listremove->Enable(false);
2118 bool marked = false;
2119 bool unmarked = false;
2121 long item = list->GetNextItem(-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
2122 while (item != -1) {
2123 switch (((wxbTreeItemData*)list->GetItemData(item))->GetMarked()) {
2136 // Should never happen
2138 if (marked && unmarked) break;
2139 item = list->GetNextItem(item, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
2142 listadd->Enable(unmarked);
2143 listremove->Enable(marked);
2146 void wxbRestorePanel::OnListAdd(wxCommandEvent& WXUNUSED(event)) {
2151 SetCursor(*wxHOURGLASS_CURSOR);
2154 long* items = new long[list->GetSelectedItemCount()];
2158 long item = list->GetNextItem(-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
2159 while (item != -1) {
2162 item = list->GetNextItem(item, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
2165 CmdMark(wxTreeItemId(), items, num, 1);
2171 SetCursor(*wxSTANDARD_CURSOR);
2173 listadd->Enable(false);
2174 listremove->Enable(true);
2177 void wxbRestorePanel::OnListRemove(wxCommandEvent& WXUNUSED(event)) {
2182 SetCursor(*wxHOURGLASS_CURSOR);
2185 long* items = new long[list->GetSelectedItemCount()];
2189 long item = list->GetNextItem(-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
2190 while (item != -1) {
2193 item = list->GetNextItem(item, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
2196 CmdMark(wxTreeItemId(), items, num, 0);
2202 SetCursor(*wxSTANDARD_CURSOR);
2204 listadd->Enable(true);
2205 listremove->Enable(false);
2208 void wxbRestorePanel::OnListRefresh(wxCommandEvent& WXUNUSED(event)) {
2216 void wxbRestorePanel::OnConfigUpdated(wxCommandEvent& event) {
2217 if (status == entered) {
2218 if (event.GetId() == ConfigJobName) {
2222 SetCursor(*wxHOURGLASS_CURSOR);
2224 UpdateFirstConfig();
2226 SetCursor(*wxSTANDARD_CURSOR);
2228 else if (event.GetId() == ConfigClient) {
2232 SetCursor(*wxHOURGLASS_CURSOR);
2234 configPanel->Enable(false);
2236 configPanel->Enable(true);
2238 SetCursor(*wxSTANDARD_CURSOR);
2240 cfgUpdated = cfgUpdated | (1 << event.GetId());
2242 else if (status == configuring) {
2243 restorePanel->EnableApply(true);
2244 cfgUpdated = cfgUpdated | (1 << event.GetId());
2248 void wxbRestorePanel::OnConfigOk(wxCommandEvent& WXUNUSED(event)) {
2249 if (status != configuring) return;
2253 SetCursor(*wxHOURGLASS_CURSOR);
2257 SetCursor(*wxSTANDARD_CURSOR);
2260 void wxbRestorePanel::OnConfigApply(wxCommandEvent& WXUNUSED(event)) {
2261 if (status != configuring) return;
2265 SetCursor(*wxHOURGLASS_CURSOR);
2268 if (cfgUpdated == 0) {
2269 restorePanel->EnableApply(false);
2272 SetCursor(*wxSTANDARD_CURSOR);
2275 void wxbRestorePanel::OnConfigCancel(wxCommandEvent& WXUNUSED(event)) {
2276 if (status != configuring) return;
2280 SetCursor(*wxHOURGLASS_CURSOR);
2284 SetCursor(*wxSTANDARD_CURSOR);