3 * wxbPanel for restoring files
5 * Nicolas Boichat, April-July 2004
10 Copyright (C) 2004-2006 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):
53 #include "wxbrestorepanel.h"
54 #include "wxbmainframe.h"
56 #include <wx/choice.h>
57 #include <wx/datetime.h>
59 #include "unmarked.xpm"
61 #include "partmarked.xpm"
62 #include <wx/listimpl.cpp>
64 /* A macro named Yield is defined under MinGW */
67 WX_DEFINE_LIST(wxbEventList);
70 * Class which is stored in the tree and in the list to keep informations
73 class wxbTreeItemData : public wxTreeItemData {
75 wxbTreeItemData(wxString path, wxString name, int marked, long listid = -1);
81 void SetMarked(int marked);
85 wxString* path; /* Full path */
86 wxString* name; /* File name */
87 int marked; /* 0 - Not Marked, 1 - Marked, 2 - Some file under is marked */
88 long listid; /* list ID : >-1 if this data is in the list (and/or on the tree) */
91 wxbTreeItemData::wxbTreeItemData(wxString path, wxString name, int marked, long listid): wxTreeItemData() {
92 this->path = new wxString(path);
93 this->name = new wxString(name);
94 this->marked = marked;
95 this->listid = listid;
98 wxbTreeItemData::~wxbTreeItemData() {
103 int wxbTreeItemData::GetMarked() {
107 void wxbTreeItemData::SetMarked(int marked) {
108 this->marked = marked;
111 long wxbTreeItemData::GetListId() {
115 wxString wxbTreeItemData::GetPath() {
119 wxString wxbTreeItemData::GetName() {
123 // ----------------------------------------------------------------------------
124 // event tables and other macros for wxWindows
125 // ----------------------------------------------------------------------------
153 BEGIN_EVENT_TABLE(wxbRestorePanel, wxPanel)
154 EVT_BUTTON(RestoreStart, wxbRestorePanel::OnStart)
155 EVT_BUTTON(RestoreCancel, wxbRestorePanel::OnCancel)
157 EVT_TREE_SEL_CHANGING(TreeCtrl, wxbRestorePanel::OnTreeChanging)
158 EVT_TREE_SEL_CHANGED(TreeCtrl, wxbRestorePanel::OnTreeChanged)
159 EVT_TREE_ITEM_EXPANDING(TreeCtrl, wxbRestorePanel::OnTreeExpanding)
160 EVT_TREE_MARKED_EVENT(TreeCtrl, wxbRestorePanel::OnTreeMarked)
161 EVT_BUTTON(TreeAdd, wxbRestorePanel::OnTreeAdd)
162 EVT_BUTTON(TreeRemove, wxbRestorePanel::OnTreeRemove)
163 EVT_BUTTON(TreeRefresh, wxbRestorePanel::OnTreeRefresh)
165 EVT_LIST_ITEM_ACTIVATED(ListCtrl, wxbRestorePanel::OnListActivated)
166 EVT_LIST_MARKED_EVENT(ListCtrl, wxbRestorePanel::OnListMarked)
167 EVT_LIST_ITEM_SELECTED(ListCtrl, wxbRestorePanel::OnListChanged)
168 EVT_LIST_ITEM_DESELECTED(ListCtrl, wxbRestorePanel::OnListChanged)
169 EVT_BUTTON(ListAdd, wxbRestorePanel::OnListAdd)
170 EVT_BUTTON(ListRemove, wxbRestorePanel::OnListRemove)
171 EVT_BUTTON(ListRefresh, wxbRestorePanel::OnListRefresh)
173 EVT_TEXT(ConfigWhere, wxbRestorePanel::OnConfigUpdated)
174 EVT_TEXT(ConfigWhen, wxbRestorePanel::OnConfigUpdated)
175 EVT_TEXT(ConfigPriority, wxbRestorePanel::OnConfigUpdated)
176 EVT_CHOICE(ConfigWhen, wxbRestorePanel::OnConfigUpdated)
177 EVT_CHOICE(ConfigReplace, wxbRestorePanel::OnConfigUpdated)
178 EVT_CHOICE(ConfigClient, wxbRestorePanel::OnConfigUpdated)
179 EVT_CHOICE(ConfigFileset, wxbRestorePanel::OnConfigUpdated)
180 EVT_CHOICE(ConfigStorage, wxbRestorePanel::OnConfigUpdated)
181 EVT_CHOICE(ConfigJobName, wxbRestorePanel::OnConfigUpdated)
182 EVT_CHOICE(ConfigPool, wxbRestorePanel::OnConfigUpdated)
184 EVT_BUTTON(ConfigOk, wxbRestorePanel::OnConfigOk)
185 EVT_BUTTON(ConfigApply, wxbRestorePanel::OnConfigApply)
186 EVT_BUTTON(ConfigCancel, wxbRestorePanel::OnConfigCancel)
190 * wxbRestorePanel constructor
192 wxbRestorePanel::wxbRestorePanel(wxWindow* parent): wxbPanel(parent)
194 //pendingEvents = new wxbEventList(); //EVTQUEUE
195 //processing = false; //EVTQUEUE
198 imagelist = new wxImageList(16, 16, TRUE, 3);
199 imagelist->Add(wxIcon(unmarked_xpm));
200 imagelist->Add(wxIcon(marked_xpm));
201 imagelist->Add(wxIcon(partmarked_xpm));
203 wxFlexGridSizer* mainSizer = new wxFlexGridSizer(3, 1, 10, 10);
204 mainSizer->AddGrowableCol(0);
205 mainSizer->AddGrowableRow(1);
207 wxFlexGridSizer *firstSizer = new wxFlexGridSizer(1, 2, 10, 10);
209 firstSizer->AddGrowableCol(0);
210 firstSizer->AddGrowableRow(0);
212 start = new wxButton(this, RestoreStart, _("Enter restore mode"), wxDefaultPosition, wxSize(150, 30));
213 firstSizer->Add(start, 0, wxALIGN_CENTER_HORIZONTAL | wxALIGN_CENTER_VERTICAL, 10);
215 cancel = new wxButton(this, RestoreCancel, _("Cancel restore"), wxDefaultPosition, wxSize(150, 30));
216 firstSizer->Add(cancel, 0, wxALIGN_CENTER_HORIZONTAL | wxALIGN_RIGHT, 10);
220 /* clientChoice = new wxChoice(this, ClientChoice, wxDefaultPosition, wxSize(150, 30), 0, elist);
221 firstSizer->Add(clientChoice, 1, wxALIGN_CENTER_HORIZONTAL | wxALIGN_CENTER_VERTICAL, 10);
223 jobChoice = new wxChoice(this, -1, wxDefaultPosition, wxSize(150, 30), 0, elist);
224 firstSizer->Add(jobChoice, 1, wxALIGN_CENTER_HORIZONTAL | wxALIGN_CENTER_VERTICAL, 10);*/
226 mainSizer->Add(firstSizer, 1, wxEXPAND, 10);
228 treelistPanel = new wxSplitterWindow(this);
230 wxPanel* treePanel = new wxPanel(treelistPanel);
231 wxFlexGridSizer *treeSizer = new wxFlexGridSizer(2, 1, 0, 0);
232 treeSizer->AddGrowableCol(0);
233 treeSizer->AddGrowableRow(0);
235 tree = new wxbTreeCtrl(treePanel, this, TreeCtrl, wxDefaultPosition, wxSize(200,50));
236 tree->SetImageList(imagelist);
238 treeSizer->Add(tree, 1, wxEXPAND, 0);
240 wxBoxSizer *treeCtrlSizer = new wxBoxSizer(wxHORIZONTAL);
241 treeadd = new wxButton(treePanel, TreeAdd, _("Add"), wxDefaultPosition, wxSize(60, 25));
242 treeCtrlSizer->Add(treeadd, 0, wxLEFT | wxRIGHT, 3);
243 treeremove = new wxButton(treePanel, TreeRemove, _("Remove"), wxDefaultPosition, wxSize(60, 25));
244 treeCtrlSizer->Add(treeremove, 0, wxLEFT | wxRIGHT, 3);
245 treerefresh = new wxButton(treePanel, TreeRefresh, _("Refresh"), wxDefaultPosition, wxSize(60, 25));
246 treeCtrlSizer->Add(treerefresh, 0, wxLEFT | wxRIGHT, 3);
248 treeSizer->Add(treeCtrlSizer, 1, wxALIGN_CENTER_HORIZONTAL, 0);
250 treePanel->SetSizer(treeSizer);
252 wxPanel* listPanel = new wxPanel(treelistPanel);
253 wxFlexGridSizer *listSizer = new wxFlexGridSizer(2, 1, 0, 0);
254 listSizer->AddGrowableCol(0);
255 listSizer->AddGrowableRow(0);
257 list = new wxbListCtrl(listPanel, this, ListCtrl, wxDefaultPosition, wxSize(200,50));
258 //treelistSizer->Add(list, 1, wxEXPAND, 10);
260 list->SetImageList(imagelist, wxIMAGE_LIST_SMALL);
263 info.SetMask(wxLIST_MASK_TEXT | wxLIST_MASK_FORMAT);
264 info.SetText(_("M"));
265 info.SetAlign(wxLIST_FORMAT_CENTER);
266 list->InsertColumn(0, info);
268 info.SetText(_("Filename"));
269 info.SetAlign(wxLIST_FORMAT_LEFT);
270 list->InsertColumn(1, info);
272 info.SetText(_("Size"));
273 info.SetAlign(wxLIST_FORMAT_RIGHT);
274 list->InsertColumn(2, info);
276 info.SetText(_("Date"));
277 info.SetAlign(wxLIST_FORMAT_LEFT);
278 list->InsertColumn(3, info);
280 info.SetText(_("Perm."));
281 info.SetAlign(wxLIST_FORMAT_LEFT);
282 list->InsertColumn(4, info);
284 info.SetText(_("User"));
285 info.SetAlign(wxLIST_FORMAT_RIGHT);
286 list->InsertColumn(5, info);
288 info.SetText(_("Group"));
289 info.SetAlign(wxLIST_FORMAT_RIGHT);
290 list->InsertColumn(6, info);
292 listSizer->Add(list, 1, wxEXPAND, 0);
294 wxBoxSizer *listCtrlSizer = new wxBoxSizer(wxHORIZONTAL);
295 listadd = new wxButton(listPanel, ListAdd, _("Add"), wxDefaultPosition, wxSize(60, 25));
296 listCtrlSizer->Add(listadd, 0, wxLEFT | wxRIGHT, 5);
297 listremove = new wxButton(listPanel, ListRemove, _("Remove"), wxDefaultPosition, wxSize(60, 25));
298 listCtrlSizer->Add(listremove, 0, wxLEFT | wxRIGHT, 5);
299 listrefresh = new wxButton(listPanel, ListRefresh, _("Refresh"), wxDefaultPosition, wxSize(60, 25));
300 listCtrlSizer->Add(listrefresh, 0, wxLEFT | wxRIGHT, 5);
302 listSizer->Add(listCtrlSizer, 1, wxALIGN_CENTER_HORIZONTAL, 0);
304 listPanel->SetSizer(listSizer);
306 treelistPanel->SplitVertically(treePanel, listPanel, 210);
308 treelistPanel->SetMinimumPaneSize(210);
310 treelistPanel->Show(false);
312 wxbConfig* config = new wxbConfig();
313 config->Add(new wxbConfigParam(_("Job Name"), ConfigJobName, choice, 0, elist));
314 config->Add(new wxbConfigParam(_("Client"), ConfigClient, choice, 0, elist));
315 config->Add(new wxbConfigParam(_("Fileset"), ConfigFileset, choice, 0, elist));
316 config->Add(new wxbConfigParam(_("Pool"), ConfigPool, choice, 0, elist));
317 config->Add(new wxbConfigParam(_("Storage"), ConfigStorage, choice, 0, elist));
318 config->Add(new wxbConfigParam(_("Before"), ConfigWhen, choice, 0, elist));
320 configPanel = new wxbConfigPanel(this, config, _("Please configure parameters concerning files to restore :"), RestoreStart, RestoreCancel, -1);
322 configPanel->Show(true);
323 configPanel->Enable(false);
325 config = new wxbConfig();
326 config->Add(new wxbConfigParam(_("Job Name"), -1, text, wxT("")));
327 config->Add(new wxbConfigParam(_("Bootstrap"), -1, text, wxT("")));
328 config->Add(new wxbConfigParam(_("Where"), ConfigWhere, modifiableText, wxT("")));
329 wxString erlist[] = {_("always"), _("if newer"), _("if older"), _("never")};
330 config->Add(new wxbConfigParam(_("Replace"), ConfigReplace, choice, 4, erlist));
331 config->Add(new wxbConfigParam(_("Fileset"), ConfigFileset, choice, 0, erlist));
332 config->Add(new wxbConfigParam(_("Client"), ConfigClient, choice, 0, erlist));
333 config->Add(new wxbConfigParam(_("Storage"), ConfigStorage, choice, 0, erlist));
334 config->Add(new wxbConfigParam(_("When"), ConfigWhen, modifiableText, wxT("")));
335 config->Add(new wxbConfigParam(_("Priority"), ConfigPriority, modifiableText, wxT("")));
337 restorePanel = new wxbConfigPanel(this, config, _("Please configure parameters concerning files restoration :"), ConfigOk, ConfigCancel, ConfigApply);
339 restorePanel->Show(false);
341 centerSizer = new wxBoxSizer(wxHORIZONTAL);
342 //centerSizer->Add(treelistPanel, 1, wxEXPAND | wxADJUST_MINSIZE);
344 mainSizer->Add(centerSizer, 1, wxEXPAND, 10);
346 gauge = new wxGauge(this, -1, 1, wxDefaultPosition, wxSize(200,20));
348 mainSizer->Add(gauge, 1, wxEXPAND, 5);
350 gauge->Enable(false);
353 mainSizer->SetSizeHints(this);
357 for (int i = 0; i < 7; i++) {
358 list->SetColumnWidth(i, 70);
361 SetCursor(*wxSTANDARD_CURSOR);
363 markWhenCommandDone = false;
369 * wxbRestorePanel destructor
371 wxbRestorePanel::~wxbRestorePanel()
376 /*----------------------------------------------------------------------------
377 wxbPanel overloadings
378 ----------------------------------------------------------------------------*/
380 wxString wxbRestorePanel::GetTitle()
385 void wxbRestorePanel::EnablePanel(bool enable)
388 if (status == disabled) {
389 SetStatus(activable);
396 /*----------------------------------------------------------------------------
397 Commands called by events handler
398 ----------------------------------------------------------------------------*/
400 /* The main button has been clicked */
401 void wxbRestorePanel::CmdStart()
404 if (status == activable) {
405 wxbMainFrame::GetInstance()->SetStatusText(_("Getting parameters list."));
406 wxbDataTokenizer* dt = wxbUtils::WaitForEnd(wxT(".clients\n"), true, false);
409 configPanel->ClearRowChoices(_("Client"));
410 restorePanel->ClearRowChoices(_("Client"));
412 if (dt->GetCount() == 0) {
413 wxbMainFrame::GetInstance()->SetStatusText(_("Error : no clients returned by the director."));
417 for (i = 0; i < dt->GetCount(); i++) {
420 configPanel->AddRowChoice(_("Client"), str);
421 restorePanel->AddRowChoice(_("Client"), str);
431 dt = wxbUtils::WaitForEnd(wxT(".filesets\n"), true, false);
433 configPanel->ClearRowChoices(_("Fileset"));
434 restorePanel->ClearRowChoices(_("Fileset"));
436 if (dt->GetCount() == 0) {
437 wxbMainFrame::GetInstance()->SetStatusText(_("Error : no filesets returned by the director."));
441 for (i = 0; i < dt->GetCount(); i++) {
444 configPanel->AddRowChoice(_("Fileset"), str);
445 restorePanel->AddRowChoice(_("Fileset"), str);
455 dt = wxbUtils::WaitForEnd(wxT(".storage\n"), true, false);
457 configPanel->ClearRowChoices(_("Storage"));
458 restorePanel->ClearRowChoices(_("Storage"));
460 if (dt->GetCount() == 0) {
461 wxbMainFrame::GetInstance()->SetStatusText(_("Error : no storage returned by the director."));
465 for (i = 0; i < dt->GetCount(); i++) {
468 configPanel->AddRowChoice(_("Storage"), str);
469 restorePanel->AddRowChoice(_("Storage"), str);
479 dt = wxbUtils::WaitForEnd(wxT(".jobs\n"), true, false);
481 configPanel->ClearRowChoices(_("Job Name"));
483 if (dt->GetCount() == 0) {
484 wxbMainFrame::GetInstance()->SetStatusText(_("Error : no jobs returned by the director."));
488 for (i = 0; i < dt->GetCount(); i++) {
491 configPanel->AddRowChoice(_("Job Name"), str);
494 configPanel->SetRowString(_("Job Name"), _("RestoreFiles"));
503 dt = wxbUtils::WaitForEnd(wxT(".pools\n"), true, false);
505 configPanel->ClearRowChoices(_("Pool"));
507 if (dt->GetCount() == 0) {
508 wxbMainFrame::GetInstance()->SetStatusText(_("Error : no jobs returned by the director."));
512 for (i = 0; i < dt->GetCount(); i++) {
515 configPanel->AddRowChoice(_("Pool"), str);
529 wxbMainFrame::GetInstance()->SetStatusText(_("Please configure your restore parameters."));
531 else if (status == entered) {
532 /* if (clientChoice->GetStringSelection().Length() < 1) {
533 wxbMainFrame::GetInstance()->SetStatusText(_("Please select a client."));
536 if (jobChoice->GetStringSelection().Length() < 1) {
537 wxbMainFrame::GetInstance()->SetStatusText(_("Please select a restore date."));
540 wxbMainFrame::GetInstance()->SetStatusText(_("Building restore tree..."));
544 wxbTableParser* tableparser = new wxbTableParser();
545 wxbDataTokenizer* dt = new wxbDataTokenizer(false);
548 * The following line was removed from ::GetInstance below because
549 * it does not work with multiple pools -- KES 5Oct05 see bug #433
550 * wxT("\" pool=\"") << configPanel->GetRowString(wxT("Pool")) <<
552 wxbMainFrame::GetInstance()->Send(wxString(wxT("restore")) <<
553 wxT(" client=\"") << configPanel->GetRowString(wxT("Client")) <<
554 wxT("\" fileset=\"") << configPanel->GetRowString(wxT("Fileset")) <<
555 wxT("\" storage=\"") << configPanel->GetRowString(wxT("Storage")) <<
556 wxT("\" before=\"") << configPanel->GetRowString(wxT("Before")) <<
558 //wxbUtils::WaitForPrompt("6\n");
560 /*wxbPromptParser *pp = wxbUtils::WaitForPrompt(wxString() << configPanel->GetRowString(wxT("Before")) << "\n", true);
561 int client = pp->getChoices()->Index(configPanel->GetRowString(wxT("Client")));
562 if (client == wxNOT_FOUND) {
563 wxbMainFrame::GetInstance()->SetStatusText("Failed to find the selected client.");
568 //wxbMainFrame::GetInstance()->Send(wxString() << configPanel->GetRowString(wxT("Before")) << "\n");
570 while (!tableparser->hasFinished() && !dt->hasFinished()) {
571 wxTheApp->Yield(true);
572 wxbUtils::MilliSleep(100);
577 if (dt->hasFinished() && !tableparser->hasFinished()) {
579 if (dt->GetCount() > 1) {
580 str = (*dt)[dt->GetCount()-2];
583 wxbMainFrame::GetInstance()->SetStatusText(wxString(_("Error while starting restore: ")) << str);
593 for (i = 0; i < tableparser->GetCount(); i++) {
594 str = (*tableparser)[i][2];
595 str.Replace(wxT(","), wxT(""));
596 if (str.ToLong(&l)) {
602 gauge->SetRange(tot);
604 /*wxbMainFrame::GetInstance()->Print(
605 wxString("[") << tot << "]", CS_DEBUG);*/
607 wxDateTime base = wxDateTime::Now();
611 unsigned int lastindex = 0;
618 newdate = wxDateTime::Now();
619 if (newdate.Subtract(base).GetMilliseconds() > 10 ) {
621 for (; lastindex < dt->GetCount(); lastindex++) {
622 if (((i1 = (*dt)[lastindex].Find(wxT("Building directory tree for JobId "))) >= 0) &&
623 ((i2 = (*dt)[lastindex].Find(wxT(" ..."))) > 0)) {
624 str = (*dt)[lastindex].Mid(i1+34, i2-(i1+34));
625 for (i = 0; i < tableparser->GetCount(); i++) {
626 if (str == (*tableparser)[i][0]) {
627 str = (*tableparser)[i][2];
628 str.Replace(wxT(","), wxT(""));
629 if (str.ToLong(&l)) {
632 var = (willdo-done)/50;
633 gauge->SetValue(done);
634 wxTheApp->Yield(true);
640 else if ((*dt)[lastindex] == wxT("+")) {
641 gauge->SetValue(gauge->GetValue()+var);
642 wxTheApp->Yield(true);
647 if (dt->hasFinished()) {
651 wxTheApp->Yield(true);
652 wxbUtils::MilliSleep(1);
655 gauge->SetValue(tot);
656 wxTheApp->Yield(true);
667 wxbUtils::WaitForEnd(wxT("unmark *\n"));
668 wxTreeItemId root = tree->AddRoot(configPanel->GetRowString(_("Client")), -1, -1, new wxbTreeItemData(wxT("/"), configPanel->GetRowString(_("Client")), 0));
669 currentTreeItem = root;
671 tree->SelectItem(root);
673 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."));
676 else if (status == choosing) {
680 wxbDataTokenizer* dt;
684 dt = new wxbDataTokenizer(true);
685 wxbPromptParser* promptparser = wxbUtils::WaitForPrompt(wxT("done\n"), true);
687 while (!promptparser->getChoices() || (promptparser->getChoices()->Index(wxT("mod")) < 0)) {
688 wxbMainFrame::GetInstance()->Print(_("Unexpected question has been received.\n"), CS_DEBUG);
691 if (promptparser->getIntroString() != wxT("")) {
692 message << promptparser->getIntroString() << wxT("\n");
694 message << promptparser->getQuestionString();
696 if (promptparser->getChoices()) {
697 wxString *choices = new wxString[promptparser->getChoices()->GetCount()];
698 int *numbers = new int[promptparser->getChoices()->GetCount()];
701 for (unsigned int i = 0; i < promptparser->getChoices()->GetCount(); i++) {
702 if ((*promptparser->getChoices())[i] != wxT("")) {
703 choices[n] = (*promptparser->getChoices())[i];
709 int res = ::wxGetSingleChoiceIndex(message,
710 _("wx-console: unexpected restore question."), n, choices, this);
713 promptparser = wxbUtils::WaitForPrompt(wxT(".\n"), true);
716 if (promptparser->isNumericalChoice()) {
718 promptparser = wxbUtils::WaitForPrompt(wxString() << numbers[res] << wxT("\n"), true);
722 promptparser = wxbUtils::WaitForPrompt(wxString() << choices[res] << wxT("\n"), true);
731 promptparser = wxbUtils::WaitForPrompt(::wxGetTextFromUser(message,
732 _("wx-console: unexpected restore question."),
733 wxT(""), this) + wxT("\n"));
736 printf("promptparser->getChoices()=%ld", (long)promptparser->getChoices());
740 SetStatus(configuring);
742 for (i = 0; i < dt->GetCount(); i++) {
743 if ((j = (*dt)[i].Find(_(" files selected to be restored."))) > -1) {
744 (*dt)[i].Mid(0, j).ToLong(&totfilemessages);
748 if ((j = (*dt)[i].Find(_(" file selected to be restored."))) > -1) {
749 (*dt)[i].Mid(0, j).ToLong(&totfilemessages);
754 wxbMainFrame::GetInstance()->SetStatusText(
755 wxString::Format(_("Please configure your restore (%ld files selected to be restored)..."), totfilemessages));
757 UpdateSecondConfig(dt);
762 restorePanel->EnableApply(false);
764 if (totfilemessages == 0) {
765 wxbMainFrame::GetInstance()->Print(_("Restore failed : no file selected.\n"), CS_DEBUG);
766 wxbMainFrame::GetInstance()->SetStatusText(_("Restore failed : no file selected."));
771 else if (status == configuring) {
772 cancel->Enable(false);
776 wxbMainFrame::GetInstance()->SetStatusText(_("Restoring, please wait..."));
778 wxbDataTokenizer* dt;
780 SetStatus(restoring);
781 dt = wxbUtils::WaitForEnd(wxT("yes\n"), true);
784 gauge->SetRange(totfilemessages);
788 for (i = 0; i < dt->GetCount(); i++) {
789 if ((j = (*dt)[i].Find(_("Job started. JobId="))) > -1) {
790 jobid = (*dt)[i].Mid(j+19);
791 wxbMainFrame::GetInstance()->SetStatusText(_("Restore started, jobid=") + jobid);
795 if ((j = (*dt)[i].Find(_("Job failed."))) > -1) {
796 wxbMainFrame::GetInstance()->Print(_("Restore failed, please look at messages.\n"), CS_DEBUG);
797 wxbMainFrame::GetInstance()->SetStatusText(_("Restore failed, please look at messages in console."));
802 if (jobid == wxT("")) {
803 wxbMainFrame::GetInstance()->Print(_("Failed to retrieve jobid.\n"), CS_DEBUG);
804 wxbMainFrame::GetInstance()->SetStatusText(_("Failed to retrieve jobid.\n"));
808 wxDateTime currenttime;
810 dt = wxbUtils::WaitForEnd(wxT("time\n"), true);
811 wxStringTokenizer ttkz((*dt)[0], wxT(" "), wxTOKEN_STRTOK);
812 if ((currenttime.ParseDate(ttkz.GetNextToken()) == NULL) || // Date
813 (currenttime.ParseTime(ttkz.GetNextToken()) == NULL)) { // Time
814 currenttime.SetYear(1990); // If parsing fails, set currenttime to a dummy date
817 currenttime -= wxTimeSpan::Seconds(30); //Adding a 30" tolerance
821 wxDateTime scheduledtime;
822 wxStringTokenizer stkz(restorePanel->GetRowString(_("When")), wxT(" "), wxTOKEN_STRTOK);
824 if ((scheduledtime.ParseDate(stkz.GetNextToken()) == NULL) || // Date
825 (scheduledtime.ParseTime(stkz.GetNextToken()) == NULL)) { // Time
826 scheduledtime.SetYear(2090); // If parsing fails, set scheduledtime to a dummy date
829 if (scheduledtime.Subtract(currenttime).IsLongerThan(wxTimeSpan::Seconds(150))) {
830 wxbMainFrame::GetInstance()->Print(_("Restore is scheduled in more than two minutes, wx-console will not wait for its completion.\n"), CS_DEBUG);
831 wxbMainFrame::GetInstance()->SetStatusText(_("Restore is scheduled in more than two minutes, wx-console will not wait for its completion."));
836 wxString cmd = wxString(wxT("list jobid=")) + jobid;
838 wxbTableParser* tableparser;
840 long filemessages = 0;
843 bool waitforever = false;
849 wxbUtils::WaitForEnd(wxT("autodisplay off\n"));
850 wxbUtils::WaitForEnd(wxT("gui on\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)
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)
1494 /* See ls_output in dird/ua_tree.c */
1495 //-rw-r-----,1,root,root,41575,2005-10-18 18:21:36, ,/usr/var/bacula/working/bacula.sql
1497 wxStringTokenizer tkz(line, wxT(","));
1499 if (!tkz.HasMoreTokens())
1501 entry->perm = tkz.GetNextToken();
1503 if (!tkz.HasMoreTokens())
1505 entry->nlink = tkz.GetNextToken();
1507 if (!tkz.HasMoreTokens())
1509 entry->user = tkz.GetNextToken();
1511 if (!tkz.HasMoreTokens())
1513 entry->group = tkz.GetNextToken();
1515 if (!tkz.HasMoreTokens())
1517 entry->size = tkz.GetNextToken();
1519 if (!tkz.HasMoreTokens())
1521 entry->date = tkz.GetNextToken();
1523 if (!tkz.HasMoreTokens())
1525 wxString marked = tkz.GetNextToken();
1526 if (marked == wxT("*")) {
1529 else if (marked == wxT("+")) {
1536 if (!tkz.HasMoreTokens())
1538 entry->fullname = tkz.GetString();
1540 /* Get only the filename (cut path by finding the last '/') */
1541 if (entry->fullname.GetChar(entry->fullname.Length()-1) == '/') {
1542 wxString tmp = entry->fullname;
1544 entry->filename = entry->fullname.Mid(tmp.Find('/', true)+1);
1547 entry->filename = entry->fullname.Mid(entry->fullname.Find('/', true)+1);
1553 /* Sets a list item state, and update its parents and children if it is a directory */
1554 void wxbRestorePanel::SetListItemState(long listitem, int newstate)
1556 wxbTreeItemData* itemdata = (wxbTreeItemData*)list->GetItemData(listitem);
1558 wxTreeItemId treeitem;
1560 itemdata->SetMarked(newstate);
1561 list->SetItemImage(listitem, newstate, 0); /* TODO: Find what these ints are for */
1562 list->SetItemImage(listitem, newstate, 1);
1564 if ((treeitem = itemdata->GetId()).IsOk()) {
1565 SetTreeItemState(treeitem, newstate);
1568 UpdateTreeItemState(tree->GetSelection());
1572 /* Sets a tree item state, and update its children, parents and list (if necessary) */
1573 void wxbRestorePanel::SetTreeItemState(wxTreeItemId item, int newstate) {
1574 #if wxCHECK_VERSION(2, 6, 0)
1575 wxTreeItemIdValue cookie;
1579 wxTreeItemId currentChild = tree->GetFirstChild(item, cookie);
1581 wxbTreeItemData* itemdata;
1583 while (currentChild.IsOk()) {
1584 itemdata = (wxbTreeItemData*)tree->GetItemData(currentChild);
1585 int state = itemdata->GetMarked();
1587 if (state != newstate) {
1588 itemdata->SetMarked(newstate);
1589 tree->SetItemImage(currentChild, newstate, wxTreeItemIcon_Normal);
1590 tree->SetItemImage(currentChild, newstate, wxTreeItemIcon_Selected);
1593 currentChild = tree->GetNextChild(item, cookie);
1596 itemdata = (wxbTreeItemData*)tree->GetItemData(item);
1597 itemdata->SetMarked(newstate);
1598 tree->SetItemImage(item, newstate, wxTreeItemIcon_Normal);
1599 tree->SetItemImage(item, newstate, wxTreeItemIcon_Selected);
1602 if (tree->GetSelection() == item) {
1603 for (long i = 0; i < list->GetItemCount(); i++) {
1604 list->SetItemImage(i, newstate, 0); /* TODO: Find what these ints are for */
1605 list->SetItemImage(i, newstate, 1);
1609 UpdateTreeItemState(tree->GetItemParent(item));
1612 /* Update a tree item state, and its parents' state */
1613 void wxbRestorePanel::UpdateTreeItemState(wxTreeItemId item) {
1620 #if wxCHECK_VERSION(2, 6, 0)
1621 wxTreeItemIdValue cookie;
1625 wxTreeItemId currentChild = tree->GetFirstChild(item, cookie);
1627 bool onechildmarked = false;
1628 bool onechildunmarked = false;
1630 while (currentChild.IsOk()) {
1631 state = ((wxbTreeItemData*)tree->GetItemData(currentChild))->GetMarked();
1634 onechildunmarked = true;
1637 onechildmarked = true;
1640 onechildmarked = true;
1641 onechildunmarked = true;
1645 if (onechildmarked && onechildunmarked) {
1649 currentChild = tree->GetNextChild(item, cookie);
1652 if (tree->GetSelection() == item) {
1653 for (long i = 0; i < list->GetItemCount(); i++) {
1654 state = ((wxbTreeItemData*)list->GetItemData(i))->GetMarked();
1658 onechildunmarked = true;
1661 onechildmarked = true;
1664 onechildmarked = true;
1665 onechildunmarked = true;
1669 if (onechildmarked && onechildunmarked) {
1677 if (onechildmarked && onechildunmarked) {
1680 else if (onechildmarked) {
1683 else if (onechildunmarked) {
1686 else { // no child, don't change anything
1687 UpdateTreeItemState(tree->GetItemParent(item));
1691 wxbTreeItemData* itemdata = (wxbTreeItemData*)tree->GetItemData(item);
1693 itemdata->SetMarked(state);
1694 tree->SetItemImage(item, state, wxTreeItemIcon_Normal);
1695 tree->SetItemImage(item, state, wxTreeItemIcon_Selected);
1697 UpdateTreeItemState(tree->GetItemParent(item));
1700 /* Refresh the whole tree. */
1701 void wxbRestorePanel::RefreshTree() {
1702 /* Save current selection */
1703 wxArrayString current;
1705 wxTreeItemId item = currentTreeItem;
1707 while ((item.IsOk()) && (item != tree->GetRootItem())) {
1708 current.Add(tree->GetItemText(item));
1709 item = tree->GetItemParent(item);
1712 /* Update the tree */
1713 UpdateTreeItem(tree->GetRootItem(), false, true);
1715 /* Reselect the former selected item */
1716 item = tree->GetRootItem();
1718 if (current.Count() == 0) {
1719 tree->SelectItem(item);
1725 for (int i = current.Count()-1; i >= 0; i--) {
1726 #if wxCHECK_VERSION(2, 6, 0)
1727 wxTreeItemIdValue cookie;
1731 wxTreeItemId currentChild = tree->GetFirstChild(item, cookie);
1735 while (currentChild.IsOk()) {
1736 if (((wxbTreeItemData*)tree->GetItemData(currentChild))->GetName() == current[i]) {
1737 item = currentChild;
1742 currentChild = tree->GetNextChild(item, cookie);
1748 UpdateTreeItem(item, true, false); /* Update the list */
1750 tree->SelectItem(item);
1753 void wxbRestorePanel::RefreshList() {
1754 if (currentTreeItem.IsOk()) {
1755 UpdateTreeItem(currentTreeItem, true, false); /* Update the list */
1759 /* Update first config, adapting settings to the job name selected */
1760 void wxbRestorePanel::UpdateFirstConfig() {
1761 configPanel->Enable(false);
1762 wxbDataTokenizer* dt = wxbUtils::WaitForEnd(wxString(wxT(".defaults job=")) + configPanel->GetRowString(_("Job Name")) + wxT("\n"), true, false);
1768 * where=/tmp/bacula-restores
1778 bool dolistjobs = false;
1780 for (i = 0; i < dt->GetCount(); i++) {
1782 if ((j = str.Find('=')) > -1) {
1783 name = str.Mid(0, j);
1784 if (name == wxT("pool")) {
1785 configPanel->SetRowString(_("Pool"), str.Mid(j+1));
1787 else if (name == wxT("client")) {
1789 if ((str != configPanel->GetRowString(_("Client"))) ||
1790 (configPanel->GetRowString(_("Before"))) == wxT("")) {
1791 configPanel->SetRowString(_("Client"), str);
1795 else if (name == wxT("storage")) {
1796 configPanel->SetRowString(_("Storage"), str.Mid(j+1));
1798 else if (name == wxT("fileset")) {
1800 if ((str != configPanel->GetRowString(_("Fileset"))) ||
1801 (configPanel->GetRowString(_("Before"))) == wxT("")) {
1802 configPanel->SetRowString(_("Fileset"), str);
1812 //wxTheApp->Yield(false);
1815 configPanel->Enable(true);
1819 * Update second config.
1822 * JobName: RestoreFiles
1823 * Bootstrap: /var/lib/bacula/restore.bsr
1824 * Where: /tmp/bacula-restores
1829 * When: 2004-04-18 01:18:56
1831 * OK to run? (yes/mod/no):
1834 bool wxbRestorePanel::UpdateSecondConfig(wxbDataTokenizer* dt) {
1836 for (i = 0; i < dt->GetCount(); i++) {
1837 if ((*dt)[i].Find(_("Run Restore job")) == 0)
1841 if ((i + 10) > dt->GetCount()) {
1847 if ((k = (*dt)[++i].Find(_("JobName:"))) != 0) return false;
1848 restorePanel->SetRowString(_("Job Name"), (*dt)[i].Mid(10).Trim(false).RemoveLast());
1849 if ((k = (*dt)[++i].Find(_("Bootstrap:"))) != 0) return false;
1850 restorePanel->SetRowString(_("Bootstrap"), (*dt)[i].Mid(10).Trim(false).RemoveLast());
1851 if ((k = (*dt)[++i].Find(_("Where:"))) != 0) return false;
1852 restorePanel->SetRowString(_("Where"), (*dt)[i].Mid(10).Trim(false).RemoveLast());
1854 if ((k = (*dt)[++i].Find(_("Replace:"))) != 0) return false;
1855 wxString str = (*dt)[i].Mid(10).Trim(false).RemoveLast();
1856 if (str == _("always")) restorePanel->SetRowSelection(_("Replace"), 0);
1857 else if (str == _("ifnewer")) restorePanel->SetRowSelection(_("Replace"), 1);
1858 else if (str == _("ifolder")) restorePanel->SetRowSelection(_("Replace"), 2);
1859 else if (str == _("never")) restorePanel->SetRowSelection(_("Replace"), 3);
1860 else restorePanel->SetRowSelection(_("Replace"), 0);
1862 if ((k = (*dt)[++i].Find(_("FileSet:"))) != 0) return false;
1863 restorePanel->SetRowString(_("Fileset"), (*dt)[i].Mid(10).Trim(false).RemoveLast());
1864 if ((k = (*dt)[++i].Find(_("Client:"))) != 0) return false;
1865 restorePanel->SetRowString(_("Client"), (*dt)[i].Mid(10).Trim(false).RemoveLast());
1866 if ((k = (*dt)[++i].Find(_("Storage:"))) != 0) return false;
1867 restorePanel->SetRowString(_("Storage"), (*dt)[i].Mid(10).Trim(false).RemoveLast());
1868 if ((k = (*dt)[++i].Find(_("When:"))) != 0) return false;
1869 restorePanel->SetRowString(_("When"), (*dt)[i].Mid(10).Trim(false).RemoveLast());
1870 if ((k = (*dt)[++i].Find(_("Priority:"))) != 0) return false;
1871 restorePanel->SetRowString(_("Priority"), (*dt)[i].Mid(10).Trim(false).RemoveLast());
1874 restorePanel->Layout();
1879 /*----------------------------------------------------------------------------
1881 ----------------------------------------------------------------------------*/
1883 /* Set current status by enabling/disabling components */
1884 void wxbRestorePanel::SetStatus(status_enum newstatus) {
1885 switch (newstatus) {
1887 centerSizer->Remove(configPanel);
1888 centerSizer->Remove(restorePanel);
1889 centerSizer->Remove(treelistPanel);
1890 treelistPanel->Show(false);
1891 restorePanel->Show(false);
1892 centerSizer->Add(configPanel, 1, wxEXPAND);
1893 configPanel->Show(true);
1894 configPanel->Layout();
1895 centerSizer->Layout();
1897 start->SetLabel(_("Enter restore mode"));
1898 start->Enable(false);
1899 configPanel->Enable(false);
1900 tree->Enable(false);
1901 list->Enable(false);
1902 gauge->Enable(false);
1903 cancel->Enable(false);
1908 centerSizer->Remove(configPanel);
1909 centerSizer->Remove(restorePanel);
1910 centerSizer->Remove(treelistPanel);
1911 treelistPanel->Show(false);
1912 restorePanel->Show(false);
1913 centerSizer->Add(configPanel, 1, wxEXPAND);
1914 configPanel->Show(true);
1915 configPanel->Layout();
1916 centerSizer->Layout();
1918 tree->DeleteAllItems();
1919 list->DeleteAllItems();
1920 configPanel->ClearRowChoices(_("Client"));
1921 configPanel->ClearRowChoices(_("Before"));
1922 wxbMainFrame::GetInstance()->EnablePanels();
1923 newstatus = activable;
1926 start->SetLabel(_("Enter restore mode"));
1927 start->Enable(true);
1928 configPanel->Enable(false);
1929 tree->Enable(false);
1930 list->Enable(false);
1931 gauge->Enable(false);
1932 cancel->Enable(false);
1936 wxbMainFrame::GetInstance()->DisablePanels(this);
1938 start->Enable(false);
1939 //start->SetLabel(_("Choose files to restore"));
1940 configPanel->Enable(true);
1941 tree->Enable(false);
1942 list->Enable(false);
1943 cancel->Enable(true);
1950 start->Enable(true);
1951 start->SetLabel(_("Restore"));
1952 centerSizer->Remove(configPanel);
1953 configPanel->Show(false);
1954 centerSizer->Add(treelistPanel, 1, wxEXPAND);
1955 treelistPanel->Show(true);
1956 treelistPanel->Layout();
1957 centerSizer->Layout();
1964 start->Enable(false);
1965 configPanel->Enable(false);
1966 tree->Enable(false);
1967 list->Enable(false);
1968 centerSizer->Remove(treelistPanel);
1969 treelistPanel->Show(false);
1970 centerSizer->Add(restorePanel, 1, wxEXPAND);
1971 restorePanel->Show(true);
1972 restorePanel->Layout();
1973 centerSizer->Layout();
1975 restorePanel->EnableApply(false);
1978 start->SetLabel(_("Restoring..."));
1979 gauge->Enable(true);
1981 start->Enable(false);
1982 configPanel->Enable(false);
1983 tree->Enable(false);
1984 list->Enable(false);
1991 /*----------------------------------------------------------------------------
1993 ----------------------------------------------------------------------------*/
1995 void wxbRestorePanel::SetWorking(bool working) {
1996 this->working = working;
1998 SetCursor(*wxHOURGLASS_CURSOR);
1999 // SetEvtHandlerEnabled(false); //EVTQUEUE
2001 // else if (!processing) { /* Empty event queue if we aren't already doing this */ //EVTQUEUE
2003 // processing = true; //EVTQUEUE
2004 SetCursor(*wxSTANDARD_CURSOR);
2005 // SetEvtHandlerEnabled(true); //EVTQUEUE
2006 /* wxNode *node = pendingEvents->First(); //EVTQUEUE
2008 wxEvent *event = (wxEvent *)node->Data();
2011 wxEvtHandler::ProcessEvent(*event);
2014 node = pendingEvents->First();
2016 processing = false;*/
2020 bool wxbRestorePanel::IsWorking() {
2021 return this->working;
2024 void wxbRestorePanel::EnableConfig(bool enable) {
2025 restorePanel->Enable(enable);
2028 /*----------------------------------------------------------------------------
2030 ----------------------------------------------------------------------------*/
2035 bool wxbRestorePanel::ProcessEvent(wxEvent& event) {
2036 if (IsWorking() || processing) {
2037 wxEvent *eventCopy = event.Clone();
2039 pendingEvents->Append(eventCopy);
2043 return wxEvtHandler::ProcessEvent(event);
2048 void wxbRestorePanel::OnCancel(wxCommandEvent& event) {
2049 cancel->Enable(false);
2050 SetCursor(*wxHOURGLASS_CURSOR);
2052 SetCursor(*wxSTANDARD_CURSOR);
2055 void wxbRestorePanel::OnStart(wxCommandEvent& event) {
2064 void wxbRestorePanel::OnTreeChanging(wxTreeEvent& event) {
2070 void wxbRestorePanel::OnTreeExpanding(wxTreeEvent& event) {
2076 //CmdList(event.GetItem());
2077 if (tree->GetSelection() != event.GetItem()) {
2078 tree->SelectItem(event.GetItem());
2083 void wxbRestorePanel::OnTreeChanged(wxTreeEvent& event) {
2087 if (currentTreeItem == event.GetItem()) {
2090 treeadd->Enable(false);
2091 treeremove->Enable(false);
2092 treerefresh->Enable(false);
2093 markWhenCommandDone = false;
2095 currentTreeItem = event.GetItem();
2096 CmdList(event.GetItem());
2097 if (markWhenCommandDone) {
2098 CmdMark(event.GetItem(), NULL, 0);
2102 if (event.GetItem().IsOk()) {
2103 int status = ((wxbTreeItemData*)tree->GetItemData(event.GetItem()))->GetMarked();
2104 treeadd->Enable(status != 1);
2105 treeremove->Enable(status != 0);
2107 treerefresh->Enable(true);
2110 void wxbRestorePanel::OnTreeMarked(wxbTreeMarkedEvent& event) {
2112 if (tree->GetSelection() == event.GetItem()) {
2113 markWhenCommandDone = !markWhenCommandDone;
2118 markWhenCommandDone = false;
2119 CmdMark(event.GetItem(), NULL, 0);
2120 if (markWhenCommandDone) {
2121 CmdMark(event.GetItem(), NULL, 0);
2126 if (event.GetItem().IsOk()) {
2127 int status = ((wxbTreeItemData*)tree->GetItemData(event.GetItem()))->GetMarked();
2128 treeadd->Enable(status != 1);
2129 treeremove->Enable(status != 0);
2133 void wxbRestorePanel::OnTreeAdd(wxCommandEvent& event) {
2138 if (currentTreeItem.IsOk()) {
2140 CmdMark(currentTreeItem, NULL, 0, 1);
2143 treeremove->Enable(1);
2148 void wxbRestorePanel::OnTreeRemove(wxCommandEvent& event) {
2153 if (currentTreeItem.IsOk()) {
2155 CmdMark(currentTreeItem, NULL, 0, 0);
2158 treeremove->Enable(0);
2163 void wxbRestorePanel::OnTreeRefresh(wxCommandEvent& event) {
2173 void wxbRestorePanel::OnListMarked(wxbListMarkedEvent& event) {
2178 if (list->GetSelectedItemCount() == 0) {
2184 long* items = new long[list->GetSelectedItemCount()];
2188 long item = list->GetNextItem(-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
2189 while (item != -1) {
2192 item = list->GetNextItem(item, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
2195 CmdMark(wxTreeItemId(), items, num);
2199 wxListEvent listevt;
2201 OnListChanged(listevt);
2208 void wxbRestorePanel::OnListActivated(wxListEvent& event) {
2213 long item = event.GetIndex();
2214 // long item = list->GetNextItem(-1, wxLIST_NEXT_ALL, wxLIST_STATE_FOCUSED);
2216 wxbTreeItemData* itemdata = (wxbTreeItemData*)list->GetItemData(item);
2217 wxString name = itemdata->GetName();
2222 #if wxCHECK_VERSION(2, 6, 0)
2223 wxTreeItemIdValue cookie;
2228 if (name.GetChar(name.Length()-1) == '/') {
2229 wxTreeItemId currentChild = tree->GetFirstChild(currentTreeItem, cookie);
2231 while (currentChild.IsOk()) {
2232 wxString name2 = ((wxbTreeItemData*)tree->GetItemData(currentChild))->GetName();
2233 if (name2 == name) {
2234 //tree->UnselectAll();
2236 tree->Expand(currentTreeItem);
2237 tree->SelectItem(currentChild);
2241 currentChild = tree->GetNextChild(currentTreeItem, cookie);
2248 void wxbRestorePanel::OnListChanged(wxListEvent& event) {
2253 listadd->Enable(false);
2254 listremove->Enable(false);
2256 bool marked = false;
2257 bool unmarked = false;
2259 long item = list->GetNextItem(-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
2260 while (item != -1) {
2261 switch (((wxbTreeItemData*)list->GetItemData(item))->GetMarked()) {
2274 // Should never happen
2276 if (marked && unmarked) break;
2277 item = list->GetNextItem(item, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
2280 listadd->Enable(unmarked);
2281 listremove->Enable(marked);
2284 void wxbRestorePanel::OnListAdd(wxCommandEvent& event) {
2291 long* items = new long[list->GetSelectedItemCount()];
2295 long item = list->GetNextItem(-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
2296 while (item != -1) {
2299 item = list->GetNextItem(item, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
2302 CmdMark(wxTreeItemId(), items, num, 1);
2309 listadd->Enable(false);
2310 listremove->Enable(true);
2313 void wxbRestorePanel::OnListRemove(wxCommandEvent& event) {
2320 long* items = new long[list->GetSelectedItemCount()];
2324 long item = list->GetNextItem(-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
2325 while (item != -1) {
2328 item = list->GetNextItem(item, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
2331 CmdMark(wxTreeItemId(), items, num, 0);
2338 listadd->Enable(true);
2339 listremove->Enable(false);
2342 void wxbRestorePanel::OnListRefresh(wxCommandEvent& event) {
2352 void wxbRestorePanel::OnConfigUpdated(wxCommandEvent& event) {
2353 if (status == entered) {
2354 if (event.GetId() == ConfigJobName) {
2359 UpdateFirstConfig();
2362 else if ((event.GetId() == ConfigClient) || (event.GetId() == ConfigFileset)) {
2367 configPanel->Enable(false);
2369 configPanel->Enable(true);
2372 cfgUpdated = cfgUpdated | (1 << event.GetId());
2374 else if (status == configuring) {
2375 restorePanel->EnableApply(true);
2376 cfgUpdated = cfgUpdated | (1 << event.GetId());
2380 void wxbRestorePanel::OnConfigOk(wxCommandEvent& WXUNUSED(event)) {
2381 if (status != configuring) return;
2390 void wxbRestorePanel::OnConfigApply(wxCommandEvent& WXUNUSED(event)) {
2391 if (status != configuring) return;
2397 if (cfgUpdated == 0) {
2398 restorePanel->EnableApply(false);
2403 void wxbRestorePanel::OnConfigCancel(wxCommandEvent& WXUNUSED(event)) {
2404 if (status != configuring) return;