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);
590 wxbMainFrame::GetInstance()->Send(wxString(wxT("restore")) <<
591 wxT(" client=\"") << configPanel->GetRowString(wxT("Client")) <<
592 wxT("\" fileset=\"") << configPanel->GetRowString(wxT("Fileset")) <<
593 wxT("\" pool=\"") << configPanel->GetRowString(wxT("Pool")) <<
594 wxT("\" storage=\"") << configPanel->GetRowString(wxT("Storage")) <<
595 wxT("\" before=\"") << configPanel->GetRowString(wxT("Before")) <<
597 //wxbUtils::WaitForPrompt("6\n");
599 /*wxbPromptParser *pp = wxbUtils::WaitForPrompt(wxString() << configPanel->GetRowString(wxT("Before")) << "\n", true);
600 int client = pp->getChoices()->Index(configPanel->GetRowString(wxT("Client")));
601 if (client == wxNOT_FOUND) {
602 wxbMainFrame::GetInstance()->SetStatusText("Failed to find the selected client.");
607 //wxbMainFrame::GetInstance()->Send(wxString() << configPanel->GetRowString(wxT("Before")) << "\n");
609 while (!tableparser->hasFinished() && !dt->hasFinished()) {
610 wxTheApp->Yield(true);
611 wxbUtils::MilliSleep(100);
616 if (dt->hasFinished() && !tableparser->hasFinished()) {
618 if (dt->GetCount() > 1) {
619 str = (*dt)[dt->GetCount()-2];
622 wxbMainFrame::GetInstance()->SetStatusText(wxString(_("Error while starting restore: ")) << str);
632 for (i = 0; i < tableparser->GetCount(); i++) {
633 str = (*tableparser)[i][2];
634 str.Replace(wxT(","), wxT(""));
635 if (str.ToLong(&l)) {
641 gauge->SetRange(tot);
643 /*wxbMainFrame::GetInstance()->Print(
644 wxString("[") << tot << "]", CS_DEBUG);*/
646 wxDateTime base = wxDateTime::Now();
650 unsigned int lastindex = 0;
657 newdate = wxDateTime::Now();
658 if (newdate.Subtract(base).GetMilliseconds() > 10 ) {
660 for (; lastindex < dt->GetCount(); lastindex++) {
661 if (((i1 = (*dt)[lastindex].Find(wxT("Building directory tree for JobId "))) >= 0) &&
662 ((i2 = (*dt)[lastindex].Find(wxT(" ..."))) > 0)) {
663 str = (*dt)[lastindex].Mid(i1+34, i2-(i1+34));
664 for (i = 0; i < tableparser->GetCount(); i++) {
665 if (str == (*tableparser)[i][0]) {
666 str = (*tableparser)[i][2];
667 str.Replace(wxT(","), wxT(""));
668 if (str.ToLong(&l)) {
671 var = (willdo-done)/50;
672 gauge->SetValue(done);
673 wxTheApp->Yield(true);
679 else if ((*dt)[lastindex] == wxT("+")) {
680 gauge->SetValue(gauge->GetValue()+var);
681 wxTheApp->Yield(true);
686 if (dt->hasFinished()) {
690 wxTheApp->Yield(true);
691 wxbUtils::MilliSleep(1);
694 gauge->SetValue(tot);
695 wxTheApp->Yield(true);
706 wxbUtils::WaitForEnd(wxT("unmark *\n"));
707 wxTreeItemId root = tree->AddRoot(configPanel->GetRowString(_("Client")), -1, -1, new wxbTreeItemData(wxT("/"), configPanel->GetRowString(_("Client")), 0));
708 currentTreeItem = root;
710 tree->SelectItem(root);
712 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."));
715 else if (status == choosing) {
719 wxbDataTokenizer* dt;
723 dt = new wxbDataTokenizer(true);
724 wxbUtils::WaitForPrompt(wxT("done\n"));
726 SetStatus(configuring);
728 for (i = 0; i < dt->GetCount(); i++) {
729 if ((j = (*dt)[i].Find(_(" files selected to be restored."))) > -1) {
730 (*dt)[i].Mid(0, j).ToLong(&totfilemessages);
734 if ((j = (*dt)[i].Find(_(" file selected to be restored."))) > -1) {
735 (*dt)[i].Mid(0, j).ToLong(&totfilemessages);
740 wxbMainFrame::GetInstance()->SetStatusText(
741 wxString::Format(_("Please configure your restore (%ld files selected to be restored)..."), totfilemessages));
743 UpdateSecondConfig(dt);
748 restorePanel->EnableApply(false);
750 if (totfilemessages == 0) {
751 wxbMainFrame::GetInstance()->Print(_("Restore failed : no file selected.\n"), CS_DEBUG);
752 wxbMainFrame::GetInstance()->SetStatusText(_("Restore failed : no file selected."));
757 else if (status == configuring) {
758 cancel->Enable(false);
762 wxbMainFrame::GetInstance()->SetStatusText(_("Restoring, please wait..."));
764 wxbDataTokenizer* dt;
766 SetStatus(restoring);
767 dt = wxbUtils::WaitForEnd(wxT("yes\n"), true);
770 gauge->SetRange(totfilemessages);
774 for (i = 0; i < dt->GetCount(); i++) {
775 if ((j = (*dt)[i].Find(_("Job started. JobId="))) > -1) {
776 jobid = (*dt)[i].Mid(j+19);
777 wxbMainFrame::GetInstance()->SetStatusText(_("Restore started, jobid=") + jobid);
781 if ((j = (*dt)[i].Find(_("Job failed."))) > -1) {
782 wxbMainFrame::GetInstance()->Print(_("Restore failed, please look at messages.\n"), CS_DEBUG);
783 wxbMainFrame::GetInstance()->SetStatusText(_("Restore failed, please look at messages in console."));
788 if (jobid == wxT("")) {
789 wxbMainFrame::GetInstance()->Print(_("Failed to retrieve jobid.\n"), CS_DEBUG);
790 wxbMainFrame::GetInstance()->SetStatusText(_("Failed to retrieve jobid.\n"));
794 wxDateTime currenttime;
796 dt = wxbUtils::WaitForEnd(wxT("time\n"), true);
797 wxStringTokenizer ttkz((*dt)[0], wxT(" "), wxTOKEN_STRTOK);
798 if ((currenttime.ParseDate(ttkz.GetNextToken()) == NULL) || // Date
799 (currenttime.ParseTime(ttkz.GetNextToken()) == NULL)) { // Time
800 currenttime.SetYear(1990); // If parsing fails, set currenttime to a dummy date
803 currenttime -= wxTimeSpan::Seconds(30); //Adding a 30" tolerance
807 wxDateTime scheduledtime;
808 wxStringTokenizer stkz(restorePanel->GetRowString(_("When")), wxT(" "), wxTOKEN_STRTOK);
810 if ((scheduledtime.ParseDate(stkz.GetNextToken()) == NULL) || // Date
811 (scheduledtime.ParseTime(stkz.GetNextToken()) == NULL)) { // Time
812 scheduledtime.SetYear(2090); // If parsing fails, set scheduledtime to a dummy date
815 if (scheduledtime.Subtract(currenttime).IsLongerThan(wxTimeSpan::Seconds(150))) {
816 wxbMainFrame::GetInstance()->Print(_("Restore is scheduled in more than two minutes, wx-console will not wait for its completion.\n"), CS_DEBUG);
817 wxbMainFrame::GetInstance()->SetStatusText(_("Restore is scheduled in more than two minutes, wx-console will not wait for its completion."));
822 wxString cmd = wxString(wxT("list jobid=")) + jobid;
824 wxbTableParser* tableparser;
826 long filemessages = 0;
829 bool waitforever = false;
836 tableparser = wxbUtils::CreateAndWaitForParser(cmd);
838 status = (*tableparser)[0][7].GetChar(0);
841 wxbMainFrame::GetInstance()->SetStatusText(_("Restore job created, but not yet running."));
845 wxbMainFrame::GetInstance()->SetStatusText(
846 wxString::Format(_("Restore job running, please wait (%ld of %ld files restored)..."), filemessages, totfilemessages));
850 wxbMainFrame::GetInstance()->SetStatusText(_("Restore job terminated successfully."));
851 wxbMainFrame::GetInstance()->Print(_("Restore job terminated successfully.\n"), CS_DEBUG);
855 case JS_ErrorTerminated:
856 wxbMainFrame::GetInstance()->SetStatusText(_("Restore job terminated in error, see messages in console."));
857 wxbMainFrame::GetInstance()->Print(_("Restore job terminated in error, see messages.\n"), CS_DEBUG);
862 wxbMainFrame::GetInstance()->SetStatusText(_("Restore job reported a non-fatal error."));
866 wxbMainFrame::GetInstance()->SetStatusText(_("Restore job reported a fatal error."));
871 wxbMainFrame::GetInstance()->SetStatusText(_("Restore job cancelled by user."));
872 wxbMainFrame::GetInstance()->Print(_("Restore job cancelled by user.\n"), CS_DEBUG);
877 wxbMainFrame::GetInstance()->SetStatusText(_("Restore job is waiting on File daemon."));
881 wxbMainFrame::GetInstance()->SetStatusText(_("Restore job is waiting for new media."));
884 case JS_WaitStoreRes:
885 wxbMainFrame::GetInstance()->SetStatusText(_("Restore job is waiting for storage resource."));
889 wxbMainFrame::GetInstance()->SetStatusText(_("Restore job is waiting for job resource."));
892 case JS_WaitClientRes:
893 wxbMainFrame::GetInstance()->SetStatusText(_("Restore job is waiting for Client resource."));
897 wxbMainFrame::GetInstance()->SetStatusText(_("Restore job is waiting for maximum jobs."));
900 case JS_WaitStartTime:
901 wxbMainFrame::GetInstance()->SetStatusText(_("Restore job is waiting for start time."));
904 case JS_WaitPriority:
905 wxbMainFrame::GetInstance()->SetStatusText(_("Restore job is waiting for higher priority jobs to finish."));
911 dt = wxbUtils::WaitForEnd(wxT(".messages\n"), true);
913 for (unsigned int i = 0; i < dt->GetCount(); i++) {
914 wxStringTokenizer tkz((*dt)[i], wxT(" "), wxTOKEN_STRTOK);
918 // Date Time name: perm ? user grp size date time
919 //04-Apr-2004 17:19 Tom-fd: -rwx------ 1 nicolas None 514967 2004-03-20 20:03:42 filename
921 if (datetime.ParseDate(tkz.GetNextToken()) != NULL) { // Date
922 if (datetime.ParseTime(tkz.GetNextToken()) != NULL) { // Time
923 if (tkz.GetNextToken().Last() == ':') { // name:
924 tkz.GetNextToken(); // perm
925 tkz.GetNextToken(); // ?
926 tkz.GetNextToken(); // user
927 tkz.GetNextToken(); // grp
928 tkz.GetNextToken(); // size
929 if (datetime.ParseDate(tkz.GetNextToken()) != NULL) { //date
930 if (datetime.ParseTime(tkz.GetNextToken()) != NULL) { //time
932 //wxbMainFrame::GetInstance()->Print(wxString("(") << filemessages << ")", CS_DEBUG);
933 gauge->SetValue(filemessages);
944 while (sw2.Time() < 10000) {
945 wxTheApp->Yield(true);
946 wxbUtils::MilliSleep(100);
953 if ((!waitforever) && (sw.Time() > 60000)) {
954 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);
955 wxbMainFrame::GetInstance()->SetStatusText(_("The restore job has not been started within one minute, wx-console will not wait for its completion anymore."));
960 wxbUtils::WaitForEnd(wxT(".messages\n"));
962 gauge->SetValue(totfilemessages);
964 if (status == JS_Terminated) {
965 wxbMainFrame::GetInstance()->Print(_("Restore done successfully.\n"), CS_DEBUG);
966 wxbMainFrame::GetInstance()->SetStatusText(_("Restore done successfully."));
972 /* The cancel button has been clicked */
973 void wxbRestorePanel::CmdCancel() {
976 if (status == restoring) {
977 if (jobid != wxT("")) {
978 wxbMainFrame::GetInstance()->Send(wxString(wxT("cancel job=")) << jobid << wxT("\n"));
980 cancel->Enable(true);
985 while ((IsWorking()) && (cancelled != 2)) {
986 wxTheApp->Yield(true);
987 wxbUtils::MilliSleep(100);
988 if (sw.Time() > 30000) { /* 30 seconds timeout */
989 if (status == choosing) {
990 wxbMainFrame::GetInstance()->Send(wxT("quit\n"));
992 else if (status == configuring) {
993 wxbMainFrame::GetInstance()->Send(wxT("no\n"));
995 else if (status == restoring) {
999 wxbUtils::MilliSleep(1000);
1006 wxbMainFrame::GetInstance()->Send(wxT("quit\n"));
1009 wxbMainFrame::GetInstance()->Send(wxT("no\n"));
1014 wxbUtils::MilliSleep(1000);
1015 SetStatus(finished);
1018 /* Apply configuration changes */
1020 /* 1: Level (not appropriate)
1025 * 6: When (yes : "Please enter desired start time as YYYY-MM-DD HH:MM:SS (return for now):")
1026 * 7: Priority (yes : "Enter new Priority: (positive integer)")
1028 * 9: Where (yes : "Please enter path prefix for restore (/ for none):")
1029 * 10: Replace (yes : "Replace:\n 1: always\n 2: ifnewer\n 3: ifolder\n 4: never\n
1030 * Select replace option (1-4):")
1034 void wxbRestorePanel::CmdConfigApply() {
1035 if (cfgUpdated == 0) return;
1037 wxbMainFrame::GetInstance()->SetStatusText(_("Applying restore configuration changes..."));
1039 EnableConfig(false);
1041 wxbDataTokenizer* dt = NULL;
1043 bool failed = false;
1045 while (cfgUpdated > 0) {
1050 wxString def; //String to send if can't use our data
1051 if ((cfgUpdated >> ConfigWhere) & 1) {
1052 wxbUtils::WaitForPrompt(wxT("mod\n")); /* TODO: check results */
1053 wxbUtils::WaitForPrompt(wxT("9\n"));
1054 dt = new wxbDataTokenizer(true);
1055 wxbUtils::WaitForPrompt(restorePanel->GetRowString(_("Where")) + wxT("\n"));
1057 cfgUpdated = cfgUpdated & (~(1 << ConfigWhere));
1059 else if ((cfgUpdated >> ConfigReplace) & 1) {
1060 wxbUtils::WaitForPrompt(wxT("mod\n")); /* TODO: check results */
1061 wxbUtils::WaitForPrompt(wxT("10\n"));
1062 dt = new wxbDataTokenizer(true);
1063 wxbUtils::WaitForPrompt(wxString() << (restorePanel->GetRowSelection(_("Replace"))+1) << wxT("\n"));
1065 cfgUpdated = cfgUpdated & (~(1 << ConfigReplace));
1067 else if ((cfgUpdated >> ConfigWhen) & 1) {
1068 wxbUtils::WaitForPrompt(wxT("mod\n")); /* TODO: check results */
1069 wxbUtils::WaitForPrompt(wxT("6\n"));
1070 dt = new wxbDataTokenizer(true);
1071 wxbUtils::WaitForPrompt(restorePanel->GetRowString(wxT("When")) + wxT("\n"));
1073 cfgUpdated = cfgUpdated & (~(1 << ConfigWhen));
1075 else if ((cfgUpdated >> ConfigPriority) & 1) {
1076 wxbUtils::WaitForPrompt(wxT("mod\n")); /* TODO: check results */
1077 wxbUtils::WaitForPrompt(wxT("7\n"));
1078 dt = new wxbDataTokenizer(true);
1079 wxbUtils::WaitForPrompt(restorePanel->GetRowString(_("Priority")) + wxT("\n"));
1081 cfgUpdated = cfgUpdated & (~(1 << ConfigPriority));
1083 else if ((cfgUpdated >> ConfigClient) & 1) {
1084 wxbUtils::WaitForPrompt(wxT("mod\n")); /* TODO: check results */
1085 wxbPromptParser *pp = wxbUtils::WaitForPrompt(wxT("5\n"), true);
1086 int client = pp->getChoices()->Index(restorePanel->GetRowString(_("Client")));
1087 if (client == wxNOT_FOUND) {
1088 wxbMainFrame::GetInstance()->SetStatusText(_("Failed to find the selected client."));
1093 dt = new wxbDataTokenizer(true);
1094 wxbUtils::WaitForPrompt(wxString() << client << wxT("\n"));
1096 cfgUpdated = cfgUpdated & (~(1 << ConfigClient));
1098 else if ((cfgUpdated >> ConfigFileset) & 1) {
1099 wxbUtils::WaitForPrompt(wxT("mod\n")); /* TODO: check results */
1100 wxbPromptParser *pp = wxbUtils::WaitForPrompt(wxT("4\n"), true);
1101 int fileset = pp->getChoices()->Index(restorePanel->GetRowString(_("Fileset")));
1102 if (fileset == wxNOT_FOUND) {
1103 wxbMainFrame::GetInstance()->SetStatusText(_("Failed to find the selected fileset."));
1108 dt = new wxbDataTokenizer(true);
1109 wxbUtils::WaitForPrompt(wxString() << fileset << wxT("\n"));
1111 cfgUpdated = cfgUpdated & (~(1 << ConfigFileset));
1113 else if ((cfgUpdated >> ConfigStorage) & 1) {
1114 wxbUtils::WaitForPrompt(wxT("mod\n")); /* TODO: check results */
1115 wxbPromptParser *pp = wxbUtils::WaitForPrompt(wxT("2\n"), true);
1116 int fileset = pp->getChoices()->Index(restorePanel->GetRowString(_("Storage")));
1117 if (fileset == wxNOT_FOUND) {
1118 wxbMainFrame::GetInstance()->SetStatusText(_("Failed to find the selected storage."));
1123 dt = new wxbDataTokenizer(true);
1124 wxbUtils::WaitForPrompt(wxString() << fileset << wxT("\n"));
1126 cfgUpdated = cfgUpdated & (~(1 << ConfigFileset));
1134 for (i = 0; i < dt->GetCount(); i++) {
1135 if ((*dt)[i].Find(_("Run Restore job")) == 0) {
1140 if (i == dt->GetCount()) {
1142 dt = wxbUtils::WaitForEnd(def + wxT("\n"), true);
1146 UpdateSecondConfig(dt); /* TODO: Check result */
1151 wxbMainFrame::GetInstance()->SetStatusText(_("Restore configuration changes were applied."));
1157 /* Cancel restore */
1158 void wxbRestorePanel::CmdConfigCancel() {
1159 wxbUtils::WaitForEnd(wxT("no\n"));
1160 wxbMainFrame::GetInstance()->Print(_("Restore cancelled.\n"), CS_DEBUG);
1161 wxbMainFrame::GetInstance()->SetStatusText(_("Restore cancelled."));
1162 SetStatus(finished);
1165 /* List jobs for a specified client */
1166 void wxbRestorePanel::CmdListJobs() {
1167 if (status == entered) {
1168 configPanel->ClearRowChoices(_("Before"));
1169 /*wxbUtils::WaitForPrompt("query\n");
1170 wxbUtils::WaitForPrompt("6\n");*/
1171 wxbTableParser* tableparser = new wxbTableParser(false);
1172 wxbDataTokenizer* dt = wxbUtils::WaitForEnd(
1173 wxString(wxT(".backups client=") + configPanel->GetRowString(_("Client")) + wxT("\n"), true));
1175 while (!tableparser->hasFinished()) {
1176 wxTheApp->Yield(true);
1177 wxbUtils::MilliSleep(100);
1180 if (!tableparser->GetCount() == 0) {
1181 for (unsigned int i = 0; i < dt->Count(); i++) {
1182 if ((*dt)[i].Find(_("No results to list.")) == 0) {
1183 configPanel->AddRowChoice(_("Before"),
1184 _("No backup found for this client."));
1185 configPanel->SetRowSelection(_("Before"), 0);
1186 configPanel->EnableApply(true); // Enabling the not existing apply button disables the ok button.
1191 else if (((*dt)[i].Find(_("ERROR")) > -1) ||
1192 ((*dt)[i].Find(_("Query failed")) > -1)) {
1193 configPanel->AddRowChoice(_("Before"),
1194 _("Cannot get previous backups list, see console."));
1195 configPanel->SetRowSelection(_("Before"), 0);
1196 configPanel->EnableApply(true); // Enabling the not existing apply button disables the ok button.
1206 for (int i = tableparser->GetCount()-1; i > -1; i--) {
1207 wxString str = (*tableparser)[i][3];
1208 wxDateTime datetime;
1210 if ( ( (chr = datetime.ParseDate(str.GetData()) ) != NULL ) && ( datetime.ParseTime(++chr) != NULL ) ) {
1211 datetime += wxTimeSpan::Seconds(1);
1212 configPanel->AddRowChoice(_("Before"),
1213 datetime.Format(wxT("%Y-%m-%d %H:%M:%S")));
1219 configPanel->SetRowSelection(_("Before"), 0);
1220 configPanel->EnableApply(false); // Disabling the not existing apply button enables the ok button.
1224 /* List files and directories for a specified tree item */
1225 void wxbRestorePanel::CmdList(wxTreeItemId item) {
1226 if (status == choosing) {
1227 list->DeleteAllItems();
1232 UpdateTreeItem(item, true, false);
1234 if (list->GetItemCount() >= 1) {
1235 int firstwidth = list->GetSize().GetWidth();
1236 for (int i = 2; i < 7; i++) {
1237 list->SetColumnWidth(i, wxLIST_AUTOSIZE);
1238 firstwidth -= list->GetColumnWidth(i);
1241 list->SetColumnWidth(0, 18);
1243 list->SetColumnWidth(1, wxLIST_AUTOSIZE);
1244 if (list->GetColumnWidth(1) < firstwidth) {
1245 list->SetColumnWidth(1, firstwidth-25);
1251 /* Mark a treeitem (directory) or a listitem (file or directory) */
1252 void wxbRestorePanel::CmdMark(wxTreeItemId treeitem, long* listitems, int listsize, int state) {
1253 if (status == choosing) {
1254 wxbTreeItemData** itemdata;
1255 int itemdatasize = 0;
1256 if (listsize == 0) {
1257 itemdata = new wxbTreeItemData*[1];
1261 itemdata = new wxbTreeItemData*[listsize];
1262 itemdatasize = listsize;
1265 if (listitems != NULL) {
1266 for (int i = 0; i < listsize; i++) {
1267 itemdata[i] = (wxbTreeItemData*)list->GetItemData(listitems[i]);
1270 else if (treeitem.IsOk()) {
1271 itemdata[0] = (wxbTreeItemData*)tree->GetItemData(treeitem);
1278 if (itemdata[0] == NULL) { //Should never happen
1283 wxString dir = itemdata[0]->GetPath();
1286 if (dir != wxT("/")) {
1287 if (dir.GetChar(dir.Length()-1) == '/') {
1291 int i = dir.Find('/', TRUE);
1296 else { /* first dir below root */
1297 file = dir.Mid(i+1);
1298 dir = dir.Mid(0, i+1);
1307 bool marked = false;
1308 bool unmarked = false;
1310 for (int i = 0; i < itemdatasize; i++) {
1311 switch(itemdata[i]->GetMarked()) {
1325 if (marked && unmarked)
1341 wxbUtils::WaitForEnd(wxString(wxT("cd \"")) << dir << wxT("\"\n"));
1342 wxbUtils::WaitForEnd(wxString((state==1) ? wxT("mark") : wxT("unmark")) << wxT(" \"") << file << wxT("\"\n"));
1344 /* TODO: Check commands results */
1346 /*if ((dir == "/") && (file == "*")) {
1347 itemdata->SetMarked((itemdata->GetMarked() == 1) ? 0 : 1);
1350 if (listitems == NULL) { /* tree item state changed */
1351 SetTreeItemState(treeitem, state);
1352 /*treeitem = tree->GetSelection();
1353 UpdateTree(treeitem, true);
1354 treeitem = tree->GetItemParent(treeitem);*/
1357 for (int i = 0; i < listsize; i++) {
1358 SetListItemState(listitems[i], state);
1360 /*UpdateTree(treeitem, (tree->GetSelection() == treeitem));
1361 treeitem = tree->GetItemParent(treeitem);*/
1364 /*while (treeitem.IsOk()) {
1365 WaitForList(treeitem, false);
1366 treeitem = tree->GetItemParent(treeitem);
1373 /*----------------------------------------------------------------------------
1375 ----------------------------------------------------------------------------*/
1377 /* Run a dir command, and waits until result is fully received. */
1378 void wxbRestorePanel::UpdateTreeItem(wxTreeItemId item, bool updatelist, bool recurse) {
1379 // this->updatelist = updatelist;
1380 wxbDataTokenizer* dt;
1382 dt = wxbUtils::WaitForEnd(wxString(wxT("cd \"")) <<
1383 static_cast<wxbTreeItemData*>(tree->GetItemData(item))
1384 ->GetPath() << wxT("\"\n"), false);
1386 /* TODO: check command result */
1393 list->DeleteAllItems();
1394 dt = wxbUtils::WaitForEnd(wxT("dir\n"), true);
1398 for (unsigned int i = 0; i < dt->GetCount(); i++) {
1401 if (str.Find(wxT("cwd is:")) == 0) { // Sometimes cd command result "infiltrate" into listings.
1407 wxString* file = ParseList(str);
1412 wxTreeItemId treeid;
1414 if (file[8].GetChar(file[8].Length()-1) == '/') {
1417 #if wxCHECK_VERSION(2, 6, 0)
1418 wxTreeItemIdValue cookie;
1423 treeid = tree->GetFirstChild(item, cookie);
1425 bool updated = false;
1427 while (treeid.IsOk()) {
1428 itemStr = ((wxbTreeItemData*)tree->GetItemData(treeid))->GetName();
1429 if (file[8] == itemStr) {
1430 int stat = wxbTreeItemData::GetMarkedStatus(file[6]);
1431 if (static_cast<wxbTreeItemData*>(tree->GetItemData(treeid))->GetMarked() != stat) {
1432 tree->SetItemImage(treeid, stat, wxTreeItemIcon_Normal);
1433 tree->SetItemImage(treeid, stat, wxTreeItemIcon_Selected);
1434 static_cast<wxbTreeItemData*>(tree->GetItemData(treeid))->SetMarked(file[6]);
1436 if ((recurse) && (tree->IsExpanded(treeid))) {
1437 UpdateTreeItem(treeid, false, true);
1442 treeid = tree->GetNextChild(item, cookie);
1446 int img = wxbTreeItemData::GetMarkedStatus(file[6]);
1447 treeid = tree->AppendItem(item, wxbUtils::ConvertToPrintable(file[8]), img, img, new wxbTreeItemData(file[7], file[8], file[6]));
1452 long ind = list->InsertItem(list->GetItemCount(), wxbTreeItemData::GetMarkedStatus(file[6]));
1453 wxbTreeItemData* data = new wxbTreeItemData(file[7], file[8], file[6], ind);
1454 data->SetId(treeid);
1455 list->SetItemData(ind, (long)data);
1456 list->SetItem(ind, 1, wxbUtils::ConvertToPrintable(file[8])); // filename
1457 list->SetItem(ind, 2, file[4]); //Size
1458 list->SetItem(ind, 3, file[5]); //date
1459 list->SetItem(ind, 4, file[0]); //perm
1460 list->SetItem(ind, 5, file[2]); //user
1461 list->SetItem(ind, 6, file[3]); //grp
1473 /* Parse dir command results. */
1476 * It sure would be nice to have some comments here, especially
1477 * when setting up ret[7] and ret[8].
1478 * Also, it would be a lot easier for everyone if this were based
1479 * on variable width fields everywhere. All the fields except
1480 * the last (filename) are separated by spaces (the date is
1481 * composed of two blank terminated fields date + time.
1483 wxString* wxbRestorePanel::ParseList(wxString line) {
1484 /* See ls_output in dird/ua_tree.c */
1486 //drwxrwxrwx 111 root root 0 2004-04-03 14:35:21 f:/tocd/NVSU 1.00.00/
1487 //+ 10 + +i+ + 8 + + 8 ++ 10 + + 19 + *+ ->
1488 //0 12 i+15 i+24 i+32 i+42 i+62
1492 if (line.Length() < 63)
1495 wxString* ret = new wxString[9];
1497 ret[0] = line.Mid(0, 10).Trim(); // modes
1499 /* Column 1 has a variable width */
1500 i = line.find(' ', 14) - 14;
1501 ret[1] = line.Mid(12, 2+i).Trim(); // number of links
1503 ret[2] = line.Mid(15+i, 8).Trim(); // user
1504 ret[3] = line.Mid(24+i, 8).Trim(); // group
1505 ret[4] = line.Mid(32+i, 10).Trim(); // file size
1506 ret[5] = line.Mid(44+i, 19).Trim(); // date + time
1507 ret[6] = line.Mid(65+i, 1); // drive letter or /
1508 ret[7] = line.Mid(65+i).Trim(); // filename
1510 if (ret[6] == wxT(" ")) ret[6] = wxT("");
1512 if (ret[7].GetChar(ret[7].Length()-1) == '/') {
1514 ret[8].RemoveLast();
1515 ret[8] = ret[7].Mid(ret[8].Find('/', true)+1);
1518 ret[8] = ret[7].Mid(ret[7].Find('/', true)+1);
1524 /* Sets a list item state, and update its parents and children if it is a directory */
1525 void wxbRestorePanel::SetListItemState(long listitem, int newstate) {
1526 wxbTreeItemData* itemdata = (wxbTreeItemData*)list->GetItemData(listitem);
1528 wxTreeItemId treeitem;
1530 itemdata->SetMarked(newstate);
1531 list->SetItemImage(listitem, newstate, 0); /* TODO: Find what these ints are for */
1532 list->SetItemImage(listitem, newstate, 1);
1534 if ((treeitem = itemdata->GetId()).IsOk()) {
1535 SetTreeItemState(treeitem, newstate);
1538 UpdateTreeItemState(tree->GetSelection());
1542 /* Sets a tree item state, and update its children, parents and list (if necessary) */
1543 void wxbRestorePanel::SetTreeItemState(wxTreeItemId item, int newstate) {
1544 #if wxCHECK_VERSION(2, 6, 0)
1545 wxTreeItemIdValue cookie;
1549 wxTreeItemId currentChild = tree->GetFirstChild(item, cookie);
1551 wxbTreeItemData* itemdata;
1553 while (currentChild.IsOk()) {
1554 itemdata = (wxbTreeItemData*)tree->GetItemData(currentChild);
1555 int state = itemdata->GetMarked();
1557 if (state != newstate) {
1558 itemdata->SetMarked(newstate);
1559 tree->SetItemImage(currentChild, newstate, wxTreeItemIcon_Normal);
1560 tree->SetItemImage(currentChild, newstate, wxTreeItemIcon_Selected);
1563 currentChild = tree->GetNextChild(item, cookie);
1566 itemdata = (wxbTreeItemData*)tree->GetItemData(item);
1567 itemdata->SetMarked(newstate);
1568 tree->SetItemImage(item, newstate, wxTreeItemIcon_Normal);
1569 tree->SetItemImage(item, newstate, wxTreeItemIcon_Selected);
1572 if (tree->GetSelection() == item) {
1573 for (long i = 0; i < list->GetItemCount(); i++) {
1574 list->SetItemImage(i, newstate, 0); /* TODO: Find what these ints are for */
1575 list->SetItemImage(i, newstate, 1);
1579 UpdateTreeItemState(tree->GetItemParent(item));
1582 /* Update a tree item state, and its parents' state */
1583 void wxbRestorePanel::UpdateTreeItemState(wxTreeItemId item) {
1590 #if wxCHECK_VERSION(2, 6, 0)
1591 wxTreeItemIdValue cookie;
1595 wxTreeItemId currentChild = tree->GetFirstChild(item, cookie);
1597 bool onechildmarked = false;
1598 bool onechildunmarked = false;
1600 while (currentChild.IsOk()) {
1601 state = ((wxbTreeItemData*)tree->GetItemData(currentChild))->GetMarked();
1604 onechildunmarked = true;
1607 onechildmarked = true;
1610 onechildmarked = true;
1611 onechildunmarked = true;
1615 if (onechildmarked && onechildunmarked) {
1619 currentChild = tree->GetNextChild(item, cookie);
1622 if (tree->GetSelection() == item) {
1623 for (long i = 0; i < list->GetItemCount(); i++) {
1624 state = ((wxbTreeItemData*)list->GetItemData(i))->GetMarked();
1628 onechildunmarked = true;
1631 onechildmarked = true;
1634 onechildmarked = true;
1635 onechildunmarked = true;
1639 if (onechildmarked && onechildunmarked) {
1647 if (onechildmarked && onechildunmarked) {
1650 else if (onechildmarked) {
1653 else if (onechildunmarked) {
1656 else { // no child, don't change anything
1657 UpdateTreeItemState(tree->GetItemParent(item));
1661 wxbTreeItemData* itemdata = (wxbTreeItemData*)tree->GetItemData(item);
1663 itemdata->SetMarked(state);
1664 tree->SetItemImage(item, state, wxTreeItemIcon_Normal);
1665 tree->SetItemImage(item, state, wxTreeItemIcon_Selected);
1667 UpdateTreeItemState(tree->GetItemParent(item));
1670 /* Refresh the whole tree. */
1671 void wxbRestorePanel::RefreshTree() {
1672 /* Save current selection */
1673 wxArrayString current;
1675 wxTreeItemId item = currentTreeItem;
1677 while ((item.IsOk()) && (item != tree->GetRootItem())) {
1678 current.Add(tree->GetItemText(item));
1679 item = tree->GetItemParent(item);
1682 /* Update the tree */
1683 UpdateTreeItem(tree->GetRootItem(), false, true);
1685 /* Reselect the former selected item */
1686 item = tree->GetRootItem();
1688 if (current.Count() == 0) {
1689 tree->SelectItem(item);
1695 for (int i = current.Count()-1; i >= 0; i--) {
1696 #if wxCHECK_VERSION(2, 6, 0)
1697 wxTreeItemIdValue cookie;
1701 wxTreeItemId currentChild = tree->GetFirstChild(item, cookie);
1705 while (currentChild.IsOk()) {
1706 if (((wxbTreeItemData*)tree->GetItemData(currentChild))->GetName() == current[i]) {
1707 item = currentChild;
1712 currentChild = tree->GetNextChild(item, cookie);
1718 UpdateTreeItem(item, true, false); /* Update the list */
1720 tree->SelectItem(item);
1723 void wxbRestorePanel::RefreshList() {
1724 if (currentTreeItem.IsOk()) {
1725 UpdateTreeItem(currentTreeItem, true, false); /* Update the list */
1729 /* Update first config, adapting settings to the job name selected */
1730 void wxbRestorePanel::UpdateFirstConfig() {
1731 configPanel->Enable(false);
1732 wxbDataTokenizer* dt = wxbUtils::WaitForEnd(wxString(wxT(".defaults job=")) + configPanel->GetRowString(_("Job Name")) + wxT("\n"), true, false);
1738 * where=/tmp/bacula-restores
1741 * fileset=Full Set */
1747 bool dolistjobs = false;
1749 for (i = 0; i < dt->GetCount(); i++) {
1751 if ((j = str.Find('=')) > -1) {
1752 name = str.Mid(0, j);
1753 if (name == wxT("pool")) {
1754 configPanel->SetRowString(_("Pool"), str.Mid(j+1));
1756 else if (name == wxT("client")) {
1758 if ((str != configPanel->GetRowString(_("Client"))) ||
1759 (configPanel->GetRowString(_("Before"))) == wxT("")) {
1760 configPanel->SetRowString(_("Client"), str);
1764 else if (name == wxT("storage")) {
1765 configPanel->SetRowString(_("Storage"), str.Mid(j+1));
1767 else if (name == wxT("fileset")) {
1768 configPanel->SetRowString(_("Fileset"), str.Mid(j+1));
1776 //wxTheApp->Yield(false);
1779 configPanel->Enable(true);
1783 * Update second config.
1786 * JobName: RestoreFiles
1787 * Bootstrap: /var/lib/bacula/restore.bsr
1788 * Where: /tmp/bacula-restores
1793 * When: 2004-04-18 01:18:56
1795 * OK to run? (yes/mod/no):
1798 bool wxbRestorePanel::UpdateSecondConfig(wxbDataTokenizer* dt) {
1800 for (i = 0; i < dt->GetCount(); i++) {
1801 if ((*dt)[i].Find(_("Run Restore job")) == 0)
1805 if ((i + 10) > dt->GetCount()) {
1811 if ((k = (*dt)[++i].Find(_("JobName:"))) != 0) return false;
1812 restorePanel->SetRowString(_("Job Name"), (*dt)[i].Mid(10).Trim(false).RemoveLast());
1813 if ((k = (*dt)[++i].Find(_("Bootstrap:"))) != 0) return false;
1814 restorePanel->SetRowString(_("Bootstrap"), (*dt)[i].Mid(10).Trim(false).RemoveLast());
1815 if ((k = (*dt)[++i].Find(_("Where:"))) != 0) return false;
1816 restorePanel->SetRowString(_("Where"), (*dt)[i].Mid(10).Trim(false).RemoveLast());
1818 if ((k = (*dt)[++i].Find(_("Replace:"))) != 0) return false;
1819 wxString str = (*dt)[i].Mid(10).Trim(false).RemoveLast();
1820 if (str == _("always")) restorePanel->SetRowSelection(_("Replace"), 0);
1821 else if (str == _("ifnewer")) restorePanel->SetRowSelection(_("Replace"), 1);
1822 else if (str == _("ifolder")) restorePanel->SetRowSelection(_("Replace"), 2);
1823 else if (str == _("never")) restorePanel->SetRowSelection(_("Replace"), 3);
1824 else restorePanel->SetRowSelection(_("Replace"), 0);
1826 if ((k = (*dt)[++i].Find(_("FileSet:"))) != 0) return false;
1827 restorePanel->SetRowString(_("Fileset"), (*dt)[i].Mid(10).Trim(false).RemoveLast());
1828 if ((k = (*dt)[++i].Find(_("Client:"))) != 0) return false;
1829 restorePanel->SetRowString(_("Client"), (*dt)[i].Mid(10).Trim(false).RemoveLast());
1830 if ((k = (*dt)[++i].Find(_("Storage:"))) != 0) return false;
1831 restorePanel->SetRowString(_("Storage"), (*dt)[i].Mid(10).Trim(false).RemoveLast());
1832 if ((k = (*dt)[++i].Find(_("When:"))) != 0) return false;
1833 restorePanel->SetRowString(_("When"), (*dt)[i].Mid(10).Trim(false).RemoveLast());
1834 if ((k = (*dt)[++i].Find(_("Priority:"))) != 0) return false;
1835 restorePanel->SetRowString(_("Priority"), (*dt)[i].Mid(10).Trim(false).RemoveLast());
1838 restorePanel->Layout();
1843 /*----------------------------------------------------------------------------
1845 ----------------------------------------------------------------------------*/
1847 /* Set current status by enabling/disabling components */
1848 void wxbRestorePanel::SetStatus(status_enum newstatus) {
1849 switch (newstatus) {
1851 centerSizer->Remove(configPanel);
1852 centerSizer->Remove(restorePanel);
1853 centerSizer->Remove(treelistPanel);
1854 treelistPanel->Show(false);
1855 restorePanel->Show(false);
1856 centerSizer->Add(configPanel, 1, wxEXPAND);
1857 configPanel->Show(true);
1858 configPanel->Layout();
1859 centerSizer->Layout();
1861 start->SetLabel(_("Enter restore mode"));
1862 start->Enable(false);
1863 configPanel->Enable(false);
1864 tree->Enable(false);
1865 list->Enable(false);
1866 gauge->Enable(false);
1867 cancel->Enable(false);
1872 centerSizer->Remove(configPanel);
1873 centerSizer->Remove(restorePanel);
1874 centerSizer->Remove(treelistPanel);
1875 treelistPanel->Show(false);
1876 restorePanel->Show(false);
1877 centerSizer->Add(configPanel, 1, wxEXPAND);
1878 configPanel->Show(true);
1879 configPanel->Layout();
1880 centerSizer->Layout();
1882 tree->DeleteAllItems();
1883 list->DeleteAllItems();
1884 configPanel->ClearRowChoices(_("Client"));
1885 configPanel->ClearRowChoices(_("Before"));
1886 wxbMainFrame::GetInstance()->EnablePanels();
1887 newstatus = activable;
1890 start->SetLabel(_("Enter restore mode"));
1891 start->Enable(true);
1892 configPanel->Enable(false);
1893 tree->Enable(false);
1894 list->Enable(false);
1895 gauge->Enable(false);
1896 cancel->Enable(false);
1900 wxbMainFrame::GetInstance()->DisablePanels(this);
1902 start->Enable(false);
1903 //start->SetLabel(_("Choose files to restore"));
1904 configPanel->Enable(true);
1905 tree->Enable(false);
1906 list->Enable(false);
1907 cancel->Enable(true);
1914 start->Enable(true);
1915 start->SetLabel(_("Restore"));
1916 centerSizer->Remove(configPanel);
1917 configPanel->Show(false);
1918 centerSizer->Add(treelistPanel, 1, wxEXPAND);
1919 treelistPanel->Show(true);
1920 treelistPanel->Layout();
1921 centerSizer->Layout();
1928 start->Enable(false);
1929 configPanel->Enable(false);
1930 tree->Enable(false);
1931 list->Enable(false);
1932 centerSizer->Remove(treelistPanel);
1933 treelistPanel->Show(false);
1934 centerSizer->Add(restorePanel, 1, wxEXPAND);
1935 restorePanel->Show(true);
1936 restorePanel->Layout();
1937 centerSizer->Layout();
1939 restorePanel->EnableApply(false);
1942 start->SetLabel(_("Restoring..."));
1943 gauge->Enable(true);
1945 start->Enable(false);
1946 configPanel->Enable(false);
1947 tree->Enable(false);
1948 list->Enable(false);
1955 /*----------------------------------------------------------------------------
1957 ----------------------------------------------------------------------------*/
1959 void wxbRestorePanel::SetWorking(bool working) {
1960 this->working = working;
1962 SetCursor(*wxHOURGLASS_CURSOR);
1963 // SetEvtHandlerEnabled(false); //EVTQUEUE
1965 // else if (!processing) { /* Empty event queue if we aren't already doing this */ //EVTQUEUE
1967 // processing = true; //EVTQUEUE
1968 SetCursor(*wxSTANDARD_CURSOR);
1969 // SetEvtHandlerEnabled(true); //EVTQUEUE
1970 /* wxNode *node = pendingEvents->First(); //EVTQUEUE
1972 wxEvent *event = (wxEvent *)node->Data();
1975 wxEvtHandler::ProcessEvent(*event);
1978 node = pendingEvents->First();
1980 processing = false;*/
1984 bool wxbRestorePanel::IsWorking() {
1985 return this->working;
1988 void wxbRestorePanel::EnableConfig(bool enable) {
1989 restorePanel->Enable(enable);
1992 /*----------------------------------------------------------------------------
1994 ----------------------------------------------------------------------------*/
1999 bool wxbRestorePanel::ProcessEvent(wxEvent& event) {
2000 if (IsWorking() || processing) {
2001 wxEvent *eventCopy = event.Clone();
2003 pendingEvents->Append(eventCopy);
2007 return wxEvtHandler::ProcessEvent(event);
2012 void wxbRestorePanel::OnCancel(wxCommandEvent& event) {
2013 cancel->Enable(false);
2014 SetCursor(*wxHOURGLASS_CURSOR);
2016 SetCursor(*wxSTANDARD_CURSOR);
2019 void wxbRestorePanel::OnStart(wxCommandEvent& event) {
2028 void wxbRestorePanel::OnTreeChanging(wxTreeEvent& event) {
2034 void wxbRestorePanel::OnTreeExpanding(wxTreeEvent& event) {
2040 //CmdList(event.GetItem());
2041 if (tree->GetSelection() != event.GetItem()) {
2042 tree->SelectItem(event.GetItem());
2047 void wxbRestorePanel::OnTreeChanged(wxTreeEvent& event) {
2051 if (currentTreeItem == event.GetItem()) {
2054 treeadd->Enable(false);
2055 treeremove->Enable(false);
2056 treerefresh->Enable(false);
2057 markWhenCommandDone = false;
2059 currentTreeItem = event.GetItem();
2060 CmdList(event.GetItem());
2061 if (markWhenCommandDone) {
2062 CmdMark(event.GetItem(), NULL, 0);
2066 if (event.GetItem().IsOk()) {
2067 int status = ((wxbTreeItemData*)tree->GetItemData(event.GetItem()))->GetMarked();
2068 treeadd->Enable(status != 1);
2069 treeremove->Enable(status != 0);
2071 treerefresh->Enable(true);
2074 void wxbRestorePanel::OnTreeMarked(wxbTreeMarkedEvent& event) {
2076 if (tree->GetSelection() == event.GetItem()) {
2077 markWhenCommandDone = !markWhenCommandDone;
2082 markWhenCommandDone = false;
2083 CmdMark(event.GetItem(), NULL, 0);
2084 if (markWhenCommandDone) {
2085 CmdMark(event.GetItem(), NULL, 0);
2090 if (event.GetItem().IsOk()) {
2091 int status = ((wxbTreeItemData*)tree->GetItemData(event.GetItem()))->GetMarked();
2092 treeadd->Enable(status != 1);
2093 treeremove->Enable(status != 0);
2097 void wxbRestorePanel::OnTreeAdd(wxCommandEvent& event) {
2102 if (currentTreeItem.IsOk()) {
2104 CmdMark(currentTreeItem, NULL, 0, 1);
2107 treeremove->Enable(1);
2112 void wxbRestorePanel::OnTreeRemove(wxCommandEvent& event) {
2117 if (currentTreeItem.IsOk()) {
2119 CmdMark(currentTreeItem, NULL, 0, 0);
2122 treeremove->Enable(0);
2127 void wxbRestorePanel::OnTreeRefresh(wxCommandEvent& event) {
2137 void wxbRestorePanel::OnListMarked(wxbListMarkedEvent& event) {
2142 if (list->GetSelectedItemCount() == 0) {
2148 long* items = new long[list->GetSelectedItemCount()];
2152 long item = list->GetNextItem(-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
2153 while (item != -1) {
2156 item = list->GetNextItem(item, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
2159 CmdMark(wxTreeItemId(), items, num);
2163 wxListEvent listevt;
2165 OnListChanged(listevt);
2172 void wxbRestorePanel::OnListActivated(wxListEvent& event) {
2177 long item = event.GetIndex();
2178 // long item = list->GetNextItem(-1, wxLIST_NEXT_ALL, wxLIST_STATE_FOCUSED);
2180 wxbTreeItemData* itemdata = (wxbTreeItemData*)list->GetItemData(item);
2181 wxString name = itemdata->GetName();
2186 #if wxCHECK_VERSION(2, 6, 0)
2187 wxTreeItemIdValue cookie;
2192 if (name.GetChar(name.Length()-1) == '/') {
2193 wxTreeItemId currentChild = tree->GetFirstChild(currentTreeItem, cookie);
2195 while (currentChild.IsOk()) {
2196 wxString name2 = ((wxbTreeItemData*)tree->GetItemData(currentChild))->GetName();
2197 if (name2 == name) {
2198 //tree->UnselectAll();
2200 tree->Expand(currentTreeItem);
2201 tree->SelectItem(currentChild);
2205 currentChild = tree->GetNextChild(currentTreeItem, cookie);
2212 void wxbRestorePanel::OnListChanged(wxListEvent& event) {
2217 listadd->Enable(false);
2218 listremove->Enable(false);
2220 bool marked = false;
2221 bool unmarked = false;
2223 long item = list->GetNextItem(-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
2224 while (item != -1) {
2225 switch (((wxbTreeItemData*)list->GetItemData(item))->GetMarked()) {
2238 // Should never happen
2240 if (marked && unmarked) break;
2241 item = list->GetNextItem(item, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
2244 listadd->Enable(unmarked);
2245 listremove->Enable(marked);
2248 void wxbRestorePanel::OnListAdd(wxCommandEvent& event) {
2255 long* items = new long[list->GetSelectedItemCount()];
2259 long item = list->GetNextItem(-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
2260 while (item != -1) {
2263 item = list->GetNextItem(item, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
2266 CmdMark(wxTreeItemId(), items, num, 1);
2273 listadd->Enable(false);
2274 listremove->Enable(true);
2277 void wxbRestorePanel::OnListRemove(wxCommandEvent& event) {
2284 long* items = new long[list->GetSelectedItemCount()];
2288 long item = list->GetNextItem(-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
2289 while (item != -1) {
2292 item = list->GetNextItem(item, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
2295 CmdMark(wxTreeItemId(), items, num, 0);
2302 listadd->Enable(true);
2303 listremove->Enable(false);
2306 void wxbRestorePanel::OnListRefresh(wxCommandEvent& event) {
2316 void wxbRestorePanel::OnConfigUpdated(wxCommandEvent& event) {
2317 if (status == entered) {
2318 if (event.GetId() == ConfigJobName) {
2323 UpdateFirstConfig();
2326 else if (event.GetId() == ConfigClient) {
2331 configPanel->Enable(false);
2333 configPanel->Enable(true);
2336 cfgUpdated = cfgUpdated | (1 << event.GetId());
2338 else if (status == configuring) {
2339 restorePanel->EnableApply(true);
2340 cfgUpdated = cfgUpdated | (1 << event.GetId());
2344 void wxbRestorePanel::OnConfigOk(wxCommandEvent& WXUNUSED(event)) {
2345 if (status != configuring) return;
2354 void wxbRestorePanel::OnConfigApply(wxCommandEvent& WXUNUSED(event)) {
2355 if (status != configuring) return;
2361 if (cfgUpdated == 0) {
2362 restorePanel->EnableApply(false);
2367 void wxbRestorePanel::OnConfigCancel(wxCommandEvent& WXUNUSED(event)) {
2368 if (status != configuring) return;