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);
86 void SetMarked(int marked);
90 wxString* path; /* Full path */
91 wxString* name; /* File name */
92 int marked; /* 0 - Not Marked, 1 - Marked, 2 - Some file under is marked */
93 long listid; /* list ID : >-1 if this data is in the list (and/or on the tree) */
96 wxbTreeItemData::wxbTreeItemData(wxString path, wxString name, int marked, long listid): wxTreeItemData() {
97 this->path = new wxString(path);
98 this->name = new wxString(name);
99 this->marked = marked;
100 this->listid = listid;
103 wxbTreeItemData::~wxbTreeItemData() {
108 int wxbTreeItemData::GetMarked() {
112 void wxbTreeItemData::SetMarked(int marked) {
113 this->marked = marked;
116 long wxbTreeItemData::GetListId() {
120 wxString wxbTreeItemData::GetPath() {
124 wxString wxbTreeItemData::GetName() {
128 // ----------------------------------------------------------------------------
129 // event tables and other macros for wxWindows
130 // ----------------------------------------------------------------------------
158 BEGIN_EVENT_TABLE(wxbRestorePanel, wxPanel)
159 EVT_BUTTON(RestoreStart, wxbRestorePanel::OnStart)
160 EVT_BUTTON(RestoreCancel, wxbRestorePanel::OnCancel)
162 EVT_TREE_SEL_CHANGING(TreeCtrl, wxbRestorePanel::OnTreeChanging)
163 EVT_TREE_SEL_CHANGED(TreeCtrl, wxbRestorePanel::OnTreeChanged)
164 EVT_TREE_ITEM_EXPANDING(TreeCtrl, wxbRestorePanel::OnTreeExpanding)
165 EVT_TREE_MARKED_EVENT(TreeCtrl, wxbRestorePanel::OnTreeMarked)
166 EVT_BUTTON(TreeAdd, wxbRestorePanel::OnTreeAdd)
167 EVT_BUTTON(TreeRemove, wxbRestorePanel::OnTreeRemove)
168 EVT_BUTTON(TreeRefresh, wxbRestorePanel::OnTreeRefresh)
170 EVT_LIST_ITEM_ACTIVATED(ListCtrl, wxbRestorePanel::OnListActivated)
171 EVT_LIST_MARKED_EVENT(ListCtrl, wxbRestorePanel::OnListMarked)
172 EVT_LIST_ITEM_SELECTED(ListCtrl, wxbRestorePanel::OnListChanged)
173 EVT_LIST_ITEM_DESELECTED(ListCtrl, wxbRestorePanel::OnListChanged)
174 EVT_BUTTON(ListAdd, wxbRestorePanel::OnListAdd)
175 EVT_BUTTON(ListRemove, wxbRestorePanel::OnListRemove)
176 EVT_BUTTON(ListRefresh, wxbRestorePanel::OnListRefresh)
178 EVT_TEXT(ConfigWhere, wxbRestorePanel::OnConfigUpdated)
179 EVT_TEXT(ConfigWhen, wxbRestorePanel::OnConfigUpdated)
180 EVT_TEXT(ConfigPriority, wxbRestorePanel::OnConfigUpdated)
181 EVT_CHOICE(ConfigWhen, wxbRestorePanel::OnConfigUpdated)
182 EVT_CHOICE(ConfigReplace, wxbRestorePanel::OnConfigUpdated)
183 EVT_CHOICE(ConfigClient, wxbRestorePanel::OnConfigUpdated)
184 EVT_CHOICE(ConfigFileset, wxbRestorePanel::OnConfigUpdated)
185 EVT_CHOICE(ConfigStorage, wxbRestorePanel::OnConfigUpdated)
186 EVT_CHOICE(ConfigJobName, wxbRestorePanel::OnConfigUpdated)
187 EVT_CHOICE(ConfigPool, wxbRestorePanel::OnConfigUpdated)
189 EVT_BUTTON(ConfigOk, wxbRestorePanel::OnConfigOk)
190 EVT_BUTTON(ConfigApply, wxbRestorePanel::OnConfigApply)
191 EVT_BUTTON(ConfigCancel, wxbRestorePanel::OnConfigCancel)
195 * wxbRestorePanel constructor
197 wxbRestorePanel::wxbRestorePanel(wxWindow* parent): wxbPanel(parent) {
198 //pendingEvents = new wxbEventList(); //EVTQUEUE
199 //processing = false; //EVTQUEUE
202 imagelist = new wxImageList(16, 16, TRUE, 3);
203 imagelist->Add(wxIcon(unmarked_xpm));
204 imagelist->Add(wxIcon(marked_xpm));
205 imagelist->Add(wxIcon(partmarked_xpm));
207 wxFlexGridSizer* mainSizer = new wxFlexGridSizer(3, 1, 10, 10);
208 mainSizer->AddGrowableCol(0);
209 mainSizer->AddGrowableRow(1);
211 wxFlexGridSizer *firstSizer = new wxFlexGridSizer(1, 2, 10, 10);
213 firstSizer->AddGrowableCol(0);
214 firstSizer->AddGrowableRow(0);
216 start = new wxButton(this, RestoreStart, _("Enter restore mode"), wxDefaultPosition, wxSize(150, 30));
217 firstSizer->Add(start, 0, wxALIGN_CENTER_HORIZONTAL | wxALIGN_CENTER_VERTICAL, 10);
219 cancel = new wxButton(this, RestoreCancel, _("Cancel restore"), wxDefaultPosition, wxSize(150, 30));
220 firstSizer->Add(cancel, 0, wxALIGN_CENTER_HORIZONTAL | wxALIGN_RIGHT, 10);
224 /* clientChoice = new wxChoice(this, ClientChoice, wxDefaultPosition, wxSize(150, 30), 0, elist);
225 firstSizer->Add(clientChoice, 1, wxALIGN_CENTER_HORIZONTAL | wxALIGN_CENTER_VERTICAL, 10);
227 jobChoice = new wxChoice(this, -1, wxDefaultPosition, wxSize(150, 30), 0, elist);
228 firstSizer->Add(jobChoice, 1, wxALIGN_CENTER_HORIZONTAL | wxALIGN_CENTER_VERTICAL, 10);*/
230 mainSizer->Add(firstSizer, 1, wxEXPAND, 10);
232 treelistPanel = new wxSplitterWindow(this);
234 wxPanel* treePanel = new wxPanel(treelistPanel);
235 wxFlexGridSizer *treeSizer = new wxFlexGridSizer(2, 1, 0, 0);
236 treeSizer->AddGrowableCol(0);
237 treeSizer->AddGrowableRow(0);
239 tree = new wxbTreeCtrl(treePanel, this, TreeCtrl, wxDefaultPosition, wxSize(200,50));
240 tree->SetImageList(imagelist);
242 treeSizer->Add(tree, 1, wxEXPAND, 0);
244 wxBoxSizer *treeCtrlSizer = new wxBoxSizer(wxHORIZONTAL);
245 treeadd = new wxButton(treePanel, TreeAdd, _("Add"), wxDefaultPosition, wxSize(60, 25));
246 treeCtrlSizer->Add(treeadd, 0, wxLEFT | wxRIGHT, 3);
247 treeremove = new wxButton(treePanel, TreeRemove, _("Remove"), wxDefaultPosition, wxSize(60, 25));
248 treeCtrlSizer->Add(treeremove, 0, wxLEFT | wxRIGHT, 3);
249 treerefresh = new wxButton(treePanel, TreeRefresh, _("Refresh"), wxDefaultPosition, wxSize(60, 25));
250 treeCtrlSizer->Add(treerefresh, 0, wxLEFT | wxRIGHT, 3);
252 treeSizer->Add(treeCtrlSizer, 1, wxALIGN_CENTER_HORIZONTAL, 0);
254 treePanel->SetSizer(treeSizer);
256 wxPanel* listPanel = new wxPanel(treelistPanel);
257 wxFlexGridSizer *listSizer = new wxFlexGridSizer(2, 1, 0, 0);
258 listSizer->AddGrowableCol(0);
259 listSizer->AddGrowableRow(0);
261 list = new wxbListCtrl(listPanel, this, ListCtrl, wxDefaultPosition, wxSize(200,50));
262 //treelistSizer->Add(list, 1, wxEXPAND, 10);
264 list->SetImageList(imagelist, wxIMAGE_LIST_SMALL);
267 info.SetMask(wxLIST_MASK_TEXT | wxLIST_MASK_FORMAT);
268 info.SetText(_("M"));
269 info.SetAlign(wxLIST_FORMAT_CENTER);
270 list->InsertColumn(0, info);
272 info.SetText(_("Filename"));
273 info.SetAlign(wxLIST_FORMAT_LEFT);
274 list->InsertColumn(1, info);
276 info.SetText(_("Size"));
277 info.SetAlign(wxLIST_FORMAT_RIGHT);
278 list->InsertColumn(2, info);
280 info.SetText(_("Date"));
281 info.SetAlign(wxLIST_FORMAT_LEFT);
282 list->InsertColumn(3, info);
284 info.SetText(_("Perm."));
285 info.SetAlign(wxLIST_FORMAT_LEFT);
286 list->InsertColumn(4, info);
288 info.SetText(_("User"));
289 info.SetAlign(wxLIST_FORMAT_RIGHT);
290 list->InsertColumn(5, info);
292 info.SetText(_("Group"));
293 info.SetAlign(wxLIST_FORMAT_RIGHT);
294 list->InsertColumn(6, info);
296 listSizer->Add(list, 1, wxEXPAND, 0);
298 wxBoxSizer *listCtrlSizer = new wxBoxSizer(wxHORIZONTAL);
299 listadd = new wxButton(listPanel, ListAdd, _("Add"), wxDefaultPosition, wxSize(60, 25));
300 listCtrlSizer->Add(listadd, 0, wxLEFT | wxRIGHT, 5);
301 listremove = new wxButton(listPanel, ListRemove, _("Remove"), wxDefaultPosition, wxSize(60, 25));
302 listCtrlSizer->Add(listremove, 0, wxLEFT | wxRIGHT, 5);
303 listrefresh = new wxButton(listPanel, ListRefresh, _("Refresh"), wxDefaultPosition, wxSize(60, 25));
304 listCtrlSizer->Add(listrefresh, 0, wxLEFT | wxRIGHT, 5);
306 listSizer->Add(listCtrlSizer, 1, wxALIGN_CENTER_HORIZONTAL, 0);
308 listPanel->SetSizer(listSizer);
310 treelistPanel->SplitVertically(treePanel, listPanel, 210);
312 treelistPanel->SetMinimumPaneSize(210);
314 treelistPanel->Show(false);
316 wxbConfig* config = new wxbConfig();
317 config->Add(new wxbConfigParam(_("Job Name"), ConfigJobName, choice, 0, elist));
318 config->Add(new wxbConfigParam(_("Client"), ConfigClient, choice, 0, elist));
319 config->Add(new wxbConfigParam(_("Fileset"), ConfigFileset, choice, 0, elist));
320 config->Add(new wxbConfigParam(_("Pool"), ConfigPool, choice, 0, elist));
321 config->Add(new wxbConfigParam(_("Storage"), ConfigStorage, choice, 0, elist));
322 config->Add(new wxbConfigParam(_("Before"), ConfigWhen, choice, 0, elist));
324 configPanel = new wxbConfigPanel(this, config, _("Please configure parameters concerning files to restore :"), RestoreStart, RestoreCancel, -1);
326 configPanel->Show(true);
327 configPanel->Enable(false);
329 config = new wxbConfig();
330 config->Add(new wxbConfigParam(_("Job Name"), -1, text, wxT("")));
331 config->Add(new wxbConfigParam(_("Bootstrap"), -1, text, wxT("")));
332 config->Add(new wxbConfigParam(_("Where"), ConfigWhere, modifiableText, wxT("")));
333 wxString erlist[] = {_("always"), _("if newer"), _("if older"), _("never")};
334 config->Add(new wxbConfigParam(_("Replace"), ConfigReplace, choice, 4, erlist));
335 config->Add(new wxbConfigParam(_("Fileset"), ConfigFileset, choice, 0, erlist));
336 config->Add(new wxbConfigParam(_("Client"), ConfigClient, choice, 0, erlist));
337 config->Add(new wxbConfigParam(_("Storage"), ConfigStorage, choice, 0, erlist));
338 config->Add(new wxbConfigParam(_("When"), ConfigWhen, modifiableText, wxT("")));
339 config->Add(new wxbConfigParam(_("Priority"), ConfigPriority, modifiableText, wxT("")));
341 restorePanel = new wxbConfigPanel(this, config, _("Please configure parameters concerning files restoration :"), ConfigOk, ConfigCancel, ConfigApply);
343 restorePanel->Show(false);
345 centerSizer = new wxBoxSizer(wxHORIZONTAL);
346 //centerSizer->Add(treelistPanel, 1, wxEXPAND | wxADJUST_MINSIZE);
348 mainSizer->Add(centerSizer, 1, wxEXPAND, 10);
350 gauge = new wxGauge(this, -1, 1, wxDefaultPosition, wxSize(200,20));
352 mainSizer->Add(gauge, 1, wxEXPAND, 5);
354 gauge->Enable(false);
357 mainSizer->SetSizeHints(this);
361 for (int i = 0; i < 7; i++) {
362 list->SetColumnWidth(i, 70);
365 SetCursor(*wxSTANDARD_CURSOR);
367 markWhenCommandDone = false;
373 * wxbRestorePanel destructor
375 wxbRestorePanel::~wxbRestorePanel() {
379 /*----------------------------------------------------------------------------
380 wxbPanel overloadings
381 ----------------------------------------------------------------------------*/
383 wxString wxbRestorePanel::GetTitle() {
387 void wxbRestorePanel::EnablePanel(bool enable) {
389 if (status == disabled) {
390 SetStatus(activable);
398 /*----------------------------------------------------------------------------
399 Commands called by events handler
400 ----------------------------------------------------------------------------*/
402 /* The main button has been clicked */
403 void wxbRestorePanel::CmdStart() {
405 if (status == activable) {
406 wxbMainFrame::GetInstance()->SetStatusText(_("Getting parameters list."));
407 wxbDataTokenizer* dt = wxbUtils::WaitForEnd(wxT(".clients\n"), true, false);
410 configPanel->ClearRowChoices(_("Client"));
411 restorePanel->ClearRowChoices(_("Client"));
413 if (dt->GetCount() == 0) {
414 wxbMainFrame::GetInstance()->SetStatusText(_("Error : no clients returned by the director."));
418 for (i = 0; i < dt->GetCount(); i++) {
421 configPanel->AddRowChoice(_("Client"), str);
422 restorePanel->AddRowChoice(_("Client"), str);
432 dt = wxbUtils::WaitForEnd(wxT(".filesets\n"), true, false);
434 configPanel->ClearRowChoices(_("Fileset"));
435 restorePanel->ClearRowChoices(_("Fileset"));
437 if (dt->GetCount() == 0) {
438 wxbMainFrame::GetInstance()->SetStatusText(_("Error : no filesets returned by the director."));
442 for (i = 0; i < dt->GetCount(); i++) {
445 configPanel->AddRowChoice(_("Fileset"), str);
446 restorePanel->AddRowChoice(_("Fileset"), str);
456 dt = wxbUtils::WaitForEnd(wxT(".storage\n"), true, false);
458 configPanel->ClearRowChoices(_("Storage"));
459 restorePanel->ClearRowChoices(_("Storage"));
461 if (dt->GetCount() == 0) {
462 wxbMainFrame::GetInstance()->SetStatusText(_("Error : no storage returned by the director."));
466 for (i = 0; i < dt->GetCount(); i++) {
469 configPanel->AddRowChoice(_("Storage"), str);
470 restorePanel->AddRowChoice(_("Storage"), str);
480 dt = wxbUtils::WaitForEnd(wxT(".jobs\n"), true, false);
482 configPanel->ClearRowChoices(_("Job Name"));
484 if (dt->GetCount() == 0) {
485 wxbMainFrame::GetInstance()->SetStatusText(_("Error : no jobs returned by the director."));
489 for (i = 0; i < dt->GetCount(); i++) {
492 configPanel->AddRowChoice(_("Job Name"), str);
495 configPanel->SetRowString(_("Job Name"), _("RestoreFiles"));
504 dt = wxbUtils::WaitForEnd(wxT(".pools\n"), true, false);
506 configPanel->ClearRowChoices(_("Pool"));
508 if (dt->GetCount() == 0) {
509 wxbMainFrame::GetInstance()->SetStatusText(_("Error : no jobs returned by the director."));
513 for (i = 0; i < dt->GetCount(); i++) {
516 configPanel->AddRowChoice(_("Pool"), str);
530 wxbMainFrame::GetInstance()->SetStatusText(_("Please configure your restore parameters."));
532 else if (status == entered) {
533 /* if (clientChoice->GetStringSelection().Length() < 1) {
534 wxbMainFrame::GetInstance()->SetStatusText(_("Please select a client."));
537 if (jobChoice->GetStringSelection().Length() < 1) {
538 wxbMainFrame::GetInstance()->SetStatusText(_("Please select a restore date."));
541 wxbMainFrame::GetInstance()->SetStatusText(_("Building restore tree..."));
545 wxbTableParser* tableparser = new wxbTableParser();
546 wxbDataTokenizer* dt = new wxbDataTokenizer(false);
549 * The following line was removed from ::GetInstance below because
550 * it does not work with multiple pools -- KES 5Oct05 see bug #433
551 * wxT("\" pool=\"") << configPanel->GetRowString(wxT("Pool")) <<
553 wxbMainFrame::GetInstance()->Send(wxString(wxT("restore")) <<
554 wxT(" client=\"") << configPanel->GetRowString(wxT("Client")) <<
555 wxT("\" fileset=\"") << configPanel->GetRowString(wxT("Fileset")) <<
556 wxT("\" storage=\"") << configPanel->GetRowString(wxT("Storage")) <<
557 wxT("\" before=\"") << configPanel->GetRowString(wxT("Before")) <<
559 //wxbUtils::WaitForPrompt("6\n");
561 /*wxbPromptParser *pp = wxbUtils::WaitForPrompt(wxString() << configPanel->GetRowString(wxT("Before")) << "\n", true);
562 int client = pp->getChoices()->Index(configPanel->GetRowString(wxT("Client")));
563 if (client == wxNOT_FOUND) {
564 wxbMainFrame::GetInstance()->SetStatusText("Failed to find the selected client.");
569 //wxbMainFrame::GetInstance()->Send(wxString() << configPanel->GetRowString(wxT("Before")) << "\n");
571 while (!tableparser->hasFinished() && !dt->hasFinished()) {
572 wxTheApp->Yield(true);
573 wxbUtils::MilliSleep(100);
578 if (dt->hasFinished() && !tableparser->hasFinished()) {
580 if (dt->GetCount() > 1) {
581 str = (*dt)[dt->GetCount()-2];
584 wxbMainFrame::GetInstance()->SetStatusText(wxString(_("Error while starting restore: ")) << str);
594 for (i = 0; i < tableparser->GetCount(); i++) {
595 str = (*tableparser)[i][2];
596 str.Replace(wxT(","), wxT(""));
597 if (str.ToLong(&l)) {
603 gauge->SetRange(tot);
605 /*wxbMainFrame::GetInstance()->Print(
606 wxString("[") << tot << "]", CS_DEBUG);*/
608 wxDateTime base = wxDateTime::Now();
612 unsigned int lastindex = 0;
619 newdate = wxDateTime::Now();
620 if (newdate.Subtract(base).GetMilliseconds() > 10 ) {
622 for (; lastindex < dt->GetCount(); lastindex++) {
623 if (((i1 = (*dt)[lastindex].Find(wxT("Building directory tree for JobId "))) >= 0) &&
624 ((i2 = (*dt)[lastindex].Find(wxT(" ..."))) > 0)) {
625 str = (*dt)[lastindex].Mid(i1+34, i2-(i1+34));
626 for (i = 0; i < tableparser->GetCount(); i++) {
627 if (str == (*tableparser)[i][0]) {
628 str = (*tableparser)[i][2];
629 str.Replace(wxT(","), wxT(""));
630 if (str.ToLong(&l)) {
633 var = (willdo-done)/50;
634 gauge->SetValue(done);
635 wxTheApp->Yield(true);
641 else if ((*dt)[lastindex] == wxT("+")) {
642 gauge->SetValue(gauge->GetValue()+var);
643 wxTheApp->Yield(true);
648 if (dt->hasFinished()) {
652 wxTheApp->Yield(true);
653 wxbUtils::MilliSleep(1);
656 gauge->SetValue(tot);
657 wxTheApp->Yield(true);
668 wxbUtils::WaitForEnd(wxT("unmark *\n"));
669 wxTreeItemId root = tree->AddRoot(configPanel->GetRowString(_("Client")), -1, -1, new wxbTreeItemData(wxT("/"), configPanel->GetRowString(_("Client")), 0));
670 currentTreeItem = root;
672 tree->SelectItem(root);
674 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."));
677 else if (status == choosing) {
681 wxbDataTokenizer* dt;
685 dt = new wxbDataTokenizer(true);
686 wxbPromptParser* promptparser = wxbUtils::WaitForPrompt(wxT("done\n"), true);
688 while (!promptparser->getChoices() || (promptparser->getChoices()->Index(wxT("mod")) < 0)) {
689 wxbMainFrame::GetInstance()->Print(_("Unexpected question has been received.\n"), CS_DEBUG);
692 if (promptparser->getIntroString() != wxT("")) {
693 message << promptparser->getIntroString() << wxT("\n");
695 message << promptparser->getQuestionString();
697 if (promptparser->getChoices()) {
698 wxString *choices = new wxString[promptparser->getChoices()->GetCount()];
699 int *numbers = new int[promptparser->getChoices()->GetCount()];
702 for (unsigned int i = 0; i < promptparser->getChoices()->GetCount(); i++) {
703 if ((*promptparser->getChoices())[i] != wxT("")) {
704 choices[n] = (*promptparser->getChoices())[i];
710 int res = ::wxGetSingleChoiceIndex(message,
711 _("wx-console: unexpected restore question."), n, choices, this);
714 promptparser = wxbUtils::WaitForPrompt(wxT(".\n"), true);
717 if (promptparser->isNumericalChoice()) {
719 promptparser = wxbUtils::WaitForPrompt(wxString() << numbers[res] << wxT("\n"), true);
723 promptparser = wxbUtils::WaitForPrompt(wxString() << choices[res] << wxT("\n"), true);
732 promptparser = wxbUtils::WaitForPrompt(::wxGetTextFromUser(message,
733 _("wx-console: unexpected restore question."),
734 wxT(""), this) + wxT("\n"));
737 printf("promptparser->getChoices()=%ld", (long)promptparser->getChoices());
741 SetStatus(configuring);
743 for (i = 0; i < dt->GetCount(); i++) {
744 if ((j = (*dt)[i].Find(_(" files selected to be restored."))) > -1) {
745 (*dt)[i].Mid(0, j).ToLong(&totfilemessages);
749 if ((j = (*dt)[i].Find(_(" file selected to be restored."))) > -1) {
750 (*dt)[i].Mid(0, j).ToLong(&totfilemessages);
755 wxbMainFrame::GetInstance()->SetStatusText(
756 wxString::Format(_("Please configure your restore (%ld files selected to be restored)..."), totfilemessages));
758 UpdateSecondConfig(dt);
763 restorePanel->EnableApply(false);
765 if (totfilemessages == 0) {
766 wxbMainFrame::GetInstance()->Print(_("Restore failed : no file selected.\n"), CS_DEBUG);
767 wxbMainFrame::GetInstance()->SetStatusText(_("Restore failed : no file selected."));
772 else if (status == configuring) {
773 cancel->Enable(false);
777 wxbMainFrame::GetInstance()->SetStatusText(_("Restoring, please wait..."));
779 wxbDataTokenizer* dt;
781 SetStatus(restoring);
782 dt = wxbUtils::WaitForEnd(wxT("yes\n"), true);
785 gauge->SetRange(totfilemessages);
789 for (i = 0; i < dt->GetCount(); i++) {
790 if ((j = (*dt)[i].Find(_("Job started. JobId="))) > -1) {
791 jobid = (*dt)[i].Mid(j+19);
792 wxbMainFrame::GetInstance()->SetStatusText(_("Restore started, jobid=") + jobid);
796 if ((j = (*dt)[i].Find(_("Job failed."))) > -1) {
797 wxbMainFrame::GetInstance()->Print(_("Restore failed, please look at messages.\n"), CS_DEBUG);
798 wxbMainFrame::GetInstance()->SetStatusText(_("Restore failed, please look at messages in console."));
803 if (jobid == wxT("")) {
804 wxbMainFrame::GetInstance()->Print(_("Failed to retrieve jobid.\n"), CS_DEBUG);
805 wxbMainFrame::GetInstance()->SetStatusText(_("Failed to retrieve jobid.\n"));
809 wxDateTime currenttime;
811 dt = wxbUtils::WaitForEnd(wxT("time\n"), true);
812 wxStringTokenizer ttkz((*dt)[0], wxT(" "), wxTOKEN_STRTOK);
813 if ((currenttime.ParseDate(ttkz.GetNextToken()) == NULL) || // Date
814 (currenttime.ParseTime(ttkz.GetNextToken()) == NULL)) { // Time
815 currenttime.SetYear(1990); // If parsing fails, set currenttime to a dummy date
818 currenttime -= wxTimeSpan::Seconds(30); //Adding a 30" tolerance
822 wxDateTime scheduledtime;
823 wxStringTokenizer stkz(restorePanel->GetRowString(_("When")), wxT(" "), wxTOKEN_STRTOK);
825 if ((scheduledtime.ParseDate(stkz.GetNextToken()) == NULL) || // Date
826 (scheduledtime.ParseTime(stkz.GetNextToken()) == NULL)) { // Time
827 scheduledtime.SetYear(2090); // If parsing fails, set scheduledtime to a dummy date
830 if (scheduledtime.Subtract(currenttime).IsLongerThan(wxTimeSpan::Seconds(150))) {
831 wxbMainFrame::GetInstance()->Print(_("Restore is scheduled in more than two minutes, wx-console will not wait for its completion.\n"), CS_DEBUG);
832 wxbMainFrame::GetInstance()->SetStatusText(_("Restore is scheduled in more than two minutes, wx-console will not wait for its completion."));
837 wxString cmd = wxString(wxT("list jobid=")) + jobid;
839 wxbTableParser* tableparser;
841 long filemessages = 0;
844 bool waitforever = false;
850 wxbUtils::WaitForEnd(wxT("autodisplay off\n"));
851 wxbUtils::WaitForEnd(wxT("gui on\n"));
853 tableparser = wxbUtils::CreateAndWaitForParser(cmd);
855 status = (*tableparser)[0][7].GetChar(0);
858 wxbMainFrame::GetInstance()->SetStatusText(_("Restore job created, but not yet running."));
862 wxbMainFrame::GetInstance()->SetStatusText(
863 wxString::Format(_("Restore job running, please wait (%ld of %ld files restored)..."), filemessages, totfilemessages));
867 wxbMainFrame::GetInstance()->SetStatusText(_("Restore job terminated successfully."));
868 wxbMainFrame::GetInstance()->Print(_("Restore job terminated successfully.\n"), CS_DEBUG);
872 case JS_ErrorTerminated:
873 wxbMainFrame::GetInstance()->SetStatusText(_("Restore job terminated in error, see messages in console."));
874 wxbMainFrame::GetInstance()->Print(_("Restore job terminated in error, see messages.\n"), CS_DEBUG);
879 wxbMainFrame::GetInstance()->SetStatusText(_("Restore job reported a non-fatal error."));
883 wxbMainFrame::GetInstance()->SetStatusText(_("Restore job reported a fatal error."));
888 wxbMainFrame::GetInstance()->SetStatusText(_("Restore job cancelled by user."));
889 wxbMainFrame::GetInstance()->Print(_("Restore job cancelled by user.\n"), CS_DEBUG);
894 wxbMainFrame::GetInstance()->SetStatusText(_("Restore job is waiting on File daemon."));
898 wxbMainFrame::GetInstance()->SetStatusText(_("Restore job is waiting for new media."));
901 case JS_WaitStoreRes:
902 wxbMainFrame::GetInstance()->SetStatusText(_("Restore job is waiting for storage resource."));
906 wxbMainFrame::GetInstance()->SetStatusText(_("Restore job is waiting for job resource."));
909 case JS_WaitClientRes:
910 wxbMainFrame::GetInstance()->SetStatusText(_("Restore job is waiting for Client resource."));
914 wxbMainFrame::GetInstance()->SetStatusText(_("Restore job is waiting for maximum jobs."));
917 case JS_WaitStartTime:
918 wxbMainFrame::GetInstance()->SetStatusText(_("Restore job is waiting for start time."));
921 case JS_WaitPriority:
922 wxbMainFrame::GetInstance()->SetStatusText(_("Restore job is waiting for higher priority jobs to finish."));
928 dt = wxbUtils::WaitForEnd(wxT(".messages\n"), true);
930 for (unsigned int i = 0; i < dt->GetCount(); i++) {
931 wxStringTokenizer tkz((*dt)[i], wxT(" "), wxTOKEN_STRTOK);
935 // Date Time name: perm ? user grp size date time
936 //04-Apr-2004 17:19 Tom-fd: -rwx------ 1 nicolas None 514967 2004-03-20 20:03:42 filename
938 if (datetime.ParseDate(tkz.GetNextToken()) != NULL) { // Date
939 if (datetime.ParseTime(tkz.GetNextToken()) != NULL) { // Time
940 if (tkz.GetNextToken().Last() == ':') { // name:
941 tkz.GetNextToken(); // perm
942 tkz.GetNextToken(); // ?
943 tkz.GetNextToken(); // user
944 tkz.GetNextToken(); // grp
945 tkz.GetNextToken(); // size
946 if (datetime.ParseDate(tkz.GetNextToken()) != NULL) { //date
947 if (datetime.ParseTime(tkz.GetNextToken()) != NULL) { //time
949 //wxbMainFrame::GetInstance()->Print(wxString("(") << filemessages << ")", CS_DEBUG);
950 gauge->SetValue(filemessages);
961 while (sw2.Time() < 10000) {
962 wxTheApp->Yield(true);
963 wxbUtils::MilliSleep(100);
970 if ((!waitforever) && (sw.Time() > 60000)) {
971 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);
972 wxbMainFrame::GetInstance()->SetStatusText(_("The restore job has not been started within one minute, wx-console will not wait for its completion anymore."));
976 wxbUtils::WaitForEnd(wxT("autodisplay on\n"));
977 wxbUtils::WaitForEnd(wxT(".messages\n"));
979 gauge->SetValue(totfilemessages);
981 if (status == JS_Terminated) {
982 wxbMainFrame::GetInstance()->Print(_("Restore done successfully.\n"), CS_DEBUG);
983 wxbMainFrame::GetInstance()->SetStatusText(_("Restore done successfully."));
989 /* The cancel button has been clicked */
990 void wxbRestorePanel::CmdCancel() {
993 if (status == restoring) {
994 if (jobid != wxT("")) {
995 wxbMainFrame::GetInstance()->Send(wxString(wxT("cancel job=")) << jobid << wxT("\n"));
997 cancel->Enable(true);
1002 while ((IsWorking()) && (cancelled != 2)) {
1003 wxTheApp->Yield(true);
1004 wxbUtils::MilliSleep(100);
1005 if (sw.Time() > 30000) { /* 30 seconds timeout */
1006 if (status == choosing) {
1007 wxbMainFrame::GetInstance()->Send(wxT("quit\n"));
1009 else if (status == configuring) {
1010 wxbMainFrame::GetInstance()->Send(wxT("no\n"));
1012 else if (status == restoring) {
1015 SetStatus(finished);
1016 wxbUtils::MilliSleep(1000);
1023 wxbMainFrame::GetInstance()->Send(wxT("quit\n"));
1026 wxbMainFrame::GetInstance()->Send(wxT("no\n"));
1031 wxbUtils::MilliSleep(1000);
1032 SetStatus(finished);
1035 /* Apply configuration changes */
1037 /* 1: Level (not appropriate)
1042 * 6: When (yes : "Please enter desired start time as YYYY-MM-DD HH:MM:SS (return for now):")
1043 * 7: Priority (yes : "Enter new Priority: (positive integer)")
1045 * 9: Where (yes : "Please enter path prefix for restore (/ for none):")
1046 * 10: Replace (yes : "Replace:\n 1: always\n 2: ifnewer\n 3: ifolder\n 4: never\n
1047 * Select replace option (1-4):")
1051 void wxbRestorePanel::CmdConfigApply() {
1052 if (cfgUpdated == 0) return;
1054 wxbMainFrame::GetInstance()->SetStatusText(_("Applying restore configuration changes..."));
1056 EnableConfig(false);
1058 wxbDataTokenizer* dt = NULL;
1060 bool failed = false;
1062 while (cfgUpdated > 0) {
1067 wxString def; //String to send if can't use our data
1068 if ((cfgUpdated >> ConfigWhere) & 1) {
1069 wxbUtils::WaitForPrompt(wxT("mod\n")); /* TODO: check results */
1070 wxbUtils::WaitForPrompt(wxT("9\n"));
1071 dt = new wxbDataTokenizer(true);
1072 wxbUtils::WaitForPrompt(restorePanel->GetRowString(_("Where")) + wxT("\n"));
1074 cfgUpdated = cfgUpdated & (~(1 << ConfigWhere));
1076 else if ((cfgUpdated >> ConfigReplace) & 1) {
1077 wxbUtils::WaitForPrompt(wxT("mod\n")); /* TODO: check results */
1078 wxbUtils::WaitForPrompt(wxT("10\n"));
1079 dt = new wxbDataTokenizer(true);
1080 wxbUtils::WaitForPrompt(wxString() << (restorePanel->GetRowSelection(_("Replace"))+1) << wxT("\n"));
1082 cfgUpdated = cfgUpdated & (~(1 << ConfigReplace));
1084 else if ((cfgUpdated >> ConfigWhen) & 1) {
1085 wxbUtils::WaitForPrompt(wxT("mod\n")); /* TODO: check results */
1086 wxbUtils::WaitForPrompt(wxT("6\n"));
1087 dt = new wxbDataTokenizer(true);
1088 wxbUtils::WaitForPrompt(restorePanel->GetRowString(wxT("When")) + wxT("\n"));
1090 cfgUpdated = cfgUpdated & (~(1 << ConfigWhen));
1092 else if ((cfgUpdated >> ConfigPriority) & 1) {
1093 wxbUtils::WaitForPrompt(wxT("mod\n")); /* TODO: check results */
1094 wxbUtils::WaitForPrompt(wxT("7\n"));
1095 dt = new wxbDataTokenizer(true);
1096 wxbUtils::WaitForPrompt(restorePanel->GetRowString(_("Priority")) + wxT("\n"));
1098 cfgUpdated = cfgUpdated & (~(1 << ConfigPriority));
1100 else if ((cfgUpdated >> ConfigClient) & 1) {
1101 wxbUtils::WaitForPrompt(wxT("mod\n")); /* TODO: check results */
1102 wxbPromptParser *pp = wxbUtils::WaitForPrompt(wxT("5\n"), true);
1103 int client = pp->getChoices()->Index(restorePanel->GetRowString(_("Client")));
1104 if (client == wxNOT_FOUND) {
1105 wxbMainFrame::GetInstance()->SetStatusText(_("Failed to find the selected client."));
1110 dt = new wxbDataTokenizer(true);
1111 wxbUtils::WaitForPrompt(wxString() << client << wxT("\n"));
1113 cfgUpdated = cfgUpdated & (~(1 << ConfigClient));
1115 else if ((cfgUpdated >> ConfigFileset) & 1) {
1116 wxbUtils::WaitForPrompt(wxT("mod\n")); /* TODO: check results */
1117 wxbPromptParser *pp = wxbUtils::WaitForPrompt(wxT("4\n"), true);
1118 int fileset = pp->getChoices()->Index(restorePanel->GetRowString(_("Fileset")));
1119 if (fileset == wxNOT_FOUND) {
1120 wxbMainFrame::GetInstance()->SetStatusText(_("Failed to find the selected fileset."));
1125 dt = new wxbDataTokenizer(true);
1126 wxbUtils::WaitForPrompt(wxString() << fileset << wxT("\n"));
1128 cfgUpdated = cfgUpdated & (~(1 << ConfigFileset));
1130 else if ((cfgUpdated >> ConfigStorage) & 1) {
1131 wxbUtils::WaitForPrompt(wxT("mod\n")); /* TODO: check results */
1132 wxbPromptParser *pp = wxbUtils::WaitForPrompt(wxT("2\n"), true);
1133 int fileset = pp->getChoices()->Index(restorePanel->GetRowString(_("Storage")));
1134 if (fileset == wxNOT_FOUND) {
1135 wxbMainFrame::GetInstance()->SetStatusText(_("Failed to find the selected storage."));
1140 dt = new wxbDataTokenizer(true);
1141 wxbUtils::WaitForPrompt(wxString() << fileset << wxT("\n"));
1143 cfgUpdated = cfgUpdated & (~(1 << ConfigStorage));
1151 for (i = 0; i < dt->GetCount(); i++) {
1152 if ((*dt)[i].Find(_("Run Restore job")) == 0) {
1157 if (i == dt->GetCount()) {
1159 dt = wxbUtils::WaitForEnd(def + wxT("\n"), true);
1163 UpdateSecondConfig(dt); /* TODO: Check result */
1168 wxbMainFrame::GetInstance()->SetStatusText(_("Restore configuration changes were applied."));
1174 /* Cancel restore */
1175 void wxbRestorePanel::CmdConfigCancel() {
1176 wxbUtils::WaitForEnd(wxT("no\n"));
1177 wxbMainFrame::GetInstance()->Print(_("Restore cancelled.\n"), CS_DEBUG);
1178 wxbMainFrame::GetInstance()->SetStatusText(_("Restore cancelled."));
1179 SetStatus(finished);
1182 /* List jobs for a specified client and fileset */
1183 void wxbRestorePanel::CmdListJobs() {
1184 if (status == entered) {
1185 configPanel->ClearRowChoices(_("Before"));
1186 /*wxbUtils::WaitForPrompt("query\n");
1187 wxbUtils::WaitForPrompt("6\n");*/
1188 wxbTableParser* tableparser = new wxbTableParser(false);
1189 wxbDataTokenizer* dt = wxbUtils::WaitForEnd(
1190 wxString(wxT(".backups client=\"")) + configPanel->GetRowString(_("Client")) +
1191 wxT("\" fileset=\"") + configPanel->GetRowString(_("Fileset")) + wxT("\"\n"), true);
1193 while (!tableparser->hasFinished()) {
1194 wxTheApp->Yield(true);
1195 wxbUtils::MilliSleep(100);
1198 if (!tableparser->GetCount() == 0) {
1199 for (unsigned int i = 0; i < dt->Count(); i++) {
1200 if ((*dt)[i].Find(_("No results to list.")) == 0) {
1201 configPanel->AddRowChoice(_("Before"),
1202 _("No backup found for this client."));
1203 configPanel->SetRowSelection(_("Before"), 0);
1204 configPanel->EnableApply(true); // Enabling the not existing apply button disables the ok button.
1209 else if (((*dt)[i].Find(_("ERROR")) > -1) ||
1210 ((*dt)[i].Find(_("Query failed")) > -1)) {
1211 configPanel->AddRowChoice(_("Before"),
1212 _("Cannot get previous backups list, see console."));
1213 configPanel->SetRowSelection(_("Before"), 0);
1214 configPanel->EnableApply(true); // Enabling the not existing apply button disables the ok button.
1224 wxDateTime lastdatetime = (time_t) 0;
1225 for (int i = tableparser->GetCount()-1; i > -1; i--) {
1226 wxString str = (*tableparser)[i][3];
1227 wxDateTime datetime;
1229 if ( ( (chr = datetime.ParseDate(str.GetData()) ) != NULL ) && ( datetime.ParseTime(++chr) != NULL ) && ! lastdatetime.IsEqualTo(datetime) ) {
1230 lastdatetime = datetime;
1231 datetime += wxTimeSpan::Seconds(1);
1232 configPanel->AddRowChoice(_("Before"),
1233 datetime.Format(wxT("%Y-%m-%d %H:%M:%S")));
1239 configPanel->SetRowSelection(_("Before"), 0);
1240 configPanel->EnableApply(false); // Disabling the not existing apply button enables the ok button.
1244 /* List files and directories for a specified tree item */
1245 void wxbRestorePanel::CmdList(wxTreeItemId item) {
1246 if (status == choosing) {
1247 list->DeleteAllItems();
1252 UpdateTreeItem(item, true, false);
1254 if (list->GetItemCount() >= 1) {
1255 int firstwidth = list->GetSize().GetWidth();
1256 for (int i = 2; i < 7; i++) {
1257 list->SetColumnWidth(i, wxLIST_AUTOSIZE);
1258 firstwidth -= list->GetColumnWidth(i);
1261 list->SetColumnWidth(0, 18);
1263 list->SetColumnWidth(1, wxLIST_AUTOSIZE);
1264 if (list->GetColumnWidth(1) < firstwidth) {
1265 list->SetColumnWidth(1, firstwidth-25);
1271 /* Mark a treeitem (directory) or a listitem (file or directory) */
1272 void wxbRestorePanel::CmdMark(wxTreeItemId treeitem, long* listitems, int listsize, int state) {
1273 if (status == choosing) {
1274 wxbTreeItemData** itemdata;
1275 int itemdatasize = 0;
1276 if (listsize == 0) {
1277 itemdata = new wxbTreeItemData*[1];
1281 itemdata = new wxbTreeItemData*[listsize];
1282 itemdatasize = listsize;
1285 if (listitems != NULL) {
1286 for (int i = 0; i < itemdatasize; i++) {
1287 itemdata[i] = (wxbTreeItemData*)list->GetItemData(listitems[i]);
1290 else if (treeitem.IsOk()) {
1291 itemdata[0] = (wxbTreeItemData*)tree->GetItemData(treeitem);
1298 if (itemdata[0] == NULL) { //Should never happen
1303 wxString dir = itemdata[0]->GetPath();
1306 if (dir != wxT("/")) {
1307 if (dir.GetChar(dir.Length()-1) == '/') {
1311 int i = dir.Find('/', TRUE);
1316 else { /* first dir below root */
1317 file = dir.Mid(i+1);
1318 dir = dir.Mid(0, i+1);
1327 bool marked = false;
1328 bool unmarked = false;
1330 for (int i = 0; i < itemdatasize; i++) {
1331 switch(itemdata[i]->GetMarked()) {
1345 if (marked && unmarked)
1361 wxbUtils::WaitForEnd(wxString(wxT("cd \"")) << dir << wxT("\"\n"));
1362 wxbUtils::WaitForEnd(wxString((state==1) ? wxT("mark") : wxT("unmark")) << wxT(" \"") << file << wxT("\"\n"));
1364 /* TODO: Check commands results */
1366 /*if ((dir == "/") && (file == "*")) {
1367 itemdata->SetMarked((itemdata->GetMarked() == 1) ? 0 : 1);
1370 if (listitems == NULL) { /* tree item state changed */
1371 SetTreeItemState(treeitem, state);
1372 /*treeitem = tree->GetSelection();
1373 UpdateTree(treeitem, true);
1374 treeitem = tree->GetItemParent(treeitem);*/
1377 for (int i = 0; i < itemdatasize; i++) {
1378 SetListItemState(listitems[i], state);
1380 listadd->Enable(state == 0);
1381 listremove->Enable(state == 1);
1382 /*UpdateTree(treeitem, (tree->GetSelection() == treeitem));
1383 treeitem = tree->GetItemParent(treeitem);*/
1386 /*while (treeitem.IsOk()) {
1387 WaitForList(treeitem, false);
1388 treeitem = tree->GetItemParent(treeitem);
1395 /*----------------------------------------------------------------------------
1397 ----------------------------------------------------------------------------*/
1399 /* Run a dir command, and waits until result is fully received. */
1400 void wxbRestorePanel::UpdateTreeItem(wxTreeItemId item, bool updatelist, bool recurse) {
1401 // this->updatelist = updatelist;
1402 wxbDataTokenizer* dt;
1404 dt = wxbUtils::WaitForEnd(wxString(wxT("cd \"")) <<
1405 static_cast<wxbTreeItemData*>(tree->GetItemData(item))
1406 ->GetPath() << wxT("\"\n"), false);
1408 /* TODO: check command result */
1415 list->DeleteAllItems();
1416 dt = wxbUtils::WaitForEnd(wxT(".dir\n"), true);
1420 for (unsigned int i = 0; i < dt->GetCount(); i++) {
1423 if (str.Find(wxT("cwd is:")) == 0) { // Sometimes cd command result "infiltrate" into listings.
1431 if (!ParseList(str, &entry))
1434 wxTreeItemId treeid;
1436 if (entry.fullname.GetChar(entry.fullname.Length()-1) == '/') {
1439 #if wxCHECK_VERSION(2, 6, 0)
1440 wxTreeItemIdValue cookie;
1445 treeid = tree->GetFirstChild(item, cookie);
1447 bool updated = false;
1449 while (treeid.IsOk()) {
1450 itemStr = ((wxbTreeItemData*)tree->GetItemData(treeid))->GetName();
1451 if (entry.filename == itemStr) {
1452 if (static_cast<wxbTreeItemData*>(tree->GetItemData(treeid))->GetMarked() != entry.marked) {
1453 tree->SetItemImage(treeid, entry.marked, wxTreeItemIcon_Normal);
1454 tree->SetItemImage(treeid, entry.marked, wxTreeItemIcon_Selected);
1455 static_cast<wxbTreeItemData*>(tree->GetItemData(treeid))->SetMarked(entry.marked);
1457 if ((recurse) && (tree->IsExpanded(treeid))) {
1458 UpdateTreeItem(treeid, false, true);
1463 treeid = tree->GetNextChild(item, cookie);
1467 treeid = tree->AppendItem(item, wxbUtils::ConvertToPrintable(entry.filename), entry.marked, entry.marked, new wxbTreeItemData(entry.fullname, entry.filename, entry.marked));
1472 long ind = list->InsertItem(list->GetItemCount(), entry.marked);
1473 wxbTreeItemData* data = new wxbTreeItemData(entry.fullname, entry.filename, entry.marked, ind);
1474 data->SetId(treeid);
1475 list->SetItemData(ind, (long)data);
1476 list->SetItem(ind, 1, wxbUtils::ConvertToPrintable(entry.filename));
1477 list->SetItem(ind, 2, entry.size);
1478 list->SetItem(ind, 3, entry.date);
1479 list->SetItem(ind, 4, entry.perm);
1480 list->SetItem(ind, 5, entry.user);
1481 list->SetItem(ind, 6, entry.group);
1491 /* Parse .dir command results, returns true if the result has been stored in entry, false otherwise. */
1492 int wxbRestorePanel::ParseList(wxString line, wxbDirEntry* entry) {
1493 /* See ls_output in dird/ua_tree.c */
1494 //-rw-r-----,1,root,root,41575,2005-10-18 18:21:36, ,/usr/var/bacula/working/bacula.sql
1496 wxStringTokenizer tkz(line, wxT(","));
1498 if (!tkz.HasMoreTokens())
1500 entry->perm = tkz.GetNextToken();
1502 if (!tkz.HasMoreTokens())
1504 entry->nlink = tkz.GetNextToken();
1506 if (!tkz.HasMoreTokens())
1508 entry->user = tkz.GetNextToken();
1510 if (!tkz.HasMoreTokens())
1512 entry->group = tkz.GetNextToken();
1514 if (!tkz.HasMoreTokens())
1516 entry->size = tkz.GetNextToken();
1518 if (!tkz.HasMoreTokens())
1520 entry->date = tkz.GetNextToken();
1522 if (!tkz.HasMoreTokens())
1524 wxString marked = tkz.GetNextToken();
1525 if (marked == wxT("*")) {
1528 else if (marked == wxT("+")) {
1535 if (!tkz.HasMoreTokens())
1537 entry->fullname = tkz.GetNextToken();
1539 /* Get only the filename (cut path by finding the last '/') */
1540 if (entry->fullname.GetChar(entry->fullname.Length()-1) == '/') {
1541 wxString tmp = entry->fullname;
1543 entry->filename = entry->fullname.Mid(tmp.Find('/', true)+1);
1546 entry->filename = entry->fullname.Mid(entry->fullname.Find('/', true)+1);
1552 /* Sets a list item state, and update its parents and children if it is a directory */
1553 void wxbRestorePanel::SetListItemState(long listitem, int newstate) {
1554 wxbTreeItemData* itemdata = (wxbTreeItemData*)list->GetItemData(listitem);
1556 wxTreeItemId treeitem;
1558 itemdata->SetMarked(newstate);
1559 list->SetItemImage(listitem, newstate, 0); /* TODO: Find what these ints are for */
1560 list->SetItemImage(listitem, newstate, 1);
1562 if ((treeitem = itemdata->GetId()).IsOk()) {
1563 SetTreeItemState(treeitem, newstate);
1566 UpdateTreeItemState(tree->GetSelection());
1570 /* Sets a tree item state, and update its children, parents and list (if necessary) */
1571 void wxbRestorePanel::SetTreeItemState(wxTreeItemId item, int newstate) {
1572 #if wxCHECK_VERSION(2, 6, 0)
1573 wxTreeItemIdValue cookie;
1577 wxTreeItemId currentChild = tree->GetFirstChild(item, cookie);
1579 wxbTreeItemData* itemdata;
1581 while (currentChild.IsOk()) {
1582 itemdata = (wxbTreeItemData*)tree->GetItemData(currentChild);
1583 int state = itemdata->GetMarked();
1585 if (state != newstate) {
1586 itemdata->SetMarked(newstate);
1587 tree->SetItemImage(currentChild, newstate, wxTreeItemIcon_Normal);
1588 tree->SetItemImage(currentChild, newstate, wxTreeItemIcon_Selected);
1591 currentChild = tree->GetNextChild(item, cookie);
1594 itemdata = (wxbTreeItemData*)tree->GetItemData(item);
1595 itemdata->SetMarked(newstate);
1596 tree->SetItemImage(item, newstate, wxTreeItemIcon_Normal);
1597 tree->SetItemImage(item, newstate, wxTreeItemIcon_Selected);
1600 if (tree->GetSelection() == item) {
1601 for (long i = 0; i < list->GetItemCount(); i++) {
1602 list->SetItemImage(i, newstate, 0); /* TODO: Find what these ints are for */
1603 list->SetItemImage(i, newstate, 1);
1607 UpdateTreeItemState(tree->GetItemParent(item));
1610 /* Update a tree item state, and its parents' state */
1611 void wxbRestorePanel::UpdateTreeItemState(wxTreeItemId item) {
1618 #if wxCHECK_VERSION(2, 6, 0)
1619 wxTreeItemIdValue cookie;
1623 wxTreeItemId currentChild = tree->GetFirstChild(item, cookie);
1625 bool onechildmarked = false;
1626 bool onechildunmarked = false;
1628 while (currentChild.IsOk()) {
1629 state = ((wxbTreeItemData*)tree->GetItemData(currentChild))->GetMarked();
1632 onechildunmarked = true;
1635 onechildmarked = true;
1638 onechildmarked = true;
1639 onechildunmarked = true;
1643 if (onechildmarked && onechildunmarked) {
1647 currentChild = tree->GetNextChild(item, cookie);
1650 if (tree->GetSelection() == item) {
1651 for (long i = 0; i < list->GetItemCount(); i++) {
1652 state = ((wxbTreeItemData*)list->GetItemData(i))->GetMarked();
1656 onechildunmarked = true;
1659 onechildmarked = true;
1662 onechildmarked = true;
1663 onechildunmarked = true;
1667 if (onechildmarked && onechildunmarked) {
1675 if (onechildmarked && onechildunmarked) {
1678 else if (onechildmarked) {
1681 else if (onechildunmarked) {
1684 else { // no child, don't change anything
1685 UpdateTreeItemState(tree->GetItemParent(item));
1689 wxbTreeItemData* itemdata = (wxbTreeItemData*)tree->GetItemData(item);
1691 itemdata->SetMarked(state);
1692 tree->SetItemImage(item, state, wxTreeItemIcon_Normal);
1693 tree->SetItemImage(item, state, wxTreeItemIcon_Selected);
1695 UpdateTreeItemState(tree->GetItemParent(item));
1698 /* Refresh the whole tree. */
1699 void wxbRestorePanel::RefreshTree() {
1700 /* Save current selection */
1701 wxArrayString current;
1703 wxTreeItemId item = currentTreeItem;
1705 while ((item.IsOk()) && (item != tree->GetRootItem())) {
1706 current.Add(tree->GetItemText(item));
1707 item = tree->GetItemParent(item);
1710 /* Update the tree */
1711 UpdateTreeItem(tree->GetRootItem(), false, true);
1713 /* Reselect the former selected item */
1714 item = tree->GetRootItem();
1716 if (current.Count() == 0) {
1717 tree->SelectItem(item);
1723 for (int i = current.Count()-1; i >= 0; i--) {
1724 #if wxCHECK_VERSION(2, 6, 0)
1725 wxTreeItemIdValue cookie;
1729 wxTreeItemId currentChild = tree->GetFirstChild(item, cookie);
1733 while (currentChild.IsOk()) {
1734 if (((wxbTreeItemData*)tree->GetItemData(currentChild))->GetName() == current[i]) {
1735 item = currentChild;
1740 currentChild = tree->GetNextChild(item, cookie);
1746 UpdateTreeItem(item, true, false); /* Update the list */
1748 tree->SelectItem(item);
1751 void wxbRestorePanel::RefreshList() {
1752 if (currentTreeItem.IsOk()) {
1753 UpdateTreeItem(currentTreeItem, true, false); /* Update the list */
1757 /* Update first config, adapting settings to the job name selected */
1758 void wxbRestorePanel::UpdateFirstConfig() {
1759 configPanel->Enable(false);
1760 wxbDataTokenizer* dt = wxbUtils::WaitForEnd(wxString(wxT(".defaults job=")) + configPanel->GetRowString(_("Job Name")) + wxT("\n"), true, false);
1766 * where=/tmp/bacula-restores
1776 bool dolistjobs = false;
1778 for (i = 0; i < dt->GetCount(); i++) {
1780 if ((j = str.Find('=')) > -1) {
1781 name = str.Mid(0, j);
1782 if (name == wxT("pool")) {
1783 configPanel->SetRowString(_("Pool"), str.Mid(j+1));
1785 else if (name == wxT("client")) {
1787 if ((str != configPanel->GetRowString(_("Client"))) ||
1788 (configPanel->GetRowString(_("Before"))) == wxT("")) {
1789 configPanel->SetRowString(_("Client"), str);
1793 else if (name == wxT("storage")) {
1794 configPanel->SetRowString(_("Storage"), str.Mid(j+1));
1796 else if (name == wxT("fileset")) {
1798 if ((str != configPanel->GetRowString(_("Fileset"))) ||
1799 (configPanel->GetRowString(_("Before"))) == wxT("")) {
1800 configPanel->SetRowString(_("Fileset"), str);
1810 //wxTheApp->Yield(false);
1813 configPanel->Enable(true);
1817 * Update second config.
1820 * JobName: RestoreFiles
1821 * Bootstrap: /var/lib/bacula/restore.bsr
1822 * Where: /tmp/bacula-restores
1827 * When: 2004-04-18 01:18:56
1829 * OK to run? (yes/mod/no):
1832 bool wxbRestorePanel::UpdateSecondConfig(wxbDataTokenizer* dt) {
1834 for (i = 0; i < dt->GetCount(); i++) {
1835 if ((*dt)[i].Find(_("Run Restore job")) == 0)
1839 if ((i + 10) > dt->GetCount()) {
1845 if ((k = (*dt)[++i].Find(_("JobName:"))) != 0) return false;
1846 restorePanel->SetRowString(_("Job Name"), (*dt)[i].Mid(10).Trim(false).RemoveLast());
1847 if ((k = (*dt)[++i].Find(_("Bootstrap:"))) != 0) return false;
1848 restorePanel->SetRowString(_("Bootstrap"), (*dt)[i].Mid(10).Trim(false).RemoveLast());
1849 if ((k = (*dt)[++i].Find(_("Where:"))) != 0) return false;
1850 restorePanel->SetRowString(_("Where"), (*dt)[i].Mid(10).Trim(false).RemoveLast());
1852 if ((k = (*dt)[++i].Find(_("Replace:"))) != 0) return false;
1853 wxString str = (*dt)[i].Mid(10).Trim(false).RemoveLast();
1854 if (str == _("always")) restorePanel->SetRowSelection(_("Replace"), 0);
1855 else if (str == _("ifnewer")) restorePanel->SetRowSelection(_("Replace"), 1);
1856 else if (str == _("ifolder")) restorePanel->SetRowSelection(_("Replace"), 2);
1857 else if (str == _("never")) restorePanel->SetRowSelection(_("Replace"), 3);
1858 else restorePanel->SetRowSelection(_("Replace"), 0);
1860 if ((k = (*dt)[++i].Find(_("FileSet:"))) != 0) return false;
1861 restorePanel->SetRowString(_("Fileset"), (*dt)[i].Mid(10).Trim(false).RemoveLast());
1862 if ((k = (*dt)[++i].Find(_("Client:"))) != 0) return false;
1863 restorePanel->SetRowString(_("Client"), (*dt)[i].Mid(10).Trim(false).RemoveLast());
1864 if ((k = (*dt)[++i].Find(_("Storage:"))) != 0) return false;
1865 restorePanel->SetRowString(_("Storage"), (*dt)[i].Mid(10).Trim(false).RemoveLast());
1866 if ((k = (*dt)[++i].Find(_("When:"))) != 0) return false;
1867 restorePanel->SetRowString(_("When"), (*dt)[i].Mid(10).Trim(false).RemoveLast());
1868 if ((k = (*dt)[++i].Find(_("Priority:"))) != 0) return false;
1869 restorePanel->SetRowString(_("Priority"), (*dt)[i].Mid(10).Trim(false).RemoveLast());
1872 restorePanel->Layout();
1877 /*----------------------------------------------------------------------------
1879 ----------------------------------------------------------------------------*/
1881 /* Set current status by enabling/disabling components */
1882 void wxbRestorePanel::SetStatus(status_enum newstatus) {
1883 switch (newstatus) {
1885 centerSizer->Remove(configPanel);
1886 centerSizer->Remove(restorePanel);
1887 centerSizer->Remove(treelistPanel);
1888 treelistPanel->Show(false);
1889 restorePanel->Show(false);
1890 centerSizer->Add(configPanel, 1, wxEXPAND);
1891 configPanel->Show(true);
1892 configPanel->Layout();
1893 centerSizer->Layout();
1895 start->SetLabel(_("Enter restore mode"));
1896 start->Enable(false);
1897 configPanel->Enable(false);
1898 tree->Enable(false);
1899 list->Enable(false);
1900 gauge->Enable(false);
1901 cancel->Enable(false);
1906 centerSizer->Remove(configPanel);
1907 centerSizer->Remove(restorePanel);
1908 centerSizer->Remove(treelistPanel);
1909 treelistPanel->Show(false);
1910 restorePanel->Show(false);
1911 centerSizer->Add(configPanel, 1, wxEXPAND);
1912 configPanel->Show(true);
1913 configPanel->Layout();
1914 centerSizer->Layout();
1916 tree->DeleteAllItems();
1917 list->DeleteAllItems();
1918 configPanel->ClearRowChoices(_("Client"));
1919 configPanel->ClearRowChoices(_("Before"));
1920 wxbMainFrame::GetInstance()->EnablePanels();
1921 newstatus = activable;
1924 start->SetLabel(_("Enter restore mode"));
1925 start->Enable(true);
1926 configPanel->Enable(false);
1927 tree->Enable(false);
1928 list->Enable(false);
1929 gauge->Enable(false);
1930 cancel->Enable(false);
1934 wxbMainFrame::GetInstance()->DisablePanels(this);
1936 start->Enable(false);
1937 //start->SetLabel(_("Choose files to restore"));
1938 configPanel->Enable(true);
1939 tree->Enable(false);
1940 list->Enable(false);
1941 cancel->Enable(true);
1948 start->Enable(true);
1949 start->SetLabel(_("Restore"));
1950 centerSizer->Remove(configPanel);
1951 configPanel->Show(false);
1952 centerSizer->Add(treelistPanel, 1, wxEXPAND);
1953 treelistPanel->Show(true);
1954 treelistPanel->Layout();
1955 centerSizer->Layout();
1962 start->Enable(false);
1963 configPanel->Enable(false);
1964 tree->Enable(false);
1965 list->Enable(false);
1966 centerSizer->Remove(treelistPanel);
1967 treelistPanel->Show(false);
1968 centerSizer->Add(restorePanel, 1, wxEXPAND);
1969 restorePanel->Show(true);
1970 restorePanel->Layout();
1971 centerSizer->Layout();
1973 restorePanel->EnableApply(false);
1976 start->SetLabel(_("Restoring..."));
1977 gauge->Enable(true);
1979 start->Enable(false);
1980 configPanel->Enable(false);
1981 tree->Enable(false);
1982 list->Enable(false);
1989 /*----------------------------------------------------------------------------
1991 ----------------------------------------------------------------------------*/
1993 void wxbRestorePanel::SetWorking(bool working) {
1994 this->working = working;
1996 SetCursor(*wxHOURGLASS_CURSOR);
1997 // SetEvtHandlerEnabled(false); //EVTQUEUE
1999 // else if (!processing) { /* Empty event queue if we aren't already doing this */ //EVTQUEUE
2001 // processing = true; //EVTQUEUE
2002 SetCursor(*wxSTANDARD_CURSOR);
2003 // SetEvtHandlerEnabled(true); //EVTQUEUE
2004 /* wxNode *node = pendingEvents->First(); //EVTQUEUE
2006 wxEvent *event = (wxEvent *)node->Data();
2009 wxEvtHandler::ProcessEvent(*event);
2012 node = pendingEvents->First();
2014 processing = false;*/
2018 bool wxbRestorePanel::IsWorking() {
2019 return this->working;
2022 void wxbRestorePanel::EnableConfig(bool enable) {
2023 restorePanel->Enable(enable);
2026 /*----------------------------------------------------------------------------
2028 ----------------------------------------------------------------------------*/
2033 bool wxbRestorePanel::ProcessEvent(wxEvent& event) {
2034 if (IsWorking() || processing) {
2035 wxEvent *eventCopy = event.Clone();
2037 pendingEvents->Append(eventCopy);
2041 return wxEvtHandler::ProcessEvent(event);
2046 void wxbRestorePanel::OnCancel(wxCommandEvent& event) {
2047 cancel->Enable(false);
2048 SetCursor(*wxHOURGLASS_CURSOR);
2050 SetCursor(*wxSTANDARD_CURSOR);
2053 void wxbRestorePanel::OnStart(wxCommandEvent& event) {
2062 void wxbRestorePanel::OnTreeChanging(wxTreeEvent& event) {
2068 void wxbRestorePanel::OnTreeExpanding(wxTreeEvent& event) {
2074 //CmdList(event.GetItem());
2075 if (tree->GetSelection() != event.GetItem()) {
2076 tree->SelectItem(event.GetItem());
2081 void wxbRestorePanel::OnTreeChanged(wxTreeEvent& event) {
2085 if (currentTreeItem == event.GetItem()) {
2088 treeadd->Enable(false);
2089 treeremove->Enable(false);
2090 treerefresh->Enable(false);
2091 markWhenCommandDone = false;
2093 currentTreeItem = event.GetItem();
2094 CmdList(event.GetItem());
2095 if (markWhenCommandDone) {
2096 CmdMark(event.GetItem(), NULL, 0);
2100 if (event.GetItem().IsOk()) {
2101 int status = ((wxbTreeItemData*)tree->GetItemData(event.GetItem()))->GetMarked();
2102 treeadd->Enable(status != 1);
2103 treeremove->Enable(status != 0);
2105 treerefresh->Enable(true);
2108 void wxbRestorePanel::OnTreeMarked(wxbTreeMarkedEvent& event) {
2110 if (tree->GetSelection() == event.GetItem()) {
2111 markWhenCommandDone = !markWhenCommandDone;
2116 markWhenCommandDone = false;
2117 CmdMark(event.GetItem(), NULL, 0);
2118 if (markWhenCommandDone) {
2119 CmdMark(event.GetItem(), NULL, 0);
2124 if (event.GetItem().IsOk()) {
2125 int status = ((wxbTreeItemData*)tree->GetItemData(event.GetItem()))->GetMarked();
2126 treeadd->Enable(status != 1);
2127 treeremove->Enable(status != 0);
2131 void wxbRestorePanel::OnTreeAdd(wxCommandEvent& event) {
2136 if (currentTreeItem.IsOk()) {
2138 CmdMark(currentTreeItem, NULL, 0, 1);
2141 treeremove->Enable(1);
2146 void wxbRestorePanel::OnTreeRemove(wxCommandEvent& event) {
2151 if (currentTreeItem.IsOk()) {
2153 CmdMark(currentTreeItem, NULL, 0, 0);
2156 treeremove->Enable(0);
2161 void wxbRestorePanel::OnTreeRefresh(wxCommandEvent& event) {
2171 void wxbRestorePanel::OnListMarked(wxbListMarkedEvent& event) {
2176 if (list->GetSelectedItemCount() == 0) {
2182 long* items = new long[list->GetSelectedItemCount()];
2186 long item = list->GetNextItem(-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
2187 while (item != -1) {
2190 item = list->GetNextItem(item, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
2193 CmdMark(wxTreeItemId(), items, num);
2197 wxListEvent listevt;
2199 OnListChanged(listevt);
2206 void wxbRestorePanel::OnListActivated(wxListEvent& event) {
2211 long item = event.GetIndex();
2212 // long item = list->GetNextItem(-1, wxLIST_NEXT_ALL, wxLIST_STATE_FOCUSED);
2214 wxbTreeItemData* itemdata = (wxbTreeItemData*)list->GetItemData(item);
2215 wxString name = itemdata->GetName();
2220 #if wxCHECK_VERSION(2, 6, 0)
2221 wxTreeItemIdValue cookie;
2226 if (name.GetChar(name.Length()-1) == '/') {
2227 wxTreeItemId currentChild = tree->GetFirstChild(currentTreeItem, cookie);
2229 while (currentChild.IsOk()) {
2230 wxString name2 = ((wxbTreeItemData*)tree->GetItemData(currentChild))->GetName();
2231 if (name2 == name) {
2232 //tree->UnselectAll();
2234 tree->Expand(currentTreeItem);
2235 tree->SelectItem(currentChild);
2239 currentChild = tree->GetNextChild(currentTreeItem, cookie);
2246 void wxbRestorePanel::OnListChanged(wxListEvent& event) {
2251 listadd->Enable(false);
2252 listremove->Enable(false);
2254 bool marked = false;
2255 bool unmarked = false;
2257 long item = list->GetNextItem(-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
2258 while (item != -1) {
2259 switch (((wxbTreeItemData*)list->GetItemData(item))->GetMarked()) {
2272 // Should never happen
2274 if (marked && unmarked) break;
2275 item = list->GetNextItem(item, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
2278 listadd->Enable(unmarked);
2279 listremove->Enable(marked);
2282 void wxbRestorePanel::OnListAdd(wxCommandEvent& event) {
2289 long* items = new long[list->GetSelectedItemCount()];
2293 long item = list->GetNextItem(-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
2294 while (item != -1) {
2297 item = list->GetNextItem(item, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
2300 CmdMark(wxTreeItemId(), items, num, 1);
2307 listadd->Enable(false);
2308 listremove->Enable(true);
2311 void wxbRestorePanel::OnListRemove(wxCommandEvent& event) {
2318 long* items = new long[list->GetSelectedItemCount()];
2322 long item = list->GetNextItem(-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
2323 while (item != -1) {
2326 item = list->GetNextItem(item, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
2329 CmdMark(wxTreeItemId(), items, num, 0);
2336 listadd->Enable(true);
2337 listremove->Enable(false);
2340 void wxbRestorePanel::OnListRefresh(wxCommandEvent& event) {
2350 void wxbRestorePanel::OnConfigUpdated(wxCommandEvent& event) {
2351 if (status == entered) {
2352 if (event.GetId() == ConfigJobName) {
2357 UpdateFirstConfig();
2360 else if ((event.GetId() == ConfigClient) || (event.GetId() == ConfigFileset)) {
2365 configPanel->Enable(false);
2367 configPanel->Enable(true);
2370 cfgUpdated = cfgUpdated | (1 << event.GetId());
2372 else if (status == configuring) {
2373 restorePanel->EnableApply(true);
2374 cfgUpdated = cfgUpdated | (1 << event.GetId());
2378 void wxbRestorePanel::OnConfigOk(wxCommandEvent& WXUNUSED(event)) {
2379 if (status != configuring) return;
2388 void wxbRestorePanel::OnConfigApply(wxCommandEvent& WXUNUSED(event)) {
2389 if (status != configuring) return;
2395 if (cfgUpdated == 0) {
2396 restorePanel->EnableApply(false);
2401 void wxbRestorePanel::OnConfigCancel(wxCommandEvent& WXUNUSED(event)) {
2402 if (status != configuring) return;