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"));
852 tableparser = wxbUtils::CreateAndWaitForParser(cmd);
854 status = (*tableparser)[0][7].GetChar(0);
857 wxbMainFrame::GetInstance()->SetStatusText(_("Restore job created, but not yet running."));
861 wxbMainFrame::GetInstance()->SetStatusText(
862 wxString::Format(_("Restore job running, please wait (%ld of %ld files restored)..."), filemessages, totfilemessages));
866 wxbMainFrame::GetInstance()->SetStatusText(_("Restore job terminated successfully."));
867 wxbMainFrame::GetInstance()->Print(_("Restore job terminated successfully.\n"), CS_DEBUG);
871 case JS_ErrorTerminated:
872 wxbMainFrame::GetInstance()->SetStatusText(_("Restore job terminated in error, see messages in console."));
873 wxbMainFrame::GetInstance()->Print(_("Restore job terminated in error, see messages.\n"), CS_DEBUG);
878 wxbMainFrame::GetInstance()->SetStatusText(_("Restore job reported a non-fatal error."));
882 wxbMainFrame::GetInstance()->SetStatusText(_("Restore job reported a fatal error."));
887 wxbMainFrame::GetInstance()->SetStatusText(_("Restore job cancelled by user."));
888 wxbMainFrame::GetInstance()->Print(_("Restore job cancelled by user.\n"), CS_DEBUG);
893 wxbMainFrame::GetInstance()->SetStatusText(_("Restore job is waiting on File daemon."));
897 wxbMainFrame::GetInstance()->SetStatusText(_("Restore job is waiting for new media."));
900 case JS_WaitStoreRes:
901 wxbMainFrame::GetInstance()->SetStatusText(_("Restore job is waiting for storage resource."));
905 wxbMainFrame::GetInstance()->SetStatusText(_("Restore job is waiting for job resource."));
908 case JS_WaitClientRes:
909 wxbMainFrame::GetInstance()->SetStatusText(_("Restore job is waiting for Client resource."));
913 wxbMainFrame::GetInstance()->SetStatusText(_("Restore job is waiting for maximum jobs."));
916 case JS_WaitStartTime:
917 wxbMainFrame::GetInstance()->SetStatusText(_("Restore job is waiting for start time."));
920 case JS_WaitPriority:
921 wxbMainFrame::GetInstance()->SetStatusText(_("Restore job is waiting for higher priority jobs to finish."));
927 dt = wxbUtils::WaitForEnd(wxT("messages\n"), true);
929 for (unsigned int i = 0; i < dt->GetCount(); i++) {
930 wxStringTokenizer tkz((*dt)[i], wxT(" "), wxTOKEN_STRTOK);
934 // Date Time name: perm ? user grp size date time
935 //04-Apr-2004 17:19 Tom-fd: -rwx------ 1 nicolas None 514967 2004-03-20 20:03:42 filename
937 if (datetime.ParseDate(tkz.GetNextToken()) != NULL) { // Date
938 if (datetime.ParseTime(tkz.GetNextToken()) != NULL) { // Time
939 if (tkz.GetNextToken().Last() == ':') { // name:
940 tkz.GetNextToken(); // perm
941 tkz.GetNextToken(); // ?
942 tkz.GetNextToken(); // user
943 tkz.GetNextToken(); // grp
944 tkz.GetNextToken(); // size
945 if (datetime.ParseDate(tkz.GetNextToken()) != NULL) { //date
946 if (datetime.ParseTime(tkz.GetNextToken()) != NULL) { //time
948 //wxbMainFrame::GetInstance()->Print(wxString("(") << filemessages << ")", CS_DEBUG);
949 gauge->SetValue(filemessages);
960 while (sw2.Time() < 10000) {
961 wxTheApp->Yield(true);
962 wxbUtils::MilliSleep(100);
969 if ((!waitforever) && (sw.Time() > 60000)) {
970 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);
971 wxbMainFrame::GetInstance()->SetStatusText(_("The restore job has not been started within one minute, wx-console will not wait for its completion anymore."));
975 wxbUtils::WaitForEnd(wxT("autodisplay on\n"));
976 wxbUtils::WaitForEnd(wxT(".messages\n"));
978 gauge->SetValue(totfilemessages);
980 if (status == JS_Terminated) {
981 wxbMainFrame::GetInstance()->Print(_("Restore done successfully.\n"), CS_DEBUG);
982 wxbMainFrame::GetInstance()->SetStatusText(_("Restore done successfully."));
988 /* The cancel button has been clicked */
989 void wxbRestorePanel::CmdCancel() {
992 if (status == restoring) {
993 if (jobid != wxT("")) {
994 wxbMainFrame::GetInstance()->Send(wxString(wxT("cancel job=")) << jobid << wxT("\n"));
996 cancel->Enable(true);
1001 while ((IsWorking()) && (cancelled != 2)) {
1002 wxTheApp->Yield(true);
1003 wxbUtils::MilliSleep(100);
1004 if (sw.Time() > 30000) { /* 30 seconds timeout */
1005 if (status == choosing) {
1006 wxbMainFrame::GetInstance()->Send(wxT("quit\n"));
1008 else if (status == configuring) {
1009 wxbMainFrame::GetInstance()->Send(wxT("no\n"));
1011 else if (status == restoring) {
1014 SetStatus(finished);
1015 wxbUtils::MilliSleep(1000);
1022 wxbMainFrame::GetInstance()->Send(wxT("quit\n"));
1025 wxbMainFrame::GetInstance()->Send(wxT("no\n"));
1030 wxbUtils::MilliSleep(1000);
1031 SetStatus(finished);
1034 /* Apply configuration changes */
1036 /* 1: Level (not appropriate)
1041 * 6: When (yes : "Please enter desired start time as YYYY-MM-DD HH:MM:SS (return for now):")
1042 * 7: Priority (yes : "Enter new Priority: (positive integer)")
1044 * 9: Where (yes : "Please enter path prefix for restore (/ for none):")
1045 * 10: Replace (yes : "Replace:\n 1: always\n 2: ifnewer\n 3: ifolder\n 4: never\n
1046 * Select replace option (1-4):")
1050 void wxbRestorePanel::CmdConfigApply() {
1051 if (cfgUpdated == 0) return;
1053 wxbMainFrame::GetInstance()->SetStatusText(_("Applying restore configuration changes..."));
1055 EnableConfig(false);
1057 wxbDataTokenizer* dt = NULL;
1059 bool failed = false;
1061 while (cfgUpdated > 0) {
1066 wxString def; //String to send if can't use our data
1067 if ((cfgUpdated >> ConfigWhere) & 1) {
1068 wxbUtils::WaitForPrompt(wxT("mod\n")); /* TODO: check results */
1069 wxbUtils::WaitForPrompt(wxT("9\n"));
1070 dt = new wxbDataTokenizer(true);
1071 wxbUtils::WaitForPrompt(restorePanel->GetRowString(_("Where")) + wxT("\n"));
1073 cfgUpdated = cfgUpdated & (~(1 << ConfigWhere));
1075 else if ((cfgUpdated >> ConfigReplace) & 1) {
1076 wxbUtils::WaitForPrompt(wxT("mod\n")); /* TODO: check results */
1077 wxbUtils::WaitForPrompt(wxT("10\n"));
1078 dt = new wxbDataTokenizer(true);
1079 wxbUtils::WaitForPrompt(wxString() << (restorePanel->GetRowSelection(_("Replace"))+1) << wxT("\n"));
1081 cfgUpdated = cfgUpdated & (~(1 << ConfigReplace));
1083 else if ((cfgUpdated >> ConfigWhen) & 1) {
1084 wxbUtils::WaitForPrompt(wxT("mod\n")); /* TODO: check results */
1085 wxbUtils::WaitForPrompt(wxT("6\n"));
1086 dt = new wxbDataTokenizer(true);
1087 wxbUtils::WaitForPrompt(restorePanel->GetRowString(wxT("When")) + wxT("\n"));
1089 cfgUpdated = cfgUpdated & (~(1 << ConfigWhen));
1091 else if ((cfgUpdated >> ConfigPriority) & 1) {
1092 wxbUtils::WaitForPrompt(wxT("mod\n")); /* TODO: check results */
1093 wxbUtils::WaitForPrompt(wxT("7\n"));
1094 dt = new wxbDataTokenizer(true);
1095 wxbUtils::WaitForPrompt(restorePanel->GetRowString(_("Priority")) + wxT("\n"));
1097 cfgUpdated = cfgUpdated & (~(1 << ConfigPriority));
1099 else if ((cfgUpdated >> ConfigClient) & 1) {
1100 wxbUtils::WaitForPrompt(wxT("mod\n")); /* TODO: check results */
1101 wxbPromptParser *pp = wxbUtils::WaitForPrompt(wxT("5\n"), true);
1102 int client = pp->getChoices()->Index(restorePanel->GetRowString(_("Client")));
1103 if (client == wxNOT_FOUND) {
1104 wxbMainFrame::GetInstance()->SetStatusText(_("Failed to find the selected client."));
1109 dt = new wxbDataTokenizer(true);
1110 wxbUtils::WaitForPrompt(wxString() << client << wxT("\n"));
1112 cfgUpdated = cfgUpdated & (~(1 << ConfigClient));
1114 else if ((cfgUpdated >> ConfigFileset) & 1) {
1115 wxbUtils::WaitForPrompt(wxT("mod\n")); /* TODO: check results */
1116 wxbPromptParser *pp = wxbUtils::WaitForPrompt(wxT("4\n"), true);
1117 int fileset = pp->getChoices()->Index(restorePanel->GetRowString(_("Fileset")));
1118 if (fileset == wxNOT_FOUND) {
1119 wxbMainFrame::GetInstance()->SetStatusText(_("Failed to find the selected fileset."));
1124 dt = new wxbDataTokenizer(true);
1125 wxbUtils::WaitForPrompt(wxString() << fileset << wxT("\n"));
1127 cfgUpdated = cfgUpdated & (~(1 << ConfigFileset));
1129 else if ((cfgUpdated >> ConfigStorage) & 1) {
1130 wxbUtils::WaitForPrompt(wxT("mod\n")); /* TODO: check results */
1131 wxbPromptParser *pp = wxbUtils::WaitForPrompt(wxT("2\n"), true);
1132 int fileset = pp->getChoices()->Index(restorePanel->GetRowString(_("Storage")));
1133 if (fileset == wxNOT_FOUND) {
1134 wxbMainFrame::GetInstance()->SetStatusText(_("Failed to find the selected storage."));
1139 dt = new wxbDataTokenizer(true);
1140 wxbUtils::WaitForPrompt(wxString() << fileset << wxT("\n"));
1142 cfgUpdated = cfgUpdated & (~(1 << ConfigStorage));
1150 for (i = 0; i < dt->GetCount(); i++) {
1151 if ((*dt)[i].Find(_("Run Restore job")) == 0) {
1156 if (i == dt->GetCount()) {
1158 dt = wxbUtils::WaitForEnd(def + wxT("\n"), true);
1162 UpdateSecondConfig(dt); /* TODO: Check result */
1167 wxbMainFrame::GetInstance()->SetStatusText(_("Restore configuration changes were applied."));
1173 /* Cancel restore */
1174 void wxbRestorePanel::CmdConfigCancel() {
1175 wxbUtils::WaitForEnd(wxT("no\n"));
1176 wxbMainFrame::GetInstance()->Print(_("Restore cancelled.\n"), CS_DEBUG);
1177 wxbMainFrame::GetInstance()->SetStatusText(_("Restore cancelled."));
1178 SetStatus(finished);
1181 /* List jobs for a specified client and fileset */
1182 void wxbRestorePanel::CmdListJobs() {
1183 if (status == entered) {
1184 configPanel->ClearRowChoices(_("Before"));
1185 /*wxbUtils::WaitForPrompt("query\n");
1186 wxbUtils::WaitForPrompt("6\n");*/
1187 wxbTableParser* tableparser = new wxbTableParser(false);
1188 wxbDataTokenizer* dt = wxbUtils::WaitForEnd(
1189 wxString(wxT(".backups client=\"")) + configPanel->GetRowString(_("Client")) +
1190 wxT("\" fileset=\"") + configPanel->GetRowString(_("Fileset")) + wxT("\"\n"), true);
1192 while (!tableparser->hasFinished()) {
1193 wxTheApp->Yield(true);
1194 wxbUtils::MilliSleep(100);
1197 if (!tableparser->GetCount() == 0) {
1198 for (unsigned int i = 0; i < dt->Count(); i++) {
1199 if ((*dt)[i].Find(_("No results to list.")) == 0) {
1200 configPanel->AddRowChoice(_("Before"),
1201 _("No backup found for this client."));
1202 configPanel->SetRowSelection(_("Before"), 0);
1203 configPanel->EnableApply(true); // Enabling the not existing apply button disables the ok button.
1208 else if (((*dt)[i].Find(_("ERROR")) > -1) ||
1209 ((*dt)[i].Find(_("Query failed")) > -1)) {
1210 configPanel->AddRowChoice(_("Before"),
1211 _("Cannot get previous backups list, see console."));
1212 configPanel->SetRowSelection(_("Before"), 0);
1213 configPanel->EnableApply(true); // Enabling the not existing apply button disables the ok button.
1223 wxDateTime lastdatetime = (time_t) 0;
1224 for (int i = tableparser->GetCount()-1; i > -1; i--) {
1225 wxString str = (*tableparser)[i][3];
1226 wxDateTime datetime;
1228 if ( ( (chr = datetime.ParseDate(str.GetData()) ) != NULL ) && ( datetime.ParseTime(++chr) != NULL ) && ! lastdatetime.IsEqualTo(datetime) ) {
1229 lastdatetime = datetime;
1230 datetime += wxTimeSpan::Seconds(1);
1231 configPanel->AddRowChoice(_("Before"),
1232 datetime.Format(wxT("%Y-%m-%d %H:%M:%S")));
1238 configPanel->SetRowSelection(_("Before"), 0);
1239 configPanel->EnableApply(false); // Disabling the not existing apply button enables the ok button.
1243 /* List files and directories for a specified tree item */
1244 void wxbRestorePanel::CmdList(wxTreeItemId item) {
1245 if (status == choosing) {
1246 list->DeleteAllItems();
1251 UpdateTreeItem(item, true, false);
1253 if (list->GetItemCount() >= 1) {
1254 int firstwidth = list->GetSize().GetWidth();
1255 for (int i = 2; i < 7; i++) {
1256 list->SetColumnWidth(i, wxLIST_AUTOSIZE);
1257 firstwidth -= list->GetColumnWidth(i);
1260 list->SetColumnWidth(0, 18);
1262 list->SetColumnWidth(1, wxLIST_AUTOSIZE);
1263 if (list->GetColumnWidth(1) < firstwidth) {
1264 list->SetColumnWidth(1, firstwidth-25);
1270 /* Mark a treeitem (directory) or a listitem (file or directory) */
1271 void wxbRestorePanel::CmdMark(wxTreeItemId treeitem, long* listitems, int listsize, int state) {
1272 if (status == choosing) {
1273 wxbTreeItemData** itemdata;
1274 int itemdatasize = 0;
1275 if (listsize == 0) {
1276 itemdata = new wxbTreeItemData*[1];
1280 itemdata = new wxbTreeItemData*[listsize];
1281 itemdatasize = listsize;
1284 if (listitems != NULL) {
1285 for (int i = 0; i < itemdatasize; i++) {
1286 itemdata[i] = (wxbTreeItemData*)list->GetItemData(listitems[i]);
1289 else if (treeitem.IsOk()) {
1290 itemdata[0] = (wxbTreeItemData*)tree->GetItemData(treeitem);
1297 if (itemdata[0] == NULL) { //Should never happen
1302 wxString dir = itemdata[0]->GetPath();
1305 if (dir != wxT("/")) {
1306 if (dir.GetChar(dir.Length()-1) == '/') {
1310 int i = dir.Find('/', TRUE);
1315 else { /* first dir below root */
1316 file = dir.Mid(i+1);
1317 dir = dir.Mid(0, i+1);
1326 bool marked = false;
1327 bool unmarked = false;
1329 for (int i = 0; i < itemdatasize; i++) {
1330 switch(itemdata[i]->GetMarked()) {
1344 if (marked && unmarked)
1360 wxbUtils::WaitForEnd(wxString(wxT("cd \"")) << dir << wxT("\"\n"));
1361 wxbUtils::WaitForEnd(wxString((state==1) ? wxT("mark") : wxT("unmark")) << wxT(" \"") << file << wxT("\"\n"));
1363 /* TODO: Check commands results */
1365 /*if ((dir == "/") && (file == "*")) {
1366 itemdata->SetMarked((itemdata->GetMarked() == 1) ? 0 : 1);
1369 if (listitems == NULL) { /* tree item state changed */
1370 SetTreeItemState(treeitem, state);
1371 /*treeitem = tree->GetSelection();
1372 UpdateTree(treeitem, true);
1373 treeitem = tree->GetItemParent(treeitem);*/
1376 for (int i = 0; i < itemdatasize; i++) {
1377 SetListItemState(listitems[i], state);
1379 listadd->Enable(state == 0);
1380 listremove->Enable(state == 1);
1381 /*UpdateTree(treeitem, (tree->GetSelection() == treeitem));
1382 treeitem = tree->GetItemParent(treeitem);*/
1385 /*while (treeitem.IsOk()) {
1386 WaitForList(treeitem, false);
1387 treeitem = tree->GetItemParent(treeitem);
1394 /*----------------------------------------------------------------------------
1396 ----------------------------------------------------------------------------*/
1398 /* Run a dir command, and waits until result is fully received. */
1399 void wxbRestorePanel::UpdateTreeItem(wxTreeItemId item, bool updatelist, bool recurse) {
1400 // this->updatelist = updatelist;
1401 wxbDataTokenizer* dt;
1403 dt = wxbUtils::WaitForEnd(wxString(wxT("cd \"")) <<
1404 static_cast<wxbTreeItemData*>(tree->GetItemData(item))
1405 ->GetPath() << wxT("\"\n"), false);
1407 /* TODO: check command result */
1414 list->DeleteAllItems();
1415 dt = wxbUtils::WaitForEnd(wxT(".dir\n"), true);
1419 for (unsigned int i = 0; i < dt->GetCount(); i++) {
1422 if (str.Find(wxT("cwd is:")) == 0) { // Sometimes cd command result "infiltrate" into listings.
1430 if (!ParseList(str, &entry))
1433 wxTreeItemId treeid;
1435 if (entry.fullname.GetChar(entry.fullname.Length()-1) == '/') {
1438 #if wxCHECK_VERSION(2, 6, 0)
1439 wxTreeItemIdValue cookie;
1444 treeid = tree->GetFirstChild(item, cookie);
1446 bool updated = false;
1448 while (treeid.IsOk()) {
1449 itemStr = ((wxbTreeItemData*)tree->GetItemData(treeid))->GetName();
1450 if (entry.filename == itemStr) {
1451 if (static_cast<wxbTreeItemData*>(tree->GetItemData(treeid))->GetMarked() != entry.marked) {
1452 tree->SetItemImage(treeid, entry.marked, wxTreeItemIcon_Normal);
1453 tree->SetItemImage(treeid, entry.marked, wxTreeItemIcon_Selected);
1454 static_cast<wxbTreeItemData*>(tree->GetItemData(treeid))->SetMarked(entry.marked);
1456 if ((recurse) && (tree->IsExpanded(treeid))) {
1457 UpdateTreeItem(treeid, false, true);
1462 treeid = tree->GetNextChild(item, cookie);
1466 treeid = tree->AppendItem(item, wxbUtils::ConvertToPrintable(entry.filename), entry.marked, entry.marked, new wxbTreeItemData(entry.fullname, entry.filename, entry.marked));
1471 long ind = list->InsertItem(list->GetItemCount(), entry.marked);
1472 wxbTreeItemData* data = new wxbTreeItemData(entry.fullname, entry.filename, entry.marked, ind);
1473 data->SetId(treeid);
1474 list->SetItemData(ind, (long)data);
1475 list->SetItem(ind, 1, wxbUtils::ConvertToPrintable(entry.filename));
1476 list->SetItem(ind, 2, entry.size);
1477 list->SetItem(ind, 3, entry.date);
1478 list->SetItem(ind, 4, entry.perm);
1479 list->SetItem(ind, 5, entry.user);
1480 list->SetItem(ind, 6, entry.group);
1490 /* Parse .dir command results, returns true if the result has been stored in entry, false otherwise. */
1491 int wxbRestorePanel::ParseList(wxString line, wxbDirEntry* entry) {
1492 /* See ls_output in dird/ua_tree.c */
1493 //-rw-r-----,1,root,root,41575,2005-10-18 18:21:36, ,/usr/var/bacula/working/bacula.sql
1495 wxStringTokenizer tkz(line, wxT(","));
1497 if (!tkz.HasMoreTokens())
1499 entry->perm = tkz.GetNextToken();
1501 if (!tkz.HasMoreTokens())
1503 entry->nlink = tkz.GetNextToken();
1505 if (!tkz.HasMoreTokens())
1507 entry->user = tkz.GetNextToken();
1509 if (!tkz.HasMoreTokens())
1511 entry->group = tkz.GetNextToken();
1513 if (!tkz.HasMoreTokens())
1515 entry->size = tkz.GetNextToken();
1517 if (!tkz.HasMoreTokens())
1519 entry->date = tkz.GetNextToken();
1521 if (!tkz.HasMoreTokens())
1523 wxString marked = tkz.GetNextToken();
1524 if (marked == wxT("*")) {
1527 else if (marked == wxT("+")) {
1534 if (!tkz.HasMoreTokens())
1536 entry->fullname = tkz.GetNextToken();
1538 /* Get only the filename (cut path by finding the last '/') */
1539 if (entry->fullname.GetChar(entry->fullname.Length()-1) == '/') {
1540 wxString tmp = entry->fullname;
1542 entry->filename = entry->fullname.Mid(tmp.Find('/', true)+1);
1545 entry->filename = entry->fullname.Mid(entry->fullname.Find('/', true)+1);
1551 /* Sets a list item state, and update its parents and children if it is a directory */
1552 void wxbRestorePanel::SetListItemState(long listitem, int newstate) {
1553 wxbTreeItemData* itemdata = (wxbTreeItemData*)list->GetItemData(listitem);
1555 wxTreeItemId treeitem;
1557 itemdata->SetMarked(newstate);
1558 list->SetItemImage(listitem, newstate, 0); /* TODO: Find what these ints are for */
1559 list->SetItemImage(listitem, newstate, 1);
1561 if ((treeitem = itemdata->GetId()).IsOk()) {
1562 SetTreeItemState(treeitem, newstate);
1565 UpdateTreeItemState(tree->GetSelection());
1569 /* Sets a tree item state, and update its children, parents and list (if necessary) */
1570 void wxbRestorePanel::SetTreeItemState(wxTreeItemId item, int newstate) {
1571 #if wxCHECK_VERSION(2, 6, 0)
1572 wxTreeItemIdValue cookie;
1576 wxTreeItemId currentChild = tree->GetFirstChild(item, cookie);
1578 wxbTreeItemData* itemdata;
1580 while (currentChild.IsOk()) {
1581 itemdata = (wxbTreeItemData*)tree->GetItemData(currentChild);
1582 int state = itemdata->GetMarked();
1584 if (state != newstate) {
1585 itemdata->SetMarked(newstate);
1586 tree->SetItemImage(currentChild, newstate, wxTreeItemIcon_Normal);
1587 tree->SetItemImage(currentChild, newstate, wxTreeItemIcon_Selected);
1590 currentChild = tree->GetNextChild(item, cookie);
1593 itemdata = (wxbTreeItemData*)tree->GetItemData(item);
1594 itemdata->SetMarked(newstate);
1595 tree->SetItemImage(item, newstate, wxTreeItemIcon_Normal);
1596 tree->SetItemImage(item, newstate, wxTreeItemIcon_Selected);
1599 if (tree->GetSelection() == item) {
1600 for (long i = 0; i < list->GetItemCount(); i++) {
1601 list->SetItemImage(i, newstate, 0); /* TODO: Find what these ints are for */
1602 list->SetItemImage(i, newstate, 1);
1606 UpdateTreeItemState(tree->GetItemParent(item));
1609 /* Update a tree item state, and its parents' state */
1610 void wxbRestorePanel::UpdateTreeItemState(wxTreeItemId item) {
1617 #if wxCHECK_VERSION(2, 6, 0)
1618 wxTreeItemIdValue cookie;
1622 wxTreeItemId currentChild = tree->GetFirstChild(item, cookie);
1624 bool onechildmarked = false;
1625 bool onechildunmarked = false;
1627 while (currentChild.IsOk()) {
1628 state = ((wxbTreeItemData*)tree->GetItemData(currentChild))->GetMarked();
1631 onechildunmarked = true;
1634 onechildmarked = true;
1637 onechildmarked = true;
1638 onechildunmarked = true;
1642 if (onechildmarked && onechildunmarked) {
1646 currentChild = tree->GetNextChild(item, cookie);
1649 if (tree->GetSelection() == item) {
1650 for (long i = 0; i < list->GetItemCount(); i++) {
1651 state = ((wxbTreeItemData*)list->GetItemData(i))->GetMarked();
1655 onechildunmarked = true;
1658 onechildmarked = true;
1661 onechildmarked = true;
1662 onechildunmarked = true;
1666 if (onechildmarked && onechildunmarked) {
1674 if (onechildmarked && onechildunmarked) {
1677 else if (onechildmarked) {
1680 else if (onechildunmarked) {
1683 else { // no child, don't change anything
1684 UpdateTreeItemState(tree->GetItemParent(item));
1688 wxbTreeItemData* itemdata = (wxbTreeItemData*)tree->GetItemData(item);
1690 itemdata->SetMarked(state);
1691 tree->SetItemImage(item, state, wxTreeItemIcon_Normal);
1692 tree->SetItemImage(item, state, wxTreeItemIcon_Selected);
1694 UpdateTreeItemState(tree->GetItemParent(item));
1697 /* Refresh the whole tree. */
1698 void wxbRestorePanel::RefreshTree() {
1699 /* Save current selection */
1700 wxArrayString current;
1702 wxTreeItemId item = currentTreeItem;
1704 while ((item.IsOk()) && (item != tree->GetRootItem())) {
1705 current.Add(tree->GetItemText(item));
1706 item = tree->GetItemParent(item);
1709 /* Update the tree */
1710 UpdateTreeItem(tree->GetRootItem(), false, true);
1712 /* Reselect the former selected item */
1713 item = tree->GetRootItem();
1715 if (current.Count() == 0) {
1716 tree->SelectItem(item);
1722 for (int i = current.Count()-1; i >= 0; i--) {
1723 #if wxCHECK_VERSION(2, 6, 0)
1724 wxTreeItemIdValue cookie;
1728 wxTreeItemId currentChild = tree->GetFirstChild(item, cookie);
1732 while (currentChild.IsOk()) {
1733 if (((wxbTreeItemData*)tree->GetItemData(currentChild))->GetName() == current[i]) {
1734 item = currentChild;
1739 currentChild = tree->GetNextChild(item, cookie);
1745 UpdateTreeItem(item, true, false); /* Update the list */
1747 tree->SelectItem(item);
1750 void wxbRestorePanel::RefreshList() {
1751 if (currentTreeItem.IsOk()) {
1752 UpdateTreeItem(currentTreeItem, true, false); /* Update the list */
1756 /* Update first config, adapting settings to the job name selected */
1757 void wxbRestorePanel::UpdateFirstConfig() {
1758 configPanel->Enable(false);
1759 wxbDataTokenizer* dt = wxbUtils::WaitForEnd(wxString(wxT(".defaults job=")) + configPanel->GetRowString(_("Job Name")) + wxT("\n"), true, false);
1765 * where=/tmp/bacula-restores
1775 bool dolistjobs = false;
1777 for (i = 0; i < dt->GetCount(); i++) {
1779 if ((j = str.Find('=')) > -1) {
1780 name = str.Mid(0, j);
1781 if (name == wxT("pool")) {
1782 configPanel->SetRowString(_("Pool"), str.Mid(j+1));
1784 else if (name == wxT("client")) {
1786 if ((str != configPanel->GetRowString(_("Client"))) ||
1787 (configPanel->GetRowString(_("Before"))) == wxT("")) {
1788 configPanel->SetRowString(_("Client"), str);
1792 else if (name == wxT("storage")) {
1793 configPanel->SetRowString(_("Storage"), str.Mid(j+1));
1795 else if (name == wxT("fileset")) {
1797 if ((str != configPanel->GetRowString(_("Fileset"))) ||
1798 (configPanel->GetRowString(_("Before"))) == wxT("")) {
1799 configPanel->SetRowString(_("Fileset"), str);
1809 //wxTheApp->Yield(false);
1812 configPanel->Enable(true);
1816 * Update second config.
1819 * JobName: RestoreFiles
1820 * Bootstrap: /var/lib/bacula/restore.bsr
1821 * Where: /tmp/bacula-restores
1826 * When: 2004-04-18 01:18:56
1828 * OK to run? (yes/mod/no):
1831 bool wxbRestorePanel::UpdateSecondConfig(wxbDataTokenizer* dt) {
1833 for (i = 0; i < dt->GetCount(); i++) {
1834 if ((*dt)[i].Find(_("Run Restore job")) == 0)
1838 if ((i + 10) > dt->GetCount()) {
1844 if ((k = (*dt)[++i].Find(_("JobName:"))) != 0) return false;
1845 restorePanel->SetRowString(_("Job Name"), (*dt)[i].Mid(10).Trim(false).RemoveLast());
1846 if ((k = (*dt)[++i].Find(_("Bootstrap:"))) != 0) return false;
1847 restorePanel->SetRowString(_("Bootstrap"), (*dt)[i].Mid(10).Trim(false).RemoveLast());
1848 if ((k = (*dt)[++i].Find(_("Where:"))) != 0) return false;
1849 restorePanel->SetRowString(_("Where"), (*dt)[i].Mid(10).Trim(false).RemoveLast());
1851 if ((k = (*dt)[++i].Find(_("Replace:"))) != 0) return false;
1852 wxString str = (*dt)[i].Mid(10).Trim(false).RemoveLast();
1853 if (str == _("always")) restorePanel->SetRowSelection(_("Replace"), 0);
1854 else if (str == _("ifnewer")) restorePanel->SetRowSelection(_("Replace"), 1);
1855 else if (str == _("ifolder")) restorePanel->SetRowSelection(_("Replace"), 2);
1856 else if (str == _("never")) restorePanel->SetRowSelection(_("Replace"), 3);
1857 else restorePanel->SetRowSelection(_("Replace"), 0);
1859 if ((k = (*dt)[++i].Find(_("FileSet:"))) != 0) return false;
1860 restorePanel->SetRowString(_("Fileset"), (*dt)[i].Mid(10).Trim(false).RemoveLast());
1861 if ((k = (*dt)[++i].Find(_("Client:"))) != 0) return false;
1862 restorePanel->SetRowString(_("Client"), (*dt)[i].Mid(10).Trim(false).RemoveLast());
1863 if ((k = (*dt)[++i].Find(_("Storage:"))) != 0) return false;
1864 restorePanel->SetRowString(_("Storage"), (*dt)[i].Mid(10).Trim(false).RemoveLast());
1865 if ((k = (*dt)[++i].Find(_("When:"))) != 0) return false;
1866 restorePanel->SetRowString(_("When"), (*dt)[i].Mid(10).Trim(false).RemoveLast());
1867 if ((k = (*dt)[++i].Find(_("Priority:"))) != 0) return false;
1868 restorePanel->SetRowString(_("Priority"), (*dt)[i].Mid(10).Trim(false).RemoveLast());
1871 restorePanel->Layout();
1876 /*----------------------------------------------------------------------------
1878 ----------------------------------------------------------------------------*/
1880 /* Set current status by enabling/disabling components */
1881 void wxbRestorePanel::SetStatus(status_enum newstatus) {
1882 switch (newstatus) {
1884 centerSizer->Remove(configPanel);
1885 centerSizer->Remove(restorePanel);
1886 centerSizer->Remove(treelistPanel);
1887 treelistPanel->Show(false);
1888 restorePanel->Show(false);
1889 centerSizer->Add(configPanel, 1, wxEXPAND);
1890 configPanel->Show(true);
1891 configPanel->Layout();
1892 centerSizer->Layout();
1894 start->SetLabel(_("Enter restore mode"));
1895 start->Enable(false);
1896 configPanel->Enable(false);
1897 tree->Enable(false);
1898 list->Enable(false);
1899 gauge->Enable(false);
1900 cancel->Enable(false);
1905 centerSizer->Remove(configPanel);
1906 centerSizer->Remove(restorePanel);
1907 centerSizer->Remove(treelistPanel);
1908 treelistPanel->Show(false);
1909 restorePanel->Show(false);
1910 centerSizer->Add(configPanel, 1, wxEXPAND);
1911 configPanel->Show(true);
1912 configPanel->Layout();
1913 centerSizer->Layout();
1915 tree->DeleteAllItems();
1916 list->DeleteAllItems();
1917 configPanel->ClearRowChoices(_("Client"));
1918 configPanel->ClearRowChoices(_("Before"));
1919 wxbMainFrame::GetInstance()->EnablePanels();
1920 newstatus = activable;
1923 start->SetLabel(_("Enter restore mode"));
1924 start->Enable(true);
1925 configPanel->Enable(false);
1926 tree->Enable(false);
1927 list->Enable(false);
1928 gauge->Enable(false);
1929 cancel->Enable(false);
1933 wxbMainFrame::GetInstance()->DisablePanels(this);
1935 start->Enable(false);
1936 //start->SetLabel(_("Choose files to restore"));
1937 configPanel->Enable(true);
1938 tree->Enable(false);
1939 list->Enable(false);
1940 cancel->Enable(true);
1947 start->Enable(true);
1948 start->SetLabel(_("Restore"));
1949 centerSizer->Remove(configPanel);
1950 configPanel->Show(false);
1951 centerSizer->Add(treelistPanel, 1, wxEXPAND);
1952 treelistPanel->Show(true);
1953 treelistPanel->Layout();
1954 centerSizer->Layout();
1961 start->Enable(false);
1962 configPanel->Enable(false);
1963 tree->Enable(false);
1964 list->Enable(false);
1965 centerSizer->Remove(treelistPanel);
1966 treelistPanel->Show(false);
1967 centerSizer->Add(restorePanel, 1, wxEXPAND);
1968 restorePanel->Show(true);
1969 restorePanel->Layout();
1970 centerSizer->Layout();
1972 restorePanel->EnableApply(false);
1975 start->SetLabel(_("Restoring..."));
1976 gauge->Enable(true);
1978 start->Enable(false);
1979 configPanel->Enable(false);
1980 tree->Enable(false);
1981 list->Enable(false);
1988 /*----------------------------------------------------------------------------
1990 ----------------------------------------------------------------------------*/
1992 void wxbRestorePanel::SetWorking(bool working) {
1993 this->working = working;
1995 SetCursor(*wxHOURGLASS_CURSOR);
1996 // SetEvtHandlerEnabled(false); //EVTQUEUE
1998 // else if (!processing) { /* Empty event queue if we aren't already doing this */ //EVTQUEUE
2000 // processing = true; //EVTQUEUE
2001 SetCursor(*wxSTANDARD_CURSOR);
2002 // SetEvtHandlerEnabled(true); //EVTQUEUE
2003 /* wxNode *node = pendingEvents->First(); //EVTQUEUE
2005 wxEvent *event = (wxEvent *)node->Data();
2008 wxEvtHandler::ProcessEvent(*event);
2011 node = pendingEvents->First();
2013 processing = false;*/
2017 bool wxbRestorePanel::IsWorking() {
2018 return this->working;
2021 void wxbRestorePanel::EnableConfig(bool enable) {
2022 restorePanel->Enable(enable);
2025 /*----------------------------------------------------------------------------
2027 ----------------------------------------------------------------------------*/
2032 bool wxbRestorePanel::ProcessEvent(wxEvent& event) {
2033 if (IsWorking() || processing) {
2034 wxEvent *eventCopy = event.Clone();
2036 pendingEvents->Append(eventCopy);
2040 return wxEvtHandler::ProcessEvent(event);
2045 void wxbRestorePanel::OnCancel(wxCommandEvent& event) {
2046 cancel->Enable(false);
2047 SetCursor(*wxHOURGLASS_CURSOR);
2049 SetCursor(*wxSTANDARD_CURSOR);
2052 void wxbRestorePanel::OnStart(wxCommandEvent& event) {
2061 void wxbRestorePanel::OnTreeChanging(wxTreeEvent& event) {
2067 void wxbRestorePanel::OnTreeExpanding(wxTreeEvent& event) {
2073 //CmdList(event.GetItem());
2074 if (tree->GetSelection() != event.GetItem()) {
2075 tree->SelectItem(event.GetItem());
2080 void wxbRestorePanel::OnTreeChanged(wxTreeEvent& event) {
2084 if (currentTreeItem == event.GetItem()) {
2087 treeadd->Enable(false);
2088 treeremove->Enable(false);
2089 treerefresh->Enable(false);
2090 markWhenCommandDone = false;
2092 currentTreeItem = event.GetItem();
2093 CmdList(event.GetItem());
2094 if (markWhenCommandDone) {
2095 CmdMark(event.GetItem(), NULL, 0);
2099 if (event.GetItem().IsOk()) {
2100 int status = ((wxbTreeItemData*)tree->GetItemData(event.GetItem()))->GetMarked();
2101 treeadd->Enable(status != 1);
2102 treeremove->Enable(status != 0);
2104 treerefresh->Enable(true);
2107 void wxbRestorePanel::OnTreeMarked(wxbTreeMarkedEvent& event) {
2109 if (tree->GetSelection() == event.GetItem()) {
2110 markWhenCommandDone = !markWhenCommandDone;
2115 markWhenCommandDone = false;
2116 CmdMark(event.GetItem(), NULL, 0);
2117 if (markWhenCommandDone) {
2118 CmdMark(event.GetItem(), NULL, 0);
2123 if (event.GetItem().IsOk()) {
2124 int status = ((wxbTreeItemData*)tree->GetItemData(event.GetItem()))->GetMarked();
2125 treeadd->Enable(status != 1);
2126 treeremove->Enable(status != 0);
2130 void wxbRestorePanel::OnTreeAdd(wxCommandEvent& event) {
2135 if (currentTreeItem.IsOk()) {
2137 CmdMark(currentTreeItem, NULL, 0, 1);
2140 treeremove->Enable(1);
2145 void wxbRestorePanel::OnTreeRemove(wxCommandEvent& event) {
2150 if (currentTreeItem.IsOk()) {
2152 CmdMark(currentTreeItem, NULL, 0, 0);
2155 treeremove->Enable(0);
2160 void wxbRestorePanel::OnTreeRefresh(wxCommandEvent& event) {
2170 void wxbRestorePanel::OnListMarked(wxbListMarkedEvent& event) {
2175 if (list->GetSelectedItemCount() == 0) {
2181 long* items = new long[list->GetSelectedItemCount()];
2185 long item = list->GetNextItem(-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
2186 while (item != -1) {
2189 item = list->GetNextItem(item, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
2192 CmdMark(wxTreeItemId(), items, num);
2196 wxListEvent listevt;
2198 OnListChanged(listevt);
2205 void wxbRestorePanel::OnListActivated(wxListEvent& event) {
2210 long item = event.GetIndex();
2211 // long item = list->GetNextItem(-1, wxLIST_NEXT_ALL, wxLIST_STATE_FOCUSED);
2213 wxbTreeItemData* itemdata = (wxbTreeItemData*)list->GetItemData(item);
2214 wxString name = itemdata->GetName();
2219 #if wxCHECK_VERSION(2, 6, 0)
2220 wxTreeItemIdValue cookie;
2225 if (name.GetChar(name.Length()-1) == '/') {
2226 wxTreeItemId currentChild = tree->GetFirstChild(currentTreeItem, cookie);
2228 while (currentChild.IsOk()) {
2229 wxString name2 = ((wxbTreeItemData*)tree->GetItemData(currentChild))->GetName();
2230 if (name2 == name) {
2231 //tree->UnselectAll();
2233 tree->Expand(currentTreeItem);
2234 tree->SelectItem(currentChild);
2238 currentChild = tree->GetNextChild(currentTreeItem, cookie);
2245 void wxbRestorePanel::OnListChanged(wxListEvent& event) {
2250 listadd->Enable(false);
2251 listremove->Enable(false);
2253 bool marked = false;
2254 bool unmarked = false;
2256 long item = list->GetNextItem(-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
2257 while (item != -1) {
2258 switch (((wxbTreeItemData*)list->GetItemData(item))->GetMarked()) {
2271 // Should never happen
2273 if (marked && unmarked) break;
2274 item = list->GetNextItem(item, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
2277 listadd->Enable(unmarked);
2278 listremove->Enable(marked);
2281 void wxbRestorePanel::OnListAdd(wxCommandEvent& event) {
2288 long* items = new long[list->GetSelectedItemCount()];
2292 long item = list->GetNextItem(-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
2293 while (item != -1) {
2296 item = list->GetNextItem(item, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
2299 CmdMark(wxTreeItemId(), items, num, 1);
2306 listadd->Enable(false);
2307 listremove->Enable(true);
2310 void wxbRestorePanel::OnListRemove(wxCommandEvent& event) {
2317 long* items = new long[list->GetSelectedItemCount()];
2321 long item = list->GetNextItem(-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
2322 while (item != -1) {
2325 item = list->GetNextItem(item, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
2328 CmdMark(wxTreeItemId(), items, num, 0);
2335 listadd->Enable(true);
2336 listremove->Enable(false);
2339 void wxbRestorePanel::OnListRefresh(wxCommandEvent& event) {
2349 void wxbRestorePanel::OnConfigUpdated(wxCommandEvent& event) {
2350 if (status == entered) {
2351 if (event.GetId() == ConfigJobName) {
2356 UpdateFirstConfig();
2359 else if ((event.GetId() == ConfigClient) || (event.GetId() == ConfigFileset)) {
2364 configPanel->Enable(false);
2366 configPanel->Enable(true);
2369 cfgUpdated = cfgUpdated | (1 << event.GetId());
2371 else if (status == configuring) {
2372 restorePanel->EnableApply(true);
2373 cfgUpdated = cfgUpdated | (1 << event.GetId());
2377 void wxbRestorePanel::OnConfigOk(wxCommandEvent& WXUNUSED(event)) {
2378 if (status != configuring) return;
2387 void wxbRestorePanel::OnConfigApply(wxCommandEvent& WXUNUSED(event)) {
2388 if (status != configuring) return;
2394 if (cfgUpdated == 0) {
2395 restorePanel->EnableApply(false);
2400 void wxbRestorePanel::OnConfigCancel(wxCommandEvent& WXUNUSED(event)) {
2401 if (status != configuring) return;