3 * wxbPanel for restoring files
5 * Nicolas Boichat, April-July 2004
10 Copyright (C) 2004-2005 Kern Sibbald
12 This program is free software; you can redistribute it and/or
13 modify it under the terms of the GNU General Public License
14 version 2 as amended with additional clauses defined in the
15 file LICENSE in the main source directory.
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 the file LICENSE for additional details.
24 /* Note concerning "done" output (modifiable marked with +)
26 +JobName: RestoreFiles
27 Bootstrap: /var/lib/bacula/restore.bsr
28 +Where: /tmp/bacula-restores
33 +When: 2004-04-18 01:18:56
35 OK to run? (yes/mod/no):mod
37 1: Level (not appropriate)
38 2: Storage (automatic ?)
41 5: Client (yes : "The defined Client resources are:\n\t1: velours-fd\n\t2: tom-fd\nSelect Client (File daemon) resource (1-2):")
42 6: When (yes : "Please enter desired start time as YYYY-MM-DD HH:MM:SS (return for now):")
43 7: Priority (yes : "Enter new Priority: (positive integer)")
45 9: Where (yes : "Please enter path prefix for restore (/ for none):")
46 10: Replace (yes : "Replace:\n 1: always\n 2: ifnewer\n 3: ifolder\n 4: never\n
47 Select replace option (1-4):")
49 Select parameter to modify (1-11):
52 #include "wxbrestorepanel.h"
54 #include "wxbmainframe.h"
58 #include <wx/choice.h>
59 #include <wx/datetime.h>
63 #include "unmarked.xpm"
65 #include "partmarked.xpm"
67 #include <wx/listimpl.cpp>
69 /* A macro named Yield is defined under MinGW */
72 WX_DEFINE_LIST(wxbEventList);
75 * Class which is stored in the tree and in the list to keep informations
78 class wxbTreeItemData : public wxTreeItemData {
80 wxbTreeItemData(wxString path, wxString name, int marked, long listid = -1);
81 wxbTreeItemData(wxString path, wxString name, wxString marked, long listid = -1);
87 void SetMarked(int marked);
88 void SetMarked(wxString marked);
92 static int GetMarkedStatus(wxString file);
94 wxString* path; /* Full path */
95 wxString* name; /* File name */
96 int marked; /* 0 - Not Marked, 1 - Marked, 2 - Some file under is marked */
97 long listid; /* list ID : >-1 if this data is in the list (and/or on the tree) */
100 wxbTreeItemData::wxbTreeItemData(wxString path, wxString name, int marked, long listid): wxTreeItemData() {
101 this->path = new wxString(path);
102 this->name = new wxString(name);
103 this->marked = marked;
104 this->listid = listid;
107 wxbTreeItemData::wxbTreeItemData(wxString path, wxString name, wxString marked, long listid): wxTreeItemData() {
108 this->path = new wxString(path);
109 this->name = new wxString(name);
111 this->listid = listid;
114 wxbTreeItemData::~wxbTreeItemData() {
119 int wxbTreeItemData::GetMarked() {
123 void wxbTreeItemData::SetMarked(wxString marked) {
124 if (marked == wxT("*")) {
127 else if (marked == wxT("+")) {
135 void wxbTreeItemData::SetMarked(int marked) {
136 this->marked = marked;
139 long wxbTreeItemData::GetListId() {
143 wxString wxbTreeItemData::GetPath() {
147 wxString wxbTreeItemData::GetName() {
151 /*wxbTreeItemData* wxbTreeItemData::GetChild(wxString dirname) {
152 int marked = GetMarkedStatus(dirname);
153 return new wxbTreeItemData(path + (marked ? dirname.Mid(1) : dirname), marked);
156 int wxbTreeItemData::GetMarkedStatus(wxString file) {
157 if (file.Length() == 0)
160 switch (file.GetChar(0)) {
170 // ----------------------------------------------------------------------------
171 // event tables and other macros for wxWindows
172 // ----------------------------------------------------------------------------
200 BEGIN_EVENT_TABLE(wxbRestorePanel, wxPanel)
201 EVT_BUTTON(RestoreStart, wxbRestorePanel::OnStart)
202 EVT_BUTTON(RestoreCancel, wxbRestorePanel::OnCancel)
204 EVT_TREE_SEL_CHANGING(TreeCtrl, wxbRestorePanel::OnTreeChanging)
205 EVT_TREE_SEL_CHANGED(TreeCtrl, wxbRestorePanel::OnTreeChanged)
206 EVT_TREE_ITEM_EXPANDING(TreeCtrl, wxbRestorePanel::OnTreeExpanding)
207 EVT_TREE_MARKED_EVENT(TreeCtrl, wxbRestorePanel::OnTreeMarked)
208 EVT_BUTTON(TreeAdd, wxbRestorePanel::OnTreeAdd)
209 EVT_BUTTON(TreeRemove, wxbRestorePanel::OnTreeRemove)
210 EVT_BUTTON(TreeRefresh, wxbRestorePanel::OnTreeRefresh)
212 EVT_LIST_ITEM_ACTIVATED(ListCtrl, wxbRestorePanel::OnListActivated)
213 EVT_LIST_MARKED_EVENT(ListCtrl, wxbRestorePanel::OnListMarked)
214 EVT_LIST_ITEM_SELECTED(ListCtrl, wxbRestorePanel::OnListChanged)
215 EVT_LIST_ITEM_DESELECTED(ListCtrl, wxbRestorePanel::OnListChanged)
216 EVT_BUTTON(ListAdd, wxbRestorePanel::OnListAdd)
217 EVT_BUTTON(ListRemove, wxbRestorePanel::OnListRemove)
218 EVT_BUTTON(ListRefresh, wxbRestorePanel::OnListRefresh)
220 EVT_TEXT(ConfigWhere, wxbRestorePanel::OnConfigUpdated)
221 EVT_TEXT(ConfigWhen, wxbRestorePanel::OnConfigUpdated)
222 EVT_TEXT(ConfigPriority, wxbRestorePanel::OnConfigUpdated)
223 EVT_CHOICE(ConfigWhen, wxbRestorePanel::OnConfigUpdated)
224 EVT_CHOICE(ConfigReplace, wxbRestorePanel::OnConfigUpdated)
225 EVT_CHOICE(ConfigClient, wxbRestorePanel::OnConfigUpdated)
226 EVT_CHOICE(ConfigFileset, wxbRestorePanel::OnConfigUpdated)
227 EVT_CHOICE(ConfigStorage, wxbRestorePanel::OnConfigUpdated)
228 EVT_CHOICE(ConfigJobName, wxbRestorePanel::OnConfigUpdated)
229 EVT_CHOICE(ConfigPool, wxbRestorePanel::OnConfigUpdated)
231 EVT_BUTTON(ConfigOk, wxbRestorePanel::OnConfigOk)
232 EVT_BUTTON(ConfigApply, wxbRestorePanel::OnConfigApply)
233 EVT_BUTTON(ConfigCancel, wxbRestorePanel::OnConfigCancel)
237 * wxbRestorePanel constructor
239 wxbRestorePanel::wxbRestorePanel(wxWindow* parent): wxbPanel(parent) {
240 //pendingEvents = new wxbEventList(); //EVTQUEUE
241 //processing = false; //EVTQUEUE
244 imagelist = new wxImageList(16, 16, TRUE, 3);
245 imagelist->Add(wxIcon(unmarked_xpm));
246 imagelist->Add(wxIcon(marked_xpm));
247 imagelist->Add(wxIcon(partmarked_xpm));
249 wxFlexGridSizer* mainSizer = new wxFlexGridSizer(3, 1, 10, 10);
250 mainSizer->AddGrowableCol(0);
251 mainSizer->AddGrowableRow(1);
253 wxFlexGridSizer *firstSizer = new wxFlexGridSizer(1, 2, 10, 10);
255 firstSizer->AddGrowableCol(0);
256 firstSizer->AddGrowableRow(0);
258 start = new wxButton(this, RestoreStart, _("Enter restore mode"), wxDefaultPosition, wxSize(150, 30));
259 firstSizer->Add(start, 0, wxALIGN_CENTER_HORIZONTAL | wxALIGN_CENTER_VERTICAL, 10);
261 cancel = new wxButton(this, RestoreCancel, _("Cancel restore"), wxDefaultPosition, wxSize(150, 30));
262 firstSizer->Add(cancel, 0, wxALIGN_CENTER_HORIZONTAL | wxALIGN_RIGHT, 10);
266 /* clientChoice = new wxChoice(this, ClientChoice, wxDefaultPosition, wxSize(150, 30), 0, elist);
267 firstSizer->Add(clientChoice, 1, wxALIGN_CENTER_HORIZONTAL | wxALIGN_CENTER_VERTICAL, 10);
269 jobChoice = new wxChoice(this, -1, wxDefaultPosition, wxSize(150, 30), 0, elist);
270 firstSizer->Add(jobChoice, 1, wxALIGN_CENTER_HORIZONTAL | wxALIGN_CENTER_VERTICAL, 10);*/
272 mainSizer->Add(firstSizer, 1, wxEXPAND, 10);
274 treelistPanel = new wxSplitterWindow(this);
276 wxPanel* treePanel = new wxPanel(treelistPanel);
277 wxFlexGridSizer *treeSizer = new wxFlexGridSizer(2, 1, 0, 0);
278 treeSizer->AddGrowableCol(0);
279 treeSizer->AddGrowableRow(0);
281 tree = new wxbTreeCtrl(treePanel, this, TreeCtrl, wxDefaultPosition, wxSize(200,50));
282 tree->SetImageList(imagelist);
284 treeSizer->Add(tree, 1, wxEXPAND, 0);
286 wxBoxSizer *treeCtrlSizer = new wxBoxSizer(wxHORIZONTAL);
287 treeadd = new wxButton(treePanel, TreeAdd, _("Add"), wxDefaultPosition, wxSize(60, 25));
288 treeCtrlSizer->Add(treeadd, 0, wxLEFT | wxRIGHT, 3);
289 treeremove = new wxButton(treePanel, TreeRemove, _("Remove"), wxDefaultPosition, wxSize(60, 25));
290 treeCtrlSizer->Add(treeremove, 0, wxLEFT | wxRIGHT, 3);
291 treerefresh = new wxButton(treePanel, TreeRefresh, _("Refresh"), wxDefaultPosition, wxSize(60, 25));
292 treeCtrlSizer->Add(treerefresh, 0, wxLEFT | wxRIGHT, 3);
294 treeSizer->Add(treeCtrlSizer, 1, wxALIGN_CENTER_HORIZONTAL, 0);
296 treePanel->SetSizer(treeSizer);
298 wxPanel* listPanel = new wxPanel(treelistPanel);
299 wxFlexGridSizer *listSizer = new wxFlexGridSizer(2, 1, 0, 0);
300 listSizer->AddGrowableCol(0);
301 listSizer->AddGrowableRow(0);
303 list = new wxbListCtrl(listPanel, this, ListCtrl, wxDefaultPosition, wxSize(200,50));
304 //treelistSizer->Add(list, 1, wxEXPAND, 10);
306 list->SetImageList(imagelist, wxIMAGE_LIST_SMALL);
309 info.SetMask(wxLIST_MASK_TEXT | wxLIST_MASK_FORMAT);
310 info.SetText(_("M"));
311 info.SetAlign(wxLIST_FORMAT_CENTER);
312 list->InsertColumn(0, info);
314 info.SetText(_("Filename"));
315 info.SetAlign(wxLIST_FORMAT_LEFT);
316 list->InsertColumn(1, info);
318 info.SetText(_("Size"));
319 info.SetAlign(wxLIST_FORMAT_RIGHT);
320 list->InsertColumn(2, info);
322 info.SetText(_("Date"));
323 info.SetAlign(wxLIST_FORMAT_LEFT);
324 list->InsertColumn(3, info);
326 info.SetText(_("Perm."));
327 info.SetAlign(wxLIST_FORMAT_LEFT);
328 list->InsertColumn(4, info);
330 info.SetText(_("User"));
331 info.SetAlign(wxLIST_FORMAT_RIGHT);
332 list->InsertColumn(5, info);
334 info.SetText(_("Group"));
335 info.SetAlign(wxLIST_FORMAT_RIGHT);
336 list->InsertColumn(6, info);
338 listSizer->Add(list, 1, wxEXPAND, 0);
340 wxBoxSizer *listCtrlSizer = new wxBoxSizer(wxHORIZONTAL);
341 listadd = new wxButton(listPanel, ListAdd, _("Add"), wxDefaultPosition, wxSize(60, 25));
342 listCtrlSizer->Add(listadd, 0, wxLEFT | wxRIGHT, 5);
343 listremove = new wxButton(listPanel, ListRemove, _("Remove"), wxDefaultPosition, wxSize(60, 25));
344 listCtrlSizer->Add(listremove, 0, wxLEFT | wxRIGHT, 5);
345 listrefresh = new wxButton(listPanel, ListRefresh, _("Refresh"), wxDefaultPosition, wxSize(60, 25));
346 listCtrlSizer->Add(listrefresh, 0, wxLEFT | wxRIGHT, 5);
348 listSizer->Add(listCtrlSizer, 1, wxALIGN_CENTER_HORIZONTAL, 0);
350 listPanel->SetSizer(listSizer);
352 treelistPanel->SplitVertically(treePanel, listPanel, 210);
354 treelistPanel->SetMinimumPaneSize(210);
356 treelistPanel->Show(false);
358 wxbConfig* config = new wxbConfig();
359 config->Add(new wxbConfigParam(_("Job Name"), ConfigJobName, choice, 0, elist));
360 config->Add(new wxbConfigParam(_("Client"), ConfigClient, choice, 0, elist));
361 config->Add(new wxbConfigParam(_("Fileset"), ConfigFileset, choice, 0, elist));
362 config->Add(new wxbConfigParam(_("Pool"), ConfigPool, choice, 0, elist));
363 config->Add(new wxbConfigParam(_("Storage"), ConfigStorage, choice, 0, elist));
364 config->Add(new wxbConfigParam(_("Before"), ConfigWhen, choice, 0, elist));
366 configPanel = new wxbConfigPanel(this, config, _("Please configure parameters concerning files to restore :"), RestoreStart, RestoreCancel, -1);
368 configPanel->Show(true);
369 configPanel->Enable(false);
371 config = new wxbConfig();
372 config->Add(new wxbConfigParam(_("Job Name"), -1, text, wxT("")));
373 config->Add(new wxbConfigParam(_("Bootstrap"), -1, text, wxT("")));
374 config->Add(new wxbConfigParam(_("Where"), ConfigWhere, modifiableText, wxT("")));
375 wxString erlist[] = {_("always"), _("if newer"), _("if older"), _("never")};
376 config->Add(new wxbConfigParam(_("Replace"), ConfigReplace, choice, 4, erlist));
377 config->Add(new wxbConfigParam(_("Fileset"), ConfigFileset, choice, 0, erlist));
378 config->Add(new wxbConfigParam(_("Client"), ConfigClient, choice, 0, erlist));
379 config->Add(new wxbConfigParam(_("Storage"), ConfigStorage, choice, 0, erlist));
380 config->Add(new wxbConfigParam(_("When"), ConfigWhen, modifiableText, wxT("")));
381 config->Add(new wxbConfigParam(_("Priority"), ConfigPriority, modifiableText, wxT("")));
383 restorePanel = new wxbConfigPanel(this, config, _("Please configure parameters concerning files restoration :"), ConfigOk, ConfigCancel, ConfigApply);
385 restorePanel->Show(false);
387 centerSizer = new wxBoxSizer(wxHORIZONTAL);
388 //centerSizer->Add(treelistPanel, 1, wxEXPAND | wxADJUST_MINSIZE);
390 mainSizer->Add(centerSizer, 1, wxEXPAND, 10);
392 gauge = new wxGauge(this, -1, 1, wxDefaultPosition, wxSize(200,20));
394 mainSizer->Add(gauge, 1, wxEXPAND, 5);
396 gauge->Enable(false);
399 mainSizer->SetSizeHints(this);
403 for (int i = 0; i < 7; i++) {
404 list->SetColumnWidth(i, 70);
407 SetCursor(*wxSTANDARD_CURSOR);
409 markWhenCommandDone = false;
415 * wxbRestorePanel destructor
417 wxbRestorePanel::~wxbRestorePanel() {
421 /*----------------------------------------------------------------------------
422 wxbPanel overloadings
423 ----------------------------------------------------------------------------*/
425 wxString wxbRestorePanel::GetTitle() {
429 void wxbRestorePanel::EnablePanel(bool enable) {
431 if (status == disabled) {
432 SetStatus(activable);
440 /*----------------------------------------------------------------------------
441 Commands called by events handler
442 ----------------------------------------------------------------------------*/
444 /* The main button has been clicked */
445 void wxbRestorePanel::CmdStart() {
447 if (status == activable) {
448 wxbMainFrame::GetInstance()->SetStatusText(_("Getting parameters list."));
449 wxbDataTokenizer* dt = wxbUtils::WaitForEnd(wxT(".clients\n"), true, false);
452 configPanel->ClearRowChoices(_("Client"));
453 restorePanel->ClearRowChoices(_("Client"));
455 if (dt->GetCount() == 0) {
456 wxbMainFrame::GetInstance()->SetStatusText(_("Error : no clients returned by the director."));
460 for (i = 0; i < dt->GetCount(); i++) {
463 configPanel->AddRowChoice(_("Client"), str);
464 restorePanel->AddRowChoice(_("Client"), str);
474 dt = wxbUtils::WaitForEnd(wxT(".filesets\n"), true, false);
476 configPanel->ClearRowChoices(_("Fileset"));
477 restorePanel->ClearRowChoices(_("Fileset"));
479 if (dt->GetCount() == 0) {
480 wxbMainFrame::GetInstance()->SetStatusText(_("Error : no filesets returned by the director."));
484 for (i = 0; i < dt->GetCount(); i++) {
487 configPanel->AddRowChoice(_("Fileset"), str);
488 restorePanel->AddRowChoice(_("Fileset"), str);
498 dt = wxbUtils::WaitForEnd(wxT(".storage\n"), true, false);
500 configPanel->ClearRowChoices(_("Storage"));
501 restorePanel->ClearRowChoices(_("Storage"));
503 if (dt->GetCount() == 0) {
504 wxbMainFrame::GetInstance()->SetStatusText(_("Error : no storage returned by the director."));
508 for (i = 0; i < dt->GetCount(); i++) {
511 configPanel->AddRowChoice(_("Storage"), str);
512 restorePanel->AddRowChoice(_("Storage"), str);
522 dt = wxbUtils::WaitForEnd(wxT(".jobs\n"), true, false);
524 configPanel->ClearRowChoices(_("Job Name"));
526 if (dt->GetCount() == 0) {
527 wxbMainFrame::GetInstance()->SetStatusText(_("Error : no jobs returned by the director."));
531 for (i = 0; i < dt->GetCount(); i++) {
534 configPanel->AddRowChoice(_("Job Name"), str);
537 configPanel->SetRowString(_("Job Name"), _("RestoreFiles"));
546 dt = wxbUtils::WaitForEnd(wxT(".pools\n"), true, false);
548 configPanel->ClearRowChoices(_("Pool"));
550 if (dt->GetCount() == 0) {
551 wxbMainFrame::GetInstance()->SetStatusText(_("Error : no jobs returned by the director."));
555 for (i = 0; i < dt->GetCount(); i++) {
558 configPanel->AddRowChoice(_("Pool"), str);
572 wxbMainFrame::GetInstance()->SetStatusText(_("Please configure your restore parameters."));
574 else if (status == entered) {
575 /* if (clientChoice->GetStringSelection().Length() < 1) {
576 wxbMainFrame::GetInstance()->SetStatusText(_("Please select a client."));
579 if (jobChoice->GetStringSelection().Length() < 1) {
580 wxbMainFrame::GetInstance()->SetStatusText(_("Please select a restore date."));
583 wxbMainFrame::GetInstance()->SetStatusText(_("Building restore tree..."));
587 wxbTableParser* tableparser = new wxbTableParser();
588 wxbDataTokenizer* dt = new wxbDataTokenizer(false);
591 * The following line was removed from ::GetInstance below because
592 * it does not work with multiple pools -- KES 5Oct05 see bug #433
593 * wxT("\" pool=\"") << configPanel->GetRowString(wxT("Pool")) <<
595 wxbMainFrame::GetInstance()->Send(wxString(wxT("restore")) <<
596 wxT(" client=\"") << configPanel->GetRowString(wxT("Client")) <<
597 wxT("\" fileset=\"") << configPanel->GetRowString(wxT("Fileset")) <<
598 wxT("\" storage=\"") << configPanel->GetRowString(wxT("Storage")) <<
599 wxT("\" before=\"") << configPanel->GetRowString(wxT("Before")) <<
601 //wxbUtils::WaitForPrompt("6\n");
603 /*wxbPromptParser *pp = wxbUtils::WaitForPrompt(wxString() << configPanel->GetRowString(wxT("Before")) << "\n", true);
604 int client = pp->getChoices()->Index(configPanel->GetRowString(wxT("Client")));
605 if (client == wxNOT_FOUND) {
606 wxbMainFrame::GetInstance()->SetStatusText("Failed to find the selected client.");
611 //wxbMainFrame::GetInstance()->Send(wxString() << configPanel->GetRowString(wxT("Before")) << "\n");
613 while (!tableparser->hasFinished() && !dt->hasFinished()) {
614 wxTheApp->Yield(true);
615 wxbUtils::MilliSleep(100);
620 if (dt->hasFinished() && !tableparser->hasFinished()) {
622 if (dt->GetCount() > 1) {
623 str = (*dt)[dt->GetCount()-2];
626 wxbMainFrame::GetInstance()->SetStatusText(wxString(_("Error while starting restore: ")) << str);
636 for (i = 0; i < tableparser->GetCount(); i++) {
637 str = (*tableparser)[i][2];
638 str.Replace(wxT(","), wxT(""));
639 if (str.ToLong(&l)) {
645 gauge->SetRange(tot);
647 /*wxbMainFrame::GetInstance()->Print(
648 wxString("[") << tot << "]", CS_DEBUG);*/
650 wxDateTime base = wxDateTime::Now();
654 unsigned int lastindex = 0;
661 newdate = wxDateTime::Now();
662 if (newdate.Subtract(base).GetMilliseconds() > 10 ) {
664 for (; lastindex < dt->GetCount(); lastindex++) {
665 if (((i1 = (*dt)[lastindex].Find(wxT("Building directory tree for JobId "))) >= 0) &&
666 ((i2 = (*dt)[lastindex].Find(wxT(" ..."))) > 0)) {
667 str = (*dt)[lastindex].Mid(i1+34, i2-(i1+34));
668 for (i = 0; i < tableparser->GetCount(); i++) {
669 if (str == (*tableparser)[i][0]) {
670 str = (*tableparser)[i][2];
671 str.Replace(wxT(","), wxT(""));
672 if (str.ToLong(&l)) {
675 var = (willdo-done)/50;
676 gauge->SetValue(done);
677 wxTheApp->Yield(true);
683 else if ((*dt)[lastindex] == wxT("+")) {
684 gauge->SetValue(gauge->GetValue()+var);
685 wxTheApp->Yield(true);
690 if (dt->hasFinished()) {
694 wxTheApp->Yield(true);
695 wxbUtils::MilliSleep(1);
698 gauge->SetValue(tot);
699 wxTheApp->Yield(true);
710 wxbUtils::WaitForEnd(wxT("unmark *\n"));
711 wxTreeItemId root = tree->AddRoot(configPanel->GetRowString(_("Client")), -1, -1, new wxbTreeItemData(wxT("/"), configPanel->GetRowString(_("Client")), 0));
712 currentTreeItem = root;
714 tree->SelectItem(root);
716 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."));
719 else if (status == choosing) {
723 wxbDataTokenizer* dt;
727 dt = new wxbDataTokenizer(true);
728 wxbUtils::WaitForPrompt(wxT("done\n"));
730 SetStatus(configuring);
732 for (i = 0; i < dt->GetCount(); i++) {
733 if ((j = (*dt)[i].Find(_(" files selected to be restored."))) > -1) {
734 (*dt)[i].Mid(0, j).ToLong(&totfilemessages);
738 if ((j = (*dt)[i].Find(_(" file selected to be restored."))) > -1) {
739 (*dt)[i].Mid(0, j).ToLong(&totfilemessages);
744 wxbMainFrame::GetInstance()->SetStatusText(
745 wxString::Format(_("Please configure your restore (%ld files selected to be restored)..."), totfilemessages));
747 UpdateSecondConfig(dt);
752 restorePanel->EnableApply(false);
754 if (totfilemessages == 0) {
755 wxbMainFrame::GetInstance()->Print(_("Restore failed : no file selected.\n"), CS_DEBUG);
756 wxbMainFrame::GetInstance()->SetStatusText(_("Restore failed : no file selected."));
761 else if (status == configuring) {
762 cancel->Enable(false);
766 wxbMainFrame::GetInstance()->SetStatusText(_("Restoring, please wait..."));
768 wxbDataTokenizer* dt;
770 SetStatus(restoring);
771 dt = wxbUtils::WaitForEnd(wxT("yes\n"), true);
774 gauge->SetRange(totfilemessages);
778 for (i = 0; i < dt->GetCount(); i++) {
779 if ((j = (*dt)[i].Find(_("Job started. JobId="))) > -1) {
780 jobid = (*dt)[i].Mid(j+19);
781 wxbMainFrame::GetInstance()->SetStatusText(_("Restore started, jobid=") + jobid);
785 if ((j = (*dt)[i].Find(_("Job failed."))) > -1) {
786 wxbMainFrame::GetInstance()->Print(_("Restore failed, please look at messages.\n"), CS_DEBUG);
787 wxbMainFrame::GetInstance()->SetStatusText(_("Restore failed, please look at messages in console."));
792 if (jobid == wxT("")) {
793 wxbMainFrame::GetInstance()->Print(_("Failed to retrieve jobid.\n"), CS_DEBUG);
794 wxbMainFrame::GetInstance()->SetStatusText(_("Failed to retrieve jobid.\n"));
798 wxDateTime currenttime;
800 dt = wxbUtils::WaitForEnd(wxT("time\n"), true);
801 wxStringTokenizer ttkz((*dt)[0], wxT(" "), wxTOKEN_STRTOK);
802 if ((currenttime.ParseDate(ttkz.GetNextToken()) == NULL) || // Date
803 (currenttime.ParseTime(ttkz.GetNextToken()) == NULL)) { // Time
804 currenttime.SetYear(1990); // If parsing fails, set currenttime to a dummy date
807 currenttime -= wxTimeSpan::Seconds(30); //Adding a 30" tolerance
811 wxDateTime scheduledtime;
812 wxStringTokenizer stkz(restorePanel->GetRowString(_("When")), wxT(" "), wxTOKEN_STRTOK);
814 if ((scheduledtime.ParseDate(stkz.GetNextToken()) == NULL) || // Date
815 (scheduledtime.ParseTime(stkz.GetNextToken()) == NULL)) { // Time
816 scheduledtime.SetYear(2090); // If parsing fails, set scheduledtime to a dummy date
819 if (scheduledtime.Subtract(currenttime).IsLongerThan(wxTimeSpan::Seconds(150))) {
820 wxbMainFrame::GetInstance()->Print(_("Restore is scheduled in more than two minutes, wx-console will not wait for its completion.\n"), CS_DEBUG);
821 wxbMainFrame::GetInstance()->SetStatusText(_("Restore is scheduled in more than two minutes, wx-console will not wait for its completion."));
826 wxString cmd = wxString(wxT("list jobid=")) + jobid;
828 wxbTableParser* tableparser;
830 long filemessages = 0;
833 bool waitforever = false;
840 tableparser = wxbUtils::CreateAndWaitForParser(cmd);
842 status = (*tableparser)[0][7].GetChar(0);
845 wxbMainFrame::GetInstance()->SetStatusText(_("Restore job created, but not yet running."));
849 wxbMainFrame::GetInstance()->SetStatusText(
850 wxString::Format(_("Restore job running, please wait (%ld of %ld files restored)..."), filemessages, totfilemessages));
854 wxbMainFrame::GetInstance()->SetStatusText(_("Restore job terminated successfully."));
855 wxbMainFrame::GetInstance()->Print(_("Restore job terminated successfully.\n"), CS_DEBUG);
859 case JS_ErrorTerminated:
860 wxbMainFrame::GetInstance()->SetStatusText(_("Restore job terminated in error, see messages in console."));
861 wxbMainFrame::GetInstance()->Print(_("Restore job terminated in error, see messages.\n"), CS_DEBUG);
866 wxbMainFrame::GetInstance()->SetStatusText(_("Restore job reported a non-fatal error."));
870 wxbMainFrame::GetInstance()->SetStatusText(_("Restore job reported a fatal error."));
875 wxbMainFrame::GetInstance()->SetStatusText(_("Restore job cancelled by user."));
876 wxbMainFrame::GetInstance()->Print(_("Restore job cancelled by user.\n"), CS_DEBUG);
881 wxbMainFrame::GetInstance()->SetStatusText(_("Restore job is waiting on File daemon."));
885 wxbMainFrame::GetInstance()->SetStatusText(_("Restore job is waiting for new media."));
888 case JS_WaitStoreRes:
889 wxbMainFrame::GetInstance()->SetStatusText(_("Restore job is waiting for storage resource."));
893 wxbMainFrame::GetInstance()->SetStatusText(_("Restore job is waiting for job resource."));
896 case JS_WaitClientRes:
897 wxbMainFrame::GetInstance()->SetStatusText(_("Restore job is waiting for Client resource."));
901 wxbMainFrame::GetInstance()->SetStatusText(_("Restore job is waiting for maximum jobs."));
904 case JS_WaitStartTime:
905 wxbMainFrame::GetInstance()->SetStatusText(_("Restore job is waiting for start time."));
908 case JS_WaitPriority:
909 wxbMainFrame::GetInstance()->SetStatusText(_("Restore job is waiting for higher priority jobs to finish."));
915 dt = wxbUtils::WaitForEnd(wxT(".messages\n"), true);
917 for (unsigned int i = 0; i < dt->GetCount(); i++) {
918 wxStringTokenizer tkz((*dt)[i], wxT(" "), wxTOKEN_STRTOK);
922 // Date Time name: perm ? user grp size date time
923 //04-Apr-2004 17:19 Tom-fd: -rwx------ 1 nicolas None 514967 2004-03-20 20:03:42 filename
925 if (datetime.ParseDate(tkz.GetNextToken()) != NULL) { // Date
926 if (datetime.ParseTime(tkz.GetNextToken()) != NULL) { // Time
927 if (tkz.GetNextToken().Last() == ':') { // name:
928 tkz.GetNextToken(); // perm
929 tkz.GetNextToken(); // ?
930 tkz.GetNextToken(); // user
931 tkz.GetNextToken(); // grp
932 tkz.GetNextToken(); // size
933 if (datetime.ParseDate(tkz.GetNextToken()) != NULL) { //date
934 if (datetime.ParseTime(tkz.GetNextToken()) != NULL) { //time
936 //wxbMainFrame::GetInstance()->Print(wxString("(") << filemessages << ")", CS_DEBUG);
937 gauge->SetValue(filemessages);
948 while (sw2.Time() < 10000) {
949 wxTheApp->Yield(true);
950 wxbUtils::MilliSleep(100);
957 if ((!waitforever) && (sw.Time() > 60000)) {
958 wxbMainFrame::GetInstance()->Print(_("The restore job has not been started within one minute, wx-console will not wait for its completion anymore.\n"), CS_DEBUG);
959 wxbMainFrame::GetInstance()->SetStatusText(_("The restore job has not been started within one minute, wx-console will not wait for its completion anymore."));
964 wxbUtils::WaitForEnd(wxT(".messages\n"));
966 gauge->SetValue(totfilemessages);
968 if (status == JS_Terminated) {
969 wxbMainFrame::GetInstance()->Print(_("Restore done successfully.\n"), CS_DEBUG);
970 wxbMainFrame::GetInstance()->SetStatusText(_("Restore done successfully."));
976 /* The cancel button has been clicked */
977 void wxbRestorePanel::CmdCancel() {
980 if (status == restoring) {
981 if (jobid != wxT("")) {
982 wxbMainFrame::GetInstance()->Send(wxString(wxT("cancel job=")) << jobid << wxT("\n"));
984 cancel->Enable(true);
989 while ((IsWorking()) && (cancelled != 2)) {
990 wxTheApp->Yield(true);
991 wxbUtils::MilliSleep(100);
992 if (sw.Time() > 30000) { /* 30 seconds timeout */
993 if (status == choosing) {
994 wxbMainFrame::GetInstance()->Send(wxT("quit\n"));
996 else if (status == configuring) {
997 wxbMainFrame::GetInstance()->Send(wxT("no\n"));
999 else if (status == restoring) {
1002 SetStatus(finished);
1003 wxbUtils::MilliSleep(1000);
1010 wxbMainFrame::GetInstance()->Send(wxT("quit\n"));
1013 wxbMainFrame::GetInstance()->Send(wxT("no\n"));
1018 wxbUtils::MilliSleep(1000);
1019 SetStatus(finished);
1022 /* Apply configuration changes */
1024 /* 1: Level (not appropriate)
1029 * 6: When (yes : "Please enter desired start time as YYYY-MM-DD HH:MM:SS (return for now):")
1030 * 7: Priority (yes : "Enter new Priority: (positive integer)")
1032 * 9: Where (yes : "Please enter path prefix for restore (/ for none):")
1033 * 10: Replace (yes : "Replace:\n 1: always\n 2: ifnewer\n 3: ifolder\n 4: never\n
1034 * Select replace option (1-4):")
1038 void wxbRestorePanel::CmdConfigApply() {
1039 if (cfgUpdated == 0) return;
1041 wxbMainFrame::GetInstance()->SetStatusText(_("Applying restore configuration changes..."));
1043 EnableConfig(false);
1045 wxbDataTokenizer* dt = NULL;
1047 bool failed = false;
1049 while (cfgUpdated > 0) {
1054 wxString def; //String to send if can't use our data
1055 if ((cfgUpdated >> ConfigWhere) & 1) {
1056 wxbUtils::WaitForPrompt(wxT("mod\n")); /* TODO: check results */
1057 wxbUtils::WaitForPrompt(wxT("9\n"));
1058 dt = new wxbDataTokenizer(true);
1059 wxbUtils::WaitForPrompt(restorePanel->GetRowString(_("Where")) + wxT("\n"));
1061 cfgUpdated = cfgUpdated & (~(1 << ConfigWhere));
1063 else if ((cfgUpdated >> ConfigReplace) & 1) {
1064 wxbUtils::WaitForPrompt(wxT("mod\n")); /* TODO: check results */
1065 wxbUtils::WaitForPrompt(wxT("10\n"));
1066 dt = new wxbDataTokenizer(true);
1067 wxbUtils::WaitForPrompt(wxString() << (restorePanel->GetRowSelection(_("Replace"))+1) << wxT("\n"));
1069 cfgUpdated = cfgUpdated & (~(1 << ConfigReplace));
1071 else if ((cfgUpdated >> ConfigWhen) & 1) {
1072 wxbUtils::WaitForPrompt(wxT("mod\n")); /* TODO: check results */
1073 wxbUtils::WaitForPrompt(wxT("6\n"));
1074 dt = new wxbDataTokenizer(true);
1075 wxbUtils::WaitForPrompt(restorePanel->GetRowString(wxT("When")) + wxT("\n"));
1077 cfgUpdated = cfgUpdated & (~(1 << ConfigWhen));
1079 else if ((cfgUpdated >> ConfigPriority) & 1) {
1080 wxbUtils::WaitForPrompt(wxT("mod\n")); /* TODO: check results */
1081 wxbUtils::WaitForPrompt(wxT("7\n"));
1082 dt = new wxbDataTokenizer(true);
1083 wxbUtils::WaitForPrompt(restorePanel->GetRowString(_("Priority")) + wxT("\n"));
1085 cfgUpdated = cfgUpdated & (~(1 << ConfigPriority));
1087 else if ((cfgUpdated >> ConfigClient) & 1) {
1088 wxbUtils::WaitForPrompt(wxT("mod\n")); /* TODO: check results */
1089 wxbPromptParser *pp = wxbUtils::WaitForPrompt(wxT("5\n"), true);
1090 int client = pp->getChoices()->Index(restorePanel->GetRowString(_("Client")));
1091 if (client == wxNOT_FOUND) {
1092 wxbMainFrame::GetInstance()->SetStatusText(_("Failed to find the selected client."));
1097 dt = new wxbDataTokenizer(true);
1098 wxbUtils::WaitForPrompt(wxString() << client << wxT("\n"));
1100 cfgUpdated = cfgUpdated & (~(1 << ConfigClient));
1102 else if ((cfgUpdated >> ConfigFileset) & 1) {
1103 wxbUtils::WaitForPrompt(wxT("mod\n")); /* TODO: check results */
1104 wxbPromptParser *pp = wxbUtils::WaitForPrompt(wxT("4\n"), true);
1105 int fileset = pp->getChoices()->Index(restorePanel->GetRowString(_("Fileset")));
1106 if (fileset == wxNOT_FOUND) {
1107 wxbMainFrame::GetInstance()->SetStatusText(_("Failed to find the selected fileset."));
1112 dt = new wxbDataTokenizer(true);
1113 wxbUtils::WaitForPrompt(wxString() << fileset << wxT("\n"));
1115 cfgUpdated = cfgUpdated & (~(1 << ConfigFileset));
1117 else if ((cfgUpdated >> ConfigStorage) & 1) {
1118 wxbUtils::WaitForPrompt(wxT("mod\n")); /* TODO: check results */
1119 wxbPromptParser *pp = wxbUtils::WaitForPrompt(wxT("2\n"), true);
1120 int fileset = pp->getChoices()->Index(restorePanel->GetRowString(_("Storage")));
1121 if (fileset == wxNOT_FOUND) {
1122 wxbMainFrame::GetInstance()->SetStatusText(_("Failed to find the selected storage."));
1127 dt = new wxbDataTokenizer(true);
1128 wxbUtils::WaitForPrompt(wxString() << fileset << wxT("\n"));
1130 cfgUpdated = cfgUpdated & (~(1 << ConfigFileset));
1138 for (i = 0; i < dt->GetCount(); i++) {
1139 if ((*dt)[i].Find(_("Run Restore job")) == 0) {
1144 if (i == dt->GetCount()) {
1146 dt = wxbUtils::WaitForEnd(def + wxT("\n"), true);
1150 UpdateSecondConfig(dt); /* TODO: Check result */
1155 wxbMainFrame::GetInstance()->SetStatusText(_("Restore configuration changes were applied."));
1161 /* Cancel restore */
1162 void wxbRestorePanel::CmdConfigCancel() {
1163 wxbUtils::WaitForEnd(wxT("no\n"));
1164 wxbMainFrame::GetInstance()->Print(_("Restore cancelled.\n"), CS_DEBUG);
1165 wxbMainFrame::GetInstance()->SetStatusText(_("Restore cancelled."));
1166 SetStatus(finished);
1169 /* List jobs for a specified client */
1170 void wxbRestorePanel::CmdListJobs() {
1171 if (status == entered) {
1172 configPanel->ClearRowChoices(_("Before"));
1173 /*wxbUtils::WaitForPrompt("query\n");
1174 wxbUtils::WaitForPrompt("6\n");*/
1175 wxbTableParser* tableparser = new wxbTableParser(false);
1176 wxbDataTokenizer* dt = wxbUtils::WaitForEnd(
1177 wxString(wxT(".backups client=")) + configPanel->GetRowString(_("Client")) + wxT("\n"), true);
1179 while (!tableparser->hasFinished()) {
1180 wxTheApp->Yield(true);
1181 wxbUtils::MilliSleep(100);
1184 if (!tableparser->GetCount() == 0) {
1185 for (unsigned int i = 0; i < dt->Count(); i++) {
1186 if ((*dt)[i].Find(_("No results to list.")) == 0) {
1187 configPanel->AddRowChoice(_("Before"),
1188 _("No backup found for this client."));
1189 configPanel->SetRowSelection(_("Before"), 0);
1190 configPanel->EnableApply(true); // Enabling the not existing apply button disables the ok button.
1195 else if (((*dt)[i].Find(_("ERROR")) > -1) ||
1196 ((*dt)[i].Find(_("Query failed")) > -1)) {
1197 configPanel->AddRowChoice(_("Before"),
1198 _("Cannot get previous backups list, see console."));
1199 configPanel->SetRowSelection(_("Before"), 0);
1200 configPanel->EnableApply(true); // Enabling the not existing apply button disables the ok button.
1210 for (int i = tableparser->GetCount()-1; i > -1; i--) {
1211 wxString str = (*tableparser)[i][3];
1212 wxDateTime datetime;
1214 if ( ( (chr = datetime.ParseDate(str.GetData()) ) != NULL ) && ( datetime.ParseTime(++chr) != NULL ) ) {
1215 datetime += wxTimeSpan::Seconds(1);
1216 configPanel->AddRowChoice(_("Before"),
1217 datetime.Format(wxT("%Y-%m-%d %H:%M:%S")));
1223 configPanel->SetRowSelection(_("Before"), 0);
1224 configPanel->EnableApply(false); // Disabling the not existing apply button enables the ok button.
1228 /* List files and directories for a specified tree item */
1229 void wxbRestorePanel::CmdList(wxTreeItemId item) {
1230 if (status == choosing) {
1231 list->DeleteAllItems();
1236 UpdateTreeItem(item, true, false);
1238 if (list->GetItemCount() >= 1) {
1239 int firstwidth = list->GetSize().GetWidth();
1240 for (int i = 2; i < 7; i++) {
1241 list->SetColumnWidth(i, wxLIST_AUTOSIZE);
1242 firstwidth -= list->GetColumnWidth(i);
1245 list->SetColumnWidth(0, 18);
1247 list->SetColumnWidth(1, wxLIST_AUTOSIZE);
1248 if (list->GetColumnWidth(1) < firstwidth) {
1249 list->SetColumnWidth(1, firstwidth-25);
1255 /* Mark a treeitem (directory) or a listitem (file or directory) */
1256 void wxbRestorePanel::CmdMark(wxTreeItemId treeitem, long* listitems, int listsize, int state) {
1257 if (status == choosing) {
1258 wxbTreeItemData** itemdata;
1259 int itemdatasize = 0;
1260 if (listsize == 0) {
1261 itemdata = new wxbTreeItemData*[1];
1265 itemdata = new wxbTreeItemData*[listsize];
1266 itemdatasize = listsize;
1269 if (listitems != NULL) {
1270 for (int i = 0; i < listsize; i++) {
1271 itemdata[i] = (wxbTreeItemData*)list->GetItemData(listitems[i]);
1274 else if (treeitem.IsOk()) {
1275 itemdata[0] = (wxbTreeItemData*)tree->GetItemData(treeitem);
1282 if (itemdata[0] == NULL) { //Should never happen
1287 wxString dir = itemdata[0]->GetPath();
1290 if (dir != wxT("/")) {
1291 if (dir.GetChar(dir.Length()-1) == '/') {
1295 int i = dir.Find('/', TRUE);
1300 else { /* first dir below root */
1301 file = dir.Mid(i+1);
1302 dir = dir.Mid(0, i+1);
1311 bool marked = false;
1312 bool unmarked = false;
1314 for (int i = 0; i < itemdatasize; i++) {
1315 switch(itemdata[i]->GetMarked()) {
1329 if (marked && unmarked)
1345 wxbUtils::WaitForEnd(wxString(wxT("cd \"")) << dir << wxT("\"\n"));
1346 wxbUtils::WaitForEnd(wxString((state==1) ? wxT("mark") : wxT("unmark")) << wxT(" \"") << file << wxT("\"\n"));
1348 /* TODO: Check commands results */
1350 /*if ((dir == "/") && (file == "*")) {
1351 itemdata->SetMarked((itemdata->GetMarked() == 1) ? 0 : 1);
1354 if (listitems == NULL) { /* tree item state changed */
1355 SetTreeItemState(treeitem, state);
1356 /*treeitem = tree->GetSelection();
1357 UpdateTree(treeitem, true);
1358 treeitem = tree->GetItemParent(treeitem);*/
1361 for (int i = 0; i < listsize; i++) {
1362 SetListItemState(listitems[i], state);
1364 /*UpdateTree(treeitem, (tree->GetSelection() == treeitem));
1365 treeitem = tree->GetItemParent(treeitem);*/
1368 /*while (treeitem.IsOk()) {
1369 WaitForList(treeitem, false);
1370 treeitem = tree->GetItemParent(treeitem);
1377 /*----------------------------------------------------------------------------
1379 ----------------------------------------------------------------------------*/
1381 /* Run a dir command, and waits until result is fully received. */
1382 void wxbRestorePanel::UpdateTreeItem(wxTreeItemId item, bool updatelist, bool recurse) {
1383 // this->updatelist = updatelist;
1384 wxbDataTokenizer* dt;
1386 dt = wxbUtils::WaitForEnd(wxString(wxT("cd \"")) <<
1387 static_cast<wxbTreeItemData*>(tree->GetItemData(item))
1388 ->GetPath() << wxT("\"\n"), false);
1390 /* TODO: check command result */
1397 list->DeleteAllItems();
1398 dt = wxbUtils::WaitForEnd(wxT("dir\n"), true);
1402 for (unsigned int i = 0; i < dt->GetCount(); i++) {
1405 if (str.Find(wxT("cwd is:")) == 0) { // Sometimes cd command result "infiltrate" into listings.
1411 wxString* file = ParseList(str);
1416 wxTreeItemId treeid;
1418 if (file[8].GetChar(file[8].Length()-1) == '/') {
1421 #if wxCHECK_VERSION(2, 6, 0)
1422 wxTreeItemIdValue cookie;
1427 treeid = tree->GetFirstChild(item, cookie);
1429 bool updated = false;
1431 while (treeid.IsOk()) {
1432 itemStr = ((wxbTreeItemData*)tree->GetItemData(treeid))->GetName();
1433 if (file[8] == itemStr) {
1434 int stat = wxbTreeItemData::GetMarkedStatus(file[6]);
1435 if (static_cast<wxbTreeItemData*>(tree->GetItemData(treeid))->GetMarked() != stat) {
1436 tree->SetItemImage(treeid, stat, wxTreeItemIcon_Normal);
1437 tree->SetItemImage(treeid, stat, wxTreeItemIcon_Selected);
1438 static_cast<wxbTreeItemData*>(tree->GetItemData(treeid))->SetMarked(file[6]);
1440 if ((recurse) && (tree->IsExpanded(treeid))) {
1441 UpdateTreeItem(treeid, false, true);
1446 treeid = tree->GetNextChild(item, cookie);
1450 int img = wxbTreeItemData::GetMarkedStatus(file[6]);
1451 treeid = tree->AppendItem(item, wxbUtils::ConvertToPrintable(file[8]), img, img, new wxbTreeItemData(file[7], file[8], file[6]));
1456 long ind = list->InsertItem(list->GetItemCount(), wxbTreeItemData::GetMarkedStatus(file[6]));
1457 wxbTreeItemData* data = new wxbTreeItemData(file[7], file[8], file[6], ind);
1458 data->SetId(treeid);
1459 list->SetItemData(ind, (long)data);
1460 list->SetItem(ind, 1, wxbUtils::ConvertToPrintable(file[8])); // filename
1461 list->SetItem(ind, 2, file[4]); //Size
1462 list->SetItem(ind, 3, file[5]); //date
1463 list->SetItem(ind, 4, file[0]); //perm
1464 list->SetItem(ind, 5, file[2]); //user
1465 list->SetItem(ind, 6, file[3]); //grp
1477 /* Parse dir command results. */
1480 * It sure would be nice to have some comments here, especially
1481 * when setting up ret[7] and ret[8].
1482 * Also, it would be a lot easier for everyone if this were based
1483 * on variable width fields everywhere. All the fields except
1484 * the last (filename) are separated by spaces (the date is
1485 * composed of two blank terminated fields date + time.
1487 wxString* wxbRestorePanel::ParseList(wxString line) {
1488 /* See ls_output in dird/ua_tree.c */
1490 //drwxrwxrwx 111 root root 0 2004-04-03 14:35:21 f:/tocd/NVSU 1.00.00/
1491 //+ 10 + +i+ + 8 + + 8 ++ 10 + + 19 + *+ ->
1492 //0 12 i+15 i+24 i+32 i+42 i+62
1496 if (line.Length() < 63)
1499 wxString* ret = new wxString[9];
1501 ret[0] = line.Mid(0, 10).Trim(); // modes
1503 /* Column 1 has a variable width */
1504 i = line.find(' ', 14) - 14;
1505 ret[1] = line.Mid(12, 2+i).Trim(); // number of links
1507 ret[2] = line.Mid(15+i, 8).Trim(); // user
1508 ret[3] = line.Mid(24+i, 8).Trim(); // group
1509 ret[4] = line.Mid(32+i, 10).Trim(); // file size
1510 ret[5] = line.Mid(42+i, 19).Trim(); // date + time
1511 ret[6] = line.Mid(63+i, 1); // drive letter or /
1512 ret[7] = line.Mid(63+i).Trim(); // filename
1514 if (ret[6] == wxT(" ")) ret[6] = wxT("");
1516 if (ret[7].GetChar(ret[7].Length()-1) == '/') {
1518 ret[8].RemoveLast();
1519 ret[8] = ret[7].Mid(ret[8].Find('/', true)+1);
1522 ret[8] = ret[7].Mid(ret[7].Find('/', true)+1);
1528 /* Sets a list item state, and update its parents and children if it is a directory */
1529 void wxbRestorePanel::SetListItemState(long listitem, int newstate) {
1530 wxbTreeItemData* itemdata = (wxbTreeItemData*)list->GetItemData(listitem);
1532 wxTreeItemId treeitem;
1534 itemdata->SetMarked(newstate);
1535 list->SetItemImage(listitem, newstate, 0); /* TODO: Find what these ints are for */
1536 list->SetItemImage(listitem, newstate, 1);
1538 if ((treeitem = itemdata->GetId()).IsOk()) {
1539 SetTreeItemState(treeitem, newstate);
1542 UpdateTreeItemState(tree->GetSelection());
1546 /* Sets a tree item state, and update its children, parents and list (if necessary) */
1547 void wxbRestorePanel::SetTreeItemState(wxTreeItemId item, int newstate) {
1548 #if wxCHECK_VERSION(2, 6, 0)
1549 wxTreeItemIdValue cookie;
1553 wxTreeItemId currentChild = tree->GetFirstChild(item, cookie);
1555 wxbTreeItemData* itemdata;
1557 while (currentChild.IsOk()) {
1558 itemdata = (wxbTreeItemData*)tree->GetItemData(currentChild);
1559 int state = itemdata->GetMarked();
1561 if (state != newstate) {
1562 itemdata->SetMarked(newstate);
1563 tree->SetItemImage(currentChild, newstate, wxTreeItemIcon_Normal);
1564 tree->SetItemImage(currentChild, newstate, wxTreeItemIcon_Selected);
1567 currentChild = tree->GetNextChild(item, cookie);
1570 itemdata = (wxbTreeItemData*)tree->GetItemData(item);
1571 itemdata->SetMarked(newstate);
1572 tree->SetItemImage(item, newstate, wxTreeItemIcon_Normal);
1573 tree->SetItemImage(item, newstate, wxTreeItemIcon_Selected);
1576 if (tree->GetSelection() == item) {
1577 for (long i = 0; i < list->GetItemCount(); i++) {
1578 list->SetItemImage(i, newstate, 0); /* TODO: Find what these ints are for */
1579 list->SetItemImage(i, newstate, 1);
1583 UpdateTreeItemState(tree->GetItemParent(item));
1586 /* Update a tree item state, and its parents' state */
1587 void wxbRestorePanel::UpdateTreeItemState(wxTreeItemId item) {
1594 #if wxCHECK_VERSION(2, 6, 0)
1595 wxTreeItemIdValue cookie;
1599 wxTreeItemId currentChild = tree->GetFirstChild(item, cookie);
1601 bool onechildmarked = false;
1602 bool onechildunmarked = false;
1604 while (currentChild.IsOk()) {
1605 state = ((wxbTreeItemData*)tree->GetItemData(currentChild))->GetMarked();
1608 onechildunmarked = true;
1611 onechildmarked = true;
1614 onechildmarked = true;
1615 onechildunmarked = true;
1619 if (onechildmarked && onechildunmarked) {
1623 currentChild = tree->GetNextChild(item, cookie);
1626 if (tree->GetSelection() == item) {
1627 for (long i = 0; i < list->GetItemCount(); i++) {
1628 state = ((wxbTreeItemData*)list->GetItemData(i))->GetMarked();
1632 onechildunmarked = true;
1635 onechildmarked = true;
1638 onechildmarked = true;
1639 onechildunmarked = true;
1643 if (onechildmarked && onechildunmarked) {
1651 if (onechildmarked && onechildunmarked) {
1654 else if (onechildmarked) {
1657 else if (onechildunmarked) {
1660 else { // no child, don't change anything
1661 UpdateTreeItemState(tree->GetItemParent(item));
1665 wxbTreeItemData* itemdata = (wxbTreeItemData*)tree->GetItemData(item);
1667 itemdata->SetMarked(state);
1668 tree->SetItemImage(item, state, wxTreeItemIcon_Normal);
1669 tree->SetItemImage(item, state, wxTreeItemIcon_Selected);
1671 UpdateTreeItemState(tree->GetItemParent(item));
1674 /* Refresh the whole tree. */
1675 void wxbRestorePanel::RefreshTree() {
1676 /* Save current selection */
1677 wxArrayString current;
1679 wxTreeItemId item = currentTreeItem;
1681 while ((item.IsOk()) && (item != tree->GetRootItem())) {
1682 current.Add(tree->GetItemText(item));
1683 item = tree->GetItemParent(item);
1686 /* Update the tree */
1687 UpdateTreeItem(tree->GetRootItem(), false, true);
1689 /* Reselect the former selected item */
1690 item = tree->GetRootItem();
1692 if (current.Count() == 0) {
1693 tree->SelectItem(item);
1699 for (int i = current.Count()-1; i >= 0; i--) {
1700 #if wxCHECK_VERSION(2, 6, 0)
1701 wxTreeItemIdValue cookie;
1705 wxTreeItemId currentChild = tree->GetFirstChild(item, cookie);
1709 while (currentChild.IsOk()) {
1710 if (((wxbTreeItemData*)tree->GetItemData(currentChild))->GetName() == current[i]) {
1711 item = currentChild;
1716 currentChild = tree->GetNextChild(item, cookie);
1722 UpdateTreeItem(item, true, false); /* Update the list */
1724 tree->SelectItem(item);
1727 void wxbRestorePanel::RefreshList() {
1728 if (currentTreeItem.IsOk()) {
1729 UpdateTreeItem(currentTreeItem, true, false); /* Update the list */
1733 /* Update first config, adapting settings to the job name selected */
1734 void wxbRestorePanel::UpdateFirstConfig() {
1735 configPanel->Enable(false);
1736 wxbDataTokenizer* dt = wxbUtils::WaitForEnd(wxString(wxT(".defaults job=")) + configPanel->GetRowString(_("Job Name")) + wxT("\n"), true, false);
1742 * where=/tmp/bacula-restores
1745 * fileset=Full Set */
1751 bool dolistjobs = false;
1753 for (i = 0; i < dt->GetCount(); i++) {
1755 if ((j = str.Find('=')) > -1) {
1756 name = str.Mid(0, j);
1757 if (name == wxT("pool")) {
1758 configPanel->SetRowString(_("Pool"), str.Mid(j+1));
1760 else if (name == wxT("client")) {
1762 if ((str != configPanel->GetRowString(_("Client"))) ||
1763 (configPanel->GetRowString(_("Before"))) == wxT("")) {
1764 configPanel->SetRowString(_("Client"), str);
1768 else if (name == wxT("storage")) {
1769 configPanel->SetRowString(_("Storage"), str.Mid(j+1));
1771 else if (name == wxT("fileset")) {
1772 configPanel->SetRowString(_("Fileset"), str.Mid(j+1));
1780 //wxTheApp->Yield(false);
1783 configPanel->Enable(true);
1787 * Update second config.
1790 * JobName: RestoreFiles
1791 * Bootstrap: /var/lib/bacula/restore.bsr
1792 * Where: /tmp/bacula-restores
1797 * When: 2004-04-18 01:18:56
1799 * OK to run? (yes/mod/no):
1802 bool wxbRestorePanel::UpdateSecondConfig(wxbDataTokenizer* dt) {
1804 for (i = 0; i < dt->GetCount(); i++) {
1805 if ((*dt)[i].Find(_("Run Restore job")) == 0)
1809 if ((i + 10) > dt->GetCount()) {
1815 if ((k = (*dt)[++i].Find(_("JobName:"))) != 0) return false;
1816 restorePanel->SetRowString(_("Job Name"), (*dt)[i].Mid(10).Trim(false).RemoveLast());
1817 if ((k = (*dt)[++i].Find(_("Bootstrap:"))) != 0) return false;
1818 restorePanel->SetRowString(_("Bootstrap"), (*dt)[i].Mid(10).Trim(false).RemoveLast());
1819 if ((k = (*dt)[++i].Find(_("Where:"))) != 0) return false;
1820 restorePanel->SetRowString(_("Where"), (*dt)[i].Mid(10).Trim(false).RemoveLast());
1822 if ((k = (*dt)[++i].Find(_("Replace:"))) != 0) return false;
1823 wxString str = (*dt)[i].Mid(10).Trim(false).RemoveLast();
1824 if (str == _("always")) restorePanel->SetRowSelection(_("Replace"), 0);
1825 else if (str == _("ifnewer")) restorePanel->SetRowSelection(_("Replace"), 1);
1826 else if (str == _("ifolder")) restorePanel->SetRowSelection(_("Replace"), 2);
1827 else if (str == _("never")) restorePanel->SetRowSelection(_("Replace"), 3);
1828 else restorePanel->SetRowSelection(_("Replace"), 0);
1830 if ((k = (*dt)[++i].Find(_("FileSet:"))) != 0) return false;
1831 restorePanel->SetRowString(_("Fileset"), (*dt)[i].Mid(10).Trim(false).RemoveLast());
1832 if ((k = (*dt)[++i].Find(_("Client:"))) != 0) return false;
1833 restorePanel->SetRowString(_("Client"), (*dt)[i].Mid(10).Trim(false).RemoveLast());
1834 if ((k = (*dt)[++i].Find(_("Storage:"))) != 0) return false;
1835 restorePanel->SetRowString(_("Storage"), (*dt)[i].Mid(10).Trim(false).RemoveLast());
1836 if ((k = (*dt)[++i].Find(_("When:"))) != 0) return false;
1837 restorePanel->SetRowString(_("When"), (*dt)[i].Mid(10).Trim(false).RemoveLast());
1838 if ((k = (*dt)[++i].Find(_("Priority:"))) != 0) return false;
1839 restorePanel->SetRowString(_("Priority"), (*dt)[i].Mid(10).Trim(false).RemoveLast());
1842 restorePanel->Layout();
1847 /*----------------------------------------------------------------------------
1849 ----------------------------------------------------------------------------*/
1851 /* Set current status by enabling/disabling components */
1852 void wxbRestorePanel::SetStatus(status_enum newstatus) {
1853 switch (newstatus) {
1855 centerSizer->Remove(configPanel);
1856 centerSizer->Remove(restorePanel);
1857 centerSizer->Remove(treelistPanel);
1858 treelistPanel->Show(false);
1859 restorePanel->Show(false);
1860 centerSizer->Add(configPanel, 1, wxEXPAND);
1861 configPanel->Show(true);
1862 configPanel->Layout();
1863 centerSizer->Layout();
1865 start->SetLabel(_("Enter restore mode"));
1866 start->Enable(false);
1867 configPanel->Enable(false);
1868 tree->Enable(false);
1869 list->Enable(false);
1870 gauge->Enable(false);
1871 cancel->Enable(false);
1876 centerSizer->Remove(configPanel);
1877 centerSizer->Remove(restorePanel);
1878 centerSizer->Remove(treelistPanel);
1879 treelistPanel->Show(false);
1880 restorePanel->Show(false);
1881 centerSizer->Add(configPanel, 1, wxEXPAND);
1882 configPanel->Show(true);
1883 configPanel->Layout();
1884 centerSizer->Layout();
1886 tree->DeleteAllItems();
1887 list->DeleteAllItems();
1888 configPanel->ClearRowChoices(_("Client"));
1889 configPanel->ClearRowChoices(_("Before"));
1890 wxbMainFrame::GetInstance()->EnablePanels();
1891 newstatus = activable;
1894 start->SetLabel(_("Enter restore mode"));
1895 start->Enable(true);
1896 configPanel->Enable(false);
1897 tree->Enable(false);
1898 list->Enable(false);
1899 gauge->Enable(false);
1900 cancel->Enable(false);
1904 wxbMainFrame::GetInstance()->DisablePanels(this);
1906 start->Enable(false);
1907 //start->SetLabel(_("Choose files to restore"));
1908 configPanel->Enable(true);
1909 tree->Enable(false);
1910 list->Enable(false);
1911 cancel->Enable(true);
1918 start->Enable(true);
1919 start->SetLabel(_("Restore"));
1920 centerSizer->Remove(configPanel);
1921 configPanel->Show(false);
1922 centerSizer->Add(treelistPanel, 1, wxEXPAND);
1923 treelistPanel->Show(true);
1924 treelistPanel->Layout();
1925 centerSizer->Layout();
1932 start->Enable(false);
1933 configPanel->Enable(false);
1934 tree->Enable(false);
1935 list->Enable(false);
1936 centerSizer->Remove(treelistPanel);
1937 treelistPanel->Show(false);
1938 centerSizer->Add(restorePanel, 1, wxEXPAND);
1939 restorePanel->Show(true);
1940 restorePanel->Layout();
1941 centerSizer->Layout();
1943 restorePanel->EnableApply(false);
1946 start->SetLabel(_("Restoring..."));
1947 gauge->Enable(true);
1949 start->Enable(false);
1950 configPanel->Enable(false);
1951 tree->Enable(false);
1952 list->Enable(false);
1959 /*----------------------------------------------------------------------------
1961 ----------------------------------------------------------------------------*/
1963 void wxbRestorePanel::SetWorking(bool working) {
1964 this->working = working;
1966 SetCursor(*wxHOURGLASS_CURSOR);
1967 // SetEvtHandlerEnabled(false); //EVTQUEUE
1969 // else if (!processing) { /* Empty event queue if we aren't already doing this */ //EVTQUEUE
1971 // processing = true; //EVTQUEUE
1972 SetCursor(*wxSTANDARD_CURSOR);
1973 // SetEvtHandlerEnabled(true); //EVTQUEUE
1974 /* wxNode *node = pendingEvents->First(); //EVTQUEUE
1976 wxEvent *event = (wxEvent *)node->Data();
1979 wxEvtHandler::ProcessEvent(*event);
1982 node = pendingEvents->First();
1984 processing = false;*/
1988 bool wxbRestorePanel::IsWorking() {
1989 return this->working;
1992 void wxbRestorePanel::EnableConfig(bool enable) {
1993 restorePanel->Enable(enable);
1996 /*----------------------------------------------------------------------------
1998 ----------------------------------------------------------------------------*/
2003 bool wxbRestorePanel::ProcessEvent(wxEvent& event) {
2004 if (IsWorking() || processing) {
2005 wxEvent *eventCopy = event.Clone();
2007 pendingEvents->Append(eventCopy);
2011 return wxEvtHandler::ProcessEvent(event);
2016 void wxbRestorePanel::OnCancel(wxCommandEvent& event) {
2017 cancel->Enable(false);
2018 SetCursor(*wxHOURGLASS_CURSOR);
2020 SetCursor(*wxSTANDARD_CURSOR);
2023 void wxbRestorePanel::OnStart(wxCommandEvent& event) {
2032 void wxbRestorePanel::OnTreeChanging(wxTreeEvent& event) {
2038 void wxbRestorePanel::OnTreeExpanding(wxTreeEvent& event) {
2044 //CmdList(event.GetItem());
2045 if (tree->GetSelection() != event.GetItem()) {
2046 tree->SelectItem(event.GetItem());
2051 void wxbRestorePanel::OnTreeChanged(wxTreeEvent& event) {
2055 if (currentTreeItem == event.GetItem()) {
2058 treeadd->Enable(false);
2059 treeremove->Enable(false);
2060 treerefresh->Enable(false);
2061 markWhenCommandDone = false;
2063 currentTreeItem = event.GetItem();
2064 CmdList(event.GetItem());
2065 if (markWhenCommandDone) {
2066 CmdMark(event.GetItem(), NULL, 0);
2070 if (event.GetItem().IsOk()) {
2071 int status = ((wxbTreeItemData*)tree->GetItemData(event.GetItem()))->GetMarked();
2072 treeadd->Enable(status != 1);
2073 treeremove->Enable(status != 0);
2075 treerefresh->Enable(true);
2078 void wxbRestorePanel::OnTreeMarked(wxbTreeMarkedEvent& event) {
2080 if (tree->GetSelection() == event.GetItem()) {
2081 markWhenCommandDone = !markWhenCommandDone;
2086 markWhenCommandDone = false;
2087 CmdMark(event.GetItem(), NULL, 0);
2088 if (markWhenCommandDone) {
2089 CmdMark(event.GetItem(), NULL, 0);
2094 if (event.GetItem().IsOk()) {
2095 int status = ((wxbTreeItemData*)tree->GetItemData(event.GetItem()))->GetMarked();
2096 treeadd->Enable(status != 1);
2097 treeremove->Enable(status != 0);
2101 void wxbRestorePanel::OnTreeAdd(wxCommandEvent& event) {
2106 if (currentTreeItem.IsOk()) {
2108 CmdMark(currentTreeItem, NULL, 0, 1);
2111 treeremove->Enable(1);
2116 void wxbRestorePanel::OnTreeRemove(wxCommandEvent& event) {
2121 if (currentTreeItem.IsOk()) {
2123 CmdMark(currentTreeItem, NULL, 0, 0);
2126 treeremove->Enable(0);
2131 void wxbRestorePanel::OnTreeRefresh(wxCommandEvent& event) {
2141 void wxbRestorePanel::OnListMarked(wxbListMarkedEvent& event) {
2146 if (list->GetSelectedItemCount() == 0) {
2152 long* items = new long[list->GetSelectedItemCount()];
2156 long item = list->GetNextItem(-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
2157 while (item != -1) {
2160 item = list->GetNextItem(item, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
2163 CmdMark(wxTreeItemId(), items, num);
2167 wxListEvent listevt;
2169 OnListChanged(listevt);
2176 void wxbRestorePanel::OnListActivated(wxListEvent& event) {
2181 long item = event.GetIndex();
2182 // long item = list->GetNextItem(-1, wxLIST_NEXT_ALL, wxLIST_STATE_FOCUSED);
2184 wxbTreeItemData* itemdata = (wxbTreeItemData*)list->GetItemData(item);
2185 wxString name = itemdata->GetName();
2190 #if wxCHECK_VERSION(2, 6, 0)
2191 wxTreeItemIdValue cookie;
2196 if (name.GetChar(name.Length()-1) == '/') {
2197 wxTreeItemId currentChild = tree->GetFirstChild(currentTreeItem, cookie);
2199 while (currentChild.IsOk()) {
2200 wxString name2 = ((wxbTreeItemData*)tree->GetItemData(currentChild))->GetName();
2201 if (name2 == name) {
2202 //tree->UnselectAll();
2204 tree->Expand(currentTreeItem);
2205 tree->SelectItem(currentChild);
2209 currentChild = tree->GetNextChild(currentTreeItem, cookie);
2216 void wxbRestorePanel::OnListChanged(wxListEvent& event) {
2221 listadd->Enable(false);
2222 listremove->Enable(false);
2224 bool marked = false;
2225 bool unmarked = false;
2227 long item = list->GetNextItem(-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
2228 while (item != -1) {
2229 switch (((wxbTreeItemData*)list->GetItemData(item))->GetMarked()) {
2242 // Should never happen
2244 if (marked && unmarked) break;
2245 item = list->GetNextItem(item, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
2248 listadd->Enable(unmarked);
2249 listremove->Enable(marked);
2252 void wxbRestorePanel::OnListAdd(wxCommandEvent& event) {
2259 long* items = new long[list->GetSelectedItemCount()];
2263 long item = list->GetNextItem(-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
2264 while (item != -1) {
2267 item = list->GetNextItem(item, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
2270 CmdMark(wxTreeItemId(), items, num, 1);
2277 listadd->Enable(false);
2278 listremove->Enable(true);
2281 void wxbRestorePanel::OnListRemove(wxCommandEvent& event) {
2288 long* items = new long[list->GetSelectedItemCount()];
2292 long item = list->GetNextItem(-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
2293 while (item != -1) {
2296 item = list->GetNextItem(item, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
2299 CmdMark(wxTreeItemId(), items, num, 0);
2306 listadd->Enable(true);
2307 listremove->Enable(false);
2310 void wxbRestorePanel::OnListRefresh(wxCommandEvent& event) {
2320 void wxbRestorePanel::OnConfigUpdated(wxCommandEvent& event) {
2321 if (status == entered) {
2322 if (event.GetId() == ConfigJobName) {
2327 UpdateFirstConfig();
2330 else if (event.GetId() == ConfigClient) {
2335 configPanel->Enable(false);
2337 configPanel->Enable(true);
2340 cfgUpdated = cfgUpdated | (1 << event.GetId());
2342 else if (status == configuring) {
2343 restorePanel->EnableApply(true);
2344 cfgUpdated = cfgUpdated | (1 << event.GetId());
2348 void wxbRestorePanel::OnConfigOk(wxCommandEvent& WXUNUSED(event)) {
2349 if (status != configuring) return;
2358 void wxbRestorePanel::OnConfigApply(wxCommandEvent& WXUNUSED(event)) {
2359 if (status != configuring) return;
2365 if (cfgUpdated == 0) {
2366 restorePanel->EnableApply(false);
2371 void wxbRestorePanel::OnConfigCancel(wxCommandEvent& WXUNUSED(event)) {
2372 if (status != configuring) return;