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):
52 /* Windows debug builds set _DEBUG which is used by wxWidgets to select their
53 * debug memory allocator. Unfortunately it conflicts with Bacula's SmartAlloc.
54 * So we turn _DEBUG off since we aren't interested in things it enables.
60 #include "wxbrestorepanel.h"
61 #include "wxbmainframe.h"
63 #include <wx/choice.h>
64 #include <wx/datetime.h>
66 #include "unmarked.xpm"
68 #include "partmarked.xpm"
69 #include <wx/listimpl.cpp>
71 /* A macro named Yield is defined under MinGW */
74 WX_DEFINE_LIST(wxbEventList);
77 * Class which is stored in the tree and in the list to keep informations
80 class wxbTreeItemData : public wxTreeItemData {
82 wxbTreeItemData(wxString path, wxString name, int marked, long listid = -1);
88 void SetMarked(int marked);
92 wxString* path; /* Full path */
93 wxString* name; /* File name */
94 int marked; /* 0 - Not Marked, 1 - Marked, 2 - Some file under is marked */
95 long listid; /* list ID : >-1 if this data is in the list (and/or on the tree) */
98 wxbTreeItemData::wxbTreeItemData(wxString path, wxString name, int marked, long listid): wxTreeItemData() {
99 this->path = new wxString(path);
100 this->name = new wxString(name);
101 this->marked = marked;
102 this->listid = listid;
105 wxbTreeItemData::~wxbTreeItemData() {
110 int wxbTreeItemData::GetMarked() {
114 void wxbTreeItemData::SetMarked(int marked) {
115 this->marked = marked;
118 long wxbTreeItemData::GetListId() {
122 wxString wxbTreeItemData::GetPath() {
126 wxString wxbTreeItemData::GetName() {
130 // ----------------------------------------------------------------------------
131 // event tables and other macros for wxWindows
132 // ----------------------------------------------------------------------------
160 BEGIN_EVENT_TABLE(wxbRestorePanel, wxPanel)
161 EVT_BUTTON(RestoreStart, wxbRestorePanel::OnStart)
162 EVT_BUTTON(RestoreCancel, wxbRestorePanel::OnCancel)
164 EVT_TREE_SEL_CHANGING(TreeCtrl, wxbRestorePanel::OnTreeChanging)
165 EVT_TREE_SEL_CHANGED(TreeCtrl, wxbRestorePanel::OnTreeChanged)
166 EVT_TREE_ITEM_EXPANDING(TreeCtrl, wxbRestorePanel::OnTreeExpanding)
167 EVT_TREE_MARKED_EVENT(TreeCtrl, wxbRestorePanel::OnTreeMarked)
168 EVT_BUTTON(TreeAdd, wxbRestorePanel::OnTreeAdd)
169 EVT_BUTTON(TreeRemove, wxbRestorePanel::OnTreeRemove)
170 EVT_BUTTON(TreeRefresh, wxbRestorePanel::OnTreeRefresh)
172 EVT_LIST_ITEM_ACTIVATED(ListCtrl, wxbRestorePanel::OnListActivated)
173 EVT_LIST_MARKED_EVENT(ListCtrl, wxbRestorePanel::OnListMarked)
174 EVT_LIST_ITEM_SELECTED(ListCtrl, wxbRestorePanel::OnListChanged)
175 EVT_LIST_ITEM_DESELECTED(ListCtrl, wxbRestorePanel::OnListChanged)
176 EVT_BUTTON(ListAdd, wxbRestorePanel::OnListAdd)
177 EVT_BUTTON(ListRemove, wxbRestorePanel::OnListRemove)
178 EVT_BUTTON(ListRefresh, wxbRestorePanel::OnListRefresh)
180 EVT_TEXT(ConfigWhere, wxbRestorePanel::OnConfigUpdated)
181 EVT_TEXT(ConfigWhen, wxbRestorePanel::OnConfigUpdated)
182 EVT_TEXT(ConfigPriority, wxbRestorePanel::OnConfigUpdated)
183 EVT_CHOICE(ConfigWhen, wxbRestorePanel::OnConfigUpdated)
184 EVT_CHOICE(ConfigReplace, wxbRestorePanel::OnConfigUpdated)
185 EVT_CHOICE(ConfigClient, wxbRestorePanel::OnConfigUpdated)
186 EVT_CHOICE(ConfigFileset, wxbRestorePanel::OnConfigUpdated)
187 EVT_CHOICE(ConfigStorage, wxbRestorePanel::OnConfigUpdated)
188 EVT_CHOICE(ConfigJobName, wxbRestorePanel::OnConfigUpdated)
189 EVT_CHOICE(ConfigPool, wxbRestorePanel::OnConfigUpdated)
191 EVT_BUTTON(ConfigOk, wxbRestorePanel::OnConfigOk)
192 EVT_BUTTON(ConfigApply, wxbRestorePanel::OnConfigApply)
193 EVT_BUTTON(ConfigCancel, wxbRestorePanel::OnConfigCancel)
197 * wxbRestorePanel constructor
199 wxbRestorePanel::wxbRestorePanel(wxWindow* parent): wxbPanel(parent)
201 //pendingEvents = new wxbEventList(); //EVTQUEUE
202 //processing = false; //EVTQUEUE
205 imagelist = new wxImageList(16, 16, TRUE, 3);
206 imagelist->Add(wxIcon(unmarked_xpm));
207 imagelist->Add(wxIcon(marked_xpm));
208 imagelist->Add(wxIcon(partmarked_xpm));
210 wxFlexGridSizer* mainSizer = new wxFlexGridSizer(3, 1, 10, 10);
211 mainSizer->AddGrowableCol(0);
212 mainSizer->AddGrowableRow(1);
214 wxFlexGridSizer *firstSizer = new wxFlexGridSizer(1, 2, 10, 10);
216 firstSizer->AddGrowableCol(0);
217 firstSizer->AddGrowableRow(0);
219 start = new wxButton(this, RestoreStart, _("Enter restore mode"), wxDefaultPosition, wxSize(150, 30));
220 firstSizer->Add(start, 0, wxALIGN_CENTER_HORIZONTAL | wxALIGN_CENTER_VERTICAL, 10);
222 cancel = new wxButton(this, RestoreCancel, _("Cancel restore"), wxDefaultPosition, wxSize(150, 30));
223 firstSizer->Add(cancel, 0, wxALIGN_CENTER_HORIZONTAL | wxALIGN_RIGHT, 10);
227 /* clientChoice = new wxChoice(this, ClientChoice, wxDefaultPosition, wxSize(150, 30), 0, elist);
228 firstSizer->Add(clientChoice, 1, wxALIGN_CENTER_HORIZONTAL | wxALIGN_CENTER_VERTICAL, 10);
230 jobChoice = new wxChoice(this, -1, wxDefaultPosition, wxSize(150, 30), 0, elist);
231 firstSizer->Add(jobChoice, 1, wxALIGN_CENTER_HORIZONTAL | wxALIGN_CENTER_VERTICAL, 10);*/
233 mainSizer->Add(firstSizer, 1, wxEXPAND, 10);
235 treelistPanel = new wxSplitterWindow(this);
237 wxPanel* treePanel = new wxPanel(treelistPanel);
238 wxFlexGridSizer *treeSizer = new wxFlexGridSizer(2, 1, 0, 0);
239 treeSizer->AddGrowableCol(0);
240 treeSizer->AddGrowableRow(0);
242 tree = new wxbTreeCtrl(treePanel, this, TreeCtrl, wxDefaultPosition, wxSize(200,50));
243 tree->SetImageList(imagelist);
245 treeSizer->Add(tree, 1, wxEXPAND, 0);
247 wxBoxSizer *treeCtrlSizer = new wxBoxSizer(wxHORIZONTAL);
248 treeadd = new wxButton(treePanel, TreeAdd, _("Add"), wxDefaultPosition, wxSize(60, 25));
249 treeCtrlSizer->Add(treeadd, 0, wxLEFT | wxRIGHT, 3);
250 treeremove = new wxButton(treePanel, TreeRemove, _("Remove"), wxDefaultPosition, wxSize(60, 25));
251 treeCtrlSizer->Add(treeremove, 0, wxLEFT | wxRIGHT, 3);
252 treerefresh = new wxButton(treePanel, TreeRefresh, _("Refresh"), wxDefaultPosition, wxSize(60, 25));
253 treeCtrlSizer->Add(treerefresh, 0, wxLEFT | wxRIGHT, 3);
255 treeSizer->Add(treeCtrlSizer, 1, wxALIGN_CENTER_HORIZONTAL, 0);
257 treePanel->SetSizer(treeSizer);
259 wxPanel* listPanel = new wxPanel(treelistPanel);
260 wxFlexGridSizer *listSizer = new wxFlexGridSizer(2, 1, 0, 0);
261 listSizer->AddGrowableCol(0);
262 listSizer->AddGrowableRow(0);
264 list = new wxbListCtrl(listPanel, this, ListCtrl, wxDefaultPosition, wxSize(200,50));
265 //treelistSizer->Add(list, 1, wxEXPAND, 10);
267 list->SetImageList(imagelist, wxIMAGE_LIST_SMALL);
270 info.SetMask(wxLIST_MASK_TEXT | wxLIST_MASK_FORMAT);
271 info.SetText(_("M"));
272 info.SetAlign(wxLIST_FORMAT_CENTER);
273 list->InsertColumn(0, info);
275 info.SetText(_("Filename"));
276 info.SetAlign(wxLIST_FORMAT_LEFT);
277 list->InsertColumn(1, info);
279 info.SetText(_("Size"));
280 info.SetAlign(wxLIST_FORMAT_RIGHT);
281 list->InsertColumn(2, info);
283 info.SetText(_("Date"));
284 info.SetAlign(wxLIST_FORMAT_LEFT);
285 list->InsertColumn(3, info);
287 info.SetText(_("Perm."));
288 info.SetAlign(wxLIST_FORMAT_LEFT);
289 list->InsertColumn(4, info);
291 info.SetText(_("User"));
292 info.SetAlign(wxLIST_FORMAT_RIGHT);
293 list->InsertColumn(5, info);
295 info.SetText(_("Group"));
296 info.SetAlign(wxLIST_FORMAT_RIGHT);
297 list->InsertColumn(6, info);
299 listSizer->Add(list, 1, wxEXPAND, 0);
301 wxBoxSizer *listCtrlSizer = new wxBoxSizer(wxHORIZONTAL);
302 listadd = new wxButton(listPanel, ListAdd, _("Add"), wxDefaultPosition, wxSize(60, 25));
303 listCtrlSizer->Add(listadd, 0, wxLEFT | wxRIGHT, 5);
304 listremove = new wxButton(listPanel, ListRemove, _("Remove"), wxDefaultPosition, wxSize(60, 25));
305 listCtrlSizer->Add(listremove, 0, wxLEFT | wxRIGHT, 5);
306 listrefresh = new wxButton(listPanel, ListRefresh, _("Refresh"), wxDefaultPosition, wxSize(60, 25));
307 listCtrlSizer->Add(listrefresh, 0, wxLEFT | wxRIGHT, 5);
309 listSizer->Add(listCtrlSizer, 1, wxALIGN_CENTER_HORIZONTAL, 0);
311 listPanel->SetSizer(listSizer);
313 treelistPanel->SplitVertically(treePanel, listPanel, 210);
315 treelistPanel->SetMinimumPaneSize(210);
317 treelistPanel->Show(false);
319 wxbConfig* config = new wxbConfig();
320 config->Add(new wxbConfigParam(_("Job Name"), ConfigJobName, choice, 0, elist));
321 config->Add(new wxbConfigParam(_("Client"), ConfigClient, choice, 0, elist));
322 config->Add(new wxbConfigParam(_("Fileset"), ConfigFileset, choice, 0, elist));
323 config->Add(new wxbConfigParam(_("Pool"), ConfigPool, choice, 0, elist));
324 config->Add(new wxbConfigParam(_("Storage"), ConfigStorage, choice, 0, elist));
325 config->Add(new wxbConfigParam(_("Before"), ConfigWhen, choice, 0, elist));
327 configPanel = new wxbConfigPanel(this, config, _("Please configure parameters concerning files to restore :"), RestoreStart, RestoreCancel, -1);
329 configPanel->Show(true);
330 configPanel->Enable(false);
332 config = new wxbConfig();
333 config->Add(new wxbConfigParam(_("Job Name"), -1, text, wxT("")));
334 config->Add(new wxbConfigParam(_("Bootstrap"), -1, text, wxT("")));
335 config->Add(new wxbConfigParam(_("Where"), ConfigWhere, modifiableText, wxT("")));
336 wxString erlist[] = {_("always"), _("if newer"), _("if older"), _("never")};
337 config->Add(new wxbConfigParam(_("Replace"), ConfigReplace, choice, 4, erlist));
338 config->Add(new wxbConfigParam(_("Fileset"), ConfigFileset, choice, 0, erlist));
339 config->Add(new wxbConfigParam(_("Client"), ConfigClient, choice, 0, erlist));
340 config->Add(new wxbConfigParam(_("Storage"), ConfigStorage, choice, 0, erlist));
341 config->Add(new wxbConfigParam(_("When"), ConfigWhen, modifiableText, wxT("")));
342 config->Add(new wxbConfigParam(_("Priority"), ConfigPriority, modifiableText, wxT("")));
344 restorePanel = new wxbConfigPanel(this, config, _("Please configure parameters concerning files restoration :"), ConfigOk, ConfigCancel, ConfigApply);
346 restorePanel->Show(false);
348 centerSizer = new wxBoxSizer(wxHORIZONTAL);
349 //centerSizer->Add(treelistPanel, 1, wxEXPAND | wxADJUST_MINSIZE);
351 mainSizer->Add(centerSizer, 1, wxEXPAND, 10);
353 gauge = new wxGauge(this, -1, 1, wxDefaultPosition, wxSize(200,20));
355 mainSizer->Add(gauge, 1, wxEXPAND, 5);
357 gauge->Enable(false);
360 mainSizer->SetSizeHints(this);
364 for (int i = 0; i < 7; i++) {
365 list->SetColumnWidth(i, 70);
368 SetCursor(*wxSTANDARD_CURSOR);
370 markWhenCommandDone = false;
376 * wxbRestorePanel destructor
378 wxbRestorePanel::~wxbRestorePanel()
383 /*----------------------------------------------------------------------------
384 wxbPanel overloadings
385 ----------------------------------------------------------------------------*/
387 wxString wxbRestorePanel::GetTitle()
392 void wxbRestorePanel::EnablePanel(bool enable)
395 if (status == disabled) {
396 SetStatus(activable);
403 /*----------------------------------------------------------------------------
404 Commands called by events handler
405 ----------------------------------------------------------------------------*/
407 /* The main button has been clicked */
408 void wxbRestorePanel::CmdStart()
411 if (status == activable) {
412 wxbMainFrame::GetInstance()->SetStatusText(_("Getting parameters list."));
413 wxbDataTokenizer* dt = wxbUtils::WaitForEnd(wxT(".clients\n"), true, false);
416 configPanel->ClearRowChoices(_("Client"));
417 restorePanel->ClearRowChoices(_("Client"));
419 if (dt->GetCount() == 0) {
420 wxbMainFrame::GetInstance()->SetStatusText(_("Error : no clients returned by the director."));
424 for (i = 0; i < dt->GetCount(); i++) {
427 configPanel->AddRowChoice(_("Client"), str);
428 restorePanel->AddRowChoice(_("Client"), str);
438 dt = wxbUtils::WaitForEnd(wxT(".filesets\n"), true, false);
440 configPanel->ClearRowChoices(_("Fileset"));
441 restorePanel->ClearRowChoices(_("Fileset"));
443 if (dt->GetCount() == 0) {
444 wxbMainFrame::GetInstance()->SetStatusText(_("Error : no filesets returned by the director."));
448 for (i = 0; i < dt->GetCount(); i++) {
451 configPanel->AddRowChoice(_("Fileset"), str);
452 restorePanel->AddRowChoice(_("Fileset"), str);
462 dt = wxbUtils::WaitForEnd(wxT(".storage\n"), true, false);
464 configPanel->ClearRowChoices(_("Storage"));
465 restorePanel->ClearRowChoices(_("Storage"));
467 if (dt->GetCount() == 0) {
468 wxbMainFrame::GetInstance()->SetStatusText(_("Error : no storage returned by the director."));
472 for (i = 0; i < dt->GetCount(); i++) {
475 configPanel->AddRowChoice(_("Storage"), str);
476 restorePanel->AddRowChoice(_("Storage"), str);
486 dt = wxbUtils::WaitForEnd(wxT(".jobs\n"), true, false);
488 configPanel->ClearRowChoices(_("Job Name"));
490 if (dt->GetCount() == 0) {
491 wxbMainFrame::GetInstance()->SetStatusText(_("Error : no jobs returned by the director."));
495 for (i = 0; i < dt->GetCount(); i++) {
498 configPanel->AddRowChoice(_("Job Name"), str);
501 configPanel->SetRowString(_("Job Name"), _("RestoreFiles"));
510 dt = wxbUtils::WaitForEnd(wxT(".pools\n"), true, false);
512 configPanel->ClearRowChoices(_("Pool"));
514 if (dt->GetCount() == 0) {
515 wxbMainFrame::GetInstance()->SetStatusText(_("Error : no jobs returned by the director."));
519 for (i = 0; i < dt->GetCount(); i++) {
522 configPanel->AddRowChoice(_("Pool"), str);
536 wxbMainFrame::GetInstance()->SetStatusText(_("Please configure your restore parameters."));
538 else if (status == entered) {
539 /* if (clientChoice->GetStringSelection().Length() < 1) {
540 wxbMainFrame::GetInstance()->SetStatusText(_("Please select a client."));
543 if (jobChoice->GetStringSelection().Length() < 1) {
544 wxbMainFrame::GetInstance()->SetStatusText(_("Please select a restore date."));
547 wxbMainFrame::GetInstance()->SetStatusText(_("Building restore tree..."));
551 wxbTableParser* tableparser = new wxbTableParser();
552 wxbDataTokenizer* dt = new wxbDataTokenizer(false);
555 * The following line was removed from ::GetInstance below because
556 * it does not work with multiple pools -- KES 5Oct05 see bug #433
557 * wxT("\" pool=\"") << configPanel->GetRowString(wxT("Pool")) <<
559 wxbMainFrame::GetInstance()->Send(wxString(wxT("restore")) <<
560 wxT(" client=\"") << configPanel->GetRowString(wxT("Client")) <<
561 wxT("\" fileset=\"") << configPanel->GetRowString(wxT("Fileset")) <<
562 wxT("\" storage=\"") << configPanel->GetRowString(wxT("Storage")) <<
563 wxT("\" before=\"") << configPanel->GetRowString(wxT("Before")) <<
565 //wxbUtils::WaitForPrompt("6\n");
567 /*wxbPromptParser *pp = wxbUtils::WaitForPrompt(wxString() << configPanel->GetRowString(wxT("Before")) << "\n", true);
568 int client = pp->getChoices()->Index(configPanel->GetRowString(wxT("Client")));
569 if (client == wxNOT_FOUND) {
570 wxbMainFrame::GetInstance()->SetStatusText("Failed to find the selected client.");
575 //wxbMainFrame::GetInstance()->Send(wxString() << configPanel->GetRowString(wxT("Before")) << "\n");
577 while (!tableparser->hasFinished() && !dt->hasFinished()) {
578 wxTheApp->Yield(true);
579 wxbUtils::MilliSleep(100);
584 if (dt->hasFinished() && !tableparser->hasFinished()) {
586 if (dt->GetCount() > 1) {
587 str = (*dt)[dt->GetCount()-2];
590 wxbMainFrame::GetInstance()->SetStatusText(wxString(_("Error while starting restore: ")) << str);
600 for (i = 0; i < tableparser->GetCount(); i++) {
601 str = (*tableparser)[i][2];
602 str.Replace(wxT(","), wxT(""));
603 if (str.ToLong(&l)) {
609 gauge->SetRange(tot);
611 /*wxbMainFrame::GetInstance()->Print(
612 wxString("[") << tot << "]", CS_DEBUG);*/
614 wxDateTime base = wxDateTime::Now();
618 unsigned int lastindex = 0;
625 newdate = wxDateTime::Now();
626 if (newdate.Subtract(base).GetMilliseconds() > 10 ) {
628 for (; lastindex < dt->GetCount(); lastindex++) {
629 if (((i1 = (*dt)[lastindex].Find(wxT("Building directory tree for JobId "))) >= 0) &&
630 ((i2 = (*dt)[lastindex].Find(wxT(" ..."))) > 0)) {
631 str = (*dt)[lastindex].Mid(i1+34, i2-(i1+34));
632 for (i = 0; i < tableparser->GetCount(); i++) {
633 if (str == (*tableparser)[i][0]) {
634 str = (*tableparser)[i][2];
635 str.Replace(wxT(","), wxT(""));
636 if (str.ToLong(&l)) {
639 var = (willdo-done)/50;
640 gauge->SetValue(done);
641 wxTheApp->Yield(true);
647 else if ((*dt)[lastindex] == wxT("+")) {
648 gauge->SetValue(gauge->GetValue()+var);
649 wxTheApp->Yield(true);
654 if (dt->hasFinished()) {
658 wxTheApp->Yield(true);
659 wxbUtils::MilliSleep(1);
662 gauge->SetValue(tot);
663 wxTheApp->Yield(true);
674 wxbUtils::WaitForEnd(wxT("unmark *\n"));
675 wxTreeItemId root = tree->AddRoot(configPanel->GetRowString(_("Client")), -1, -1, new wxbTreeItemData(wxT("/"), configPanel->GetRowString(_("Client")), 0));
676 currentTreeItem = root;
678 tree->SelectItem(root);
680 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."));
683 else if (status == choosing) {
687 wxbDataTokenizer* dt;
691 dt = new wxbDataTokenizer(true);
692 wxbPromptParser* promptparser = wxbUtils::WaitForPrompt(wxT("done\n"), true);
694 while (!promptparser->getChoices() || (promptparser->getChoices()->Index(wxT("mod")) < 0)) {
695 wxbMainFrame::GetInstance()->Print(_("Unexpected question has been received.\n"), CS_DEBUG);
698 if (promptparser->getIntroString() != wxT("")) {
699 message << promptparser->getIntroString() << wxT("\n");
701 message << promptparser->getQuestionString();
703 if (promptparser->getChoices()) {
704 wxString *choices = new wxString[promptparser->getChoices()->GetCount()];
705 int *numbers = new int[promptparser->getChoices()->GetCount()];
708 for (unsigned int i = 0; i < promptparser->getChoices()->GetCount(); i++) {
709 if ((*promptparser->getChoices())[i] != wxT("")) {
710 choices[n] = (*promptparser->getChoices())[i];
716 int res = ::wxGetSingleChoiceIndex(message,
717 _("wx-console: unexpected restore question."), n, choices, this);
720 promptparser = wxbUtils::WaitForPrompt(wxT(".\n"), true);
723 if (promptparser->isNumericalChoice()) {
725 promptparser = wxbUtils::WaitForPrompt(wxString() << numbers[res] << wxT("\n"), true);
729 promptparser = wxbUtils::WaitForPrompt(wxString() << choices[res] << wxT("\n"), true);
738 promptparser = wxbUtils::WaitForPrompt(::wxGetTextFromUser(message,
739 _("wx-console: unexpected restore question."),
740 wxT(""), this) + wxT("\n"));
743 printf("promptparser->getChoices()=%ld", (long)promptparser->getChoices());
747 SetStatus(configuring);
749 for (i = 0; i < dt->GetCount(); i++) {
750 if ((j = (*dt)[i].Find(_(" files selected to be restored."))) > -1) {
751 (*dt)[i].Mid(0, j).ToLong(&totfilemessages);
755 if ((j = (*dt)[i].Find(_(" file selected to be restored."))) > -1) {
756 (*dt)[i].Mid(0, j).ToLong(&totfilemessages);
761 wxbMainFrame::GetInstance()->SetStatusText(
762 wxString::Format(_("Please configure your restore (%ld files selected to be restored)..."), totfilemessages));
764 UpdateSecondConfig(dt);
769 restorePanel->EnableApply(false);
771 if (totfilemessages == 0) {
772 wxbMainFrame::GetInstance()->Print(_("Restore failed : no file selected.\n"), CS_DEBUG);
773 wxbMainFrame::GetInstance()->SetStatusText(_("Restore failed : no file selected."));
778 else if (status == configuring) {
779 cancel->Enable(false);
783 wxbMainFrame::GetInstance()->SetStatusText(_("Restoring, please wait..."));
785 wxbDataTokenizer* dt;
787 SetStatus(restoring);
788 dt = wxbUtils::WaitForEnd(wxT("yes\n"), true);
791 gauge->SetRange(totfilemessages);
795 for (i = 0; i < dt->GetCount(); i++) {
796 if ((j = (*dt)[i].Find(_("Job started. JobId="))) > -1) {
797 jobid = (*dt)[i].Mid(j+19);
798 wxbMainFrame::GetInstance()->SetStatusText(_("Restore started, jobid=") + jobid);
802 if ((j = (*dt)[i].Find(_("Job failed."))) > -1) {
803 wxbMainFrame::GetInstance()->Print(_("Restore failed, please look at messages.\n"), CS_DEBUG);
804 wxbMainFrame::GetInstance()->SetStatusText(_("Restore failed, please look at messages in console."));
809 if (jobid == wxT("")) {
810 wxbMainFrame::GetInstance()->Print(_("Failed to retrieve jobid.\n"), CS_DEBUG);
811 wxbMainFrame::GetInstance()->SetStatusText(_("Failed to retrieve jobid.\n"));
815 wxDateTime currenttime;
817 dt = wxbUtils::WaitForEnd(wxT("time\n"), true);
818 wxStringTokenizer ttkz((*dt)[0], wxT(" "), wxTOKEN_STRTOK);
819 if ((currenttime.ParseDate(ttkz.GetNextToken()) == NULL) || // Date
820 (currenttime.ParseTime(ttkz.GetNextToken()) == NULL)) { // Time
821 currenttime.SetYear(1990); // If parsing fails, set currenttime to a dummy date
824 currenttime -= wxTimeSpan::Seconds(30); //Adding a 30" tolerance
828 wxDateTime scheduledtime;
829 wxStringTokenizer stkz(restorePanel->GetRowString(_("When")), wxT(" "), wxTOKEN_STRTOK);
831 if ((scheduledtime.ParseDate(stkz.GetNextToken()) == NULL) || // Date
832 (scheduledtime.ParseTime(stkz.GetNextToken()) == NULL)) { // Time
833 scheduledtime.SetYear(2090); // If parsing fails, set scheduledtime to a dummy date
836 if (scheduledtime.Subtract(currenttime).IsLongerThan(wxTimeSpan::Seconds(150))) {
837 wxbMainFrame::GetInstance()->Print(_("Restore is scheduled in more than two minutes, wx-console will not wait for its completion.\n"), CS_DEBUG);
838 wxbMainFrame::GetInstance()->SetStatusText(_("Restore is scheduled in more than two minutes, wx-console will not wait for its completion."));
843 wxString cmd = wxString(wxT("list jobid=")) + jobid;
845 wxbTableParser* tableparser;
847 long filemessages = 0;
850 bool waitforever = false;
856 wxbUtils::WaitForEnd(wxT("autodisplay off\n"));
857 wxbUtils::WaitForEnd(wxT("gui on\n"));
859 tableparser = wxbUtils::CreateAndWaitForParser(cmd);
861 status = (*tableparser)[0][7].GetChar(0);
864 wxbMainFrame::GetInstance()->SetStatusText(_("Restore job created, but not yet running."));
868 wxbMainFrame::GetInstance()->SetStatusText(
869 wxString::Format(_("Restore job running, please wait (%ld of %ld files restored)..."), filemessages, totfilemessages));
873 wxbMainFrame::GetInstance()->SetStatusText(_("Restore job terminated successfully."));
874 wxbMainFrame::GetInstance()->Print(_("Restore job terminated successfully.\n"), CS_DEBUG);
878 case JS_ErrorTerminated:
879 wxbMainFrame::GetInstance()->SetStatusText(_("Restore job terminated in error, see messages in console."));
880 wxbMainFrame::GetInstance()->Print(_("Restore job terminated in error, see messages.\n"), CS_DEBUG);
885 wxbMainFrame::GetInstance()->SetStatusText(_("Restore job reported a non-fatal error."));
889 wxbMainFrame::GetInstance()->SetStatusText(_("Restore job reported a fatal error."));
894 wxbMainFrame::GetInstance()->SetStatusText(_("Restore job cancelled by user."));
895 wxbMainFrame::GetInstance()->Print(_("Restore job cancelled by user.\n"), CS_DEBUG);
900 wxbMainFrame::GetInstance()->SetStatusText(_("Restore job is waiting on File daemon."));
904 wxbMainFrame::GetInstance()->SetStatusText(_("Restore job is waiting for new media."));
907 case JS_WaitStoreRes:
908 wxbMainFrame::GetInstance()->SetStatusText(_("Restore job is waiting for storage resource."));
912 wxbMainFrame::GetInstance()->SetStatusText(_("Restore job is waiting for job resource."));
915 case JS_WaitClientRes:
916 wxbMainFrame::GetInstance()->SetStatusText(_("Restore job is waiting for Client resource."));
920 wxbMainFrame::GetInstance()->SetStatusText(_("Restore job is waiting for maximum jobs."));
923 case JS_WaitStartTime:
924 wxbMainFrame::GetInstance()->SetStatusText(_("Restore job is waiting for start time."));
927 case JS_WaitPriority:
928 wxbMainFrame::GetInstance()->SetStatusText(_("Restore job is waiting for higher priority jobs to finish."));
934 dt = wxbUtils::WaitForEnd(wxT(".messages\n"), true);
936 for (unsigned int i = 0; i < dt->GetCount(); i++) {
937 wxStringTokenizer tkz((*dt)[i], wxT(" "), wxTOKEN_STRTOK);
941 // Date Time name: perm ? user grp size date time
942 //04-Apr-2004 17:19 Tom-fd: -rwx------ 1 nicolas None 514967 2004-03-20 20:03:42 filename
944 if (datetime.ParseDate(tkz.GetNextToken()) != NULL) { // Date
945 if (datetime.ParseTime(tkz.GetNextToken()) != NULL) { // Time
946 if (tkz.GetNextToken().Last() == ':') { // name:
947 tkz.GetNextToken(); // perm
948 tkz.GetNextToken(); // ?
949 tkz.GetNextToken(); // user
950 tkz.GetNextToken(); // grp
951 tkz.GetNextToken(); // size
952 if (datetime.ParseDate(tkz.GetNextToken()) != NULL) { //date
953 if (datetime.ParseTime(tkz.GetNextToken()) != NULL) { //time
955 //wxbMainFrame::GetInstance()->Print(wxString("(") << filemessages << ")", CS_DEBUG);
956 gauge->SetValue(filemessages);
967 while (sw2.Time() < 10000) {
968 wxTheApp->Yield(true);
969 wxbUtils::MilliSleep(100);
976 if ((!waitforever) && (sw.Time() > 60000)) {
977 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);
978 wxbMainFrame::GetInstance()->SetStatusText(_("The restore job has not been started within one minute, wx-console will not wait for its completion anymore."));
982 wxbUtils::WaitForEnd(wxT("autodisplay on\n"));
983 wxbUtils::WaitForEnd(wxT(".messages\n"));
985 gauge->SetValue(totfilemessages);
987 if (status == JS_Terminated) {
988 wxbMainFrame::GetInstance()->Print(_("Restore done successfully.\n"), CS_DEBUG);
989 wxbMainFrame::GetInstance()->SetStatusText(_("Restore done successfully."));
995 /* The cancel button has been clicked */
996 void wxbRestorePanel::CmdCancel() {
999 if (status == restoring) {
1000 if (jobid != wxT("")) {
1001 wxbMainFrame::GetInstance()->Send(wxString(wxT("cancel job=")) << jobid << wxT("\n"));
1003 cancel->Enable(true);
1008 while ((IsWorking()) && (cancelled != 2)) {
1009 wxTheApp->Yield(true);
1010 wxbUtils::MilliSleep(100);
1011 if (sw.Time() > 30000) { /* 30 seconds timeout */
1012 if (status == choosing) {
1013 wxbMainFrame::GetInstance()->Send(wxT("quit\n"));
1015 else if (status == configuring) {
1016 wxbMainFrame::GetInstance()->Send(wxT("no\n"));
1018 else if (status == restoring) {
1021 SetStatus(finished);
1022 wxbUtils::MilliSleep(1000);
1029 wxbMainFrame::GetInstance()->Send(wxT("quit\n"));
1032 wxbMainFrame::GetInstance()->Send(wxT("no\n"));
1037 wxbUtils::MilliSleep(1000);
1038 SetStatus(finished);
1041 /* Apply configuration changes */
1043 /* 1: Level (not appropriate)
1048 * 6: When (yes : "Please enter desired start time as YYYY-MM-DD HH:MM:SS (return for now):")
1049 * 7: Priority (yes : "Enter new Priority: (positive integer)")
1051 * 9: Where (yes : "Please enter path prefix for restore (/ for none):")
1052 * 10: Replace (yes : "Replace:\n 1: always\n 2: ifnewer\n 3: ifolder\n 4: never\n
1053 * Select replace option (1-4):")
1057 void wxbRestorePanel::CmdConfigApply() {
1058 if (cfgUpdated == 0) return;
1060 wxbMainFrame::GetInstance()->SetStatusText(_("Applying restore configuration changes..."));
1062 EnableConfig(false);
1064 wxbDataTokenizer* dt = NULL;
1066 bool failed = false;
1068 while (cfgUpdated > 0) {
1073 wxString def; //String to send if can't use our data
1074 if ((cfgUpdated >> ConfigWhere) & 1) {
1075 wxbUtils::WaitForPrompt(wxT("mod\n")); /* TODO: check results */
1076 wxbUtils::WaitForPrompt(wxT("9\n"));
1077 dt = new wxbDataTokenizer(true);
1078 wxbUtils::WaitForPrompt(restorePanel->GetRowString(_("Where")) + wxT("\n"));
1080 cfgUpdated = cfgUpdated & (~(1 << ConfigWhere));
1082 else if ((cfgUpdated >> ConfigReplace) & 1) {
1083 wxbUtils::WaitForPrompt(wxT("mod\n")); /* TODO: check results */
1084 wxbUtils::WaitForPrompt(wxT("10\n"));
1085 dt = new wxbDataTokenizer(true);
1086 wxbUtils::WaitForPrompt(wxString() << (restorePanel->GetRowSelection(_("Replace"))+1) << wxT("\n"));
1088 cfgUpdated = cfgUpdated & (~(1 << ConfigReplace));
1090 else if ((cfgUpdated >> ConfigWhen) & 1) {
1091 wxbUtils::WaitForPrompt(wxT("mod\n")); /* TODO: check results */
1092 wxbUtils::WaitForPrompt(wxT("6\n"));
1093 dt = new wxbDataTokenizer(true);
1094 wxbUtils::WaitForPrompt(restorePanel->GetRowString(wxT("When")) + wxT("\n"));
1096 cfgUpdated = cfgUpdated & (~(1 << ConfigWhen));
1098 else if ((cfgUpdated >> ConfigPriority) & 1) {
1099 wxbUtils::WaitForPrompt(wxT("mod\n")); /* TODO: check results */
1100 wxbUtils::WaitForPrompt(wxT("7\n"));
1101 dt = new wxbDataTokenizer(true);
1102 wxbUtils::WaitForPrompt(restorePanel->GetRowString(_("Priority")) + wxT("\n"));
1104 cfgUpdated = cfgUpdated & (~(1 << ConfigPriority));
1106 else if ((cfgUpdated >> ConfigClient) & 1) {
1107 wxbUtils::WaitForPrompt(wxT("mod\n")); /* TODO: check results */
1108 wxbPromptParser *pp = wxbUtils::WaitForPrompt(wxT("5\n"), true);
1109 int client = pp->getChoices()->Index(restorePanel->GetRowString(_("Client")));
1110 if (client == wxNOT_FOUND) {
1111 wxbMainFrame::GetInstance()->SetStatusText(_("Failed to find the selected client."));
1116 dt = new wxbDataTokenizer(true);
1117 wxbUtils::WaitForPrompt(wxString() << client << wxT("\n"));
1119 cfgUpdated = cfgUpdated & (~(1 << ConfigClient));
1121 else if ((cfgUpdated >> ConfigFileset) & 1) {
1122 wxbUtils::WaitForPrompt(wxT("mod\n")); /* TODO: check results */
1123 wxbPromptParser *pp = wxbUtils::WaitForPrompt(wxT("4\n"), true);
1124 int fileset = pp->getChoices()->Index(restorePanel->GetRowString(_("Fileset")));
1125 if (fileset == wxNOT_FOUND) {
1126 wxbMainFrame::GetInstance()->SetStatusText(_("Failed to find the selected fileset."));
1131 dt = new wxbDataTokenizer(true);
1132 wxbUtils::WaitForPrompt(wxString() << fileset << wxT("\n"));
1134 cfgUpdated = cfgUpdated & (~(1 << ConfigFileset));
1136 else if ((cfgUpdated >> ConfigStorage) & 1) {
1137 wxbUtils::WaitForPrompt(wxT("mod\n")); /* TODO: check results */
1138 wxbPromptParser *pp = wxbUtils::WaitForPrompt(wxT("2\n"), true);
1139 int fileset = pp->getChoices()->Index(restorePanel->GetRowString(_("Storage")));
1140 if (fileset == wxNOT_FOUND) {
1141 wxbMainFrame::GetInstance()->SetStatusText(_("Failed to find the selected storage."));
1146 dt = new wxbDataTokenizer(true);
1147 wxbUtils::WaitForPrompt(wxString() << fileset << wxT("\n"));
1149 cfgUpdated = cfgUpdated & (~(1 << ConfigStorage));
1157 for (i = 0; i < dt->GetCount(); i++) {
1158 if ((*dt)[i].Find(_("Run Restore job")) == 0) {
1163 if (i == dt->GetCount()) {
1165 dt = wxbUtils::WaitForEnd(def + wxT("\n"), true);
1169 UpdateSecondConfig(dt); /* TODO: Check result */
1174 wxbMainFrame::GetInstance()->SetStatusText(_("Restore configuration changes were applied."));
1180 /* Cancel restore */
1181 void wxbRestorePanel::CmdConfigCancel() {
1182 wxbUtils::WaitForEnd(wxT("no\n"));
1183 wxbMainFrame::GetInstance()->Print(_("Restore cancelled.\n"), CS_DEBUG);
1184 wxbMainFrame::GetInstance()->SetStatusText(_("Restore cancelled."));
1185 SetStatus(finished);
1188 /* List jobs for a specified client and fileset */
1189 void wxbRestorePanel::CmdListJobs() {
1190 if (status == entered) {
1191 configPanel->ClearRowChoices(_("Before"));
1192 /*wxbUtils::WaitForPrompt("query\n");
1193 wxbUtils::WaitForPrompt("6\n");*/
1194 wxbTableParser* tableparser = new wxbTableParser(false);
1195 wxbDataTokenizer* dt = wxbUtils::WaitForEnd(
1196 wxString(wxT(".backups client=\"")) + configPanel->GetRowString(_("Client")) +
1197 wxT("\" fileset=\"") + configPanel->GetRowString(_("Fileset")) + wxT("\"\n"), true);
1199 while (!tableparser->hasFinished()) {
1200 wxTheApp->Yield(true);
1201 wxbUtils::MilliSleep(100);
1204 if (!tableparser->GetCount() == 0) {
1205 for (unsigned int i = 0; i < dt->Count(); i++) {
1206 if ((*dt)[i].Find(_("No results to list.")) == 0) {
1207 configPanel->AddRowChoice(_("Before"),
1208 _("No backup found for this client."));
1209 configPanel->SetRowSelection(_("Before"), 0);
1210 configPanel->EnableApply(true); // Enabling the not existing apply button disables the ok button.
1215 else if (((*dt)[i].Find(_("ERROR")) > -1) ||
1216 ((*dt)[i].Find(_("Query failed")) > -1)) {
1217 configPanel->AddRowChoice(_("Before"),
1218 _("Cannot get previous backups list, see console."));
1219 configPanel->SetRowSelection(_("Before"), 0);
1220 configPanel->EnableApply(true); // Enabling the not existing apply button disables the ok button.
1230 wxDateTime lastdatetime = (time_t) 0;
1231 for (int i = tableparser->GetCount()-1; i > -1; i--) {
1232 wxString str = (*tableparser)[i][3];
1233 wxDateTime datetime;
1235 if ( ( (chr = datetime.ParseDate(str.GetData()) ) != NULL ) && ( datetime.ParseTime(++chr) != NULL ) && ! lastdatetime.IsEqualTo(datetime) ) {
1236 lastdatetime = datetime;
1237 datetime += wxTimeSpan::Seconds(1);
1238 configPanel->AddRowChoice(_("Before"),
1239 datetime.Format(wxT("%Y-%m-%d %H:%M:%S")));
1245 configPanel->SetRowSelection(_("Before"), 0);
1246 configPanel->EnableApply(false); // Disabling the not existing apply button enables the ok button.
1250 /* List files and directories for a specified tree item */
1251 void wxbRestorePanel::CmdList(wxTreeItemId item) {
1252 if (status == choosing) {
1253 list->DeleteAllItems();
1258 UpdateTreeItem(item, true, false);
1260 if (list->GetItemCount() >= 1) {
1261 int firstwidth = list->GetSize().GetWidth();
1262 for (int i = 2; i < 7; i++) {
1263 list->SetColumnWidth(i, wxLIST_AUTOSIZE);
1264 firstwidth -= list->GetColumnWidth(i);
1267 list->SetColumnWidth(0, 18);
1269 list->SetColumnWidth(1, wxLIST_AUTOSIZE);
1270 if (list->GetColumnWidth(1) < firstwidth) {
1271 list->SetColumnWidth(1, firstwidth-25);
1277 /* Mark a treeitem (directory) or a listitem (file or directory) */
1278 void wxbRestorePanel::CmdMark(wxTreeItemId treeitem, long* listitems, int listsize, int state) {
1279 if (status == choosing) {
1280 wxbTreeItemData** itemdata;
1281 int itemdatasize = 0;
1282 if (listsize == 0) {
1283 itemdata = new wxbTreeItemData*[1];
1287 itemdata = new wxbTreeItemData*[listsize];
1288 itemdatasize = listsize;
1291 if (listitems != NULL) {
1292 for (int i = 0; i < itemdatasize; i++) {
1293 itemdata[i] = (wxbTreeItemData*)list->GetItemData(listitems[i]);
1296 else if (treeitem.IsOk()) {
1297 itemdata[0] = (wxbTreeItemData*)tree->GetItemData(treeitem);
1304 if (itemdata[0] == NULL) { //Should never happen
1309 wxString dir = itemdata[0]->GetPath();
1312 if (dir != wxT("/")) {
1313 if (IsPathSeparator(dir.GetChar(dir.Length()-1))) {
1317 int i = dir.Find('/', TRUE);
1322 else { /* first dir below root */
1323 file = dir.Mid(i+1);
1324 dir = dir.Mid(0, i+1);
1333 bool marked = false;
1334 bool unmarked = false;
1336 for (int i = 0; i < itemdatasize; i++) {
1337 switch(itemdata[i]->GetMarked()) {
1351 if (marked && unmarked)
1367 wxbUtils::WaitForEnd(wxString(wxT("cd \"")) << dir << wxT("\"\n"));
1368 wxbUtils::WaitForEnd(wxString((state==1) ? wxT("mark") : wxT("unmark")) << wxT(" \"") << file << wxT("\"\n"));
1370 /* TODO: Check commands results */
1372 /*if ((dir == "/") && (file == "*")) {
1373 itemdata->SetMarked((itemdata->GetMarked() == 1) ? 0 : 1);
1376 if (listitems == NULL) { /* tree item state changed */
1377 SetTreeItemState(treeitem, state);
1378 /*treeitem = tree->GetSelection();
1379 UpdateTree(treeitem, true);
1380 treeitem = tree->GetItemParent(treeitem);*/
1383 for (int i = 0; i < itemdatasize; i++) {
1384 SetListItemState(listitems[i], state);
1386 listadd->Enable(state == 0);
1387 listremove->Enable(state == 1);
1388 /*UpdateTree(treeitem, (tree->GetSelection() == treeitem));
1389 treeitem = tree->GetItemParent(treeitem);*/
1392 /*while (treeitem.IsOk()) {
1393 WaitForList(treeitem, false);
1394 treeitem = tree->GetItemParent(treeitem);
1401 /*----------------------------------------------------------------------------
1403 ----------------------------------------------------------------------------*/
1405 /* Run a dir command, and waits until result is fully received. */
1406 void wxbRestorePanel::UpdateTreeItem(wxTreeItemId item, bool updatelist, bool recurse)
1408 // this->updatelist = updatelist;
1409 wxbDataTokenizer* dt;
1411 dt = wxbUtils::WaitForEnd(wxString(wxT("cd \"")) <<
1412 static_cast<wxbTreeItemData*>(tree->GetItemData(item))
1413 ->GetPath() << wxT("\"\n"), false);
1415 /* TODO: check command result */
1422 list->DeleteAllItems();
1423 dt = wxbUtils::WaitForEnd(wxT(".dir\n"), true);
1427 for (unsigned int i = 0; i < dt->GetCount(); i++) {
1430 if (str.Find(wxT("cwd is:")) == 0) { // Sometimes cd command result "infiltrate" into listings.
1438 if (!ParseList(str, &entry))
1441 wxTreeItemId treeid;
1443 if (IsPathSeparator(entry.fullname.GetChar(entry.fullname.Length()-1))) {
1446 #if wxCHECK_VERSION(2, 6, 0)
1447 wxTreeItemIdValue cookie;
1452 treeid = tree->GetFirstChild(item, cookie);
1454 bool updated = false;
1456 while (treeid.IsOk()) {
1457 itemStr = ((wxbTreeItemData*)tree->GetItemData(treeid))->GetName();
1458 if (entry.filename == itemStr) {
1459 if (static_cast<wxbTreeItemData*>(tree->GetItemData(treeid))->GetMarked() != entry.marked) {
1460 tree->SetItemImage(treeid, entry.marked, wxTreeItemIcon_Normal);
1461 tree->SetItemImage(treeid, entry.marked, wxTreeItemIcon_Selected);
1462 static_cast<wxbTreeItemData*>(tree->GetItemData(treeid))->SetMarked(entry.marked);
1464 if ((recurse) && (tree->IsExpanded(treeid))) {
1465 UpdateTreeItem(treeid, false, true);
1470 treeid = tree->GetNextChild(item, cookie);
1474 treeid = tree->AppendItem(item, wxbUtils::ConvertToPrintable(entry.filename), entry.marked, entry.marked, new wxbTreeItemData(entry.fullname, entry.filename, entry.marked));
1479 long ind = list->InsertItem(list->GetItemCount(), entry.marked);
1480 wxbTreeItemData* data = new wxbTreeItemData(entry.fullname, entry.filename, entry.marked, ind);
1481 data->SetId(treeid);
1482 list->SetItemData(ind, (long)data);
1483 list->SetItem(ind, 1, wxbUtils::ConvertToPrintable(entry.filename));
1484 list->SetItem(ind, 2, entry.size);
1485 list->SetItem(ind, 3, entry.date);
1486 list->SetItem(ind, 4, entry.perm);
1487 list->SetItem(ind, 5, entry.user);
1488 list->SetItem(ind, 6, entry.group);
1498 /* Parse .dir command results, returns true if the result has been stored in entry, false otherwise. */
1499 int wxbRestorePanel::ParseList(wxString line, wxbDirEntry* entry)
1501 /* See ls_output in dird/ua_tree.c */
1502 //-rw-r-----,1,root,root,41575,2005-10-18 18:21:36, ,/usr/var/bacula/working/bacula.sql
1504 wxStringTokenizer tkz(line, wxT(","));
1506 if (!tkz.HasMoreTokens())
1508 entry->perm = tkz.GetNextToken();
1510 if (!tkz.HasMoreTokens())
1512 entry->nlink = tkz.GetNextToken();
1514 if (!tkz.HasMoreTokens())
1516 entry->user = tkz.GetNextToken();
1518 if (!tkz.HasMoreTokens())
1520 entry->group = tkz.GetNextToken();
1522 if (!tkz.HasMoreTokens())
1524 entry->size = tkz.GetNextToken();
1526 if (!tkz.HasMoreTokens())
1528 entry->date = tkz.GetNextToken();
1530 if (!tkz.HasMoreTokens())
1532 wxString marked = tkz.GetNextToken();
1533 if (marked == wxT("*")) {
1536 else if (marked == wxT("+")) {
1543 if (!tkz.HasMoreTokens())
1545 entry->fullname = tkz.GetString();
1547 /* Get only the filename (cut path by finding the last '/') */
1548 if (IsPathSeparator(entry->fullname.GetChar(entry->fullname.Length()-1))) {
1549 wxString tmp = entry->fullname;
1551 entry->filename = entry->fullname.Mid(tmp.Find('/', true)+1);
1554 entry->filename = entry->fullname.Mid(entry->fullname.Find('/', true)+1);
1560 /* Sets a list item state, and update its parents and children if it is a directory */
1561 void wxbRestorePanel::SetListItemState(long listitem, int newstate)
1563 wxbTreeItemData* itemdata = (wxbTreeItemData*)list->GetItemData(listitem);
1565 wxTreeItemId treeitem;
1567 itemdata->SetMarked(newstate);
1568 list->SetItemImage(listitem, newstate, 0); /* TODO: Find what these ints are for */
1569 list->SetItemImage(listitem, newstate, 1);
1571 if ((treeitem = itemdata->GetId()).IsOk()) {
1572 SetTreeItemState(treeitem, newstate);
1575 UpdateTreeItemState(tree->GetSelection());
1579 /* Sets a tree item state, and update its children, parents and list (if necessary) */
1580 void wxbRestorePanel::SetTreeItemState(wxTreeItemId item, int newstate) {
1581 #if wxCHECK_VERSION(2, 6, 0)
1582 wxTreeItemIdValue cookie;
1586 wxTreeItemId currentChild = tree->GetFirstChild(item, cookie);
1588 wxbTreeItemData* itemdata;
1590 while (currentChild.IsOk()) {
1591 itemdata = (wxbTreeItemData*)tree->GetItemData(currentChild);
1592 int state = itemdata->GetMarked();
1594 if (state != newstate) {
1595 itemdata->SetMarked(newstate);
1596 tree->SetItemImage(currentChild, newstate, wxTreeItemIcon_Normal);
1597 tree->SetItemImage(currentChild, newstate, wxTreeItemIcon_Selected);
1600 currentChild = tree->GetNextChild(item, cookie);
1603 itemdata = (wxbTreeItemData*)tree->GetItemData(item);
1604 itemdata->SetMarked(newstate);
1605 tree->SetItemImage(item, newstate, wxTreeItemIcon_Normal);
1606 tree->SetItemImage(item, newstate, wxTreeItemIcon_Selected);
1609 if (tree->GetSelection() == item) {
1610 for (long i = 0; i < list->GetItemCount(); i++) {
1611 list->SetItemImage(i, newstate, 0); /* TODO: Find what these ints are for */
1612 list->SetItemImage(i, newstate, 1);
1616 UpdateTreeItemState(tree->GetItemParent(item));
1619 /* Update a tree item state, and its parents' state */
1620 void wxbRestorePanel::UpdateTreeItemState(wxTreeItemId item) {
1627 #if wxCHECK_VERSION(2, 6, 0)
1628 wxTreeItemIdValue cookie;
1632 wxTreeItemId currentChild = tree->GetFirstChild(item, cookie);
1634 bool onechildmarked = false;
1635 bool onechildunmarked = false;
1637 while (currentChild.IsOk()) {
1638 state = ((wxbTreeItemData*)tree->GetItemData(currentChild))->GetMarked();
1641 onechildunmarked = true;
1644 onechildmarked = true;
1647 onechildmarked = true;
1648 onechildunmarked = true;
1652 if (onechildmarked && onechildunmarked) {
1656 currentChild = tree->GetNextChild(item, cookie);
1659 if (tree->GetSelection() == item) {
1660 for (long i = 0; i < list->GetItemCount(); i++) {
1661 state = ((wxbTreeItemData*)list->GetItemData(i))->GetMarked();
1665 onechildunmarked = true;
1668 onechildmarked = true;
1671 onechildmarked = true;
1672 onechildunmarked = true;
1676 if (onechildmarked && onechildunmarked) {
1684 if (onechildmarked && onechildunmarked) {
1687 else if (onechildmarked) {
1690 else if (onechildunmarked) {
1693 else { // no child, don't change anything
1694 UpdateTreeItemState(tree->GetItemParent(item));
1698 wxbTreeItemData* itemdata = (wxbTreeItemData*)tree->GetItemData(item);
1700 itemdata->SetMarked(state);
1701 tree->SetItemImage(item, state, wxTreeItemIcon_Normal);
1702 tree->SetItemImage(item, state, wxTreeItemIcon_Selected);
1704 UpdateTreeItemState(tree->GetItemParent(item));
1707 /* Refresh the whole tree. */
1708 void wxbRestorePanel::RefreshTree() {
1709 /* Save current selection */
1710 wxArrayString current;
1712 wxTreeItemId item = currentTreeItem;
1714 while ((item.IsOk()) && (item != tree->GetRootItem())) {
1715 current.Add(tree->GetItemText(item));
1716 item = tree->GetItemParent(item);
1719 /* Update the tree */
1720 UpdateTreeItem(tree->GetRootItem(), false, true);
1722 /* Reselect the former selected item */
1723 item = tree->GetRootItem();
1725 if (current.Count() == 0) {
1726 tree->SelectItem(item);
1732 for (int i = current.Count()-1; i >= 0; i--) {
1733 #if wxCHECK_VERSION(2, 6, 0)
1734 wxTreeItemIdValue cookie;
1738 wxTreeItemId currentChild = tree->GetFirstChild(item, cookie);
1742 while (currentChild.IsOk()) {
1743 if (((wxbTreeItemData*)tree->GetItemData(currentChild))->GetName() == current[i]) {
1744 item = currentChild;
1749 currentChild = tree->GetNextChild(item, cookie);
1755 UpdateTreeItem(item, true, false); /* Update the list */
1757 tree->SelectItem(item);
1760 void wxbRestorePanel::RefreshList() {
1761 if (currentTreeItem.IsOk()) {
1762 UpdateTreeItem(currentTreeItem, true, false); /* Update the list */
1766 /* Update first config, adapting settings to the job name selected */
1767 void wxbRestorePanel::UpdateFirstConfig() {
1768 configPanel->Enable(false);
1769 wxbDataTokenizer* dt = wxbUtils::WaitForEnd(wxString(wxT(".defaults job=")) + configPanel->GetRowString(_("Job Name")) + wxT("\n"), true, false);
1775 * where=/tmp/bacula-restores
1785 bool dolistjobs = false;
1787 for (i = 0; i < dt->GetCount(); i++) {
1789 if ((j = str.Find('=')) > -1) {
1790 name = str.Mid(0, j);
1791 if (name == wxT("pool")) {
1792 configPanel->SetRowString(_("Pool"), str.Mid(j+1));
1794 else if (name == wxT("client")) {
1796 if ((str != configPanel->GetRowString(_("Client"))) ||
1797 (configPanel->GetRowString(_("Before"))) == wxT("")) {
1798 configPanel->SetRowString(_("Client"), str);
1802 else if (name == wxT("storage")) {
1803 configPanel->SetRowString(_("Storage"), str.Mid(j+1));
1805 else if (name == wxT("fileset")) {
1807 if ((str != configPanel->GetRowString(_("Fileset"))) ||
1808 (configPanel->GetRowString(_("Before"))) == wxT("")) {
1809 configPanel->SetRowString(_("Fileset"), str);
1819 //wxTheApp->Yield(false);
1822 configPanel->Enable(true);
1826 * Update second config.
1829 * JobName: RestoreFiles
1830 * Bootstrap: /var/lib/bacula/restore.bsr
1831 * Where: /tmp/bacula-restores
1836 * When: 2004-04-18 01:18:56
1838 * OK to run? (yes/mod/no):
1841 bool wxbRestorePanel::UpdateSecondConfig(wxbDataTokenizer* dt) {
1843 for (i = 0; i < dt->GetCount(); i++) {
1844 if ((*dt)[i].Find(_("Run Restore job")) == 0)
1848 if ((i + 10) > dt->GetCount()) {
1854 if ((k = (*dt)[++i].Find(_("JobName:"))) != 0) return false;
1855 restorePanel->SetRowString(_("Job Name"), (*dt)[i].Mid(10).Trim(false).RemoveLast());
1856 if ((k = (*dt)[++i].Find(_("Bootstrap:"))) != 0) return false;
1857 restorePanel->SetRowString(_("Bootstrap"), (*dt)[i].Mid(10).Trim(false).RemoveLast());
1858 if ((k = (*dt)[++i].Find(_("Where:"))) != 0) return false;
1859 restorePanel->SetRowString(_("Where"), (*dt)[i].Mid(10).Trim(false).RemoveLast());
1861 if ((k = (*dt)[++i].Find(_("Replace:"))) != 0) return false;
1862 wxString str = (*dt)[i].Mid(10).Trim(false).RemoveLast();
1863 if (str == _("always")) restorePanel->SetRowSelection(_("Replace"), 0);
1864 else if (str == _("ifnewer")) restorePanel->SetRowSelection(_("Replace"), 1);
1865 else if (str == _("ifolder")) restorePanel->SetRowSelection(_("Replace"), 2);
1866 else if (str == _("never")) restorePanel->SetRowSelection(_("Replace"), 3);
1867 else restorePanel->SetRowSelection(_("Replace"), 0);
1869 if ((k = (*dt)[++i].Find(_("FileSet:"))) != 0) return false;
1870 restorePanel->SetRowString(_("Fileset"), (*dt)[i].Mid(10).Trim(false).RemoveLast());
1871 if ((k = (*dt)[++i].Find(_("Client:"))) != 0) return false;
1872 restorePanel->SetRowString(_("Client"), (*dt)[i].Mid(10).Trim(false).RemoveLast());
1873 if ((k = (*dt)[++i].Find(_("Storage:"))) != 0) return false;
1874 restorePanel->SetRowString(_("Storage"), (*dt)[i].Mid(10).Trim(false).RemoveLast());
1875 if ((k = (*dt)[++i].Find(_("When:"))) != 0) return false;
1876 restorePanel->SetRowString(_("When"), (*dt)[i].Mid(10).Trim(false).RemoveLast());
1877 if ((k = (*dt)[++i].Find(_("Priority:"))) != 0) return false;
1878 restorePanel->SetRowString(_("Priority"), (*dt)[i].Mid(10).Trim(false).RemoveLast());
1881 restorePanel->Layout();
1886 /*----------------------------------------------------------------------------
1888 ----------------------------------------------------------------------------*/
1890 /* Set current status by enabling/disabling components */
1891 void wxbRestorePanel::SetStatus(status_enum newstatus) {
1892 switch (newstatus) {
1894 centerSizer->Remove(configPanel);
1895 centerSizer->Remove(restorePanel);
1896 centerSizer->Remove(treelistPanel);
1897 treelistPanel->Show(false);
1898 restorePanel->Show(false);
1899 centerSizer->Add(configPanel, 1, wxEXPAND);
1900 configPanel->Show(true);
1901 configPanel->Layout();
1902 centerSizer->Layout();
1904 start->SetLabel(_("Enter restore mode"));
1905 start->Enable(false);
1906 configPanel->Enable(false);
1907 tree->Enable(false);
1908 list->Enable(false);
1909 gauge->Enable(false);
1910 cancel->Enable(false);
1915 centerSizer->Remove(configPanel);
1916 centerSizer->Remove(restorePanel);
1917 centerSizer->Remove(treelistPanel);
1918 treelistPanel->Show(false);
1919 restorePanel->Show(false);
1920 centerSizer->Add(configPanel, 1, wxEXPAND);
1921 configPanel->Show(true);
1922 configPanel->Layout();
1923 centerSizer->Layout();
1925 tree->DeleteAllItems();
1926 list->DeleteAllItems();
1927 configPanel->ClearRowChoices(_("Client"));
1928 configPanel->ClearRowChoices(_("Before"));
1929 wxbMainFrame::GetInstance()->EnablePanels();
1930 newstatus = activable;
1933 start->SetLabel(_("Enter restore mode"));
1934 start->Enable(true);
1935 configPanel->Enable(false);
1936 tree->Enable(false);
1937 list->Enable(false);
1938 gauge->Enable(false);
1939 cancel->Enable(false);
1943 wxbMainFrame::GetInstance()->DisablePanels(this);
1945 start->Enable(false);
1946 //start->SetLabel(_("Choose files to restore"));
1947 configPanel->Enable(true);
1948 tree->Enable(false);
1949 list->Enable(false);
1950 cancel->Enable(true);
1957 start->Enable(true);
1958 start->SetLabel(_("Restore"));
1959 centerSizer->Remove(configPanel);
1960 configPanel->Show(false);
1961 centerSizer->Add(treelistPanel, 1, wxEXPAND);
1962 treelistPanel->Show(true);
1963 treelistPanel->Layout();
1964 centerSizer->Layout();
1971 start->Enable(false);
1972 configPanel->Enable(false);
1973 tree->Enable(false);
1974 list->Enable(false);
1975 centerSizer->Remove(treelistPanel);
1976 treelistPanel->Show(false);
1977 centerSizer->Add(restorePanel, 1, wxEXPAND);
1978 restorePanel->Show(true);
1979 restorePanel->Layout();
1980 centerSizer->Layout();
1982 restorePanel->EnableApply(false);
1985 start->SetLabel(_("Restoring..."));
1986 gauge->Enable(true);
1988 start->Enable(false);
1989 configPanel->Enable(false);
1990 tree->Enable(false);
1991 list->Enable(false);
1998 /*----------------------------------------------------------------------------
2000 ----------------------------------------------------------------------------*/
2002 void wxbRestorePanel::SetWorking(bool working) {
2003 this->working = working;
2005 SetCursor(*wxHOURGLASS_CURSOR);
2006 // SetEvtHandlerEnabled(false); //EVTQUEUE
2008 // else if (!processing) { /* Empty event queue if we aren't already doing this */ //EVTQUEUE
2010 // processing = true; //EVTQUEUE
2011 SetCursor(*wxSTANDARD_CURSOR);
2012 // SetEvtHandlerEnabled(true); //EVTQUEUE
2013 /* wxNode *node = pendingEvents->First(); //EVTQUEUE
2015 wxEvent *event = (wxEvent *)node->Data();
2018 wxEvtHandler::ProcessEvent(*event);
2021 node = pendingEvents->First();
2023 processing = false;*/
2027 bool wxbRestorePanel::IsWorking() {
2028 return this->working;
2031 void wxbRestorePanel::EnableConfig(bool enable) {
2032 restorePanel->Enable(enable);
2035 /*----------------------------------------------------------------------------
2037 ----------------------------------------------------------------------------*/
2042 bool wxbRestorePanel::ProcessEvent(wxEvent& event) {
2043 if (IsWorking() || processing) {
2044 wxEvent *eventCopy = event.Clone();
2046 pendingEvents->Append(eventCopy);
2050 return wxEvtHandler::ProcessEvent(event);
2055 void wxbRestorePanel::OnCancel(wxCommandEvent& event) {
2056 cancel->Enable(false);
2057 SetCursor(*wxHOURGLASS_CURSOR);
2059 SetCursor(*wxSTANDARD_CURSOR);
2062 void wxbRestorePanel::OnStart(wxCommandEvent& event) {
2071 void wxbRestorePanel::OnTreeChanging(wxTreeEvent& event) {
2077 void wxbRestorePanel::OnTreeExpanding(wxTreeEvent& event) {
2083 //CmdList(event.GetItem());
2084 if (tree->GetSelection() != event.GetItem()) {
2085 tree->SelectItem(event.GetItem());
2090 void wxbRestorePanel::OnTreeChanged(wxTreeEvent& event) {
2094 if (currentTreeItem == event.GetItem()) {
2097 treeadd->Enable(false);
2098 treeremove->Enable(false);
2099 treerefresh->Enable(false);
2100 markWhenCommandDone = false;
2102 currentTreeItem = event.GetItem();
2103 CmdList(event.GetItem());
2104 if (markWhenCommandDone) {
2105 CmdMark(event.GetItem(), NULL, 0);
2109 if (event.GetItem().IsOk()) {
2110 int status = ((wxbTreeItemData*)tree->GetItemData(event.GetItem()))->GetMarked();
2111 treeadd->Enable(status != 1);
2112 treeremove->Enable(status != 0);
2114 treerefresh->Enable(true);
2117 void wxbRestorePanel::OnTreeMarked(wxbTreeMarkedEvent& event) {
2119 if (tree->GetSelection() == event.GetItem()) {
2120 markWhenCommandDone = !markWhenCommandDone;
2125 markWhenCommandDone = false;
2126 CmdMark(event.GetItem(), NULL, 0);
2127 if (markWhenCommandDone) {
2128 CmdMark(event.GetItem(), NULL, 0);
2133 if (event.GetItem().IsOk()) {
2134 int status = ((wxbTreeItemData*)tree->GetItemData(event.GetItem()))->GetMarked();
2135 treeadd->Enable(status != 1);
2136 treeremove->Enable(status != 0);
2140 void wxbRestorePanel::OnTreeAdd(wxCommandEvent& event) {
2145 if (currentTreeItem.IsOk()) {
2147 CmdMark(currentTreeItem, NULL, 0, 1);
2150 treeremove->Enable(1);
2155 void wxbRestorePanel::OnTreeRemove(wxCommandEvent& event) {
2160 if (currentTreeItem.IsOk()) {
2162 CmdMark(currentTreeItem, NULL, 0, 0);
2165 treeremove->Enable(0);
2170 void wxbRestorePanel::OnTreeRefresh(wxCommandEvent& event) {
2180 void wxbRestorePanel::OnListMarked(wxbListMarkedEvent& event) {
2185 if (list->GetSelectedItemCount() == 0) {
2191 long* items = new long[list->GetSelectedItemCount()];
2195 long item = list->GetNextItem(-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
2196 while (item != -1) {
2199 item = list->GetNextItem(item, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
2202 CmdMark(wxTreeItemId(), items, num);
2206 wxListEvent listevt;
2208 OnListChanged(listevt);
2215 void wxbRestorePanel::OnListActivated(wxListEvent& event) {
2220 long item = event.GetIndex();
2221 // long item = list->GetNextItem(-1, wxLIST_NEXT_ALL, wxLIST_STATE_FOCUSED);
2223 wxbTreeItemData* itemdata = (wxbTreeItemData*)list->GetItemData(item);
2224 wxString name = itemdata->GetName();
2229 #if wxCHECK_VERSION(2, 6, 0)
2230 wxTreeItemIdValue cookie;
2235 if (IsPathSeparator(name.GetChar(name.Length()-1))) {
2236 wxTreeItemId currentChild = tree->GetFirstChild(currentTreeItem, cookie);
2238 while (currentChild.IsOk()) {
2239 wxString name2 = ((wxbTreeItemData*)tree->GetItemData(currentChild))->GetName();
2240 if (name2 == name) {
2241 //tree->UnselectAll();
2243 tree->Expand(currentTreeItem);
2244 tree->SelectItem(currentChild);
2248 currentChild = tree->GetNextChild(currentTreeItem, cookie);
2255 void wxbRestorePanel::OnListChanged(wxListEvent& event) {
2260 listadd->Enable(false);
2261 listremove->Enable(false);
2263 bool marked = false;
2264 bool unmarked = false;
2266 long item = list->GetNextItem(-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
2267 while (item != -1) {
2268 switch (((wxbTreeItemData*)list->GetItemData(item))->GetMarked()) {
2281 // Should never happen
2283 if (marked && unmarked) break;
2284 item = list->GetNextItem(item, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
2287 listadd->Enable(unmarked);
2288 listremove->Enable(marked);
2291 void wxbRestorePanel::OnListAdd(wxCommandEvent& event) {
2298 long* items = new long[list->GetSelectedItemCount()];
2302 long item = list->GetNextItem(-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
2303 while (item != -1) {
2306 item = list->GetNextItem(item, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
2309 CmdMark(wxTreeItemId(), items, num, 1);
2316 listadd->Enable(false);
2317 listremove->Enable(true);
2320 void wxbRestorePanel::OnListRemove(wxCommandEvent& event) {
2327 long* items = new long[list->GetSelectedItemCount()];
2331 long item = list->GetNextItem(-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
2332 while (item != -1) {
2335 item = list->GetNextItem(item, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
2338 CmdMark(wxTreeItemId(), items, num, 0);
2345 listadd->Enable(true);
2346 listremove->Enable(false);
2349 void wxbRestorePanel::OnListRefresh(wxCommandEvent& event) {
2359 void wxbRestorePanel::OnConfigUpdated(wxCommandEvent& event) {
2360 if (status == entered) {
2361 if (event.GetId() == ConfigJobName) {
2366 UpdateFirstConfig();
2369 else if ((event.GetId() == ConfigClient) || (event.GetId() == ConfigFileset)) {
2374 configPanel->Enable(false);
2376 configPanel->Enable(true);
2379 cfgUpdated = cfgUpdated | (1 << event.GetId());
2381 else if (status == configuring) {
2382 restorePanel->EnableApply(true);
2383 cfgUpdated = cfgUpdated | (1 << event.GetId());
2387 void wxbRestorePanel::OnConfigOk(wxCommandEvent& WXUNUSED(event)) {
2388 if (status != configuring) return;
2397 void wxbRestorePanel::OnConfigApply(wxCommandEvent& WXUNUSED(event)) {
2398 if (status != configuring) return;
2404 if (cfgUpdated == 0) {
2405 restorePanel->EnableApply(false);
2410 void wxbRestorePanel::OnConfigCancel(wxCommandEvent& WXUNUSED(event)) {
2411 if (status != configuring) return;