3 * wxbPanel for restoring files
5 * Nicolas Boichat, April-July 2004
10 Bacula® - The Network Backup Solution
12 Copyright (C) 2004-2006 Free Software Foundation Europe e.V.
14 The main author of Bacula is Kern Sibbald, with contributions from
15 many others, a complete list can be found in the file AUTHORS.
16 This program is Free Software; you can redistribute it and/or
17 modify it under the terms of version two of the GNU General Public
18 License as published by the Free Software Foundation plus additions
19 that are listed in the file LICENSE.
21 This program is distributed in the hope that it will be useful, but
22 WITHOUT ANY WARRANTY; without even the implied warranty of
23 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
24 General Public License for more details.
26 You should have received a copy of the GNU General Public License
27 along with this program; if not, write to the Free Software
28 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
31 Bacula® is a registered trademark of John Walker.
32 The licensor of Bacula is the Free Software Foundation Europe
33 (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
34 Switzerland, email:ftf@fsfeurope.org.
37 /* Note concerning "done" output (modifiable marked with +)
39 +JobName: RestoreFiles
40 Bootstrap: /var/lib/bacula/restore.bsr
41 +Where: /tmp/bacula-restores
46 +When: 2004-04-18 01:18:56
48 OK to run? (yes/mod/no):mod
50 1: Level (not appropriate)
51 2: Storage (automatic ?)
54 5: Client (yes : "The defined Client resources are:\n\t1: velours-fd\n\t2: tom-fd\nSelect Client (File daemon) resource (1-2):")
55 6: When (yes : "Please enter desired start time as YYYY-MM-DD HH:MM:SS (return for now):")
56 7: Priority (yes : "Enter new Priority: (positive integer)")
58 9: Where (yes : "Please enter path prefix for restore (/ for none):")
59 10: Replace (yes : "Replace:\n 1: always\n 2: ifnewer\n 3: ifolder\n 4: never\n
60 Select replace option (1-4):")
62 Select parameter to modify (1-11):
65 /* Windows debug builds set _DEBUG which is used by wxWidgets to select their
66 * debug memory allocator. Unfortunately it conflicts with Bacula's SmartAlloc.
67 * So we turn _DEBUG off since we aren't interested in things it enables.
73 #include "wxbrestorepanel.h"
74 #include "wxbmainframe.h"
76 #include <wx/choice.h>
77 #include <wx/datetime.h>
79 #include "unmarked.xpm"
81 #include "partmarked.xpm"
82 #include <wx/listimpl.cpp>
84 /* A macro named Yield is defined under MinGW */
87 WX_DEFINE_LIST(wxbEventList);
90 * Class which is stored in the tree and in the list to keep informations
93 class wxbTreeItemData : public wxTreeItemData {
95 wxbTreeItemData(wxString path, wxString name, int marked, long listid = -1);
101 void SetMarked(int marked);
105 wxString* path; /* Full path */
106 wxString* name; /* File name */
107 int marked; /* 0 - Not Marked, 1 - Marked, 2 - Some file under is marked */
108 long listid; /* list ID : >-1 if this data is in the list (and/or on the tree) */
111 wxbTreeItemData::wxbTreeItemData(wxString path, wxString name, int marked, long listid): wxTreeItemData() {
112 this->path = new wxString(path);
113 this->name = new wxString(name);
114 this->marked = marked;
115 this->listid = listid;
118 wxbTreeItemData::~wxbTreeItemData() {
123 int wxbTreeItemData::GetMarked() {
127 void wxbTreeItemData::SetMarked(int marked) {
128 this->marked = marked;
131 long wxbTreeItemData::GetListId() {
135 wxString wxbTreeItemData::GetPath() {
139 wxString wxbTreeItemData::GetName() {
143 // ----------------------------------------------------------------------------
144 // event tables and other macros for wxWindows
145 // ----------------------------------------------------------------------------
173 BEGIN_EVENT_TABLE(wxbRestorePanel, wxPanel)
174 EVT_BUTTON(RestoreStart, wxbRestorePanel::OnStart)
175 EVT_BUTTON(RestoreCancel, wxbRestorePanel::OnCancel)
177 EVT_TREE_SEL_CHANGING(TreeCtrl, wxbRestorePanel::OnTreeChanging)
178 EVT_TREE_SEL_CHANGED(TreeCtrl, wxbRestorePanel::OnTreeChanged)
179 EVT_TREE_ITEM_EXPANDING(TreeCtrl, wxbRestorePanel::OnTreeExpanding)
180 EVT_TREE_MARKED_EVENT(TreeCtrl, wxbRestorePanel::OnTreeMarked)
181 EVT_BUTTON(TreeAdd, wxbRestorePanel::OnTreeAdd)
182 EVT_BUTTON(TreeRemove, wxbRestorePanel::OnTreeRemove)
183 EVT_BUTTON(TreeRefresh, wxbRestorePanel::OnTreeRefresh)
185 EVT_LIST_ITEM_ACTIVATED(ListCtrl, wxbRestorePanel::OnListActivated)
186 EVT_LIST_MARKED_EVENT(ListCtrl, wxbRestorePanel::OnListMarked)
187 EVT_LIST_ITEM_SELECTED(ListCtrl, wxbRestorePanel::OnListChanged)
188 EVT_LIST_ITEM_DESELECTED(ListCtrl, wxbRestorePanel::OnListChanged)
189 EVT_BUTTON(ListAdd, wxbRestorePanel::OnListAdd)
190 EVT_BUTTON(ListRemove, wxbRestorePanel::OnListRemove)
191 EVT_BUTTON(ListRefresh, wxbRestorePanel::OnListRefresh)
193 EVT_TEXT(ConfigWhere, wxbRestorePanel::OnConfigUpdated)
194 EVT_TEXT(ConfigWhen, wxbRestorePanel::OnConfigUpdated)
195 EVT_TEXT(ConfigPriority, wxbRestorePanel::OnConfigUpdated)
196 EVT_CHOICE(ConfigWhen, wxbRestorePanel::OnConfigUpdated)
197 EVT_CHOICE(ConfigReplace, wxbRestorePanel::OnConfigUpdated)
198 EVT_CHOICE(ConfigClient, wxbRestorePanel::OnConfigUpdated)
199 EVT_CHOICE(ConfigFileset, wxbRestorePanel::OnConfigUpdated)
200 EVT_CHOICE(ConfigStorage, wxbRestorePanel::OnConfigUpdated)
201 EVT_CHOICE(ConfigJobName, wxbRestorePanel::OnConfigUpdated)
202 EVT_CHOICE(ConfigPool, wxbRestorePanel::OnConfigUpdated)
204 EVT_BUTTON(ConfigOk, wxbRestorePanel::OnConfigOk)
205 EVT_BUTTON(ConfigApply, wxbRestorePanel::OnConfigApply)
206 EVT_BUTTON(ConfigCancel, wxbRestorePanel::OnConfigCancel)
210 * wxbRestorePanel constructor
212 wxbRestorePanel::wxbRestorePanel(wxWindow* parent): wxbPanel(parent)
214 //pendingEvents = new wxbEventList(); //EVTQUEUE
215 //processing = false; //EVTQUEUE
218 imagelist = new wxImageList(16, 16, TRUE, 3);
219 imagelist->Add(wxIcon(unmarked_xpm));
220 imagelist->Add(wxIcon(marked_xpm));
221 imagelist->Add(wxIcon(partmarked_xpm));
223 wxFlexGridSizer* mainSizer = new wxFlexGridSizer(3, 1, 10, 10);
224 mainSizer->AddGrowableCol(0);
225 mainSizer->AddGrowableRow(1);
227 wxFlexGridSizer *firstSizer = new wxFlexGridSizer(1, 2, 10, 10);
229 firstSizer->AddGrowableCol(0);
230 firstSizer->AddGrowableRow(0);
232 start = new wxButton(this, RestoreStart, _("Enter restore mode"), wxDefaultPosition, wxSize(150, 30));
233 firstSizer->Add(start, 0, wxALIGN_CENTER_HORIZONTAL | wxALIGN_CENTER_VERTICAL, 10);
235 cancel = new wxButton(this, RestoreCancel, _("Cancel restore"), wxDefaultPosition, wxSize(150, 30));
236 firstSizer->Add(cancel, 0, wxALIGN_CENTER_HORIZONTAL | wxALIGN_RIGHT, 10);
240 /* clientChoice = new wxChoice(this, ClientChoice, wxDefaultPosition, wxSize(150, 30), 0, elist);
241 firstSizer->Add(clientChoice, 1, wxALIGN_CENTER_HORIZONTAL | wxALIGN_CENTER_VERTICAL, 10);
243 jobChoice = new wxChoice(this, -1, wxDefaultPosition, wxSize(150, 30), 0, elist);
244 firstSizer->Add(jobChoice, 1, wxALIGN_CENTER_HORIZONTAL | wxALIGN_CENTER_VERTICAL, 10);*/
246 mainSizer->Add(firstSizer, 1, wxEXPAND, 10);
248 treelistPanel = new wxSplitterWindow(this);
250 wxPanel* treePanel = new wxPanel(treelistPanel);
251 wxFlexGridSizer *treeSizer = new wxFlexGridSizer(2, 1, 0, 0);
252 treeSizer->AddGrowableCol(0);
253 treeSizer->AddGrowableRow(0);
255 tree = new wxbTreeCtrl(treePanel, this, TreeCtrl, wxDefaultPosition, wxSize(200,50));
256 tree->SetImageList(imagelist);
258 treeSizer->Add(tree, 1, wxEXPAND, 0);
260 wxBoxSizer *treeCtrlSizer = new wxBoxSizer(wxHORIZONTAL);
261 treeadd = new wxButton(treePanel, TreeAdd, _("Add"), wxDefaultPosition, wxSize(60, 25));
262 treeCtrlSizer->Add(treeadd, 0, wxLEFT | wxRIGHT, 3);
263 treeremove = new wxButton(treePanel, TreeRemove, _("Remove"), wxDefaultPosition, wxSize(60, 25));
264 treeCtrlSizer->Add(treeremove, 0, wxLEFT | wxRIGHT, 3);
265 treerefresh = new wxButton(treePanel, TreeRefresh, _("Refresh"), wxDefaultPosition, wxSize(60, 25));
266 treeCtrlSizer->Add(treerefresh, 0, wxLEFT | wxRIGHT, 3);
268 treeSizer->Add(treeCtrlSizer, 1, wxALIGN_CENTER_HORIZONTAL, 0);
270 treePanel->SetSizer(treeSizer);
272 wxPanel* listPanel = new wxPanel(treelistPanel);
273 wxFlexGridSizer *listSizer = new wxFlexGridSizer(2, 1, 0, 0);
274 listSizer->AddGrowableCol(0);
275 listSizer->AddGrowableRow(0);
277 list = new wxbListCtrl(listPanel, this, ListCtrl, wxDefaultPosition, wxSize(200,50));
278 //treelistSizer->Add(list, 1, wxEXPAND, 10);
280 list->SetImageList(imagelist, wxIMAGE_LIST_SMALL);
283 info.SetMask(wxLIST_MASK_TEXT | wxLIST_MASK_FORMAT);
284 info.SetText(_("M"));
285 info.SetAlign(wxLIST_FORMAT_CENTER);
286 list->InsertColumn(0, info);
288 info.SetText(_("Filename"));
289 info.SetAlign(wxLIST_FORMAT_LEFT);
290 list->InsertColumn(1, info);
292 info.SetText(_("Size"));
293 info.SetAlign(wxLIST_FORMAT_RIGHT);
294 list->InsertColumn(2, info);
296 info.SetText(_("Date"));
297 info.SetAlign(wxLIST_FORMAT_LEFT);
298 list->InsertColumn(3, info);
300 info.SetText(_("Perm."));
301 info.SetAlign(wxLIST_FORMAT_LEFT);
302 list->InsertColumn(4, info);
304 info.SetText(_("User"));
305 info.SetAlign(wxLIST_FORMAT_RIGHT);
306 list->InsertColumn(5, info);
308 info.SetText(_("Group"));
309 info.SetAlign(wxLIST_FORMAT_RIGHT);
310 list->InsertColumn(6, info);
312 listSizer->Add(list, 1, wxEXPAND, 0);
314 wxBoxSizer *listCtrlSizer = new wxBoxSizer(wxHORIZONTAL);
315 listadd = new wxButton(listPanel, ListAdd, _("Add"), wxDefaultPosition, wxSize(60, 25));
316 listCtrlSizer->Add(listadd, 0, wxLEFT | wxRIGHT, 5);
317 listremove = new wxButton(listPanel, ListRemove, _("Remove"), wxDefaultPosition, wxSize(60, 25));
318 listCtrlSizer->Add(listremove, 0, wxLEFT | wxRIGHT, 5);
319 listrefresh = new wxButton(listPanel, ListRefresh, _("Refresh"), wxDefaultPosition, wxSize(60, 25));
320 listCtrlSizer->Add(listrefresh, 0, wxLEFT | wxRIGHT, 5);
322 listSizer->Add(listCtrlSizer, 1, wxALIGN_CENTER_HORIZONTAL, 0);
324 listPanel->SetSizer(listSizer);
326 treelistPanel->SplitVertically(treePanel, listPanel, 210);
328 treelistPanel->SetMinimumPaneSize(210);
330 treelistPanel->Show(false);
332 wxbConfig* config = new wxbConfig();
333 config->Add(new wxbConfigParam(_("Job Name"), ConfigJobName, choice, 0, elist));
334 config->Add(new wxbConfigParam(_("Client"), ConfigClient, choice, 0, elist));
335 config->Add(new wxbConfigParam(_("Fileset"), ConfigFileset, choice, 0, elist));
336 config->Add(new wxbConfigParam(_("Pool"), ConfigPool, choice, 0, elist));
337 config->Add(new wxbConfigParam(_("Storage"), ConfigStorage, choice, 0, elist));
338 config->Add(new wxbConfigParam(_("Before"), ConfigWhen, choice, 0, elist));
340 configPanel = new wxbConfigPanel(this, config, _("Please configure parameters concerning files to restore :"), RestoreStart, RestoreCancel, -1);
342 configPanel->Show(true);
343 configPanel->Enable(false);
345 config = new wxbConfig();
346 config->Add(new wxbConfigParam(_("Job Name"), -1, text, wxT("")));
347 config->Add(new wxbConfigParam(_("Bootstrap"), -1, text, wxT("")));
348 config->Add(new wxbConfigParam(_("Where"), ConfigWhere, modifiableText, wxT("")));
349 wxString erlist[] = {_("always"), _("if newer"), _("if older"), _("never")};
350 config->Add(new wxbConfigParam(_("Replace"), ConfigReplace, choice, 4, erlist));
351 config->Add(new wxbConfigParam(_("Fileset"), ConfigFileset, choice, 0, erlist));
352 config->Add(new wxbConfigParam(_("Client"), ConfigClient, choice, 0, erlist));
353 config->Add(new wxbConfigParam(_("Storage"), ConfigStorage, choice, 0, erlist));
354 config->Add(new wxbConfigParam(_("When"), ConfigWhen, modifiableText, wxT("")));
355 config->Add(new wxbConfigParam(_("Priority"), ConfigPriority, modifiableText, wxT("")));
357 restorePanel = new wxbConfigPanel(this, config, _("Please configure parameters concerning files restoration :"), ConfigOk, ConfigCancel, ConfigApply);
359 restorePanel->Show(false);
361 centerSizer = new wxBoxSizer(wxHORIZONTAL);
362 //centerSizer->Add(treelistPanel, 1, wxEXPAND | wxADJUST_MINSIZE);
364 mainSizer->Add(centerSizer, 1, wxEXPAND, 10);
366 gauge = new wxGauge(this, -1, 1, wxDefaultPosition, wxSize(200,20));
368 mainSizer->Add(gauge, 1, wxEXPAND, 5);
370 gauge->Enable(false);
373 mainSizer->SetSizeHints(this);
377 for (int i = 0; i < 7; i++) {
378 list->SetColumnWidth(i, 70);
381 SetCursor(*wxSTANDARD_CURSOR);
383 markWhenCommandDone = false;
389 * wxbRestorePanel destructor
391 wxbRestorePanel::~wxbRestorePanel()
396 /*----------------------------------------------------------------------------
397 wxbPanel overloadings
398 ----------------------------------------------------------------------------*/
400 wxString wxbRestorePanel::GetTitle()
405 void wxbRestorePanel::EnablePanel(bool enable)
408 if (status == disabled) {
409 SetStatus(activable);
416 /*----------------------------------------------------------------------------
417 Commands called by events handler
418 ----------------------------------------------------------------------------*/
420 /* The main button has been clicked */
421 void wxbRestorePanel::CmdStart()
424 if (status == activable) {
425 wxbMainFrame::GetInstance()->SetStatusText(_("Getting parameters list."));
426 wxbDataTokenizer* dt = wxbUtils::WaitForEnd(wxT(".clients\n"), true, false);
429 configPanel->ClearRowChoices(_("Client"));
430 restorePanel->ClearRowChoices(_("Client"));
432 if (dt->GetCount() == 0) {
433 wxbMainFrame::GetInstance()->SetStatusText(_("Error : no clients returned by the director."));
437 for (i = 0; i < dt->GetCount(); i++) {
440 configPanel->AddRowChoice(_("Client"), str);
441 restorePanel->AddRowChoice(_("Client"), str);
451 dt = wxbUtils::WaitForEnd(wxT(".filesets\n"), true, false);
453 configPanel->ClearRowChoices(_("Fileset"));
454 restorePanel->ClearRowChoices(_("Fileset"));
456 if (dt->GetCount() == 0) {
457 wxbMainFrame::GetInstance()->SetStatusText(_("Error : no filesets returned by the director."));
461 for (i = 0; i < dt->GetCount(); i++) {
464 configPanel->AddRowChoice(_("Fileset"), str);
465 restorePanel->AddRowChoice(_("Fileset"), str);
475 dt = wxbUtils::WaitForEnd(wxT(".storage\n"), true, false);
477 configPanel->ClearRowChoices(_("Storage"));
478 restorePanel->ClearRowChoices(_("Storage"));
480 if (dt->GetCount() == 0) {
481 wxbMainFrame::GetInstance()->SetStatusText(_("Error : no storage returned by the director."));
485 for (i = 0; i < dt->GetCount(); i++) {
488 configPanel->AddRowChoice(_("Storage"), str);
489 restorePanel->AddRowChoice(_("Storage"), str);
499 dt = wxbUtils::WaitForEnd(wxT(".jobs\n"), true, false);
501 configPanel->ClearRowChoices(_("Job Name"));
503 if (dt->GetCount() == 0) {
504 wxbMainFrame::GetInstance()->SetStatusText(_("Error : no jobs returned by the director."));
508 for (i = 0; i < dt->GetCount(); i++) {
511 configPanel->AddRowChoice(_("Job Name"), str);
514 configPanel->SetRowString(_("Job Name"), _("RestoreFiles"));
523 dt = wxbUtils::WaitForEnd(wxT(".pools\n"), true, false);
525 configPanel->ClearRowChoices(_("Pool"));
527 if (dt->GetCount() == 0) {
528 wxbMainFrame::GetInstance()->SetStatusText(_("Error : no jobs returned by the director."));
532 for (i = 0; i < dt->GetCount(); i++) {
535 configPanel->AddRowChoice(_("Pool"), str);
549 wxbMainFrame::GetInstance()->SetStatusText(_("Please configure your restore parameters."));
551 else if (status == entered) {
552 /* if (clientChoice->GetStringSelection().Length() < 1) {
553 wxbMainFrame::GetInstance()->SetStatusText(_("Please select a client."));
556 if (jobChoice->GetStringSelection().Length() < 1) {
557 wxbMainFrame::GetInstance()->SetStatusText(_("Please select a restore date."));
560 wxbMainFrame::GetInstance()->SetStatusText(_("Building restore tree..."));
564 wxbTableParser* tableparser = new wxbTableParser();
565 wxbDataTokenizer* dt = new wxbDataTokenizer(false);
568 * The following line was removed from ::GetInstance below because
569 * it does not work with multiple pools -- KES 5Oct05 see bug #433
570 * wxT("\" pool=\"") << configPanel->GetRowString(wxT("Pool")) <<
572 wxbMainFrame::GetInstance()->Send(wxString(wxT("restore")) <<
573 wxT(" client=\"") << configPanel->GetRowString(wxT("Client")) <<
574 wxT("\" fileset=\"") << configPanel->GetRowString(wxT("Fileset")) <<
575 wxT("\" storage=\"") << configPanel->GetRowString(wxT("Storage")) <<
576 wxT("\" before=\"") << configPanel->GetRowString(wxT("Before")) <<
578 //wxbUtils::WaitForPrompt("6\n");
580 /*wxbPromptParser *pp = wxbUtils::WaitForPrompt(wxString() << configPanel->GetRowString(wxT("Before")) << "\n", true);
581 int client = pp->getChoices()->Index(configPanel->GetRowString(wxT("Client")));
582 if (client == wxNOT_FOUND) {
583 wxbMainFrame::GetInstance()->SetStatusText("Failed to find the selected client.");
588 //wxbMainFrame::GetInstance()->Send(wxString() << configPanel->GetRowString(wxT("Before")) << "\n");
590 while (!tableparser->hasFinished() && !dt->hasFinished()) {
591 wxTheApp->Yield(true);
592 wxbUtils::MilliSleep(100);
597 if (dt->hasFinished() && !tableparser->hasFinished()) {
599 if (dt->GetCount() > 1) {
600 str = (*dt)[dt->GetCount()-2];
603 wxbMainFrame::GetInstance()->SetStatusText(wxString(_("Error while starting restore: ")) << str);
613 for (i = 0; i < tableparser->GetCount(); i++) {
614 str = (*tableparser)[i][2];
615 str.Replace(wxT(","), wxT(""));
616 if (str.ToLong(&l)) {
622 gauge->SetRange(tot);
624 /*wxbMainFrame::GetInstance()->Print(
625 wxString("[") << tot << "]", CS_DEBUG);*/
627 wxDateTime base = wxDateTime::Now();
631 unsigned int lastindex = 0;
638 newdate = wxDateTime::Now();
639 if (newdate.Subtract(base).GetMilliseconds() > 10 ) {
641 for (; lastindex < dt->GetCount(); lastindex++) {
642 if (((i1 = (*dt)[lastindex].Find(wxT("Building directory tree for JobId "))) >= 0) &&
643 ((i2 = (*dt)[lastindex].Find(wxT(" ..."))) > 0)) {
644 str = (*dt)[lastindex].Mid(i1+34, i2-(i1+34));
645 for (i = 0; i < tableparser->GetCount(); i++) {
646 if (str == (*tableparser)[i][0]) {
647 str = (*tableparser)[i][2];
648 str.Replace(wxT(","), wxT(""));
649 if (str.ToLong(&l)) {
652 var = (willdo-done)/50;
653 gauge->SetValue(done);
654 wxTheApp->Yield(true);
660 else if ((*dt)[lastindex] == wxT("+")) {
661 gauge->SetValue(gauge->GetValue()+var);
662 wxTheApp->Yield(true);
667 if (dt->hasFinished()) {
671 wxTheApp->Yield(true);
672 wxbUtils::MilliSleep(1);
675 gauge->SetValue(tot);
676 wxTheApp->Yield(true);
687 wxbUtils::WaitForEnd(wxT("unmark *\n"));
688 wxTreeItemId root = tree->AddRoot(configPanel->GetRowString(_("Client")), -1, -1, new wxbTreeItemData(wxT("/"), configPanel->GetRowString(_("Client")), 0));
689 currentTreeItem = root;
691 tree->SelectItem(root);
693 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."));
696 else if (status == choosing) {
700 wxbDataTokenizer* dt;
704 dt = new wxbDataTokenizer(true);
705 wxbPromptParser* promptparser = wxbUtils::WaitForPrompt(wxT("done\n"), true);
707 while (!promptparser->getChoices() || (promptparser->getChoices()->Index(wxT("mod")) < 0)) {
708 wxbMainFrame::GetInstance()->Print(_("Unexpected question has been received.\n"), CS_DEBUG);
711 if (promptparser->getIntroString() != wxT("")) {
712 message << promptparser->getIntroString() << wxT("\n");
714 message << promptparser->getQuestionString();
716 if (promptparser->getChoices()) {
717 wxString *choices = new wxString[promptparser->getChoices()->GetCount()];
718 int *numbers = new int[promptparser->getChoices()->GetCount()];
721 for (unsigned int i = 0; i < promptparser->getChoices()->GetCount(); i++) {
722 if ((*promptparser->getChoices())[i] != wxT("")) {
723 choices[n] = (*promptparser->getChoices())[i];
729 int res = ::wxGetSingleChoiceIndex(message,
730 _("wx-console: unexpected restore question."), n, choices, this);
733 promptparser = wxbUtils::WaitForPrompt(wxT(".\n"), true);
736 if (promptparser->isNumericalChoice()) {
738 promptparser = wxbUtils::WaitForPrompt(wxString() << numbers[res] << wxT("\n"), true);
742 promptparser = wxbUtils::WaitForPrompt(wxString() << choices[res] << wxT("\n"), true);
751 promptparser = wxbUtils::WaitForPrompt(::wxGetTextFromUser(message,
752 _("wx-console: unexpected restore question."),
753 wxT(""), this) + wxT("\n"));
756 printf("promptparser->getChoices()=%ld", (long)promptparser->getChoices());
760 SetStatus(configuring);
762 for (i = 0; i < dt->GetCount(); i++) {
763 if ((j = (*dt)[i].Find(_(" files selected to be restored."))) > -1) {
764 (*dt)[i].Mid(0, j).ToLong(&totfilemessages);
768 if ((j = (*dt)[i].Find(_(" file selected to be restored."))) > -1) {
769 (*dt)[i].Mid(0, j).ToLong(&totfilemessages);
774 wxbMainFrame::GetInstance()->SetStatusText(
775 wxString::Format(_("Please configure your restore (%ld files selected to be restored)..."), totfilemessages));
777 UpdateSecondConfig(dt);
782 restorePanel->EnableApply(false);
784 if (totfilemessages == 0) {
785 wxbMainFrame::GetInstance()->Print(_("Restore failed : no file selected.\n"), CS_DEBUG);
786 wxbMainFrame::GetInstance()->SetStatusText(_("Restore failed : no file selected."));
791 else if (status == configuring) {
792 cancel->Enable(false);
796 wxbMainFrame::GetInstance()->SetStatusText(_("Restoring, please wait..."));
798 wxbDataTokenizer* dt;
800 SetStatus(restoring);
801 dt = wxbUtils::WaitForEnd(wxT("yes\n"), true);
804 gauge->SetRange(totfilemessages);
808 for (i = 0; i < dt->GetCount(); i++) {
809 if ((j = (*dt)[i].Find(_("Job started. JobId="))) > -1) {
810 jobid = (*dt)[i].Mid(j+19);
811 wxbMainFrame::GetInstance()->SetStatusText(_("Restore started, jobid=") + jobid);
815 if ((j = (*dt)[i].Find(_("Job failed."))) > -1) {
816 wxbMainFrame::GetInstance()->Print(_("Restore failed, please look at messages.\n"), CS_DEBUG);
817 wxbMainFrame::GetInstance()->SetStatusText(_("Restore failed, please look at messages in console."));
822 if (jobid == wxT("")) {
823 wxbMainFrame::GetInstance()->Print(_("Failed to retrieve jobid.\n"), CS_DEBUG);
824 wxbMainFrame::GetInstance()->SetStatusText(_("Failed to retrieve jobid.\n"));
828 wxDateTime currenttime;
830 dt = wxbUtils::WaitForEnd(wxT("time\n"), true);
831 wxStringTokenizer ttkz((*dt)[0], wxT(" "), wxTOKEN_STRTOK);
832 if ((currenttime.ParseDate(ttkz.GetNextToken()) == NULL) || // Date
833 (currenttime.ParseTime(ttkz.GetNextToken()) == NULL)) { // Time
834 currenttime.SetYear(1990); // If parsing fails, set currenttime to a dummy date
837 currenttime -= wxTimeSpan::Seconds(30); //Adding a 30" tolerance
841 wxDateTime scheduledtime;
842 wxStringTokenizer stkz(restorePanel->GetRowString(_("When")), wxT(" "), wxTOKEN_STRTOK);
844 if ((scheduledtime.ParseDate(stkz.GetNextToken()) == NULL) || // Date
845 (scheduledtime.ParseTime(stkz.GetNextToken()) == NULL)) { // Time
846 scheduledtime.SetYear(2090); // If parsing fails, set scheduledtime to a dummy date
849 if (scheduledtime.Subtract(currenttime).IsLongerThan(wxTimeSpan::Seconds(150))) {
850 wxbMainFrame::GetInstance()->Print(_("Restore is scheduled in more than two minutes, wx-console will not wait for its completion.\n"), CS_DEBUG);
851 wxbMainFrame::GetInstance()->SetStatusText(_("Restore is scheduled in more than two minutes, wx-console will not wait for its completion."));
856 wxString cmd = wxString(wxT("list jobid=")) + jobid;
858 wxbTableParser* tableparser;
860 long filemessages = 0;
863 bool waitforever = false;
869 wxbUtils::WaitForEnd(wxT("autodisplay off\n"));
870 wxbUtils::WaitForEnd(wxT("gui on\n"));
872 tableparser = wxbUtils::CreateAndWaitForParser(cmd);
874 status = (*tableparser)[0][7].GetChar(0);
877 wxbMainFrame::GetInstance()->SetStatusText(_("Restore job created, but not yet running."));
881 wxbMainFrame::GetInstance()->SetStatusText(
882 wxString::Format(_("Restore job running, please wait (%ld of %ld files restored)..."), filemessages, totfilemessages));
886 wxbMainFrame::GetInstance()->SetStatusText(_("Restore job terminated successfully."));
887 wxbMainFrame::GetInstance()->Print(_("Restore job terminated successfully.\n"), CS_DEBUG);
891 case JS_ErrorTerminated:
892 wxbMainFrame::GetInstance()->SetStatusText(_("Restore job terminated in error, see messages in console."));
893 wxbMainFrame::GetInstance()->Print(_("Restore job terminated in error, see messages.\n"), CS_DEBUG);
898 wxbMainFrame::GetInstance()->SetStatusText(_("Restore job reported a non-fatal error."));
902 wxbMainFrame::GetInstance()->SetStatusText(_("Restore job reported a fatal error."));
907 wxbMainFrame::GetInstance()->SetStatusText(_("Restore job cancelled by user."));
908 wxbMainFrame::GetInstance()->Print(_("Restore job cancelled by user.\n"), CS_DEBUG);
913 wxbMainFrame::GetInstance()->SetStatusText(_("Restore job is waiting on File daemon."));
917 wxbMainFrame::GetInstance()->SetStatusText(_("Restore job is waiting for new media."));
920 case JS_WaitStoreRes:
921 wxbMainFrame::GetInstance()->SetStatusText(_("Restore job is waiting for storage resource."));
925 wxbMainFrame::GetInstance()->SetStatusText(_("Restore job is waiting for job resource."));
928 case JS_WaitClientRes:
929 wxbMainFrame::GetInstance()->SetStatusText(_("Restore job is waiting for Client resource."));
933 wxbMainFrame::GetInstance()->SetStatusText(_("Restore job is waiting for maximum jobs."));
936 case JS_WaitStartTime:
937 wxbMainFrame::GetInstance()->SetStatusText(_("Restore job is waiting for start time."));
940 case JS_WaitPriority:
941 wxbMainFrame::GetInstance()->SetStatusText(_("Restore job is waiting for higher priority jobs to finish."));
947 dt = wxbUtils::WaitForEnd(wxT(".messages\n"), true);
949 for (unsigned int i = 0; i < dt->GetCount(); i++) {
950 wxStringTokenizer tkz((*dt)[i], wxT(" "), wxTOKEN_STRTOK);
954 // Date Time name: perm ? user grp size date time
955 //04-Apr-2004 17:19 Tom-fd: -rwx------ 1 nicolas None 514967 2004-03-20 20:03:42 filename
957 if (datetime.ParseDate(tkz.GetNextToken()) != NULL) { // Date
958 if (datetime.ParseTime(tkz.GetNextToken()) != NULL) { // Time
959 if (tkz.GetNextToken().Last() == ':') { // name:
960 tkz.GetNextToken(); // perm
961 tkz.GetNextToken(); // ?
962 tkz.GetNextToken(); // user
963 tkz.GetNextToken(); // grp
964 tkz.GetNextToken(); // size
965 if (datetime.ParseDate(tkz.GetNextToken()) != NULL) { //date
966 if (datetime.ParseTime(tkz.GetNextToken()) != NULL) { //time
968 //wxbMainFrame::GetInstance()->Print(wxString("(") << filemessages << ")", CS_DEBUG);
969 gauge->SetValue(filemessages);
980 while (sw2.Time() < 10000) {
981 wxTheApp->Yield(true);
982 wxbUtils::MilliSleep(100);
989 if ((!waitforever) && (sw.Time() > 60000)) {
990 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);
991 wxbMainFrame::GetInstance()->SetStatusText(_("The restore job has not been started within one minute, wx-console will not wait for its completion anymore."));
995 wxbUtils::WaitForEnd(wxT("autodisplay on\n"));
996 wxbUtils::WaitForEnd(wxT(".messages\n"));
998 gauge->SetValue(totfilemessages);
1000 if (status == JS_Terminated) {
1001 wxbMainFrame::GetInstance()->Print(_("Restore done successfully.\n"), CS_DEBUG);
1002 wxbMainFrame::GetInstance()->SetStatusText(_("Restore done successfully."));
1004 SetStatus(finished);
1008 /* The cancel button has been clicked */
1009 void wxbRestorePanel::CmdCancel() {
1012 if (status == restoring) {
1013 if (jobid != wxT("")) {
1014 wxbMainFrame::GetInstance()->Send(wxString(wxT("cancel job=")) << jobid << wxT("\n"));
1016 cancel->Enable(true);
1021 while ((IsWorking()) && (cancelled != 2)) {
1022 wxTheApp->Yield(true);
1023 wxbUtils::MilliSleep(100);
1024 if (sw.Time() > 30000) { /* 30 seconds timeout */
1025 if (status == choosing) {
1026 wxbMainFrame::GetInstance()->Send(wxT("quit\n"));
1028 else if (status == configuring) {
1029 wxbMainFrame::GetInstance()->Send(wxT("no\n"));
1031 else if (status == restoring) {
1034 SetStatus(finished);
1035 wxbUtils::MilliSleep(1000);
1042 wxbMainFrame::GetInstance()->Send(wxT("quit\n"));
1045 wxbMainFrame::GetInstance()->Send(wxT("no\n"));
1050 wxbUtils::MilliSleep(1000);
1051 SetStatus(finished);
1054 /* Apply configuration changes */
1056 /* 1: Level (not appropriate)
1061 * 6: When (yes : "Please enter desired start time as YYYY-MM-DD HH:MM:SS (return for now):")
1062 * 7: Priority (yes : "Enter new Priority: (positive integer)")
1064 * 9: Where (yes : "Please enter path prefix for restore (/ for none):")
1065 * 10: Replace (yes : "Replace:\n 1: always\n 2: ifnewer\n 3: ifolder\n 4: never\n
1066 * Select replace option (1-4):")
1070 void wxbRestorePanel::CmdConfigApply() {
1071 if (cfgUpdated == 0) return;
1073 wxbMainFrame::GetInstance()->SetStatusText(_("Applying restore configuration changes..."));
1075 EnableConfig(false);
1077 wxbDataTokenizer* dt = NULL;
1079 bool failed = false;
1081 while (cfgUpdated > 0) {
1086 wxString def; //String to send if can't use our data
1087 if ((cfgUpdated >> ConfigWhere) & 1) {
1088 wxbUtils::WaitForPrompt(wxT("mod\n")); /* TODO: check results */
1089 wxbUtils::WaitForPrompt(wxT("9\n"));
1090 dt = new wxbDataTokenizer(true);
1091 wxbUtils::WaitForPrompt(restorePanel->GetRowString(_("Where")) + wxT("\n"));
1093 cfgUpdated = cfgUpdated & (~(1 << ConfigWhere));
1095 else if ((cfgUpdated >> ConfigReplace) & 1) {
1096 wxbUtils::WaitForPrompt(wxT("mod\n")); /* TODO: check results */
1097 wxbUtils::WaitForPrompt(wxT("10\n"));
1098 dt = new wxbDataTokenizer(true);
1099 wxbUtils::WaitForPrompt(wxString() << (restorePanel->GetRowSelection(_("Replace"))+1) << wxT("\n"));
1101 cfgUpdated = cfgUpdated & (~(1 << ConfigReplace));
1103 else if ((cfgUpdated >> ConfigWhen) & 1) {
1104 wxbUtils::WaitForPrompt(wxT("mod\n")); /* TODO: check results */
1105 wxbUtils::WaitForPrompt(wxT("6\n"));
1106 dt = new wxbDataTokenizer(true);
1107 wxbUtils::WaitForPrompt(restorePanel->GetRowString(wxT("When")) + wxT("\n"));
1109 cfgUpdated = cfgUpdated & (~(1 << ConfigWhen));
1111 else if ((cfgUpdated >> ConfigPriority) & 1) {
1112 wxbUtils::WaitForPrompt(wxT("mod\n")); /* TODO: check results */
1113 wxbUtils::WaitForPrompt(wxT("7\n"));
1114 dt = new wxbDataTokenizer(true);
1115 wxbUtils::WaitForPrompt(restorePanel->GetRowString(_("Priority")) + wxT("\n"));
1117 cfgUpdated = cfgUpdated & (~(1 << ConfigPriority));
1119 else if ((cfgUpdated >> ConfigClient) & 1) {
1120 wxbUtils::WaitForPrompt(wxT("mod\n")); /* TODO: check results */
1121 wxbPromptParser *pp = wxbUtils::WaitForPrompt(wxT("5\n"), true);
1122 int client = pp->getChoices()->Index(restorePanel->GetRowString(_("Client")));
1123 if (client == wxNOT_FOUND) {
1124 wxbMainFrame::GetInstance()->SetStatusText(_("Failed to find the selected client."));
1129 dt = new wxbDataTokenizer(true);
1130 wxbUtils::WaitForPrompt(wxString() << client << wxT("\n"));
1132 cfgUpdated = cfgUpdated & (~(1 << ConfigClient));
1134 else if ((cfgUpdated >> ConfigFileset) & 1) {
1135 wxbUtils::WaitForPrompt(wxT("mod\n")); /* TODO: check results */
1136 wxbPromptParser *pp = wxbUtils::WaitForPrompt(wxT("4\n"), true);
1137 int fileset = pp->getChoices()->Index(restorePanel->GetRowString(_("Fileset")));
1138 if (fileset == wxNOT_FOUND) {
1139 wxbMainFrame::GetInstance()->SetStatusText(_("Failed to find the selected fileset."));
1144 dt = new wxbDataTokenizer(true);
1145 wxbUtils::WaitForPrompt(wxString() << fileset << wxT("\n"));
1147 cfgUpdated = cfgUpdated & (~(1 << ConfigFileset));
1149 else if ((cfgUpdated >> ConfigStorage) & 1) {
1150 wxbUtils::WaitForPrompt(wxT("mod\n")); /* TODO: check results */
1151 wxbPromptParser *pp = wxbUtils::WaitForPrompt(wxT("2\n"), true);
1152 int fileset = pp->getChoices()->Index(restorePanel->GetRowString(_("Storage")));
1153 if (fileset == wxNOT_FOUND) {
1154 wxbMainFrame::GetInstance()->SetStatusText(_("Failed to find the selected storage."));
1159 dt = new wxbDataTokenizer(true);
1160 wxbUtils::WaitForPrompt(wxString() << fileset << wxT("\n"));
1162 cfgUpdated = cfgUpdated & (~(1 << ConfigStorage));
1170 for (i = 0; i < dt->GetCount(); i++) {
1171 if ((*dt)[i].Find(_("Run Restore job")) == 0) {
1176 if (i == dt->GetCount()) {
1178 dt = wxbUtils::WaitForEnd(def + wxT("\n"), true);
1182 UpdateSecondConfig(dt); /* TODO: Check result */
1187 wxbMainFrame::GetInstance()->SetStatusText(_("Restore configuration changes were applied."));
1193 /* Cancel restore */
1194 void wxbRestorePanel::CmdConfigCancel() {
1195 wxbUtils::WaitForEnd(wxT("no\n"));
1196 wxbMainFrame::GetInstance()->Print(_("Restore cancelled.\n"), CS_DEBUG);
1197 wxbMainFrame::GetInstance()->SetStatusText(_("Restore cancelled."));
1198 SetStatus(finished);
1201 /* List jobs for a specified client and fileset */
1202 void wxbRestorePanel::CmdListJobs() {
1203 if (status == entered) {
1204 configPanel->ClearRowChoices(_("Before"));
1205 /*wxbUtils::WaitForPrompt("query\n");
1206 wxbUtils::WaitForPrompt("6\n");*/
1207 wxbTableParser* tableparser = new wxbTableParser(false);
1208 wxbDataTokenizer* dt = wxbUtils::WaitForEnd(
1209 wxString(wxT(".backups client=\"")) + configPanel->GetRowString(_("Client")) +
1210 wxT("\" fileset=\"") + configPanel->GetRowString(_("Fileset")) + wxT("\"\n"), true);
1212 while (!tableparser->hasFinished()) {
1213 wxTheApp->Yield(true);
1214 wxbUtils::MilliSleep(100);
1217 if (!tableparser->GetCount() == 0) {
1218 for (unsigned int i = 0; i < dt->Count(); i++) {
1219 if ((*dt)[i].Find(_("No results to list.")) == 0) {
1220 configPanel->AddRowChoice(_("Before"),
1221 _("No backup found for this client."));
1222 configPanel->SetRowSelection(_("Before"), 0);
1223 configPanel->EnableApply(true); // Enabling the not existing apply button disables the ok button.
1228 else if (((*dt)[i].Find(_("ERROR")) > -1) ||
1229 ((*dt)[i].Find(_("Query failed")) > -1)) {
1230 configPanel->AddRowChoice(_("Before"),
1231 _("Cannot get previous backups list, see console."));
1232 configPanel->SetRowSelection(_("Before"), 0);
1233 configPanel->EnableApply(true); // Enabling the not existing apply button disables the ok button.
1243 wxDateTime lastdatetime = (time_t) 0;
1244 for (int i = tableparser->GetCount()-1; i > -1; i--) {
1245 wxString str = (*tableparser)[i][3];
1246 wxDateTime datetime;
1248 if ( ( (chr = datetime.ParseDate(str.GetData()) ) != NULL ) && ( datetime.ParseTime(++chr) != NULL ) && ! lastdatetime.IsEqualTo(datetime) ) {
1249 lastdatetime = datetime;
1250 datetime += wxTimeSpan::Seconds(1);
1251 configPanel->AddRowChoice(_("Before"),
1252 datetime.Format(wxT("%Y-%m-%d %H:%M:%S")));
1258 configPanel->SetRowSelection(_("Before"), 0);
1259 configPanel->EnableApply(false); // Disabling the not existing apply button enables the ok button.
1263 /* List files and directories for a specified tree item */
1264 void wxbRestorePanel::CmdList(wxTreeItemId item) {
1265 if (status == choosing) {
1266 list->DeleteAllItems();
1271 UpdateTreeItem(item, true, false);
1273 if (list->GetItemCount() >= 1) {
1274 int firstwidth = list->GetSize().GetWidth();
1275 for (int i = 2; i < 7; i++) {
1276 list->SetColumnWidth(i, wxLIST_AUTOSIZE);
1277 firstwidth -= list->GetColumnWidth(i);
1280 list->SetColumnWidth(0, 18);
1282 list->SetColumnWidth(1, wxLIST_AUTOSIZE);
1283 if (list->GetColumnWidth(1) < firstwidth) {
1284 list->SetColumnWidth(1, firstwidth-25);
1290 /* Mark a treeitem (directory) or a listitem (file or directory) */
1291 void wxbRestorePanel::CmdMark(wxTreeItemId treeitem, long* listitems, int listsize, int state) {
1292 if (status == choosing) {
1293 wxbTreeItemData** itemdata;
1294 int itemdatasize = 0;
1295 if (listsize == 0) {
1296 itemdata = new wxbTreeItemData*[1];
1300 itemdata = new wxbTreeItemData*[listsize];
1301 itemdatasize = listsize;
1304 if (listitems != NULL) {
1305 for (int i = 0; i < itemdatasize; i++) {
1306 itemdata[i] = (wxbTreeItemData*)list->GetItemData(listitems[i]);
1309 else if (treeitem.IsOk()) {
1310 itemdata[0] = (wxbTreeItemData*)tree->GetItemData(treeitem);
1317 if (itemdata[0] == NULL) { //Should never happen
1322 wxString dir = itemdata[0]->GetPath();
1325 if (dir != wxT("/")) {
1326 if (IsPathSeparator(dir.GetChar(dir.Length()-1))) {
1330 int i = dir.Find('/', TRUE);
1335 else { /* first dir below root */
1336 file = dir.Mid(i+1);
1337 dir = dir.Mid(0, i+1);
1346 bool marked = false;
1347 bool unmarked = false;
1349 for (int i = 0; i < itemdatasize; i++) {
1350 switch(itemdata[i]->GetMarked()) {
1364 if (marked && unmarked)
1380 wxbUtils::WaitForEnd(wxString(wxT("cd \"")) << dir << wxT("\"\n"));
1381 wxbUtils::WaitForEnd(wxString((state==1) ? wxT("mark") : wxT("unmark")) << wxT(" \"") << file << wxT("\"\n"));
1383 /* TODO: Check commands results */
1385 /*if ((dir == "/") && (file == "*")) {
1386 itemdata->SetMarked((itemdata->GetMarked() == 1) ? 0 : 1);
1389 if (listitems == NULL) { /* tree item state changed */
1390 SetTreeItemState(treeitem, state);
1391 /*treeitem = tree->GetSelection();
1392 UpdateTree(treeitem, true);
1393 treeitem = tree->GetItemParent(treeitem);*/
1396 for (int i = 0; i < itemdatasize; i++) {
1397 SetListItemState(listitems[i], state);
1399 listadd->Enable(state == 0);
1400 listremove->Enable(state == 1);
1401 /*UpdateTree(treeitem, (tree->GetSelection() == treeitem));
1402 treeitem = tree->GetItemParent(treeitem);*/
1405 /*while (treeitem.IsOk()) {
1406 WaitForList(treeitem, false);
1407 treeitem = tree->GetItemParent(treeitem);
1414 /*----------------------------------------------------------------------------
1416 ----------------------------------------------------------------------------*/
1418 /* Run a dir command, and waits until result is fully received. */
1419 void wxbRestorePanel::UpdateTreeItem(wxTreeItemId item, bool updatelist, bool recurse)
1421 // this->updatelist = updatelist;
1422 wxbDataTokenizer* dt;
1424 dt = wxbUtils::WaitForEnd(wxString(wxT("cd \"")) <<
1425 static_cast<wxbTreeItemData*>(tree->GetItemData(item))
1426 ->GetPath() << wxT("\"\n"), false);
1428 /* TODO: check command result */
1435 list->DeleteAllItems();
1436 dt = wxbUtils::WaitForEnd(wxT(".dir\n"), true);
1440 for (unsigned int i = 0; i < dt->GetCount(); i++) {
1443 if (str.Find(wxT("cwd is:")) == 0) { // Sometimes cd command result "infiltrate" into listings.
1451 if (!ParseList(str, &entry))
1454 wxTreeItemId treeid;
1456 if (IsPathSeparator(entry.fullname.GetChar(entry.fullname.Length()-1))) {
1459 #if wxCHECK_VERSION(2, 6, 0)
1460 wxTreeItemIdValue cookie;
1465 treeid = tree->GetFirstChild(item, cookie);
1467 bool updated = false;
1469 while (treeid.IsOk()) {
1470 itemStr = ((wxbTreeItemData*)tree->GetItemData(treeid))->GetName();
1471 if (entry.filename == itemStr) {
1472 if (static_cast<wxbTreeItemData*>(tree->GetItemData(treeid))->GetMarked() != entry.marked) {
1473 tree->SetItemImage(treeid, entry.marked, wxTreeItemIcon_Normal);
1474 tree->SetItemImage(treeid, entry.marked, wxTreeItemIcon_Selected);
1475 static_cast<wxbTreeItemData*>(tree->GetItemData(treeid))->SetMarked(entry.marked);
1477 if ((recurse) && (tree->IsExpanded(treeid))) {
1478 UpdateTreeItem(treeid, false, true);
1483 treeid = tree->GetNextChild(item, cookie);
1487 treeid = tree->AppendItem(item, wxbUtils::ConvertToPrintable(entry.filename), entry.marked, entry.marked, new wxbTreeItemData(entry.fullname, entry.filename, entry.marked));
1492 long ind = list->InsertItem(list->GetItemCount(), entry.marked);
1493 wxbTreeItemData* data = new wxbTreeItemData(entry.fullname, entry.filename, entry.marked, ind);
1494 data->SetId(treeid);
1495 list->SetItemData(ind, (long)data);
1496 list->SetItem(ind, 1, wxbUtils::ConvertToPrintable(entry.filename));
1497 list->SetItem(ind, 2, entry.size);
1498 list->SetItem(ind, 3, entry.date);
1499 list->SetItem(ind, 4, entry.perm);
1500 list->SetItem(ind, 5, entry.user);
1501 list->SetItem(ind, 6, entry.group);
1511 /* Parse .dir command results, returns true if the result has been stored in entry, false otherwise. */
1512 int wxbRestorePanel::ParseList(wxString line, wxbDirEntry* entry)
1514 /* See ls_output in dird/ua_tree.c */
1515 //-rw-r-----,1,root,root,41575,2005-10-18 18:21:36, ,/usr/var/bacula/working/bacula.sql
1517 wxStringTokenizer tkz(line, wxT(","));
1519 if (!tkz.HasMoreTokens())
1521 entry->perm = tkz.GetNextToken();
1523 if (!tkz.HasMoreTokens())
1525 entry->nlink = tkz.GetNextToken();
1527 if (!tkz.HasMoreTokens())
1529 entry->user = tkz.GetNextToken();
1531 if (!tkz.HasMoreTokens())
1533 entry->group = tkz.GetNextToken();
1535 if (!tkz.HasMoreTokens())
1537 entry->size = tkz.GetNextToken();
1539 if (!tkz.HasMoreTokens())
1541 entry->date = tkz.GetNextToken();
1543 if (!tkz.HasMoreTokens())
1545 wxString marked = tkz.GetNextToken();
1546 if (marked == wxT("*")) {
1549 else if (marked == wxT("+")) {
1556 if (!tkz.HasMoreTokens())
1558 entry->fullname = tkz.GetString();
1560 /* Get only the filename (cut path by finding the last '/') */
1561 if (IsPathSeparator(entry->fullname.GetChar(entry->fullname.Length()-1))) {
1562 wxString tmp = entry->fullname;
1564 entry->filename = entry->fullname.Mid(tmp.Find('/', true)+1);
1567 entry->filename = entry->fullname.Mid(entry->fullname.Find('/', true)+1);
1573 /* Sets a list item state, and update its parents and children if it is a directory */
1574 void wxbRestorePanel::SetListItemState(long listitem, int newstate)
1576 wxbTreeItemData* itemdata = (wxbTreeItemData*)list->GetItemData(listitem);
1578 wxTreeItemId treeitem;
1580 itemdata->SetMarked(newstate);
1581 list->SetItemImage(listitem, newstate, 0); /* TODO: Find what these ints are for */
1582 list->SetItemImage(listitem, newstate, 1);
1584 if ((treeitem = itemdata->GetId()).IsOk()) {
1585 SetTreeItemState(treeitem, newstate);
1588 UpdateTreeItemState(tree->GetSelection());
1592 /* Sets a tree item state, and update its children, parents and list (if necessary) */
1593 void wxbRestorePanel::SetTreeItemState(wxTreeItemId item, int newstate) {
1594 #if wxCHECK_VERSION(2, 6, 0)
1595 wxTreeItemIdValue cookie;
1599 wxTreeItemId currentChild = tree->GetFirstChild(item, cookie);
1601 wxbTreeItemData* itemdata;
1603 while (currentChild.IsOk()) {
1604 itemdata = (wxbTreeItemData*)tree->GetItemData(currentChild);
1605 int state = itemdata->GetMarked();
1607 if (state != newstate) {
1608 itemdata->SetMarked(newstate);
1609 tree->SetItemImage(currentChild, newstate, wxTreeItemIcon_Normal);
1610 tree->SetItemImage(currentChild, newstate, wxTreeItemIcon_Selected);
1613 currentChild = tree->GetNextChild(item, cookie);
1616 itemdata = (wxbTreeItemData*)tree->GetItemData(item);
1617 itemdata->SetMarked(newstate);
1618 tree->SetItemImage(item, newstate, wxTreeItemIcon_Normal);
1619 tree->SetItemImage(item, newstate, wxTreeItemIcon_Selected);
1622 if (tree->GetSelection() == item) {
1623 for (long i = 0; i < list->GetItemCount(); i++) {
1624 list->SetItemImage(i, newstate, 0); /* TODO: Find what these ints are for */
1625 list->SetItemImage(i, newstate, 1);
1629 UpdateTreeItemState(tree->GetItemParent(item));
1632 /* Update a tree item state, and its parents' state */
1633 void wxbRestorePanel::UpdateTreeItemState(wxTreeItemId item) {
1640 #if wxCHECK_VERSION(2, 6, 0)
1641 wxTreeItemIdValue cookie;
1645 wxTreeItemId currentChild = tree->GetFirstChild(item, cookie);
1647 bool onechildmarked = false;
1648 bool onechildunmarked = false;
1650 while (currentChild.IsOk()) {
1651 state = ((wxbTreeItemData*)tree->GetItemData(currentChild))->GetMarked();
1654 onechildunmarked = true;
1657 onechildmarked = true;
1660 onechildmarked = true;
1661 onechildunmarked = true;
1665 if (onechildmarked && onechildunmarked) {
1669 currentChild = tree->GetNextChild(item, cookie);
1672 if (tree->GetSelection() == item) {
1673 for (long i = 0; i < list->GetItemCount(); i++) {
1674 state = ((wxbTreeItemData*)list->GetItemData(i))->GetMarked();
1678 onechildunmarked = true;
1681 onechildmarked = true;
1684 onechildmarked = true;
1685 onechildunmarked = true;
1689 if (onechildmarked && onechildunmarked) {
1697 if (onechildmarked && onechildunmarked) {
1700 else if (onechildmarked) {
1703 else if (onechildunmarked) {
1706 else { // no child, don't change anything
1707 UpdateTreeItemState(tree->GetItemParent(item));
1711 wxbTreeItemData* itemdata = (wxbTreeItemData*)tree->GetItemData(item);
1713 itemdata->SetMarked(state);
1714 tree->SetItemImage(item, state, wxTreeItemIcon_Normal);
1715 tree->SetItemImage(item, state, wxTreeItemIcon_Selected);
1717 UpdateTreeItemState(tree->GetItemParent(item));
1720 /* Refresh the whole tree. */
1721 void wxbRestorePanel::RefreshTree() {
1722 /* Save current selection */
1723 wxArrayString current;
1725 wxTreeItemId item = currentTreeItem;
1727 while ((item.IsOk()) && (item != tree->GetRootItem())) {
1728 current.Add(tree->GetItemText(item));
1729 item = tree->GetItemParent(item);
1732 /* Update the tree */
1733 UpdateTreeItem(tree->GetRootItem(), false, true);
1735 /* Reselect the former selected item */
1736 item = tree->GetRootItem();
1738 if (current.Count() == 0) {
1739 tree->SelectItem(item);
1745 for (int i = current.Count()-1; i >= 0; i--) {
1746 #if wxCHECK_VERSION(2, 6, 0)
1747 wxTreeItemIdValue cookie;
1751 wxTreeItemId currentChild = tree->GetFirstChild(item, cookie);
1755 while (currentChild.IsOk()) {
1756 if (((wxbTreeItemData*)tree->GetItemData(currentChild))->GetName() == current[i]) {
1757 item = currentChild;
1762 currentChild = tree->GetNextChild(item, cookie);
1768 UpdateTreeItem(item, true, false); /* Update the list */
1770 tree->SelectItem(item);
1773 void wxbRestorePanel::RefreshList() {
1774 if (currentTreeItem.IsOk()) {
1775 UpdateTreeItem(currentTreeItem, true, false); /* Update the list */
1779 /* Update first config, adapting settings to the job name selected */
1780 void wxbRestorePanel::UpdateFirstConfig() {
1781 configPanel->Enable(false);
1782 wxbDataTokenizer* dt = wxbUtils::WaitForEnd(wxString(wxT(".defaults job=")) + configPanel->GetRowString(_("Job Name")) + wxT("\n"), true, false);
1788 * where=/tmp/bacula-restores
1798 bool dolistjobs = false;
1800 for (i = 0; i < dt->GetCount(); i++) {
1802 if ((j = str.Find('=')) > -1) {
1803 name = str.Mid(0, j);
1804 if (name == wxT("pool")) {
1805 configPanel->SetRowString(_("Pool"), str.Mid(j+1));
1807 else if (name == wxT("client")) {
1809 if ((str != configPanel->GetRowString(_("Client"))) ||
1810 (configPanel->GetRowString(_("Before"))) == wxT("")) {
1811 configPanel->SetRowString(_("Client"), str);
1815 else if (name == wxT("storage")) {
1816 configPanel->SetRowString(_("Storage"), str.Mid(j+1));
1818 else if (name == wxT("fileset")) {
1820 if ((str != configPanel->GetRowString(_("Fileset"))) ||
1821 (configPanel->GetRowString(_("Before"))) == wxT("")) {
1822 configPanel->SetRowString(_("Fileset"), str);
1832 //wxTheApp->Yield(false);
1835 configPanel->Enable(true);
1839 * Update second config.
1842 * JobName: RestoreFiles
1843 * Bootstrap: /var/lib/bacula/restore.bsr
1844 * Where: /tmp/bacula-restores
1849 * When: 2004-04-18 01:18:56
1851 * OK to run? (yes/mod/no):
1854 bool wxbRestorePanel::UpdateSecondConfig(wxbDataTokenizer* dt) {
1856 for (i = 0; i < dt->GetCount(); i++) {
1857 if ((*dt)[i].Find(_("Run Restore job")) == 0)
1861 if ((i + 10) > dt->GetCount()) {
1867 if ((k = (*dt)[++i].Find(_("JobName:"))) != 0) return false;
1868 restorePanel->SetRowString(_("Job Name"), (*dt)[i].Mid(10).Trim(false).RemoveLast());
1869 if ((k = (*dt)[++i].Find(_("Bootstrap:"))) != 0) return false;
1870 restorePanel->SetRowString(_("Bootstrap"), (*dt)[i].Mid(10).Trim(false).RemoveLast());
1871 if ((k = (*dt)[++i].Find(_("Where:"))) != 0) return false;
1872 restorePanel->SetRowString(_("Where"), (*dt)[i].Mid(10).Trim(false).RemoveLast());
1874 if ((k = (*dt)[++i].Find(_("Replace:"))) != 0) return false;
1875 wxString str = (*dt)[i].Mid(10).Trim(false).RemoveLast();
1876 if (str == _("always")) restorePanel->SetRowSelection(_("Replace"), 0);
1877 else if (str == _("ifnewer")) restorePanel->SetRowSelection(_("Replace"), 1);
1878 else if (str == _("ifolder")) restorePanel->SetRowSelection(_("Replace"), 2);
1879 else if (str == _("never")) restorePanel->SetRowSelection(_("Replace"), 3);
1880 else restorePanel->SetRowSelection(_("Replace"), 0);
1882 if ((k = (*dt)[++i].Find(_("FileSet:"))) != 0) return false;
1883 restorePanel->SetRowString(_("Fileset"), (*dt)[i].Mid(10).Trim(false).RemoveLast());
1884 if ((k = (*dt)[++i].Find(_("Client:"))) != 0) return false;
1885 restorePanel->SetRowString(_("Client"), (*dt)[i].Mid(10).Trim(false).RemoveLast());
1886 if ((k = (*dt)[++i].Find(_("Storage:"))) != 0) return false;
1887 restorePanel->SetRowString(_("Storage"), (*dt)[i].Mid(10).Trim(false).RemoveLast());
1888 if ((k = (*dt)[++i].Find(_("When:"))) != 0) return false;
1889 restorePanel->SetRowString(_("When"), (*dt)[i].Mid(10).Trim(false).RemoveLast());
1890 if ((k = (*dt)[++i].Find(_("Priority:"))) != 0) return false;
1891 restorePanel->SetRowString(_("Priority"), (*dt)[i].Mid(10).Trim(false).RemoveLast());
1894 restorePanel->Layout();
1899 /*----------------------------------------------------------------------------
1901 ----------------------------------------------------------------------------*/
1903 /* Set current status by enabling/disabling components */
1904 void wxbRestorePanel::SetStatus(status_enum newstatus) {
1905 switch (newstatus) {
1907 centerSizer->Remove(configPanel);
1908 centerSizer->Remove(restorePanel);
1909 centerSizer->Remove(treelistPanel);
1910 treelistPanel->Show(false);
1911 restorePanel->Show(false);
1912 centerSizer->Add(configPanel, 1, wxEXPAND);
1913 configPanel->Show(true);
1914 configPanel->Layout();
1915 centerSizer->Layout();
1917 start->SetLabel(_("Enter restore mode"));
1918 start->Enable(false);
1919 configPanel->Enable(false);
1920 tree->Enable(false);
1921 list->Enable(false);
1922 gauge->Enable(false);
1923 cancel->Enable(false);
1928 centerSizer->Remove(configPanel);
1929 centerSizer->Remove(restorePanel);
1930 centerSizer->Remove(treelistPanel);
1931 treelistPanel->Show(false);
1932 restorePanel->Show(false);
1933 centerSizer->Add(configPanel, 1, wxEXPAND);
1934 configPanel->Show(true);
1935 configPanel->Layout();
1936 centerSizer->Layout();
1938 tree->DeleteAllItems();
1939 list->DeleteAllItems();
1940 configPanel->ClearRowChoices(_("Client"));
1941 configPanel->ClearRowChoices(_("Before"));
1942 wxbMainFrame::GetInstance()->EnablePanels();
1943 newstatus = activable;
1946 start->SetLabel(_("Enter restore mode"));
1947 start->Enable(true);
1948 configPanel->Enable(false);
1949 tree->Enable(false);
1950 list->Enable(false);
1951 gauge->Enable(false);
1952 cancel->Enable(false);
1956 wxbMainFrame::GetInstance()->DisablePanels(this);
1958 start->Enable(false);
1959 //start->SetLabel(_("Choose files to restore"));
1960 configPanel->Enable(true);
1961 tree->Enable(false);
1962 list->Enable(false);
1963 cancel->Enable(true);
1970 start->Enable(true);
1971 start->SetLabel(_("Restore"));
1972 centerSizer->Remove(configPanel);
1973 configPanel->Show(false);
1974 centerSizer->Add(treelistPanel, 1, wxEXPAND);
1975 treelistPanel->Show(true);
1976 treelistPanel->Layout();
1977 centerSizer->Layout();
1984 start->Enable(false);
1985 configPanel->Enable(false);
1986 tree->Enable(false);
1987 list->Enable(false);
1988 centerSizer->Remove(treelistPanel);
1989 treelistPanel->Show(false);
1990 centerSizer->Add(restorePanel, 1, wxEXPAND);
1991 restorePanel->Show(true);
1992 restorePanel->Layout();
1993 centerSizer->Layout();
1995 restorePanel->EnableApply(false);
1998 start->SetLabel(_("Restoring..."));
1999 gauge->Enable(true);
2001 start->Enable(false);
2002 configPanel->Enable(false);
2003 tree->Enable(false);
2004 list->Enable(false);
2011 /*----------------------------------------------------------------------------
2013 ----------------------------------------------------------------------------*/
2015 void wxbRestorePanel::SetWorking(bool working) {
2016 this->working = working;
2018 SetCursor(*wxHOURGLASS_CURSOR);
2019 // SetEvtHandlerEnabled(false); //EVTQUEUE
2021 // else if (!processing) { /* Empty event queue if we aren't already doing this */ //EVTQUEUE
2023 // processing = true; //EVTQUEUE
2024 SetCursor(*wxSTANDARD_CURSOR);
2025 // SetEvtHandlerEnabled(true); //EVTQUEUE
2026 /* wxNode *node = pendingEvents->First(); //EVTQUEUE
2028 wxEvent *event = (wxEvent *)node->Data();
2031 wxEvtHandler::ProcessEvent(*event);
2034 node = pendingEvents->First();
2036 processing = false;*/
2040 bool wxbRestorePanel::IsWorking() {
2041 return this->working;
2044 void wxbRestorePanel::EnableConfig(bool enable) {
2045 restorePanel->Enable(enable);
2048 /*----------------------------------------------------------------------------
2050 ----------------------------------------------------------------------------*/
2055 bool wxbRestorePanel::ProcessEvent(wxEvent& event) {
2056 if (IsWorking() || processing) {
2057 wxEvent *eventCopy = event.Clone();
2059 pendingEvents->Append(eventCopy);
2063 return wxEvtHandler::ProcessEvent(event);
2068 void wxbRestorePanel::OnCancel(wxCommandEvent& event) {
2069 cancel->Enable(false);
2070 SetCursor(*wxHOURGLASS_CURSOR);
2072 SetCursor(*wxSTANDARD_CURSOR);
2075 void wxbRestorePanel::OnStart(wxCommandEvent& event) {
2084 void wxbRestorePanel::OnTreeChanging(wxTreeEvent& event) {
2090 void wxbRestorePanel::OnTreeExpanding(wxTreeEvent& event) {
2096 //CmdList(event.GetItem());
2097 if (tree->GetSelection() != event.GetItem()) {
2098 tree->SelectItem(event.GetItem());
2103 void wxbRestorePanel::OnTreeChanged(wxTreeEvent& event) {
2107 if (currentTreeItem == event.GetItem()) {
2110 treeadd->Enable(false);
2111 treeremove->Enable(false);
2112 treerefresh->Enable(false);
2113 markWhenCommandDone = false;
2115 currentTreeItem = event.GetItem();
2116 CmdList(event.GetItem());
2117 if (markWhenCommandDone) {
2118 CmdMark(event.GetItem(), NULL, 0);
2122 if (event.GetItem().IsOk()) {
2123 int status = ((wxbTreeItemData*)tree->GetItemData(event.GetItem()))->GetMarked();
2124 treeadd->Enable(status != 1);
2125 treeremove->Enable(status != 0);
2127 treerefresh->Enable(true);
2130 void wxbRestorePanel::OnTreeMarked(wxbTreeMarkedEvent& event) {
2132 if (tree->GetSelection() == event.GetItem()) {
2133 markWhenCommandDone = !markWhenCommandDone;
2138 markWhenCommandDone = false;
2139 CmdMark(event.GetItem(), NULL, 0);
2140 if (markWhenCommandDone) {
2141 CmdMark(event.GetItem(), NULL, 0);
2146 if (event.GetItem().IsOk()) {
2147 int status = ((wxbTreeItemData*)tree->GetItemData(event.GetItem()))->GetMarked();
2148 treeadd->Enable(status != 1);
2149 treeremove->Enable(status != 0);
2153 void wxbRestorePanel::OnTreeAdd(wxCommandEvent& event) {
2158 if (currentTreeItem.IsOk()) {
2160 CmdMark(currentTreeItem, NULL, 0, 1);
2163 treeremove->Enable(1);
2168 void wxbRestorePanel::OnTreeRemove(wxCommandEvent& event) {
2173 if (currentTreeItem.IsOk()) {
2175 CmdMark(currentTreeItem, NULL, 0, 0);
2178 treeremove->Enable(0);
2183 void wxbRestorePanel::OnTreeRefresh(wxCommandEvent& event) {
2193 void wxbRestorePanel::OnListMarked(wxbListMarkedEvent& event) {
2198 if (list->GetSelectedItemCount() == 0) {
2204 long* items = new long[list->GetSelectedItemCount()];
2208 long item = list->GetNextItem(-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
2209 while (item != -1) {
2212 item = list->GetNextItem(item, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
2215 CmdMark(wxTreeItemId(), items, num);
2219 wxListEvent listevt;
2221 OnListChanged(listevt);
2228 void wxbRestorePanel::OnListActivated(wxListEvent& event) {
2233 long item = event.GetIndex();
2234 // long item = list->GetNextItem(-1, wxLIST_NEXT_ALL, wxLIST_STATE_FOCUSED);
2236 wxbTreeItemData* itemdata = (wxbTreeItemData*)list->GetItemData(item);
2237 wxString name = itemdata->GetName();
2242 #if wxCHECK_VERSION(2, 6, 0)
2243 wxTreeItemIdValue cookie;
2248 if (IsPathSeparator(name.GetChar(name.Length()-1))) {
2249 wxTreeItemId currentChild = tree->GetFirstChild(currentTreeItem, cookie);
2251 while (currentChild.IsOk()) {
2252 wxString name2 = ((wxbTreeItemData*)tree->GetItemData(currentChild))->GetName();
2253 if (name2 == name) {
2254 //tree->UnselectAll();
2256 tree->Expand(currentTreeItem);
2257 tree->SelectItem(currentChild);
2261 currentChild = tree->GetNextChild(currentTreeItem, cookie);
2268 void wxbRestorePanel::OnListChanged(wxListEvent& event) {
2273 listadd->Enable(false);
2274 listremove->Enable(false);
2276 bool marked = false;
2277 bool unmarked = false;
2279 long item = list->GetNextItem(-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
2280 while (item != -1) {
2281 switch (((wxbTreeItemData*)list->GetItemData(item))->GetMarked()) {
2294 // Should never happen
2296 if (marked && unmarked) break;
2297 item = list->GetNextItem(item, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
2300 listadd->Enable(unmarked);
2301 listremove->Enable(marked);
2304 void wxbRestorePanel::OnListAdd(wxCommandEvent& event) {
2311 long* items = new long[list->GetSelectedItemCount()];
2315 long item = list->GetNextItem(-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
2316 while (item != -1) {
2319 item = list->GetNextItem(item, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
2322 CmdMark(wxTreeItemId(), items, num, 1);
2329 listadd->Enable(false);
2330 listremove->Enable(true);
2333 void wxbRestorePanel::OnListRemove(wxCommandEvent& event) {
2340 long* items = new long[list->GetSelectedItemCount()];
2344 long item = list->GetNextItem(-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
2345 while (item != -1) {
2348 item = list->GetNextItem(item, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
2351 CmdMark(wxTreeItemId(), items, num, 0);
2358 listadd->Enable(true);
2359 listremove->Enable(false);
2362 void wxbRestorePanel::OnListRefresh(wxCommandEvent& event) {
2372 void wxbRestorePanel::OnConfigUpdated(wxCommandEvent& event) {
2373 if (status == entered) {
2374 if (event.GetId() == ConfigJobName) {
2379 UpdateFirstConfig();
2382 else if ((event.GetId() == ConfigClient) || (event.GetId() == ConfigFileset)) {
2387 configPanel->Enable(false);
2389 configPanel->Enable(true);
2392 cfgUpdated = cfgUpdated | (1 << event.GetId());
2394 else if (status == configuring) {
2395 restorePanel->EnableApply(true);
2396 cfgUpdated = cfgUpdated | (1 << event.GetId());
2400 void wxbRestorePanel::OnConfigOk(wxCommandEvent& WXUNUSED(event)) {
2401 if (status != configuring) return;
2410 void wxbRestorePanel::OnConfigApply(wxCommandEvent& WXUNUSED(event)) {
2411 if (status != configuring) return;
2417 if (cfgUpdated == 0) {
2418 restorePanel->EnableApply(false);
2423 void wxbRestorePanel::OnConfigCancel(wxCommandEvent& WXUNUSED(event)) {
2424 if (status != configuring) return;