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):
55 #include "wxbrestorepanel.h"
56 #include "wxbmainframe.h"
58 #include <wx/choice.h>
59 #include <wx/datetime.h>
61 #include "unmarked.xpm"
63 #include "partmarked.xpm"
64 #include <wx/listimpl.cpp>
66 /* A macro named Yield is defined under MinGW */
69 WX_DEFINE_LIST(wxbEventList);
72 * Class which is stored in the tree and in the list to keep informations
75 class wxbTreeItemData : public wxTreeItemData {
77 wxbTreeItemData(wxString path, wxString name, int marked, long listid = -1);
83 void SetMarked(int marked);
87 wxString* path; /* Full path */
88 wxString* name; /* File name */
89 int marked; /* 0 - Not Marked, 1 - Marked, 2 - Some file under is marked */
90 long listid; /* list ID : >-1 if this data is in the list (and/or on the tree) */
93 wxbTreeItemData::wxbTreeItemData(wxString path, wxString name, int marked, long listid): wxTreeItemData() {
94 this->path = new wxString(path);
95 this->name = new wxString(name);
96 this->marked = marked;
97 this->listid = listid;
100 wxbTreeItemData::~wxbTreeItemData() {
105 int wxbTreeItemData::GetMarked() {
109 void wxbTreeItemData::SetMarked(int marked) {
110 this->marked = marked;
113 long wxbTreeItemData::GetListId() {
117 wxString wxbTreeItemData::GetPath() {
121 wxString wxbTreeItemData::GetName() {
125 // ----------------------------------------------------------------------------
126 // event tables and other macros for wxWindows
127 // ----------------------------------------------------------------------------
155 BEGIN_EVENT_TABLE(wxbRestorePanel, wxPanel)
156 EVT_BUTTON(RestoreStart, wxbRestorePanel::OnStart)
157 EVT_BUTTON(RestoreCancel, wxbRestorePanel::OnCancel)
159 EVT_TREE_SEL_CHANGING(TreeCtrl, wxbRestorePanel::OnTreeChanging)
160 EVT_TREE_SEL_CHANGED(TreeCtrl, wxbRestorePanel::OnTreeChanged)
161 EVT_TREE_ITEM_EXPANDING(TreeCtrl, wxbRestorePanel::OnTreeExpanding)
162 EVT_TREE_MARKED_EVENT(TreeCtrl, wxbRestorePanel::OnTreeMarked)
163 EVT_BUTTON(TreeAdd, wxbRestorePanel::OnTreeAdd)
164 EVT_BUTTON(TreeRemove, wxbRestorePanel::OnTreeRemove)
165 EVT_BUTTON(TreeRefresh, wxbRestorePanel::OnTreeRefresh)
167 EVT_LIST_ITEM_ACTIVATED(ListCtrl, wxbRestorePanel::OnListActivated)
168 EVT_LIST_MARKED_EVENT(ListCtrl, wxbRestorePanel::OnListMarked)
169 EVT_LIST_ITEM_SELECTED(ListCtrl, wxbRestorePanel::OnListChanged)
170 EVT_LIST_ITEM_DESELECTED(ListCtrl, wxbRestorePanel::OnListChanged)
171 EVT_BUTTON(ListAdd, wxbRestorePanel::OnListAdd)
172 EVT_BUTTON(ListRemove, wxbRestorePanel::OnListRemove)
173 EVT_BUTTON(ListRefresh, wxbRestorePanel::OnListRefresh)
175 EVT_TEXT(ConfigWhere, wxbRestorePanel::OnConfigUpdated)
176 EVT_TEXT(ConfigWhen, wxbRestorePanel::OnConfigUpdated)
177 EVT_TEXT(ConfigPriority, wxbRestorePanel::OnConfigUpdated)
178 EVT_CHOICE(ConfigWhen, wxbRestorePanel::OnConfigUpdated)
179 EVT_CHOICE(ConfigReplace, wxbRestorePanel::OnConfigUpdated)
180 EVT_CHOICE(ConfigClient, wxbRestorePanel::OnConfigUpdated)
181 EVT_CHOICE(ConfigFileset, wxbRestorePanel::OnConfigUpdated)
182 EVT_CHOICE(ConfigStorage, wxbRestorePanel::OnConfigUpdated)
183 EVT_CHOICE(ConfigJobName, wxbRestorePanel::OnConfigUpdated)
184 EVT_CHOICE(ConfigPool, wxbRestorePanel::OnConfigUpdated)
186 EVT_BUTTON(ConfigOk, wxbRestorePanel::OnConfigOk)
187 EVT_BUTTON(ConfigApply, wxbRestorePanel::OnConfigApply)
188 EVT_BUTTON(ConfigCancel, wxbRestorePanel::OnConfigCancel)
192 * wxbRestorePanel constructor
194 wxbRestorePanel::wxbRestorePanel(wxWindow* parent): wxbPanel(parent)
196 //pendingEvents = new wxbEventList(); //EVTQUEUE
197 //processing = false; //EVTQUEUE
200 imagelist = new wxImageList(16, 16, TRUE, 3);
201 imagelist->Add(wxIcon(unmarked_xpm));
202 imagelist->Add(wxIcon(marked_xpm));
203 imagelist->Add(wxIcon(partmarked_xpm));
205 wxFlexGridSizer* mainSizer = new wxFlexGridSizer(3, 1, 10, 10);
206 mainSizer->AddGrowableCol(0);
207 mainSizer->AddGrowableRow(1);
209 wxFlexGridSizer *firstSizer = new wxFlexGridSizer(1, 2, 10, 10);
211 firstSizer->AddGrowableCol(0);
212 firstSizer->AddGrowableRow(0);
214 start = new wxButton(this, RestoreStart, _("Enter restore mode"), wxDefaultPosition, wxSize(150, 30));
215 firstSizer->Add(start, 0, wxALIGN_CENTER_HORIZONTAL | wxALIGN_CENTER_VERTICAL, 10);
217 cancel = new wxButton(this, RestoreCancel, _("Cancel restore"), wxDefaultPosition, wxSize(150, 30));
218 firstSizer->Add(cancel, 0, wxALIGN_CENTER_HORIZONTAL | wxALIGN_RIGHT, 10);
222 /* clientChoice = new wxChoice(this, ClientChoice, wxDefaultPosition, wxSize(150, 30), 0, elist);
223 firstSizer->Add(clientChoice, 1, wxALIGN_CENTER_HORIZONTAL | wxALIGN_CENTER_VERTICAL, 10);
225 jobChoice = new wxChoice(this, -1, wxDefaultPosition, wxSize(150, 30), 0, elist);
226 firstSizer->Add(jobChoice, 1, wxALIGN_CENTER_HORIZONTAL | wxALIGN_CENTER_VERTICAL, 10);*/
228 mainSizer->Add(firstSizer, 1, wxEXPAND, 10);
230 treelistPanel = new wxSplitterWindow(this);
232 wxPanel* treePanel = new wxPanel(treelistPanel);
233 wxFlexGridSizer *treeSizer = new wxFlexGridSizer(2, 1, 0, 0);
234 treeSizer->AddGrowableCol(0);
235 treeSizer->AddGrowableRow(0);
237 tree = new wxbTreeCtrl(treePanel, this, TreeCtrl, wxDefaultPosition, wxSize(200,50));
238 tree->SetImageList(imagelist);
240 treeSizer->Add(tree, 1, wxEXPAND, 0);
242 wxBoxSizer *treeCtrlSizer = new wxBoxSizer(wxHORIZONTAL);
243 treeadd = new wxButton(treePanel, TreeAdd, _("Add"), wxDefaultPosition, wxSize(60, 25));
244 treeCtrlSizer->Add(treeadd, 0, wxLEFT | wxRIGHT, 3);
245 treeremove = new wxButton(treePanel, TreeRemove, _("Remove"), wxDefaultPosition, wxSize(60, 25));
246 treeCtrlSizer->Add(treeremove, 0, wxLEFT | wxRIGHT, 3);
247 treerefresh = new wxButton(treePanel, TreeRefresh, _("Refresh"), wxDefaultPosition, wxSize(60, 25));
248 treeCtrlSizer->Add(treerefresh, 0, wxLEFT | wxRIGHT, 3);
250 treeSizer->Add(treeCtrlSizer, 1, wxALIGN_CENTER_HORIZONTAL, 0);
252 treePanel->SetSizer(treeSizer);
254 wxPanel* listPanel = new wxPanel(treelistPanel);
255 wxFlexGridSizer *listSizer = new wxFlexGridSizer(2, 1, 0, 0);
256 listSizer->AddGrowableCol(0);
257 listSizer->AddGrowableRow(0);
259 list = new wxbListCtrl(listPanel, this, ListCtrl, wxDefaultPosition, wxSize(200,50));
260 //treelistSizer->Add(list, 1, wxEXPAND, 10);
262 list->SetImageList(imagelist, wxIMAGE_LIST_SMALL);
265 info.SetMask(wxLIST_MASK_TEXT | wxLIST_MASK_FORMAT);
266 info.SetText(_("M"));
267 info.SetAlign(wxLIST_FORMAT_CENTER);
268 list->InsertColumn(0, info);
270 info.SetText(_("Filename"));
271 info.SetAlign(wxLIST_FORMAT_LEFT);
272 list->InsertColumn(1, info);
274 info.SetText(_("Size"));
275 info.SetAlign(wxLIST_FORMAT_RIGHT);
276 list->InsertColumn(2, info);
278 info.SetText(_("Date"));
279 info.SetAlign(wxLIST_FORMAT_LEFT);
280 list->InsertColumn(3, info);
282 info.SetText(_("Perm."));
283 info.SetAlign(wxLIST_FORMAT_LEFT);
284 list->InsertColumn(4, info);
286 info.SetText(_("User"));
287 info.SetAlign(wxLIST_FORMAT_RIGHT);
288 list->InsertColumn(5, info);
290 info.SetText(_("Group"));
291 info.SetAlign(wxLIST_FORMAT_RIGHT);
292 list->InsertColumn(6, info);
294 listSizer->Add(list, 1, wxEXPAND, 0);
296 wxBoxSizer *listCtrlSizer = new wxBoxSizer(wxHORIZONTAL);
297 listadd = new wxButton(listPanel, ListAdd, _("Add"), wxDefaultPosition, wxSize(60, 25));
298 listCtrlSizer->Add(listadd, 0, wxLEFT | wxRIGHT, 5);
299 listremove = new wxButton(listPanel, ListRemove, _("Remove"), wxDefaultPosition, wxSize(60, 25));
300 listCtrlSizer->Add(listremove, 0, wxLEFT | wxRIGHT, 5);
301 listrefresh = new wxButton(listPanel, ListRefresh, _("Refresh"), wxDefaultPosition, wxSize(60, 25));
302 listCtrlSizer->Add(listrefresh, 0, wxLEFT | wxRIGHT, 5);
304 listSizer->Add(listCtrlSizer, 1, wxALIGN_CENTER_HORIZONTAL, 0);
306 listPanel->SetSizer(listSizer);
308 treelistPanel->SplitVertically(treePanel, listPanel, 210);
310 treelistPanel->SetMinimumPaneSize(210);
312 treelistPanel->Show(false);
314 wxbConfig* config = new wxbConfig();
315 config->Add(new wxbConfigParam(_("Job Name"), ConfigJobName, choice, 0, elist));
316 config->Add(new wxbConfigParam(_("Client"), ConfigClient, choice, 0, elist));
317 config->Add(new wxbConfigParam(_("Fileset"), ConfigFileset, choice, 0, elist));
318 config->Add(new wxbConfigParam(_("Pool"), ConfigPool, choice, 0, elist));
319 config->Add(new wxbConfigParam(_("Storage"), ConfigStorage, choice, 0, elist));
320 config->Add(new wxbConfigParam(_("Before"), ConfigWhen, choice, 0, elist));
322 configPanel = new wxbConfigPanel(this, config, _("Please configure parameters concerning files to restore :"), RestoreStart, RestoreCancel, -1);
324 configPanel->Show(true);
325 configPanel->Enable(false);
327 config = new wxbConfig();
328 config->Add(new wxbConfigParam(_("Job Name"), -1, text, wxT("")));
329 config->Add(new wxbConfigParam(_("Bootstrap"), -1, text, wxT("")));
330 config->Add(new wxbConfigParam(_("Where"), ConfigWhere, modifiableText, wxT("")));
331 wxString erlist[] = {_("always"), _("if newer"), _("if older"), _("never")};
332 config->Add(new wxbConfigParam(_("Replace"), ConfigReplace, choice, 4, erlist));
333 config->Add(new wxbConfigParam(_("Fileset"), ConfigFileset, choice, 0, erlist));
334 config->Add(new wxbConfigParam(_("Client"), ConfigClient, choice, 0, erlist));
335 config->Add(new wxbConfigParam(_("Storage"), ConfigStorage, choice, 0, erlist));
336 config->Add(new wxbConfigParam(_("When"), ConfigWhen, modifiableText, wxT("")));
337 config->Add(new wxbConfigParam(_("Priority"), ConfigPriority, modifiableText, wxT("")));
339 restorePanel = new wxbConfigPanel(this, config, _("Please configure parameters concerning files restoration :"), ConfigOk, ConfigCancel, ConfigApply);
341 restorePanel->Show(false);
343 centerSizer = new wxBoxSizer(wxHORIZONTAL);
344 //centerSizer->Add(treelistPanel, 1, wxEXPAND | wxADJUST_MINSIZE);
346 mainSizer->Add(centerSizer, 1, wxEXPAND, 10);
348 gauge = new wxGauge(this, -1, 1, wxDefaultPosition, wxSize(200,20));
350 mainSizer->Add(gauge, 1, wxEXPAND, 5);
352 gauge->Enable(false);
355 mainSizer->SetSizeHints(this);
359 for (int i = 0; i < 7; i++) {
360 list->SetColumnWidth(i, 70);
363 SetCursor(*wxSTANDARD_CURSOR);
365 markWhenCommandDone = false;
371 * wxbRestorePanel destructor
373 wxbRestorePanel::~wxbRestorePanel()
378 /*----------------------------------------------------------------------------
379 wxbPanel overloadings
380 ----------------------------------------------------------------------------*/
382 wxString wxbRestorePanel::GetTitle()
387 void wxbRestorePanel::EnablePanel(bool enable)
390 if (status == disabled) {
391 SetStatus(activable);
398 /*----------------------------------------------------------------------------
399 Commands called by events handler
400 ----------------------------------------------------------------------------*/
402 /* The main button has been clicked */
403 void wxbRestorePanel::CmdStart()
406 if (status == activable) {
407 wxbMainFrame::GetInstance()->SetStatusText(_("Getting parameters list."));
408 wxbDataTokenizer* dt = wxbUtils::WaitForEnd(wxT(".clients\n"), true, false);
411 configPanel->ClearRowChoices(_("Client"));
412 restorePanel->ClearRowChoices(_("Client"));
414 if (dt->GetCount() == 0) {
415 wxbMainFrame::GetInstance()->SetStatusText(_("Error : no clients returned by the director."));
419 for (i = 0; i < dt->GetCount(); i++) {
422 configPanel->AddRowChoice(_("Client"), str);
423 restorePanel->AddRowChoice(_("Client"), str);
433 dt = wxbUtils::WaitForEnd(wxT(".filesets\n"), true, false);
435 configPanel->ClearRowChoices(_("Fileset"));
436 restorePanel->ClearRowChoices(_("Fileset"));
438 if (dt->GetCount() == 0) {
439 wxbMainFrame::GetInstance()->SetStatusText(_("Error : no filesets returned by the director."));
443 for (i = 0; i < dt->GetCount(); i++) {
446 configPanel->AddRowChoice(_("Fileset"), str);
447 restorePanel->AddRowChoice(_("Fileset"), str);
457 dt = wxbUtils::WaitForEnd(wxT(".storage\n"), true, false);
459 configPanel->ClearRowChoices(_("Storage"));
460 restorePanel->ClearRowChoices(_("Storage"));
462 if (dt->GetCount() == 0) {
463 wxbMainFrame::GetInstance()->SetStatusText(_("Error : no storage returned by the director."));
467 for (i = 0; i < dt->GetCount(); i++) {
470 configPanel->AddRowChoice(_("Storage"), str);
471 restorePanel->AddRowChoice(_("Storage"), str);
481 dt = wxbUtils::WaitForEnd(wxT(".jobs\n"), true, false);
483 configPanel->ClearRowChoices(_("Job Name"));
485 if (dt->GetCount() == 0) {
486 wxbMainFrame::GetInstance()->SetStatusText(_("Error : no jobs returned by the director."));
490 for (i = 0; i < dt->GetCount(); i++) {
493 configPanel->AddRowChoice(_("Job Name"), str);
496 configPanel->SetRowString(_("Job Name"), _("RestoreFiles"));
505 dt = wxbUtils::WaitForEnd(wxT(".pools\n"), true, false);
507 configPanel->ClearRowChoices(_("Pool"));
509 if (dt->GetCount() == 0) {
510 wxbMainFrame::GetInstance()->SetStatusText(_("Error : no jobs returned by the director."));
514 for (i = 0; i < dt->GetCount(); i++) {
517 configPanel->AddRowChoice(_("Pool"), str);
531 wxbMainFrame::GetInstance()->SetStatusText(_("Please configure your restore parameters."));
533 else if (status == entered) {
534 /* if (clientChoice->GetStringSelection().Length() < 1) {
535 wxbMainFrame::GetInstance()->SetStatusText(_("Please select a client."));
538 if (jobChoice->GetStringSelection().Length() < 1) {
539 wxbMainFrame::GetInstance()->SetStatusText(_("Please select a restore date."));
542 wxbMainFrame::GetInstance()->SetStatusText(_("Building restore tree..."));
546 wxbTableParser* tableparser = new wxbTableParser();
547 wxbDataTokenizer* dt = new wxbDataTokenizer(false);
550 * The following line was removed from ::GetInstance below because
551 * it does not work with multiple pools -- KES 5Oct05 see bug #433
552 * wxT("\" pool=\"") << configPanel->GetRowString(wxT("Pool")) <<
554 wxbMainFrame::GetInstance()->Send(wxString(wxT("restore")) <<
555 wxT(" client=\"") << configPanel->GetRowString(wxT("Client")) <<
556 wxT("\" fileset=\"") << configPanel->GetRowString(wxT("Fileset")) <<
557 wxT("\" storage=\"") << configPanel->GetRowString(wxT("Storage")) <<
558 wxT("\" before=\"") << configPanel->GetRowString(wxT("Before")) <<
560 //wxbUtils::WaitForPrompt("6\n");
562 /*wxbPromptParser *pp = wxbUtils::WaitForPrompt(wxString() << configPanel->GetRowString(wxT("Before")) << "\n", true);
563 int client = pp->getChoices()->Index(configPanel->GetRowString(wxT("Client")));
564 if (client == wxNOT_FOUND) {
565 wxbMainFrame::GetInstance()->SetStatusText("Failed to find the selected client.");
570 //wxbMainFrame::GetInstance()->Send(wxString() << configPanel->GetRowString(wxT("Before")) << "\n");
572 while (!tableparser->hasFinished() && !dt->hasFinished()) {
573 wxTheApp->Yield(true);
574 wxbUtils::MilliSleep(100);
579 if (dt->hasFinished() && !tableparser->hasFinished()) {
581 if (dt->GetCount() > 1) {
582 str = (*dt)[dt->GetCount()-2];
585 wxbMainFrame::GetInstance()->SetStatusText(wxString(_("Error while starting restore: ")) << str);
595 for (i = 0; i < tableparser->GetCount(); i++) {
596 str = (*tableparser)[i][2];
597 str.Replace(wxT(","), wxT(""));
598 if (str.ToLong(&l)) {
604 gauge->SetRange(tot);
606 /*wxbMainFrame::GetInstance()->Print(
607 wxString("[") << tot << "]", CS_DEBUG);*/
609 wxDateTime base = wxDateTime::Now();
613 unsigned int lastindex = 0;
620 newdate = wxDateTime::Now();
621 if (newdate.Subtract(base).GetMilliseconds() > 10 ) {
623 for (; lastindex < dt->GetCount(); lastindex++) {
624 if (((i1 = (*dt)[lastindex].Find(wxT("Building directory tree for JobId "))) >= 0) &&
625 ((i2 = (*dt)[lastindex].Find(wxT(" ..."))) > 0)) {
626 str = (*dt)[lastindex].Mid(i1+34, i2-(i1+34));
627 for (i = 0; i < tableparser->GetCount(); i++) {
628 if (str == (*tableparser)[i][0]) {
629 str = (*tableparser)[i][2];
630 str.Replace(wxT(","), wxT(""));
631 if (str.ToLong(&l)) {
634 var = (willdo-done)/50;
635 gauge->SetValue(done);
636 wxTheApp->Yield(true);
642 else if ((*dt)[lastindex] == wxT("+")) {
643 gauge->SetValue(gauge->GetValue()+var);
644 wxTheApp->Yield(true);
649 if (dt->hasFinished()) {
653 wxTheApp->Yield(true);
654 wxbUtils::MilliSleep(1);
657 gauge->SetValue(tot);
658 wxTheApp->Yield(true);
669 wxbUtils::WaitForEnd(wxT("unmark *\n"));
670 wxTreeItemId root = tree->AddRoot(configPanel->GetRowString(_("Client")), -1, -1, new wxbTreeItemData(wxT("/"), configPanel->GetRowString(_("Client")), 0));
671 currentTreeItem = root;
673 tree->SelectItem(root);
675 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."));
678 else if (status == choosing) {
682 wxbDataTokenizer* dt;
686 dt = new wxbDataTokenizer(true);
687 wxbPromptParser* promptparser = wxbUtils::WaitForPrompt(wxT("done\n"), true);
689 while (!promptparser->getChoices() || (promptparser->getChoices()->Index(wxT("mod")) < 0)) {
690 wxbMainFrame::GetInstance()->Print(_("Unexpected question has been received.\n"), CS_DEBUG);
693 if (promptparser->getIntroString() != wxT("")) {
694 message << promptparser->getIntroString() << wxT("\n");
696 message << promptparser->getQuestionString();
698 if (promptparser->getChoices()) {
699 wxString *choices = new wxString[promptparser->getChoices()->GetCount()];
700 int *numbers = new int[promptparser->getChoices()->GetCount()];
703 for (unsigned int i = 0; i < promptparser->getChoices()->GetCount(); i++) {
704 if ((*promptparser->getChoices())[i] != wxT("")) {
705 choices[n] = (*promptparser->getChoices())[i];
711 int res = ::wxGetSingleChoiceIndex(message,
712 _("wx-console: unexpected restore question."), n, choices, this);
715 promptparser = wxbUtils::WaitForPrompt(wxT(".\n"), true);
718 if (promptparser->isNumericalChoice()) {
720 promptparser = wxbUtils::WaitForPrompt(wxString() << numbers[res] << wxT("\n"), true);
724 promptparser = wxbUtils::WaitForPrompt(wxString() << choices[res] << wxT("\n"), true);
733 promptparser = wxbUtils::WaitForPrompt(::wxGetTextFromUser(message,
734 _("wx-console: unexpected restore question."),
735 wxT(""), this) + wxT("\n"));
738 printf("promptparser->getChoices()=%ld", (long)promptparser->getChoices());
742 SetStatus(configuring);
744 for (i = 0; i < dt->GetCount(); i++) {
745 if ((j = (*dt)[i].Find(_(" files selected to be restored."))) > -1) {
746 (*dt)[i].Mid(0, j).ToLong(&totfilemessages);
750 if ((j = (*dt)[i].Find(_(" file selected to be restored."))) > -1) {
751 (*dt)[i].Mid(0, j).ToLong(&totfilemessages);
756 wxbMainFrame::GetInstance()->SetStatusText(
757 wxString::Format(_("Please configure your restore (%ld files selected to be restored)..."), totfilemessages));
759 UpdateSecondConfig(dt);
764 restorePanel->EnableApply(false);
766 if (totfilemessages == 0) {
767 wxbMainFrame::GetInstance()->Print(_("Restore failed : no file selected.\n"), CS_DEBUG);
768 wxbMainFrame::GetInstance()->SetStatusText(_("Restore failed : no file selected."));
773 else if (status == configuring) {
774 cancel->Enable(false);
778 wxbMainFrame::GetInstance()->SetStatusText(_("Restoring, please wait..."));
780 wxbDataTokenizer* dt;
782 SetStatus(restoring);
783 dt = wxbUtils::WaitForEnd(wxT("yes\n"), true);
786 gauge->SetRange(totfilemessages);
790 for (i = 0; i < dt->GetCount(); i++) {
791 if ((j = (*dt)[i].Find(_("Job started. JobId="))) > -1) {
792 jobid = (*dt)[i].Mid(j+19);
793 wxbMainFrame::GetInstance()->SetStatusText(_("Restore started, jobid=") + jobid);
797 if ((j = (*dt)[i].Find(_("Job failed."))) > -1) {
798 wxbMainFrame::GetInstance()->Print(_("Restore failed, please look at messages.\n"), CS_DEBUG);
799 wxbMainFrame::GetInstance()->SetStatusText(_("Restore failed, please look at messages in console."));
804 if (jobid == wxT("")) {
805 wxbMainFrame::GetInstance()->Print(_("Failed to retrieve jobid.\n"), CS_DEBUG);
806 wxbMainFrame::GetInstance()->SetStatusText(_("Failed to retrieve jobid.\n"));
810 wxDateTime currenttime;
812 dt = wxbUtils::WaitForEnd(wxT("time\n"), true);
813 wxStringTokenizer ttkz((*dt)[0], wxT(" "), wxTOKEN_STRTOK);
814 if ((currenttime.ParseDate(ttkz.GetNextToken()) == NULL) || // Date
815 (currenttime.ParseTime(ttkz.GetNextToken()) == NULL)) { // Time
816 currenttime.SetYear(1990); // If parsing fails, set currenttime to a dummy date
819 currenttime -= wxTimeSpan::Seconds(30); //Adding a 30" tolerance
823 wxDateTime scheduledtime;
824 wxStringTokenizer stkz(restorePanel->GetRowString(_("When")), wxT(" "), wxTOKEN_STRTOK);
826 if ((scheduledtime.ParseDate(stkz.GetNextToken()) == NULL) || // Date
827 (scheduledtime.ParseTime(stkz.GetNextToken()) == NULL)) { // Time
828 scheduledtime.SetYear(2090); // If parsing fails, set scheduledtime to a dummy date
831 if (scheduledtime.Subtract(currenttime).IsLongerThan(wxTimeSpan::Seconds(150))) {
832 wxbMainFrame::GetInstance()->Print(_("Restore is scheduled in more than two minutes, wx-console will not wait for its completion.\n"), CS_DEBUG);
833 wxbMainFrame::GetInstance()->SetStatusText(_("Restore is scheduled in more than two minutes, wx-console will not wait for its completion."));
838 wxString cmd = wxString(wxT("list jobid=")) + jobid;
840 wxbTableParser* tableparser;
842 long filemessages = 0;
845 bool waitforever = false;
851 wxbUtils::WaitForEnd(wxT("autodisplay off\n"));
852 wxbUtils::WaitForEnd(wxT("gui on\n"));
854 tableparser = wxbUtils::CreateAndWaitForParser(cmd);
856 status = (*tableparser)[0][7].GetChar(0);
859 wxbMainFrame::GetInstance()->SetStatusText(_("Restore job created, but not yet running."));
863 wxbMainFrame::GetInstance()->SetStatusText(
864 wxString::Format(_("Restore job running, please wait (%ld of %ld files restored)..."), filemessages, totfilemessages));
868 wxbMainFrame::GetInstance()->SetStatusText(_("Restore job terminated successfully."));
869 wxbMainFrame::GetInstance()->Print(_("Restore job terminated successfully.\n"), CS_DEBUG);
873 case JS_ErrorTerminated:
874 wxbMainFrame::GetInstance()->SetStatusText(_("Restore job terminated in error, see messages in console."));
875 wxbMainFrame::GetInstance()->Print(_("Restore job terminated in error, see messages.\n"), CS_DEBUG);
880 wxbMainFrame::GetInstance()->SetStatusText(_("Restore job reported a non-fatal error."));
884 wxbMainFrame::GetInstance()->SetStatusText(_("Restore job reported a fatal error."));
889 wxbMainFrame::GetInstance()->SetStatusText(_("Restore job cancelled by user."));
890 wxbMainFrame::GetInstance()->Print(_("Restore job cancelled by user.\n"), CS_DEBUG);
895 wxbMainFrame::GetInstance()->SetStatusText(_("Restore job is waiting on File daemon."));
899 wxbMainFrame::GetInstance()->SetStatusText(_("Restore job is waiting for new media."));
902 case JS_WaitStoreRes:
903 wxbMainFrame::GetInstance()->SetStatusText(_("Restore job is waiting for storage resource."));
907 wxbMainFrame::GetInstance()->SetStatusText(_("Restore job is waiting for job resource."));
910 case JS_WaitClientRes:
911 wxbMainFrame::GetInstance()->SetStatusText(_("Restore job is waiting for Client resource."));
915 wxbMainFrame::GetInstance()->SetStatusText(_("Restore job is waiting for maximum jobs."));
918 case JS_WaitStartTime:
919 wxbMainFrame::GetInstance()->SetStatusText(_("Restore job is waiting for start time."));
922 case JS_WaitPriority:
923 wxbMainFrame::GetInstance()->SetStatusText(_("Restore job is waiting for higher priority jobs to finish."));
929 dt = wxbUtils::WaitForEnd(wxT(".messages\n"), true);
931 for (unsigned int i = 0; i < dt->GetCount(); i++) {
932 wxStringTokenizer tkz((*dt)[i], wxT(" "), wxTOKEN_STRTOK);
936 // Date Time name: perm ? user grp size date time
937 //04-Apr-2004 17:19 Tom-fd: -rwx------ 1 nicolas None 514967 2004-03-20 20:03:42 filename
939 if (datetime.ParseDate(tkz.GetNextToken()) != NULL) { // Date
940 if (datetime.ParseTime(tkz.GetNextToken()) != NULL) { // Time
941 if (tkz.GetNextToken().Last() == ':') { // name:
942 tkz.GetNextToken(); // perm
943 tkz.GetNextToken(); // ?
944 tkz.GetNextToken(); // user
945 tkz.GetNextToken(); // grp
946 tkz.GetNextToken(); // size
947 if (datetime.ParseDate(tkz.GetNextToken()) != NULL) { //date
948 if (datetime.ParseTime(tkz.GetNextToken()) != NULL) { //time
950 //wxbMainFrame::GetInstance()->Print(wxString("(") << filemessages << ")", CS_DEBUG);
951 gauge->SetValue(filemessages);
962 while (sw2.Time() < 10000) {
963 wxTheApp->Yield(true);
964 wxbUtils::MilliSleep(100);
971 if ((!waitforever) && (sw.Time() > 60000)) {
972 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);
973 wxbMainFrame::GetInstance()->SetStatusText(_("The restore job has not been started within one minute, wx-console will not wait for its completion anymore."));
977 wxbUtils::WaitForEnd(wxT("autodisplay on\n"));
978 wxbUtils::WaitForEnd(wxT(".messages\n"));
980 gauge->SetValue(totfilemessages);
982 if (status == JS_Terminated) {
983 wxbMainFrame::GetInstance()->Print(_("Restore done successfully.\n"), CS_DEBUG);
984 wxbMainFrame::GetInstance()->SetStatusText(_("Restore done successfully."));
990 /* The cancel button has been clicked */
991 void wxbRestorePanel::CmdCancel() {
994 if (status == restoring) {
995 if (jobid != wxT("")) {
996 wxbMainFrame::GetInstance()->Send(wxString(wxT("cancel job=")) << jobid << wxT("\n"));
998 cancel->Enable(true);
1003 while ((IsWorking()) && (cancelled != 2)) {
1004 wxTheApp->Yield(true);
1005 wxbUtils::MilliSleep(100);
1006 if (sw.Time() > 30000) { /* 30 seconds timeout */
1007 if (status == choosing) {
1008 wxbMainFrame::GetInstance()->Send(wxT("quit\n"));
1010 else if (status == configuring) {
1011 wxbMainFrame::GetInstance()->Send(wxT("no\n"));
1013 else if (status == restoring) {
1016 SetStatus(finished);
1017 wxbUtils::MilliSleep(1000);
1024 wxbMainFrame::GetInstance()->Send(wxT("quit\n"));
1027 wxbMainFrame::GetInstance()->Send(wxT("no\n"));
1032 wxbUtils::MilliSleep(1000);
1033 SetStatus(finished);
1036 /* Apply configuration changes */
1038 /* 1: Level (not appropriate)
1043 * 6: When (yes : "Please enter desired start time as YYYY-MM-DD HH:MM:SS (return for now):")
1044 * 7: Priority (yes : "Enter new Priority: (positive integer)")
1046 * 9: Where (yes : "Please enter path prefix for restore (/ for none):")
1047 * 10: Replace (yes : "Replace:\n 1: always\n 2: ifnewer\n 3: ifolder\n 4: never\n
1048 * Select replace option (1-4):")
1052 void wxbRestorePanel::CmdConfigApply() {
1053 if (cfgUpdated == 0) return;
1055 wxbMainFrame::GetInstance()->SetStatusText(_("Applying restore configuration changes..."));
1057 EnableConfig(false);
1059 wxbDataTokenizer* dt = NULL;
1061 bool failed = false;
1063 while (cfgUpdated > 0) {
1068 wxString def; //String to send if can't use our data
1069 if ((cfgUpdated >> ConfigWhere) & 1) {
1070 wxbUtils::WaitForPrompt(wxT("mod\n")); /* TODO: check results */
1071 wxbUtils::WaitForPrompt(wxT("9\n"));
1072 dt = new wxbDataTokenizer(true);
1073 wxbUtils::WaitForPrompt(restorePanel->GetRowString(_("Where")) + wxT("\n"));
1075 cfgUpdated = cfgUpdated & (~(1 << ConfigWhere));
1077 else if ((cfgUpdated >> ConfigReplace) & 1) {
1078 wxbUtils::WaitForPrompt(wxT("mod\n")); /* TODO: check results */
1079 wxbUtils::WaitForPrompt(wxT("10\n"));
1080 dt = new wxbDataTokenizer(true);
1081 wxbUtils::WaitForPrompt(wxString() << (restorePanel->GetRowSelection(_("Replace"))+1) << wxT("\n"));
1083 cfgUpdated = cfgUpdated & (~(1 << ConfigReplace));
1085 else if ((cfgUpdated >> ConfigWhen) & 1) {
1086 wxbUtils::WaitForPrompt(wxT("mod\n")); /* TODO: check results */
1087 wxbUtils::WaitForPrompt(wxT("6\n"));
1088 dt = new wxbDataTokenizer(true);
1089 wxbUtils::WaitForPrompt(restorePanel->GetRowString(wxT("When")) + wxT("\n"));
1091 cfgUpdated = cfgUpdated & (~(1 << ConfigWhen));
1093 else if ((cfgUpdated >> ConfigPriority) & 1) {
1094 wxbUtils::WaitForPrompt(wxT("mod\n")); /* TODO: check results */
1095 wxbUtils::WaitForPrompt(wxT("7\n"));
1096 dt = new wxbDataTokenizer(true);
1097 wxbUtils::WaitForPrompt(restorePanel->GetRowString(_("Priority")) + wxT("\n"));
1099 cfgUpdated = cfgUpdated & (~(1 << ConfigPriority));
1101 else if ((cfgUpdated >> ConfigClient) & 1) {
1102 wxbUtils::WaitForPrompt(wxT("mod\n")); /* TODO: check results */
1103 wxbPromptParser *pp = wxbUtils::WaitForPrompt(wxT("5\n"), true);
1104 int client = pp->getChoices()->Index(restorePanel->GetRowString(_("Client")));
1105 if (client == wxNOT_FOUND) {
1106 wxbMainFrame::GetInstance()->SetStatusText(_("Failed to find the selected client."));
1111 dt = new wxbDataTokenizer(true);
1112 wxbUtils::WaitForPrompt(wxString() << client << wxT("\n"));
1114 cfgUpdated = cfgUpdated & (~(1 << ConfigClient));
1116 else if ((cfgUpdated >> ConfigFileset) & 1) {
1117 wxbUtils::WaitForPrompt(wxT("mod\n")); /* TODO: check results */
1118 wxbPromptParser *pp = wxbUtils::WaitForPrompt(wxT("4\n"), true);
1119 int fileset = pp->getChoices()->Index(restorePanel->GetRowString(_("Fileset")));
1120 if (fileset == wxNOT_FOUND) {
1121 wxbMainFrame::GetInstance()->SetStatusText(_("Failed to find the selected fileset."));
1126 dt = new wxbDataTokenizer(true);
1127 wxbUtils::WaitForPrompt(wxString() << fileset << wxT("\n"));
1129 cfgUpdated = cfgUpdated & (~(1 << ConfigFileset));
1131 else if ((cfgUpdated >> ConfigStorage) & 1) {
1132 wxbUtils::WaitForPrompt(wxT("mod\n")); /* TODO: check results */
1133 wxbPromptParser *pp = wxbUtils::WaitForPrompt(wxT("2\n"), true);
1134 int fileset = pp->getChoices()->Index(restorePanel->GetRowString(_("Storage")));
1135 if (fileset == wxNOT_FOUND) {
1136 wxbMainFrame::GetInstance()->SetStatusText(_("Failed to find the selected storage."));
1141 dt = new wxbDataTokenizer(true);
1142 wxbUtils::WaitForPrompt(wxString() << fileset << wxT("\n"));
1144 cfgUpdated = cfgUpdated & (~(1 << ConfigStorage));
1152 for (i = 0; i < dt->GetCount(); i++) {
1153 if ((*dt)[i].Find(_("Run Restore job")) == 0) {
1158 if (i == dt->GetCount()) {
1160 dt = wxbUtils::WaitForEnd(def + wxT("\n"), true);
1164 UpdateSecondConfig(dt); /* TODO: Check result */
1169 wxbMainFrame::GetInstance()->SetStatusText(_("Restore configuration changes were applied."));
1175 /* Cancel restore */
1176 void wxbRestorePanel::CmdConfigCancel() {
1177 wxbUtils::WaitForEnd(wxT("no\n"));
1178 wxbMainFrame::GetInstance()->Print(_("Restore cancelled.\n"), CS_DEBUG);
1179 wxbMainFrame::GetInstance()->SetStatusText(_("Restore cancelled."));
1180 SetStatus(finished);
1183 /* List jobs for a specified client and fileset */
1184 void wxbRestorePanel::CmdListJobs() {
1185 if (status == entered) {
1186 configPanel->ClearRowChoices(_("Before"));
1187 /*wxbUtils::WaitForPrompt("query\n");
1188 wxbUtils::WaitForPrompt("6\n");*/
1189 wxbTableParser* tableparser = new wxbTableParser(false);
1190 wxbDataTokenizer* dt = wxbUtils::WaitForEnd(
1191 wxString(wxT(".backups client=\"")) + configPanel->GetRowString(_("Client")) +
1192 wxT("\" fileset=\"") + configPanel->GetRowString(_("Fileset")) + wxT("\"\n"), true);
1194 while (!tableparser->hasFinished()) {
1195 wxTheApp->Yield(true);
1196 wxbUtils::MilliSleep(100);
1199 if (!tableparser->GetCount() == 0) {
1200 for (unsigned int i = 0; i < dt->Count(); i++) {
1201 if ((*dt)[i].Find(_("No results to list.")) == 0) {
1202 configPanel->AddRowChoice(_("Before"),
1203 _("No backup found for this client."));
1204 configPanel->SetRowSelection(_("Before"), 0);
1205 configPanel->EnableApply(true); // Enabling the not existing apply button disables the ok button.
1210 else if (((*dt)[i].Find(_("ERROR")) > -1) ||
1211 ((*dt)[i].Find(_("Query failed")) > -1)) {
1212 configPanel->AddRowChoice(_("Before"),
1213 _("Cannot get previous backups list, see console."));
1214 configPanel->SetRowSelection(_("Before"), 0);
1215 configPanel->EnableApply(true); // Enabling the not existing apply button disables the ok button.
1225 wxDateTime lastdatetime = (time_t) 0;
1226 for (int i = tableparser->GetCount()-1; i > -1; i--) {
1227 wxString str = (*tableparser)[i][3];
1228 wxDateTime datetime;
1230 if ( ( (chr = datetime.ParseDate(str.GetData()) ) != NULL ) && ( datetime.ParseTime(++chr) != NULL ) && ! lastdatetime.IsEqualTo(datetime) ) {
1231 lastdatetime = datetime;
1232 datetime += wxTimeSpan::Seconds(1);
1233 configPanel->AddRowChoice(_("Before"),
1234 datetime.Format(wxT("%Y-%m-%d %H:%M:%S")));
1240 configPanel->SetRowSelection(_("Before"), 0);
1241 configPanel->EnableApply(false); // Disabling the not existing apply button enables the ok button.
1245 /* List files and directories for a specified tree item */
1246 void wxbRestorePanel::CmdList(wxTreeItemId item) {
1247 if (status == choosing) {
1248 list->DeleteAllItems();
1253 UpdateTreeItem(item, true, false);
1255 if (list->GetItemCount() >= 1) {
1256 int firstwidth = list->GetSize().GetWidth();
1257 for (int i = 2; i < 7; i++) {
1258 list->SetColumnWidth(i, wxLIST_AUTOSIZE);
1259 firstwidth -= list->GetColumnWidth(i);
1262 list->SetColumnWidth(0, 18);
1264 list->SetColumnWidth(1, wxLIST_AUTOSIZE);
1265 if (list->GetColumnWidth(1) < firstwidth) {
1266 list->SetColumnWidth(1, firstwidth-25);
1272 /* Mark a treeitem (directory) or a listitem (file or directory) */
1273 void wxbRestorePanel::CmdMark(wxTreeItemId treeitem, long* listitems, int listsize, int state) {
1274 if (status == choosing) {
1275 wxbTreeItemData** itemdata;
1276 int itemdatasize = 0;
1277 if (listsize == 0) {
1278 itemdata = new wxbTreeItemData*[1];
1282 itemdata = new wxbTreeItemData*[listsize];
1283 itemdatasize = listsize;
1286 if (listitems != NULL) {
1287 for (int i = 0; i < itemdatasize; i++) {
1288 itemdata[i] = (wxbTreeItemData*)list->GetItemData(listitems[i]);
1291 else if (treeitem.IsOk()) {
1292 itemdata[0] = (wxbTreeItemData*)tree->GetItemData(treeitem);
1299 if (itemdata[0] == NULL) { //Should never happen
1304 wxString dir = itemdata[0]->GetPath();
1307 if (dir != wxT("/")) {
1308 if (dir.GetChar(dir.Length()-1) == '/') {
1312 int i = dir.Find('/', TRUE);
1317 else { /* first dir below root */
1318 file = dir.Mid(i+1);
1319 dir = dir.Mid(0, i+1);
1328 bool marked = false;
1329 bool unmarked = false;
1331 for (int i = 0; i < itemdatasize; i++) {
1332 switch(itemdata[i]->GetMarked()) {
1346 if (marked && unmarked)
1362 wxbUtils::WaitForEnd(wxString(wxT("cd \"")) << dir << wxT("\"\n"));
1363 wxbUtils::WaitForEnd(wxString((state==1) ? wxT("mark") : wxT("unmark")) << wxT(" \"") << file << wxT("\"\n"));
1365 /* TODO: Check commands results */
1367 /*if ((dir == "/") && (file == "*")) {
1368 itemdata->SetMarked((itemdata->GetMarked() == 1) ? 0 : 1);
1371 if (listitems == NULL) { /* tree item state changed */
1372 SetTreeItemState(treeitem, state);
1373 /*treeitem = tree->GetSelection();
1374 UpdateTree(treeitem, true);
1375 treeitem = tree->GetItemParent(treeitem);*/
1378 for (int i = 0; i < itemdatasize; i++) {
1379 SetListItemState(listitems[i], state);
1381 listadd->Enable(state == 0);
1382 listremove->Enable(state == 1);
1383 /*UpdateTree(treeitem, (tree->GetSelection() == treeitem));
1384 treeitem = tree->GetItemParent(treeitem);*/
1387 /*while (treeitem.IsOk()) {
1388 WaitForList(treeitem, false);
1389 treeitem = tree->GetItemParent(treeitem);
1396 /*----------------------------------------------------------------------------
1398 ----------------------------------------------------------------------------*/
1400 /* Run a dir command, and waits until result is fully received. */
1401 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)
1496 /* See ls_output in dird/ua_tree.c */
1497 //-rw-r-----,1,root,root,41575,2005-10-18 18:21:36, ,/usr/var/bacula/working/bacula.sql
1499 wxStringTokenizer tkz(line, wxT(","));
1501 if (!tkz.HasMoreTokens())
1503 entry->perm = tkz.GetNextToken();
1505 if (!tkz.HasMoreTokens())
1507 entry->nlink = tkz.GetNextToken();
1509 if (!tkz.HasMoreTokens())
1511 entry->user = tkz.GetNextToken();
1513 if (!tkz.HasMoreTokens())
1515 entry->group = tkz.GetNextToken();
1517 if (!tkz.HasMoreTokens())
1519 entry->size = tkz.GetNextToken();
1521 if (!tkz.HasMoreTokens())
1523 entry->date = tkz.GetNextToken();
1525 if (!tkz.HasMoreTokens())
1527 wxString marked = tkz.GetNextToken();
1528 if (marked == wxT("*")) {
1531 else if (marked == wxT("+")) {
1538 if (!tkz.HasMoreTokens())
1540 entry->fullname = tkz.GetString();
1542 /* Get only the filename (cut path by finding the last '/') */
1543 if (entry->fullname.GetChar(entry->fullname.Length()-1) == '/') {
1544 wxString tmp = entry->fullname;
1546 entry->filename = entry->fullname.Mid(tmp.Find('/', true)+1);
1549 entry->filename = entry->fullname.Mid(entry->fullname.Find('/', true)+1);
1555 /* Sets a list item state, and update its parents and children if it is a directory */
1556 void wxbRestorePanel::SetListItemState(long listitem, int newstate)
1558 wxbTreeItemData* itemdata = (wxbTreeItemData*)list->GetItemData(listitem);
1560 wxTreeItemId treeitem;
1562 itemdata->SetMarked(newstate);
1563 list->SetItemImage(listitem, newstate, 0); /* TODO: Find what these ints are for */
1564 list->SetItemImage(listitem, newstate, 1);
1566 if ((treeitem = itemdata->GetId()).IsOk()) {
1567 SetTreeItemState(treeitem, newstate);
1570 UpdateTreeItemState(tree->GetSelection());
1574 /* Sets a tree item state, and update its children, parents and list (if necessary) */
1575 void wxbRestorePanel::SetTreeItemState(wxTreeItemId item, int newstate) {
1576 #if wxCHECK_VERSION(2, 6, 0)
1577 wxTreeItemIdValue cookie;
1581 wxTreeItemId currentChild = tree->GetFirstChild(item, cookie);
1583 wxbTreeItemData* itemdata;
1585 while (currentChild.IsOk()) {
1586 itemdata = (wxbTreeItemData*)tree->GetItemData(currentChild);
1587 int state = itemdata->GetMarked();
1589 if (state != newstate) {
1590 itemdata->SetMarked(newstate);
1591 tree->SetItemImage(currentChild, newstate, wxTreeItemIcon_Normal);
1592 tree->SetItemImage(currentChild, newstate, wxTreeItemIcon_Selected);
1595 currentChild = tree->GetNextChild(item, cookie);
1598 itemdata = (wxbTreeItemData*)tree->GetItemData(item);
1599 itemdata->SetMarked(newstate);
1600 tree->SetItemImage(item, newstate, wxTreeItemIcon_Normal);
1601 tree->SetItemImage(item, newstate, wxTreeItemIcon_Selected);
1604 if (tree->GetSelection() == item) {
1605 for (long i = 0; i < list->GetItemCount(); i++) {
1606 list->SetItemImage(i, newstate, 0); /* TODO: Find what these ints are for */
1607 list->SetItemImage(i, newstate, 1);
1611 UpdateTreeItemState(tree->GetItemParent(item));
1614 /* Update a tree item state, and its parents' state */
1615 void wxbRestorePanel::UpdateTreeItemState(wxTreeItemId item) {
1622 #if wxCHECK_VERSION(2, 6, 0)
1623 wxTreeItemIdValue cookie;
1627 wxTreeItemId currentChild = tree->GetFirstChild(item, cookie);
1629 bool onechildmarked = false;
1630 bool onechildunmarked = false;
1632 while (currentChild.IsOk()) {
1633 state = ((wxbTreeItemData*)tree->GetItemData(currentChild))->GetMarked();
1636 onechildunmarked = true;
1639 onechildmarked = true;
1642 onechildmarked = true;
1643 onechildunmarked = true;
1647 if (onechildmarked && onechildunmarked) {
1651 currentChild = tree->GetNextChild(item, cookie);
1654 if (tree->GetSelection() == item) {
1655 for (long i = 0; i < list->GetItemCount(); i++) {
1656 state = ((wxbTreeItemData*)list->GetItemData(i))->GetMarked();
1660 onechildunmarked = true;
1663 onechildmarked = true;
1666 onechildmarked = true;
1667 onechildunmarked = true;
1671 if (onechildmarked && onechildunmarked) {
1679 if (onechildmarked && onechildunmarked) {
1682 else if (onechildmarked) {
1685 else if (onechildunmarked) {
1688 else { // no child, don't change anything
1689 UpdateTreeItemState(tree->GetItemParent(item));
1693 wxbTreeItemData* itemdata = (wxbTreeItemData*)tree->GetItemData(item);
1695 itemdata->SetMarked(state);
1696 tree->SetItemImage(item, state, wxTreeItemIcon_Normal);
1697 tree->SetItemImage(item, state, wxTreeItemIcon_Selected);
1699 UpdateTreeItemState(tree->GetItemParent(item));
1702 /* Refresh the whole tree. */
1703 void wxbRestorePanel::RefreshTree() {
1704 /* Save current selection */
1705 wxArrayString current;
1707 wxTreeItemId item = currentTreeItem;
1709 while ((item.IsOk()) && (item != tree->GetRootItem())) {
1710 current.Add(tree->GetItemText(item));
1711 item = tree->GetItemParent(item);
1714 /* Update the tree */
1715 UpdateTreeItem(tree->GetRootItem(), false, true);
1717 /* Reselect the former selected item */
1718 item = tree->GetRootItem();
1720 if (current.Count() == 0) {
1721 tree->SelectItem(item);
1727 for (int i = current.Count()-1; i >= 0; i--) {
1728 #if wxCHECK_VERSION(2, 6, 0)
1729 wxTreeItemIdValue cookie;
1733 wxTreeItemId currentChild = tree->GetFirstChild(item, cookie);
1737 while (currentChild.IsOk()) {
1738 if (((wxbTreeItemData*)tree->GetItemData(currentChild))->GetName() == current[i]) {
1739 item = currentChild;
1744 currentChild = tree->GetNextChild(item, cookie);
1750 UpdateTreeItem(item, true, false); /* Update the list */
1752 tree->SelectItem(item);
1755 void wxbRestorePanel::RefreshList() {
1756 if (currentTreeItem.IsOk()) {
1757 UpdateTreeItem(currentTreeItem, true, false); /* Update the list */
1761 /* Update first config, adapting settings to the job name selected */
1762 void wxbRestorePanel::UpdateFirstConfig() {
1763 configPanel->Enable(false);
1764 wxbDataTokenizer* dt = wxbUtils::WaitForEnd(wxString(wxT(".defaults job=")) + configPanel->GetRowString(_("Job Name")) + wxT("\n"), true, false);
1770 * where=/tmp/bacula-restores
1780 bool dolistjobs = false;
1782 for (i = 0; i < dt->GetCount(); i++) {
1784 if ((j = str.Find('=')) > -1) {
1785 name = str.Mid(0, j);
1786 if (name == wxT("pool")) {
1787 configPanel->SetRowString(_("Pool"), str.Mid(j+1));
1789 else if (name == wxT("client")) {
1791 if ((str != configPanel->GetRowString(_("Client"))) ||
1792 (configPanel->GetRowString(_("Before"))) == wxT("")) {
1793 configPanel->SetRowString(_("Client"), str);
1797 else if (name == wxT("storage")) {
1798 configPanel->SetRowString(_("Storage"), str.Mid(j+1));
1800 else if (name == wxT("fileset")) {
1802 if ((str != configPanel->GetRowString(_("Fileset"))) ||
1803 (configPanel->GetRowString(_("Before"))) == wxT("")) {
1804 configPanel->SetRowString(_("Fileset"), str);
1814 //wxTheApp->Yield(false);
1817 configPanel->Enable(true);
1821 * Update second config.
1824 * JobName: RestoreFiles
1825 * Bootstrap: /var/lib/bacula/restore.bsr
1826 * Where: /tmp/bacula-restores
1831 * When: 2004-04-18 01:18:56
1833 * OK to run? (yes/mod/no):
1836 bool wxbRestorePanel::UpdateSecondConfig(wxbDataTokenizer* dt) {
1838 for (i = 0; i < dt->GetCount(); i++) {
1839 if ((*dt)[i].Find(_("Run Restore job")) == 0)
1843 if ((i + 10) > dt->GetCount()) {
1849 if ((k = (*dt)[++i].Find(_("JobName:"))) != 0) return false;
1850 restorePanel->SetRowString(_("Job Name"), (*dt)[i].Mid(10).Trim(false).RemoveLast());
1851 if ((k = (*dt)[++i].Find(_("Bootstrap:"))) != 0) return false;
1852 restorePanel->SetRowString(_("Bootstrap"), (*dt)[i].Mid(10).Trim(false).RemoveLast());
1853 if ((k = (*dt)[++i].Find(_("Where:"))) != 0) return false;
1854 restorePanel->SetRowString(_("Where"), (*dt)[i].Mid(10).Trim(false).RemoveLast());
1856 if ((k = (*dt)[++i].Find(_("Replace:"))) != 0) return false;
1857 wxString str = (*dt)[i].Mid(10).Trim(false).RemoveLast();
1858 if (str == _("always")) restorePanel->SetRowSelection(_("Replace"), 0);
1859 else if (str == _("ifnewer")) restorePanel->SetRowSelection(_("Replace"), 1);
1860 else if (str == _("ifolder")) restorePanel->SetRowSelection(_("Replace"), 2);
1861 else if (str == _("never")) restorePanel->SetRowSelection(_("Replace"), 3);
1862 else restorePanel->SetRowSelection(_("Replace"), 0);
1864 if ((k = (*dt)[++i].Find(_("FileSet:"))) != 0) return false;
1865 restorePanel->SetRowString(_("Fileset"), (*dt)[i].Mid(10).Trim(false).RemoveLast());
1866 if ((k = (*dt)[++i].Find(_("Client:"))) != 0) return false;
1867 restorePanel->SetRowString(_("Client"), (*dt)[i].Mid(10).Trim(false).RemoveLast());
1868 if ((k = (*dt)[++i].Find(_("Storage:"))) != 0) return false;
1869 restorePanel->SetRowString(_("Storage"), (*dt)[i].Mid(10).Trim(false).RemoveLast());
1870 if ((k = (*dt)[++i].Find(_("When:"))) != 0) return false;
1871 restorePanel->SetRowString(_("When"), (*dt)[i].Mid(10).Trim(false).RemoveLast());
1872 if ((k = (*dt)[++i].Find(_("Priority:"))) != 0) return false;
1873 restorePanel->SetRowString(_("Priority"), (*dt)[i].Mid(10).Trim(false).RemoveLast());
1876 restorePanel->Layout();
1881 /*----------------------------------------------------------------------------
1883 ----------------------------------------------------------------------------*/
1885 /* Set current status by enabling/disabling components */
1886 void wxbRestorePanel::SetStatus(status_enum newstatus) {
1887 switch (newstatus) {
1889 centerSizer->Remove(configPanel);
1890 centerSizer->Remove(restorePanel);
1891 centerSizer->Remove(treelistPanel);
1892 treelistPanel->Show(false);
1893 restorePanel->Show(false);
1894 centerSizer->Add(configPanel, 1, wxEXPAND);
1895 configPanel->Show(true);
1896 configPanel->Layout();
1897 centerSizer->Layout();
1899 start->SetLabel(_("Enter restore mode"));
1900 start->Enable(false);
1901 configPanel->Enable(false);
1902 tree->Enable(false);
1903 list->Enable(false);
1904 gauge->Enable(false);
1905 cancel->Enable(false);
1910 centerSizer->Remove(configPanel);
1911 centerSizer->Remove(restorePanel);
1912 centerSizer->Remove(treelistPanel);
1913 treelistPanel->Show(false);
1914 restorePanel->Show(false);
1915 centerSizer->Add(configPanel, 1, wxEXPAND);
1916 configPanel->Show(true);
1917 configPanel->Layout();
1918 centerSizer->Layout();
1920 tree->DeleteAllItems();
1921 list->DeleteAllItems();
1922 configPanel->ClearRowChoices(_("Client"));
1923 configPanel->ClearRowChoices(_("Before"));
1924 wxbMainFrame::GetInstance()->EnablePanels();
1925 newstatus = activable;
1928 start->SetLabel(_("Enter restore mode"));
1929 start->Enable(true);
1930 configPanel->Enable(false);
1931 tree->Enable(false);
1932 list->Enable(false);
1933 gauge->Enable(false);
1934 cancel->Enable(false);
1938 wxbMainFrame::GetInstance()->DisablePanels(this);
1940 start->Enable(false);
1941 //start->SetLabel(_("Choose files to restore"));
1942 configPanel->Enable(true);
1943 tree->Enable(false);
1944 list->Enable(false);
1945 cancel->Enable(true);
1952 start->Enable(true);
1953 start->SetLabel(_("Restore"));
1954 centerSizer->Remove(configPanel);
1955 configPanel->Show(false);
1956 centerSizer->Add(treelistPanel, 1, wxEXPAND);
1957 treelistPanel->Show(true);
1958 treelistPanel->Layout();
1959 centerSizer->Layout();
1966 start->Enable(false);
1967 configPanel->Enable(false);
1968 tree->Enable(false);
1969 list->Enable(false);
1970 centerSizer->Remove(treelistPanel);
1971 treelistPanel->Show(false);
1972 centerSizer->Add(restorePanel, 1, wxEXPAND);
1973 restorePanel->Show(true);
1974 restorePanel->Layout();
1975 centerSizer->Layout();
1977 restorePanel->EnableApply(false);
1980 start->SetLabel(_("Restoring..."));
1981 gauge->Enable(true);
1983 start->Enable(false);
1984 configPanel->Enable(false);
1985 tree->Enable(false);
1986 list->Enable(false);
1993 /*----------------------------------------------------------------------------
1995 ----------------------------------------------------------------------------*/
1997 void wxbRestorePanel::SetWorking(bool working) {
1998 this->working = working;
2000 SetCursor(*wxHOURGLASS_CURSOR);
2001 // SetEvtHandlerEnabled(false); //EVTQUEUE
2003 // else if (!processing) { /* Empty event queue if we aren't already doing this */ //EVTQUEUE
2005 // processing = true; //EVTQUEUE
2006 SetCursor(*wxSTANDARD_CURSOR);
2007 // SetEvtHandlerEnabled(true); //EVTQUEUE
2008 /* wxNode *node = pendingEvents->First(); //EVTQUEUE
2010 wxEvent *event = (wxEvent *)node->Data();
2013 wxEvtHandler::ProcessEvent(*event);
2016 node = pendingEvents->First();
2018 processing = false;*/
2022 bool wxbRestorePanel::IsWorking() {
2023 return this->working;
2026 void wxbRestorePanel::EnableConfig(bool enable) {
2027 restorePanel->Enable(enable);
2030 /*----------------------------------------------------------------------------
2032 ----------------------------------------------------------------------------*/
2037 bool wxbRestorePanel::ProcessEvent(wxEvent& event) {
2038 if (IsWorking() || processing) {
2039 wxEvent *eventCopy = event.Clone();
2041 pendingEvents->Append(eventCopy);
2045 return wxEvtHandler::ProcessEvent(event);
2050 void wxbRestorePanel::OnCancel(wxCommandEvent& event) {
2051 cancel->Enable(false);
2052 SetCursor(*wxHOURGLASS_CURSOR);
2054 SetCursor(*wxSTANDARD_CURSOR);
2057 void wxbRestorePanel::OnStart(wxCommandEvent& event) {
2066 void wxbRestorePanel::OnTreeChanging(wxTreeEvent& event) {
2072 void wxbRestorePanel::OnTreeExpanding(wxTreeEvent& event) {
2078 //CmdList(event.GetItem());
2079 if (tree->GetSelection() != event.GetItem()) {
2080 tree->SelectItem(event.GetItem());
2085 void wxbRestorePanel::OnTreeChanged(wxTreeEvent& event) {
2089 if (currentTreeItem == event.GetItem()) {
2092 treeadd->Enable(false);
2093 treeremove->Enable(false);
2094 treerefresh->Enable(false);
2095 markWhenCommandDone = false;
2097 currentTreeItem = event.GetItem();
2098 CmdList(event.GetItem());
2099 if (markWhenCommandDone) {
2100 CmdMark(event.GetItem(), NULL, 0);
2104 if (event.GetItem().IsOk()) {
2105 int status = ((wxbTreeItemData*)tree->GetItemData(event.GetItem()))->GetMarked();
2106 treeadd->Enable(status != 1);
2107 treeremove->Enable(status != 0);
2109 treerefresh->Enable(true);
2112 void wxbRestorePanel::OnTreeMarked(wxbTreeMarkedEvent& event) {
2114 if (tree->GetSelection() == event.GetItem()) {
2115 markWhenCommandDone = !markWhenCommandDone;
2120 markWhenCommandDone = false;
2121 CmdMark(event.GetItem(), NULL, 0);
2122 if (markWhenCommandDone) {
2123 CmdMark(event.GetItem(), NULL, 0);
2128 if (event.GetItem().IsOk()) {
2129 int status = ((wxbTreeItemData*)tree->GetItemData(event.GetItem()))->GetMarked();
2130 treeadd->Enable(status != 1);
2131 treeremove->Enable(status != 0);
2135 void wxbRestorePanel::OnTreeAdd(wxCommandEvent& event) {
2140 if (currentTreeItem.IsOk()) {
2142 CmdMark(currentTreeItem, NULL, 0, 1);
2145 treeremove->Enable(1);
2150 void wxbRestorePanel::OnTreeRemove(wxCommandEvent& event) {
2155 if (currentTreeItem.IsOk()) {
2157 CmdMark(currentTreeItem, NULL, 0, 0);
2160 treeremove->Enable(0);
2165 void wxbRestorePanel::OnTreeRefresh(wxCommandEvent& event) {
2175 void wxbRestorePanel::OnListMarked(wxbListMarkedEvent& event) {
2180 if (list->GetSelectedItemCount() == 0) {
2186 long* items = new long[list->GetSelectedItemCount()];
2190 long item = list->GetNextItem(-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
2191 while (item != -1) {
2194 item = list->GetNextItem(item, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
2197 CmdMark(wxTreeItemId(), items, num);
2201 wxListEvent listevt;
2203 OnListChanged(listevt);
2210 void wxbRestorePanel::OnListActivated(wxListEvent& event) {
2215 long item = event.GetIndex();
2216 // long item = list->GetNextItem(-1, wxLIST_NEXT_ALL, wxLIST_STATE_FOCUSED);
2218 wxbTreeItemData* itemdata = (wxbTreeItemData*)list->GetItemData(item);
2219 wxString name = itemdata->GetName();
2224 #if wxCHECK_VERSION(2, 6, 0)
2225 wxTreeItemIdValue cookie;
2230 if (name.GetChar(name.Length()-1) == '/') {
2231 wxTreeItemId currentChild = tree->GetFirstChild(currentTreeItem, cookie);
2233 while (currentChild.IsOk()) {
2234 wxString name2 = ((wxbTreeItemData*)tree->GetItemData(currentChild))->GetName();
2235 if (name2 == name) {
2236 //tree->UnselectAll();
2238 tree->Expand(currentTreeItem);
2239 tree->SelectItem(currentChild);
2243 currentChild = tree->GetNextChild(currentTreeItem, cookie);
2250 void wxbRestorePanel::OnListChanged(wxListEvent& event) {
2255 listadd->Enable(false);
2256 listremove->Enable(false);
2258 bool marked = false;
2259 bool unmarked = false;
2261 long item = list->GetNextItem(-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
2262 while (item != -1) {
2263 switch (((wxbTreeItemData*)list->GetItemData(item))->GetMarked()) {
2276 // Should never happen
2278 if (marked && unmarked) break;
2279 item = list->GetNextItem(item, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
2282 listadd->Enable(unmarked);
2283 listremove->Enable(marked);
2286 void wxbRestorePanel::OnListAdd(wxCommandEvent& event) {
2293 long* items = new long[list->GetSelectedItemCount()];
2297 long item = list->GetNextItem(-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
2298 while (item != -1) {
2301 item = list->GetNextItem(item, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
2304 CmdMark(wxTreeItemId(), items, num, 1);
2311 listadd->Enable(false);
2312 listremove->Enable(true);
2315 void wxbRestorePanel::OnListRemove(wxCommandEvent& event) {
2322 long* items = new long[list->GetSelectedItemCount()];
2326 long item = list->GetNextItem(-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
2327 while (item != -1) {
2330 item = list->GetNextItem(item, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
2333 CmdMark(wxTreeItemId(), items, num, 0);
2340 listadd->Enable(true);
2341 listremove->Enable(false);
2344 void wxbRestorePanel::OnListRefresh(wxCommandEvent& event) {
2354 void wxbRestorePanel::OnConfigUpdated(wxCommandEvent& event) {
2355 if (status == entered) {
2356 if (event.GetId() == ConfigJobName) {
2361 UpdateFirstConfig();
2364 else if ((event.GetId() == ConfigClient) || (event.GetId() == ConfigFileset)) {
2369 configPanel->Enable(false);
2371 configPanel->Enable(true);
2374 cfgUpdated = cfgUpdated | (1 << event.GetId());
2376 else if (status == configuring) {
2377 restorePanel->EnableApply(true);
2378 cfgUpdated = cfgUpdated | (1 << event.GetId());
2382 void wxbRestorePanel::OnConfigOk(wxCommandEvent& WXUNUSED(event)) {
2383 if (status != configuring) return;
2392 void wxbRestorePanel::OnConfigApply(wxCommandEvent& WXUNUSED(event)) {
2393 if (status != configuring) return;
2399 if (cfgUpdated == 0) {
2400 restorePanel->EnableApply(false);
2405 void wxbRestorePanel::OnConfigCancel(wxCommandEvent& WXUNUSED(event)) {
2406 if (status != configuring) return;