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):
54 #include "wxbrestorepanel.h"
56 #include "wxbmainframe.h"
60 #include <wx/choice.h>
61 #include <wx/datetime.h>
65 #include "unmarked.xpm"
67 #include "partmarked.xpm"
69 #include <wx/listimpl.cpp>
71 /* A macro named Yield is defined under MinGW */
74 WX_DEFINE_LIST(wxbEventList);
77 * Class which is stored in the tree and in the list to keep informations
80 class wxbTreeItemData : public wxTreeItemData {
82 wxbTreeItemData(wxString path, wxString name, int marked, long listid = -1);
88 void SetMarked(int marked);
92 wxString* path; /* Full path */
93 wxString* name; /* File name */
94 int marked; /* 0 - Not Marked, 1 - Marked, 2 - Some file under is marked */
95 long listid; /* list ID : >-1 if this data is in the list (and/or on the tree) */
98 wxbTreeItemData::wxbTreeItemData(wxString path, wxString name, int marked, long listid): wxTreeItemData() {
99 this->path = new wxString(path);
100 this->name = new wxString(name);
101 this->marked = marked;
102 this->listid = listid;
105 wxbTreeItemData::~wxbTreeItemData() {
110 int wxbTreeItemData::GetMarked() {
114 void wxbTreeItemData::SetMarked(int marked) {
115 this->marked = marked;
118 long wxbTreeItemData::GetListId() {
122 wxString wxbTreeItemData::GetPath() {
126 wxString wxbTreeItemData::GetName() {
130 // ----------------------------------------------------------------------------
131 // event tables and other macros for wxWindows
132 // ----------------------------------------------------------------------------
160 BEGIN_EVENT_TABLE(wxbRestorePanel, wxPanel)
161 EVT_BUTTON(RestoreStart, wxbRestorePanel::OnStart)
162 EVT_BUTTON(RestoreCancel, wxbRestorePanel::OnCancel)
164 EVT_TREE_SEL_CHANGING(TreeCtrl, wxbRestorePanel::OnTreeChanging)
165 EVT_TREE_SEL_CHANGED(TreeCtrl, wxbRestorePanel::OnTreeChanged)
166 EVT_TREE_ITEM_EXPANDING(TreeCtrl, wxbRestorePanel::OnTreeExpanding)
167 EVT_TREE_MARKED_EVENT(TreeCtrl, wxbRestorePanel::OnTreeMarked)
168 EVT_BUTTON(TreeAdd, wxbRestorePanel::OnTreeAdd)
169 EVT_BUTTON(TreeRemove, wxbRestorePanel::OnTreeRemove)
170 EVT_BUTTON(TreeRefresh, wxbRestorePanel::OnTreeRefresh)
172 EVT_LIST_ITEM_ACTIVATED(ListCtrl, wxbRestorePanel::OnListActivated)
173 EVT_LIST_MARKED_EVENT(ListCtrl, wxbRestorePanel::OnListMarked)
174 EVT_LIST_ITEM_SELECTED(ListCtrl, wxbRestorePanel::OnListChanged)
175 EVT_LIST_ITEM_DESELECTED(ListCtrl, wxbRestorePanel::OnListChanged)
176 EVT_BUTTON(ListAdd, wxbRestorePanel::OnListAdd)
177 EVT_BUTTON(ListRemove, wxbRestorePanel::OnListRemove)
178 EVT_BUTTON(ListRefresh, wxbRestorePanel::OnListRefresh)
180 EVT_TEXT(ConfigWhere, wxbRestorePanel::OnConfigUpdated)
181 EVT_TEXT(ConfigWhen, wxbRestorePanel::OnConfigUpdated)
182 EVT_TEXT(ConfigPriority, wxbRestorePanel::OnConfigUpdated)
183 EVT_CHOICE(ConfigWhen, wxbRestorePanel::OnConfigUpdated)
184 EVT_CHOICE(ConfigReplace, wxbRestorePanel::OnConfigUpdated)
185 EVT_CHOICE(ConfigClient, wxbRestorePanel::OnConfigUpdated)
186 EVT_CHOICE(ConfigFileset, wxbRestorePanel::OnConfigUpdated)
187 EVT_CHOICE(ConfigStorage, wxbRestorePanel::OnConfigUpdated)
188 EVT_CHOICE(ConfigJobName, wxbRestorePanel::OnConfigUpdated)
189 EVT_CHOICE(ConfigPool, wxbRestorePanel::OnConfigUpdated)
191 EVT_BUTTON(ConfigOk, wxbRestorePanel::OnConfigOk)
192 EVT_BUTTON(ConfigApply, wxbRestorePanel::OnConfigApply)
193 EVT_BUTTON(ConfigCancel, wxbRestorePanel::OnConfigCancel)
197 * wxbRestorePanel constructor
199 wxbRestorePanel::wxbRestorePanel(wxWindow* parent): wxbPanel(parent) {
200 //pendingEvents = new wxbEventList(); //EVTQUEUE
201 //processing = false; //EVTQUEUE
204 imagelist = new wxImageList(16, 16, TRUE, 3);
205 imagelist->Add(wxIcon(unmarked_xpm));
206 imagelist->Add(wxIcon(marked_xpm));
207 imagelist->Add(wxIcon(partmarked_xpm));
209 wxFlexGridSizer* mainSizer = new wxFlexGridSizer(3, 1, 10, 10);
210 mainSizer->AddGrowableCol(0);
211 mainSizer->AddGrowableRow(1);
213 wxFlexGridSizer *firstSizer = new wxFlexGridSizer(1, 2, 10, 10);
215 firstSizer->AddGrowableCol(0);
216 firstSizer->AddGrowableRow(0);
218 start = new wxButton(this, RestoreStart, _("Enter restore mode"), wxDefaultPosition, wxSize(150, 30));
219 firstSizer->Add(start, 0, wxALIGN_CENTER_HORIZONTAL | wxALIGN_CENTER_VERTICAL, 10);
221 cancel = new wxButton(this, RestoreCancel, _("Cancel restore"), wxDefaultPosition, wxSize(150, 30));
222 firstSizer->Add(cancel, 0, wxALIGN_CENTER_HORIZONTAL | wxALIGN_RIGHT, 10);
226 /* clientChoice = new wxChoice(this, ClientChoice, wxDefaultPosition, wxSize(150, 30), 0, elist);
227 firstSizer->Add(clientChoice, 1, wxALIGN_CENTER_HORIZONTAL | wxALIGN_CENTER_VERTICAL, 10);
229 jobChoice = new wxChoice(this, -1, wxDefaultPosition, wxSize(150, 30), 0, elist);
230 firstSizer->Add(jobChoice, 1, wxALIGN_CENTER_HORIZONTAL | wxALIGN_CENTER_VERTICAL, 10);*/
232 mainSizer->Add(firstSizer, 1, wxEXPAND, 10);
234 treelistPanel = new wxSplitterWindow(this);
236 wxPanel* treePanel = new wxPanel(treelistPanel);
237 wxFlexGridSizer *treeSizer = new wxFlexGridSizer(2, 1, 0, 0);
238 treeSizer->AddGrowableCol(0);
239 treeSizer->AddGrowableRow(0);
241 tree = new wxbTreeCtrl(treePanel, this, TreeCtrl, wxDefaultPosition, wxSize(200,50));
242 tree->SetImageList(imagelist);
244 treeSizer->Add(tree, 1, wxEXPAND, 0);
246 wxBoxSizer *treeCtrlSizer = new wxBoxSizer(wxHORIZONTAL);
247 treeadd = new wxButton(treePanel, TreeAdd, _("Add"), wxDefaultPosition, wxSize(60, 25));
248 treeCtrlSizer->Add(treeadd, 0, wxLEFT | wxRIGHT, 3);
249 treeremove = new wxButton(treePanel, TreeRemove, _("Remove"), wxDefaultPosition, wxSize(60, 25));
250 treeCtrlSizer->Add(treeremove, 0, wxLEFT | wxRIGHT, 3);
251 treerefresh = new wxButton(treePanel, TreeRefresh, _("Refresh"), wxDefaultPosition, wxSize(60, 25));
252 treeCtrlSizer->Add(treerefresh, 0, wxLEFT | wxRIGHT, 3);
254 treeSizer->Add(treeCtrlSizer, 1, wxALIGN_CENTER_HORIZONTAL, 0);
256 treePanel->SetSizer(treeSizer);
258 wxPanel* listPanel = new wxPanel(treelistPanel);
259 wxFlexGridSizer *listSizer = new wxFlexGridSizer(2, 1, 0, 0);
260 listSizer->AddGrowableCol(0);
261 listSizer->AddGrowableRow(0);
263 list = new wxbListCtrl(listPanel, this, ListCtrl, wxDefaultPosition, wxSize(200,50));
264 //treelistSizer->Add(list, 1, wxEXPAND, 10);
266 list->SetImageList(imagelist, wxIMAGE_LIST_SMALL);
269 info.SetMask(wxLIST_MASK_TEXT | wxLIST_MASK_FORMAT);
270 info.SetText(_("M"));
271 info.SetAlign(wxLIST_FORMAT_CENTER);
272 list->InsertColumn(0, info);
274 info.SetText(_("Filename"));
275 info.SetAlign(wxLIST_FORMAT_LEFT);
276 list->InsertColumn(1, info);
278 info.SetText(_("Size"));
279 info.SetAlign(wxLIST_FORMAT_RIGHT);
280 list->InsertColumn(2, info);
282 info.SetText(_("Date"));
283 info.SetAlign(wxLIST_FORMAT_LEFT);
284 list->InsertColumn(3, info);
286 info.SetText(_("Perm."));
287 info.SetAlign(wxLIST_FORMAT_LEFT);
288 list->InsertColumn(4, info);
290 info.SetText(_("User"));
291 info.SetAlign(wxLIST_FORMAT_RIGHT);
292 list->InsertColumn(5, info);
294 info.SetText(_("Group"));
295 info.SetAlign(wxLIST_FORMAT_RIGHT);
296 list->InsertColumn(6, info);
298 listSizer->Add(list, 1, wxEXPAND, 0);
300 wxBoxSizer *listCtrlSizer = new wxBoxSizer(wxHORIZONTAL);
301 listadd = new wxButton(listPanel, ListAdd, _("Add"), wxDefaultPosition, wxSize(60, 25));
302 listCtrlSizer->Add(listadd, 0, wxLEFT | wxRIGHT, 5);
303 listremove = new wxButton(listPanel, ListRemove, _("Remove"), wxDefaultPosition, wxSize(60, 25));
304 listCtrlSizer->Add(listremove, 0, wxLEFT | wxRIGHT, 5);
305 listrefresh = new wxButton(listPanel, ListRefresh, _("Refresh"), wxDefaultPosition, wxSize(60, 25));
306 listCtrlSizer->Add(listrefresh, 0, wxLEFT | wxRIGHT, 5);
308 listSizer->Add(listCtrlSizer, 1, wxALIGN_CENTER_HORIZONTAL, 0);
310 listPanel->SetSizer(listSizer);
312 treelistPanel->SplitVertically(treePanel, listPanel, 210);
314 treelistPanel->SetMinimumPaneSize(210);
316 treelistPanel->Show(false);
318 wxbConfig* config = new wxbConfig();
319 config->Add(new wxbConfigParam(_("Job Name"), ConfigJobName, choice, 0, elist));
320 config->Add(new wxbConfigParam(_("Client"), ConfigClient, choice, 0, elist));
321 config->Add(new wxbConfigParam(_("Fileset"), ConfigFileset, choice, 0, elist));
322 config->Add(new wxbConfigParam(_("Pool"), ConfigPool, choice, 0, elist));
323 config->Add(new wxbConfigParam(_("Storage"), ConfigStorage, choice, 0, elist));
324 config->Add(new wxbConfigParam(_("Before"), ConfigWhen, choice, 0, elist));
326 configPanel = new wxbConfigPanel(this, config, _("Please configure parameters concerning files to restore :"), RestoreStart, RestoreCancel, -1);
328 configPanel->Show(true);
329 configPanel->Enable(false);
331 config = new wxbConfig();
332 config->Add(new wxbConfigParam(_("Job Name"), -1, text, wxT("")));
333 config->Add(new wxbConfigParam(_("Bootstrap"), -1, text, wxT("")));
334 config->Add(new wxbConfigParam(_("Where"), ConfigWhere, modifiableText, wxT("")));
335 wxString erlist[] = {_("always"), _("if newer"), _("if older"), _("never")};
336 config->Add(new wxbConfigParam(_("Replace"), ConfigReplace, choice, 4, erlist));
337 config->Add(new wxbConfigParam(_("Fileset"), ConfigFileset, choice, 0, erlist));
338 config->Add(new wxbConfigParam(_("Client"), ConfigClient, choice, 0, erlist));
339 config->Add(new wxbConfigParam(_("Storage"), ConfigStorage, choice, 0, erlist));
340 config->Add(new wxbConfigParam(_("When"), ConfigWhen, modifiableText, wxT("")));
341 config->Add(new wxbConfigParam(_("Priority"), ConfigPriority, modifiableText, wxT("")));
343 restorePanel = new wxbConfigPanel(this, config, _("Please configure parameters concerning files restoration :"), ConfigOk, ConfigCancel, ConfigApply);
345 restorePanel->Show(false);
347 centerSizer = new wxBoxSizer(wxHORIZONTAL);
348 //centerSizer->Add(treelistPanel, 1, wxEXPAND | wxADJUST_MINSIZE);
350 mainSizer->Add(centerSizer, 1, wxEXPAND, 10);
352 gauge = new wxGauge(this, -1, 1, wxDefaultPosition, wxSize(200,20));
354 mainSizer->Add(gauge, 1, wxEXPAND, 5);
356 gauge->Enable(false);
359 mainSizer->SetSizeHints(this);
363 for (int i = 0; i < 7; i++) {
364 list->SetColumnWidth(i, 70);
367 SetCursor(*wxSTANDARD_CURSOR);
369 markWhenCommandDone = false;
375 * wxbRestorePanel destructor
377 wxbRestorePanel::~wxbRestorePanel() {
381 /*----------------------------------------------------------------------------
382 wxbPanel overloadings
383 ----------------------------------------------------------------------------*/
385 wxString wxbRestorePanel::GetTitle() {
389 void wxbRestorePanel::EnablePanel(bool enable) {
391 if (status == disabled) {
392 SetStatus(activable);
400 /*----------------------------------------------------------------------------
401 Commands called by events handler
402 ----------------------------------------------------------------------------*/
404 /* The main button has been clicked */
405 void wxbRestorePanel::CmdStart() {
407 if (status == activable) {
408 wxbMainFrame::GetInstance()->SetStatusText(_("Getting parameters list."));
409 wxbDataTokenizer* dt = wxbUtils::WaitForEnd(wxT(".clients\n"), true, false);
412 configPanel->ClearRowChoices(_("Client"));
413 restorePanel->ClearRowChoices(_("Client"));
415 if (dt->GetCount() == 0) {
416 wxbMainFrame::GetInstance()->SetStatusText(_("Error : no clients returned by the director."));
420 for (i = 0; i < dt->GetCount(); i++) {
423 configPanel->AddRowChoice(_("Client"), str);
424 restorePanel->AddRowChoice(_("Client"), str);
434 dt = wxbUtils::WaitForEnd(wxT(".filesets\n"), true, false);
436 configPanel->ClearRowChoices(_("Fileset"));
437 restorePanel->ClearRowChoices(_("Fileset"));
439 if (dt->GetCount() == 0) {
440 wxbMainFrame::GetInstance()->SetStatusText(_("Error : no filesets returned by the director."));
444 for (i = 0; i < dt->GetCount(); i++) {
447 configPanel->AddRowChoice(_("Fileset"), str);
448 restorePanel->AddRowChoice(_("Fileset"), str);
458 dt = wxbUtils::WaitForEnd(wxT(".storage\n"), true, false);
460 configPanel->ClearRowChoices(_("Storage"));
461 restorePanel->ClearRowChoices(_("Storage"));
463 if (dt->GetCount() == 0) {
464 wxbMainFrame::GetInstance()->SetStatusText(_("Error : no storage returned by the director."));
468 for (i = 0; i < dt->GetCount(); i++) {
471 configPanel->AddRowChoice(_("Storage"), str);
472 restorePanel->AddRowChoice(_("Storage"), str);
482 dt = wxbUtils::WaitForEnd(wxT(".jobs\n"), true, false);
484 configPanel->ClearRowChoices(_("Job Name"));
486 if (dt->GetCount() == 0) {
487 wxbMainFrame::GetInstance()->SetStatusText(_("Error : no jobs returned by the director."));
491 for (i = 0; i < dt->GetCount(); i++) {
494 configPanel->AddRowChoice(_("Job Name"), str);
497 configPanel->SetRowString(_("Job Name"), _("RestoreFiles"));
506 dt = wxbUtils::WaitForEnd(wxT(".pools\n"), true, false);
508 configPanel->ClearRowChoices(_("Pool"));
510 if (dt->GetCount() == 0) {
511 wxbMainFrame::GetInstance()->SetStatusText(_("Error : no jobs returned by the director."));
515 for (i = 0; i < dt->GetCount(); i++) {
518 configPanel->AddRowChoice(_("Pool"), str);
532 wxbMainFrame::GetInstance()->SetStatusText(_("Please configure your restore parameters."));
534 else if (status == entered) {
535 /* if (clientChoice->GetStringSelection().Length() < 1) {
536 wxbMainFrame::GetInstance()->SetStatusText(_("Please select a client."));
539 if (jobChoice->GetStringSelection().Length() < 1) {
540 wxbMainFrame::GetInstance()->SetStatusText(_("Please select a restore date."));
543 wxbMainFrame::GetInstance()->SetStatusText(_("Building restore tree..."));
547 wxbTableParser* tableparser = new wxbTableParser();
548 wxbDataTokenizer* dt = new wxbDataTokenizer(false);
551 * The following line was removed from ::GetInstance below because
552 * it does not work with multiple pools -- KES 5Oct05 see bug #433
553 * wxT("\" pool=\"") << configPanel->GetRowString(wxT("Pool")) <<
555 wxbMainFrame::GetInstance()->Send(wxString(wxT("restore")) <<
556 wxT(" client=\"") << configPanel->GetRowString(wxT("Client")) <<
557 wxT("\" fileset=\"") << configPanel->GetRowString(wxT("Fileset")) <<
558 wxT("\" storage=\"") << configPanel->GetRowString(wxT("Storage")) <<
559 wxT("\" before=\"") << configPanel->GetRowString(wxT("Before")) <<
561 //wxbUtils::WaitForPrompt("6\n");
563 /*wxbPromptParser *pp = wxbUtils::WaitForPrompt(wxString() << configPanel->GetRowString(wxT("Before")) << "\n", true);
564 int client = pp->getChoices()->Index(configPanel->GetRowString(wxT("Client")));
565 if (client == wxNOT_FOUND) {
566 wxbMainFrame::GetInstance()->SetStatusText("Failed to find the selected client.");
571 //wxbMainFrame::GetInstance()->Send(wxString() << configPanel->GetRowString(wxT("Before")) << "\n");
573 while (!tableparser->hasFinished() && !dt->hasFinished()) {
574 wxTheApp->Yield(true);
575 wxbUtils::MilliSleep(100);
580 if (dt->hasFinished() && !tableparser->hasFinished()) {
582 if (dt->GetCount() > 1) {
583 str = (*dt)[dt->GetCount()-2];
586 wxbMainFrame::GetInstance()->SetStatusText(wxString(_("Error while starting restore: ")) << str);
596 for (i = 0; i < tableparser->GetCount(); i++) {
597 str = (*tableparser)[i][2];
598 str.Replace(wxT(","), wxT(""));
599 if (str.ToLong(&l)) {
605 gauge->SetRange(tot);
607 /*wxbMainFrame::GetInstance()->Print(
608 wxString("[") << tot << "]", CS_DEBUG);*/
610 wxDateTime base = wxDateTime::Now();
614 unsigned int lastindex = 0;
621 newdate = wxDateTime::Now();
622 if (newdate.Subtract(base).GetMilliseconds() > 10 ) {
624 for (; lastindex < dt->GetCount(); lastindex++) {
625 if (((i1 = (*dt)[lastindex].Find(wxT("Building directory tree for JobId "))) >= 0) &&
626 ((i2 = (*dt)[lastindex].Find(wxT(" ..."))) > 0)) {
627 str = (*dt)[lastindex].Mid(i1+34, i2-(i1+34));
628 for (i = 0; i < tableparser->GetCount(); i++) {
629 if (str == (*tableparser)[i][0]) {
630 str = (*tableparser)[i][2];
631 str.Replace(wxT(","), wxT(""));
632 if (str.ToLong(&l)) {
635 var = (willdo-done)/50;
636 gauge->SetValue(done);
637 wxTheApp->Yield(true);
643 else if ((*dt)[lastindex] == wxT("+")) {
644 gauge->SetValue(gauge->GetValue()+var);
645 wxTheApp->Yield(true);
650 if (dt->hasFinished()) {
654 wxTheApp->Yield(true);
655 wxbUtils::MilliSleep(1);
658 gauge->SetValue(tot);
659 wxTheApp->Yield(true);
670 wxbUtils::WaitForEnd(wxT("unmark *\n"));
671 wxTreeItemId root = tree->AddRoot(configPanel->GetRowString(_("Client")), -1, -1, new wxbTreeItemData(wxT("/"), configPanel->GetRowString(_("Client")), 0));
672 currentTreeItem = root;
674 tree->SelectItem(root);
676 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."));
679 else if (status == choosing) {
683 wxbDataTokenizer* dt;
687 dt = new wxbDataTokenizer(true);
688 wxbPromptParser* promptparser = wxbUtils::WaitForPrompt(wxT("done\n"), true);
690 while (!promptparser->getChoices() || (promptparser->getChoices()->Index(wxT("mod")) < 0)) {
691 wxbMainFrame::GetInstance()->Print(_("Unexpected question has been received.\n"), CS_DEBUG);
694 if (promptparser->getIntroString() != wxT("")) {
695 message << promptparser->getIntroString() << wxT("\n");
697 message << promptparser->getQuestionString();
699 if (promptparser->getChoices()) {
700 wxString *choices = new wxString[promptparser->getChoices()->GetCount()];
701 int *numbers = new int[promptparser->getChoices()->GetCount()];
704 for (unsigned int i = 0; i < promptparser->getChoices()->GetCount(); i++) {
705 if ((*promptparser->getChoices())[i] != wxT("")) {
706 choices[n] = (*promptparser->getChoices())[i];
712 int res = ::wxGetSingleChoiceIndex(message,
713 _("wx-console: unexpected restore question."), n, choices, this);
716 promptparser = wxbUtils::WaitForPrompt(wxT(".\n"), true);
719 if (promptparser->isNumericalChoice()) {
721 promptparser = wxbUtils::WaitForPrompt(wxString() << numbers[res] << wxT("\n"), true);
725 promptparser = wxbUtils::WaitForPrompt(wxString() << choices[res] << wxT("\n"), true);
734 promptparser = wxbUtils::WaitForPrompt(::wxGetTextFromUser(message,
735 _("wx-console: unexpected restore question."),
736 wxT(""), this) + wxT("\n"));
739 printf("promptparser->getChoices()=%ld", (long)promptparser->getChoices());
743 SetStatus(configuring);
745 for (i = 0; i < dt->GetCount(); i++) {
746 if ((j = (*dt)[i].Find(_(" files selected to be restored."))) > -1) {
747 (*dt)[i].Mid(0, j).ToLong(&totfilemessages);
751 if ((j = (*dt)[i].Find(_(" file selected to be restored."))) > -1) {
752 (*dt)[i].Mid(0, j).ToLong(&totfilemessages);
757 wxbMainFrame::GetInstance()->SetStatusText(
758 wxString::Format(_("Please configure your restore (%ld files selected to be restored)..."), totfilemessages));
760 UpdateSecondConfig(dt);
765 restorePanel->EnableApply(false);
767 if (totfilemessages == 0) {
768 wxbMainFrame::GetInstance()->Print(_("Restore failed : no file selected.\n"), CS_DEBUG);
769 wxbMainFrame::GetInstance()->SetStatusText(_("Restore failed : no file selected."));
774 else if (status == configuring) {
775 cancel->Enable(false);
779 wxbMainFrame::GetInstance()->SetStatusText(_("Restoring, please wait..."));
781 wxbDataTokenizer* dt;
783 SetStatus(restoring);
784 dt = wxbUtils::WaitForEnd(wxT("yes\n"), true);
787 gauge->SetRange(totfilemessages);
791 for (i = 0; i < dt->GetCount(); i++) {
792 if ((j = (*dt)[i].Find(_("Job started. JobId="))) > -1) {
793 jobid = (*dt)[i].Mid(j+19);
794 wxbMainFrame::GetInstance()->SetStatusText(_("Restore started, jobid=") + jobid);
798 if ((j = (*dt)[i].Find(_("Job failed."))) > -1) {
799 wxbMainFrame::GetInstance()->Print(_("Restore failed, please look at messages.\n"), CS_DEBUG);
800 wxbMainFrame::GetInstance()->SetStatusText(_("Restore failed, please look at messages in console."));
805 if (jobid == wxT("")) {
806 wxbMainFrame::GetInstance()->Print(_("Failed to retrieve jobid.\n"), CS_DEBUG);
807 wxbMainFrame::GetInstance()->SetStatusText(_("Failed to retrieve jobid.\n"));
811 wxDateTime currenttime;
813 dt = wxbUtils::WaitForEnd(wxT("time\n"), true);
814 wxStringTokenizer ttkz((*dt)[0], wxT(" "), wxTOKEN_STRTOK);
815 if ((currenttime.ParseDate(ttkz.GetNextToken()) == NULL) || // Date
816 (currenttime.ParseTime(ttkz.GetNextToken()) == NULL)) { // Time
817 currenttime.SetYear(1990); // If parsing fails, set currenttime to a dummy date
820 currenttime -= wxTimeSpan::Seconds(30); //Adding a 30" tolerance
824 wxDateTime scheduledtime;
825 wxStringTokenizer stkz(restorePanel->GetRowString(_("When")), wxT(" "), wxTOKEN_STRTOK);
827 if ((scheduledtime.ParseDate(stkz.GetNextToken()) == NULL) || // Date
828 (scheduledtime.ParseTime(stkz.GetNextToken()) == NULL)) { // Time
829 scheduledtime.SetYear(2090); // If parsing fails, set scheduledtime to a dummy date
832 if (scheduledtime.Subtract(currenttime).IsLongerThan(wxTimeSpan::Seconds(150))) {
833 wxbMainFrame::GetInstance()->Print(_("Restore is scheduled in more than two minutes, wx-console will not wait for its completion.\n"), CS_DEBUG);
834 wxbMainFrame::GetInstance()->SetStatusText(_("Restore is scheduled in more than two minutes, wx-console will not wait for its completion."));
839 wxString cmd = wxString(wxT("list jobid=")) + jobid;
841 wxbTableParser* tableparser;
843 long filemessages = 0;
846 bool waitforever = false;
852 wxbUtils::WaitForEnd(wxT("autodisplay off\n"));
853 wxbUtils::WaitForEnd(wxT("gui on\n"));
855 tableparser = wxbUtils::CreateAndWaitForParser(cmd);
857 status = (*tableparser)[0][7].GetChar(0);
860 wxbMainFrame::GetInstance()->SetStatusText(_("Restore job created, but not yet running."));
864 wxbMainFrame::GetInstance()->SetStatusText(
865 wxString::Format(_("Restore job running, please wait (%ld of %ld files restored)..."), filemessages, totfilemessages));
869 wxbMainFrame::GetInstance()->SetStatusText(_("Restore job terminated successfully."));
870 wxbMainFrame::GetInstance()->Print(_("Restore job terminated successfully.\n"), CS_DEBUG);
874 case JS_ErrorTerminated:
875 wxbMainFrame::GetInstance()->SetStatusText(_("Restore job terminated in error, see messages in console."));
876 wxbMainFrame::GetInstance()->Print(_("Restore job terminated in error, see messages.\n"), CS_DEBUG);
881 wxbMainFrame::GetInstance()->SetStatusText(_("Restore job reported a non-fatal error."));
885 wxbMainFrame::GetInstance()->SetStatusText(_("Restore job reported a fatal error."));
890 wxbMainFrame::GetInstance()->SetStatusText(_("Restore job cancelled by user."));
891 wxbMainFrame::GetInstance()->Print(_("Restore job cancelled by user.\n"), CS_DEBUG);
896 wxbMainFrame::GetInstance()->SetStatusText(_("Restore job is waiting on File daemon."));
900 wxbMainFrame::GetInstance()->SetStatusText(_("Restore job is waiting for new media."));
903 case JS_WaitStoreRes:
904 wxbMainFrame::GetInstance()->SetStatusText(_("Restore job is waiting for storage resource."));
908 wxbMainFrame::GetInstance()->SetStatusText(_("Restore job is waiting for job resource."));
911 case JS_WaitClientRes:
912 wxbMainFrame::GetInstance()->SetStatusText(_("Restore job is waiting for Client resource."));
916 wxbMainFrame::GetInstance()->SetStatusText(_("Restore job is waiting for maximum jobs."));
919 case JS_WaitStartTime:
920 wxbMainFrame::GetInstance()->SetStatusText(_("Restore job is waiting for start time."));
923 case JS_WaitPriority:
924 wxbMainFrame::GetInstance()->SetStatusText(_("Restore job is waiting for higher priority jobs to finish."));
930 dt = wxbUtils::WaitForEnd(wxT(".messages\n"), true);
932 for (unsigned int i = 0; i < dt->GetCount(); i++) {
933 wxStringTokenizer tkz((*dt)[i], wxT(" "), wxTOKEN_STRTOK);
937 // Date Time name: perm ? user grp size date time
938 //04-Apr-2004 17:19 Tom-fd: -rwx------ 1 nicolas None 514967 2004-03-20 20:03:42 filename
940 if (datetime.ParseDate(tkz.GetNextToken()) != NULL) { // Date
941 if (datetime.ParseTime(tkz.GetNextToken()) != NULL) { // Time
942 if (tkz.GetNextToken().Last() == ':') { // name:
943 tkz.GetNextToken(); // perm
944 tkz.GetNextToken(); // ?
945 tkz.GetNextToken(); // user
946 tkz.GetNextToken(); // grp
947 tkz.GetNextToken(); // size
948 if (datetime.ParseDate(tkz.GetNextToken()) != NULL) { //date
949 if (datetime.ParseTime(tkz.GetNextToken()) != NULL) { //time
951 //wxbMainFrame::GetInstance()->Print(wxString("(") << filemessages << ")", CS_DEBUG);
952 gauge->SetValue(filemessages);
963 while (sw2.Time() < 10000) {
964 wxTheApp->Yield(true);
965 wxbUtils::MilliSleep(100);
972 if ((!waitforever) && (sw.Time() > 60000)) {
973 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);
974 wxbMainFrame::GetInstance()->SetStatusText(_("The restore job has not been started within one minute, wx-console will not wait for its completion anymore."));
978 wxbUtils::WaitForEnd(wxT("autodisplay on\n"));
979 wxbUtils::WaitForEnd(wxT(".messages\n"));
981 gauge->SetValue(totfilemessages);
983 if (status == JS_Terminated) {
984 wxbMainFrame::GetInstance()->Print(_("Restore done successfully.\n"), CS_DEBUG);
985 wxbMainFrame::GetInstance()->SetStatusText(_("Restore done successfully."));
991 /* The cancel button has been clicked */
992 void wxbRestorePanel::CmdCancel() {
995 if (status == restoring) {
996 if (jobid != wxT("")) {
997 wxbMainFrame::GetInstance()->Send(wxString(wxT("cancel job=")) << jobid << wxT("\n"));
999 cancel->Enable(true);
1004 while ((IsWorking()) && (cancelled != 2)) {
1005 wxTheApp->Yield(true);
1006 wxbUtils::MilliSleep(100);
1007 if (sw.Time() > 30000) { /* 30 seconds timeout */
1008 if (status == choosing) {
1009 wxbMainFrame::GetInstance()->Send(wxT("quit\n"));
1011 else if (status == configuring) {
1012 wxbMainFrame::GetInstance()->Send(wxT("no\n"));
1014 else if (status == restoring) {
1017 SetStatus(finished);
1018 wxbUtils::MilliSleep(1000);
1025 wxbMainFrame::GetInstance()->Send(wxT("quit\n"));
1028 wxbMainFrame::GetInstance()->Send(wxT("no\n"));
1033 wxbUtils::MilliSleep(1000);
1034 SetStatus(finished);
1037 /* Apply configuration changes */
1039 /* 1: Level (not appropriate)
1044 * 6: When (yes : "Please enter desired start time as YYYY-MM-DD HH:MM:SS (return for now):")
1045 * 7: Priority (yes : "Enter new Priority: (positive integer)")
1047 * 9: Where (yes : "Please enter path prefix for restore (/ for none):")
1048 * 10: Replace (yes : "Replace:\n 1: always\n 2: ifnewer\n 3: ifolder\n 4: never\n
1049 * Select replace option (1-4):")
1053 void wxbRestorePanel::CmdConfigApply() {
1054 if (cfgUpdated == 0) return;
1056 wxbMainFrame::GetInstance()->SetStatusText(_("Applying restore configuration changes..."));
1058 EnableConfig(false);
1060 wxbDataTokenizer* dt = NULL;
1062 bool failed = false;
1064 while (cfgUpdated > 0) {
1069 wxString def; //String to send if can't use our data
1070 if ((cfgUpdated >> ConfigWhere) & 1) {
1071 wxbUtils::WaitForPrompt(wxT("mod\n")); /* TODO: check results */
1072 wxbUtils::WaitForPrompt(wxT("9\n"));
1073 dt = new wxbDataTokenizer(true);
1074 wxbUtils::WaitForPrompt(restorePanel->GetRowString(_("Where")) + wxT("\n"));
1076 cfgUpdated = cfgUpdated & (~(1 << ConfigWhere));
1078 else if ((cfgUpdated >> ConfigReplace) & 1) {
1079 wxbUtils::WaitForPrompt(wxT("mod\n")); /* TODO: check results */
1080 wxbUtils::WaitForPrompt(wxT("10\n"));
1081 dt = new wxbDataTokenizer(true);
1082 wxbUtils::WaitForPrompt(wxString() << (restorePanel->GetRowSelection(_("Replace"))+1) << wxT("\n"));
1084 cfgUpdated = cfgUpdated & (~(1 << ConfigReplace));
1086 else if ((cfgUpdated >> ConfigWhen) & 1) {
1087 wxbUtils::WaitForPrompt(wxT("mod\n")); /* TODO: check results */
1088 wxbUtils::WaitForPrompt(wxT("6\n"));
1089 dt = new wxbDataTokenizer(true);
1090 wxbUtils::WaitForPrompt(restorePanel->GetRowString(wxT("When")) + wxT("\n"));
1092 cfgUpdated = cfgUpdated & (~(1 << ConfigWhen));
1094 else if ((cfgUpdated >> ConfigPriority) & 1) {
1095 wxbUtils::WaitForPrompt(wxT("mod\n")); /* TODO: check results */
1096 wxbUtils::WaitForPrompt(wxT("7\n"));
1097 dt = new wxbDataTokenizer(true);
1098 wxbUtils::WaitForPrompt(restorePanel->GetRowString(_("Priority")) + wxT("\n"));
1100 cfgUpdated = cfgUpdated & (~(1 << ConfigPriority));
1102 else if ((cfgUpdated >> ConfigClient) & 1) {
1103 wxbUtils::WaitForPrompt(wxT("mod\n")); /* TODO: check results */
1104 wxbPromptParser *pp = wxbUtils::WaitForPrompt(wxT("5\n"), true);
1105 int client = pp->getChoices()->Index(restorePanel->GetRowString(_("Client")));
1106 if (client == wxNOT_FOUND) {
1107 wxbMainFrame::GetInstance()->SetStatusText(_("Failed to find the selected client."));
1112 dt = new wxbDataTokenizer(true);
1113 wxbUtils::WaitForPrompt(wxString() << client << wxT("\n"));
1115 cfgUpdated = cfgUpdated & (~(1 << ConfigClient));
1117 else if ((cfgUpdated >> ConfigFileset) & 1) {
1118 wxbUtils::WaitForPrompt(wxT("mod\n")); /* TODO: check results */
1119 wxbPromptParser *pp = wxbUtils::WaitForPrompt(wxT("4\n"), true);
1120 int fileset = pp->getChoices()->Index(restorePanel->GetRowString(_("Fileset")));
1121 if (fileset == wxNOT_FOUND) {
1122 wxbMainFrame::GetInstance()->SetStatusText(_("Failed to find the selected fileset."));
1127 dt = new wxbDataTokenizer(true);
1128 wxbUtils::WaitForPrompt(wxString() << fileset << wxT("\n"));
1130 cfgUpdated = cfgUpdated & (~(1 << ConfigFileset));
1132 else if ((cfgUpdated >> ConfigStorage) & 1) {
1133 wxbUtils::WaitForPrompt(wxT("mod\n")); /* TODO: check results */
1134 wxbPromptParser *pp = wxbUtils::WaitForPrompt(wxT("2\n"), true);
1135 int fileset = pp->getChoices()->Index(restorePanel->GetRowString(_("Storage")));
1136 if (fileset == wxNOT_FOUND) {
1137 wxbMainFrame::GetInstance()->SetStatusText(_("Failed to find the selected storage."));
1142 dt = new wxbDataTokenizer(true);
1143 wxbUtils::WaitForPrompt(wxString() << fileset << wxT("\n"));
1145 cfgUpdated = cfgUpdated & (~(1 << ConfigStorage));
1153 for (i = 0; i < dt->GetCount(); i++) {
1154 if ((*dt)[i].Find(_("Run Restore job")) == 0) {
1159 if (i == dt->GetCount()) {
1161 dt = wxbUtils::WaitForEnd(def + wxT("\n"), true);
1165 UpdateSecondConfig(dt); /* TODO: Check result */
1170 wxbMainFrame::GetInstance()->SetStatusText(_("Restore configuration changes were applied."));
1176 /* Cancel restore */
1177 void wxbRestorePanel::CmdConfigCancel() {
1178 wxbUtils::WaitForEnd(wxT("no\n"));
1179 wxbMainFrame::GetInstance()->Print(_("Restore cancelled.\n"), CS_DEBUG);
1180 wxbMainFrame::GetInstance()->SetStatusText(_("Restore cancelled."));
1181 SetStatus(finished);
1184 /* List jobs for a specified client and fileset */
1185 void wxbRestorePanel::CmdListJobs() {
1186 if (status == entered) {
1187 configPanel->ClearRowChoices(_("Before"));
1188 /*wxbUtils::WaitForPrompt("query\n");
1189 wxbUtils::WaitForPrompt("6\n");*/
1190 wxbTableParser* tableparser = new wxbTableParser(false);
1191 wxbDataTokenizer* dt = wxbUtils::WaitForEnd(
1192 wxString(wxT(".backups client=\"")) + configPanel->GetRowString(_("Client")) +
1193 wxT("\" fileset=\"") + configPanel->GetRowString(_("Fileset")) + wxT("\"\n"), true);
1195 while (!tableparser->hasFinished()) {
1196 wxTheApp->Yield(true);
1197 wxbUtils::MilliSleep(100);
1200 if (!tableparser->GetCount() == 0) {
1201 for (unsigned int i = 0; i < dt->Count(); i++) {
1202 if ((*dt)[i].Find(_("No results to list.")) == 0) {
1203 configPanel->AddRowChoice(_("Before"),
1204 _("No backup found for this client."));
1205 configPanel->SetRowSelection(_("Before"), 0);
1206 configPanel->EnableApply(true); // Enabling the not existing apply button disables the ok button.
1211 else if (((*dt)[i].Find(_("ERROR")) > -1) ||
1212 ((*dt)[i].Find(_("Query failed")) > -1)) {
1213 configPanel->AddRowChoice(_("Before"),
1214 _("Cannot get previous backups list, see console."));
1215 configPanel->SetRowSelection(_("Before"), 0);
1216 configPanel->EnableApply(true); // Enabling the not existing apply button disables the ok button.
1226 wxDateTime lastdatetime = (time_t) 0;
1227 for (int i = tableparser->GetCount()-1; i > -1; i--) {
1228 wxString str = (*tableparser)[i][3];
1229 wxDateTime datetime;
1231 if ( ( (chr = datetime.ParseDate(str.GetData()) ) != NULL ) && ( datetime.ParseTime(++chr) != NULL ) && ! lastdatetime.IsEqualTo(datetime) ) {
1232 lastdatetime = datetime;
1233 datetime += wxTimeSpan::Seconds(1);
1234 configPanel->AddRowChoice(_("Before"),
1235 datetime.Format(wxT("%Y-%m-%d %H:%M:%S")));
1241 configPanel->SetRowSelection(_("Before"), 0);
1242 configPanel->EnableApply(false); // Disabling the not existing apply button enables the ok button.
1246 /* List files and directories for a specified tree item */
1247 void wxbRestorePanel::CmdList(wxTreeItemId item) {
1248 if (status == choosing) {
1249 list->DeleteAllItems();
1254 UpdateTreeItem(item, true, false);
1256 if (list->GetItemCount() >= 1) {
1257 int firstwidth = list->GetSize().GetWidth();
1258 for (int i = 2; i < 7; i++) {
1259 list->SetColumnWidth(i, wxLIST_AUTOSIZE);
1260 firstwidth -= list->GetColumnWidth(i);
1263 list->SetColumnWidth(0, 18);
1265 list->SetColumnWidth(1, wxLIST_AUTOSIZE);
1266 if (list->GetColumnWidth(1) < firstwidth) {
1267 list->SetColumnWidth(1, firstwidth-25);
1273 /* Mark a treeitem (directory) or a listitem (file or directory) */
1274 void wxbRestorePanel::CmdMark(wxTreeItemId treeitem, long* listitems, int listsize, int state) {
1275 if (status == choosing) {
1276 wxbTreeItemData** itemdata;
1277 int itemdatasize = 0;
1278 if (listsize == 0) {
1279 itemdata = new wxbTreeItemData*[1];
1283 itemdata = new wxbTreeItemData*[listsize];
1284 itemdatasize = listsize;
1287 if (listitems != NULL) {
1288 for (int i = 0; i < itemdatasize; i++) {
1289 itemdata[i] = (wxbTreeItemData*)list->GetItemData(listitems[i]);
1292 else if (treeitem.IsOk()) {
1293 itemdata[0] = (wxbTreeItemData*)tree->GetItemData(treeitem);
1300 if (itemdata[0] == NULL) { //Should never happen
1305 wxString dir = itemdata[0]->GetPath();
1308 if (dir != wxT("/")) {
1309 if (dir.GetChar(dir.Length()-1) == '/') {
1313 int i = dir.Find('/', TRUE);
1318 else { /* first dir below root */
1319 file = dir.Mid(i+1);
1320 dir = dir.Mid(0, i+1);
1329 bool marked = false;
1330 bool unmarked = false;
1332 for (int i = 0; i < itemdatasize; i++) {
1333 switch(itemdata[i]->GetMarked()) {
1347 if (marked && unmarked)
1363 wxbUtils::WaitForEnd(wxString(wxT("cd \"")) << dir << wxT("\"\n"));
1364 wxbUtils::WaitForEnd(wxString((state==1) ? wxT("mark") : wxT("unmark")) << wxT(" \"") << file << wxT("\"\n"));
1366 /* TODO: Check commands results */
1368 /*if ((dir == "/") && (file == "*")) {
1369 itemdata->SetMarked((itemdata->GetMarked() == 1) ? 0 : 1);
1372 if (listitems == NULL) { /* tree item state changed */
1373 SetTreeItemState(treeitem, state);
1374 /*treeitem = tree->GetSelection();
1375 UpdateTree(treeitem, true);
1376 treeitem = tree->GetItemParent(treeitem);*/
1379 for (int i = 0; i < itemdatasize; i++) {
1380 SetListItemState(listitems[i], state);
1382 listadd->Enable(state == 0);
1383 listremove->Enable(state == 1);
1384 /*UpdateTree(treeitem, (tree->GetSelection() == treeitem));
1385 treeitem = tree->GetItemParent(treeitem);*/
1388 /*while (treeitem.IsOk()) {
1389 WaitForList(treeitem, false);
1390 treeitem = tree->GetItemParent(treeitem);
1397 /*----------------------------------------------------------------------------
1399 ----------------------------------------------------------------------------*/
1401 /* Run a dir command, and waits until result is fully received. */
1402 void wxbRestorePanel::UpdateTreeItem(wxTreeItemId item, bool updatelist, bool recurse) {
1403 // this->updatelist = updatelist;
1404 wxbDataTokenizer* dt;
1406 dt = wxbUtils::WaitForEnd(wxString(wxT("cd \"")) <<
1407 static_cast<wxbTreeItemData*>(tree->GetItemData(item))
1408 ->GetPath() << wxT("\"\n"), false);
1410 /* TODO: check command result */
1417 list->DeleteAllItems();
1418 dt = wxbUtils::WaitForEnd(wxT(".dir\n"), true);
1422 for (unsigned int i = 0; i < dt->GetCount(); i++) {
1425 if (str.Find(wxT("cwd is:")) == 0) { // Sometimes cd command result "infiltrate" into listings.
1433 if (!ParseList(str, &entry))
1436 wxTreeItemId treeid;
1438 if (entry.fullname.GetChar(entry.fullname.Length()-1) == '/') {
1441 #if wxCHECK_VERSION(2, 6, 0)
1442 wxTreeItemIdValue cookie;
1447 treeid = tree->GetFirstChild(item, cookie);
1449 bool updated = false;
1451 while (treeid.IsOk()) {
1452 itemStr = ((wxbTreeItemData*)tree->GetItemData(treeid))->GetName();
1453 if (entry.filename == itemStr) {
1454 if (static_cast<wxbTreeItemData*>(tree->GetItemData(treeid))->GetMarked() != entry.marked) {
1455 tree->SetItemImage(treeid, entry.marked, wxTreeItemIcon_Normal);
1456 tree->SetItemImage(treeid, entry.marked, wxTreeItemIcon_Selected);
1457 static_cast<wxbTreeItemData*>(tree->GetItemData(treeid))->SetMarked(entry.marked);
1459 if ((recurse) && (tree->IsExpanded(treeid))) {
1460 UpdateTreeItem(treeid, false, true);
1465 treeid = tree->GetNextChild(item, cookie);
1469 treeid = tree->AppendItem(item, wxbUtils::ConvertToPrintable(entry.filename), entry.marked, entry.marked, new wxbTreeItemData(entry.fullname, entry.filename, entry.marked));
1474 long ind = list->InsertItem(list->GetItemCount(), entry.marked);
1475 wxbTreeItemData* data = new wxbTreeItemData(entry.fullname, entry.filename, entry.marked, ind);
1476 data->SetId(treeid);
1477 list->SetItemData(ind, (long)data);
1478 list->SetItem(ind, 1, wxbUtils::ConvertToPrintable(entry.filename));
1479 list->SetItem(ind, 2, entry.size);
1480 list->SetItem(ind, 3, entry.date);
1481 list->SetItem(ind, 4, entry.perm);
1482 list->SetItem(ind, 5, entry.user);
1483 list->SetItem(ind, 6, entry.group);
1493 /* Parse .dir command results, returns true if the result has been stored in entry, false otherwise. */
1494 int wxbRestorePanel::ParseList(wxString line, wxbDirEntry* entry) {
1495 /* See ls_output in dird/ua_tree.c */
1496 //-rw-r-----,1,root,root,41575,2005-10-18 18:21:36, ,/usr/var/bacula/working/bacula.sql
1498 wxStringTokenizer tkz(line, wxT(","));
1500 if (!tkz.HasMoreTokens())
1502 entry->perm = tkz.GetNextToken();
1504 if (!tkz.HasMoreTokens())
1506 entry->nlink = tkz.GetNextToken();
1508 if (!tkz.HasMoreTokens())
1510 entry->user = tkz.GetNextToken();
1512 if (!tkz.HasMoreTokens())
1514 entry->group = tkz.GetNextToken();
1516 if (!tkz.HasMoreTokens())
1518 entry->size = tkz.GetNextToken();
1520 if (!tkz.HasMoreTokens())
1522 entry->date = tkz.GetNextToken();
1524 if (!tkz.HasMoreTokens())
1526 wxString marked = tkz.GetNextToken();
1527 if (marked == wxT("*")) {
1530 else if (marked == wxT("+")) {
1537 if (!tkz.HasMoreTokens())
1539 entry->fullname = tkz.GetNextToken();
1541 /* Get only the filename (cut path by finding the last '/') */
1542 if (entry->fullname.GetChar(entry->fullname.Length()-1) == '/') {
1543 wxString tmp = entry->fullname;
1545 entry->filename = entry->fullname.Mid(tmp.Find('/', true)+1);
1548 entry->filename = entry->fullname.Mid(entry->fullname.Find('/', true)+1);
1554 /* Sets a list item state, and update its parents and children if it is a directory */
1555 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;