3 * wxbPanel for restoring files
5 * Nicolas Boichat, April-July 2004
10 Copyright (C) 2004 Kern Sibbald and John Walker
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 as published by the Free Software Foundation; either version 2
15 of the License, or (at your option) any later version.
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 GNU General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with this program; if not, write to the Free Software
24 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
26 /* Note concerning "done" output (modifiable marked with +)
28 +JobName: RestoreFiles
29 Bootstrap: /var/lib/bacula/restore.bsr
30 +Where: /tmp/bacula-restores
35 +When: 2004-04-18 01:18:56
37 OK to run? (yes/mod/no):mod
39 1: Level (not appropriate)
40 2: Storage (automatic ?)
43 5: Client (yes : "The defined Client resources are:\n\t1: velours-fd\n\t2: tom-fd\nSelect Client (File daemon) resource (1-2):")
44 6: When (yes : "Please enter desired start time as YYYY-MM-DD HH:MM:SS (return for now):")
45 7: Priority (yes : "Enter new Priority: (positive integer)")
47 9: Where (yes : "Please enter path prefix for restore (/ for none):")
48 10: Replace (yes : "Replace:\n 1: always\n 2: ifnewer\n 3: ifolder\n 4: never\n
49 Select replace option (1-4):")
51 Select parameter to modify (1-11):
54 #include "wxbrestorepanel.h"
56 #include "wxbmainframe.h"
60 #include <wx/choice.h>
61 #include <wx/datetime.h>
65 #include "unmarked.xpm"
67 #include "partmarked.xpm"
69 #include <wx/listimpl.cpp>
71 /* A macro named Yield is defined under MinGW */
74 WX_DEFINE_LIST(wxbEventList);
77 * Class which is stored in the tree and in the list to keep informations
80 class wxbTreeItemData : public wxTreeItemData {
82 wxbTreeItemData(wxString path, wxString name, int marked, long listid = -1);
83 wxbTreeItemData(wxString path, wxString name, wxString marked, long listid = -1);
89 void SetMarked(int marked);
90 void SetMarked(wxString marked);
94 static int GetMarkedStatus(wxString file);
96 wxString* path; /* Full path */
97 wxString* name; /* File name */
98 int marked; /* 0 - Not Marked, 1 - Marked, 2 - Some file under is marked */
99 long listid; /* list ID : >-1 if this data is in the list (and/or on the tree) */
102 wxbTreeItemData::wxbTreeItemData(wxString path, wxString name, int marked, long listid): wxTreeItemData() {
103 this->path = new wxString(path);
104 this->name = new wxString(name);
105 this->marked = marked;
106 this->listid = listid;
109 wxbTreeItemData::wxbTreeItemData(wxString path, wxString name, wxString marked, long listid): wxTreeItemData() {
110 this->path = new wxString(path);
111 this->name = new wxString(name);
113 this->listid = listid;
116 wxbTreeItemData::~wxbTreeItemData() {
121 int wxbTreeItemData::GetMarked() {
125 void wxbTreeItemData::SetMarked(wxString marked) {
126 if (marked == wxT("*")) {
129 else if (marked == wxT("+")) {
137 void wxbTreeItemData::SetMarked(int marked) {
138 this->marked = marked;
141 long wxbTreeItemData::GetListId() {
145 wxString wxbTreeItemData::GetPath() {
149 wxString wxbTreeItemData::GetName() {
153 /*wxbTreeItemData* wxbTreeItemData::GetChild(wxString dirname) {
154 int marked = GetMarkedStatus(dirname);
155 return new wxbTreeItemData(path + (marked ? dirname.Mid(1) : dirname), marked);
158 int wxbTreeItemData::GetMarkedStatus(wxString file) {
159 if (file.Length() == 0)
162 switch (file.GetChar(0)) {
172 // ----------------------------------------------------------------------------
173 // event tables and other macros for wxWindows
174 // ----------------------------------------------------------------------------
202 BEGIN_EVENT_TABLE(wxbRestorePanel, wxPanel)
203 EVT_BUTTON(RestoreStart, wxbRestorePanel::OnStart)
204 EVT_BUTTON(RestoreCancel, wxbRestorePanel::OnCancel)
206 EVT_TREE_SEL_CHANGING(TreeCtrl, wxbRestorePanel::OnTreeChanging)
207 EVT_TREE_SEL_CHANGED(TreeCtrl, wxbRestorePanel::OnTreeChanged)
208 EVT_TREE_ITEM_EXPANDING(TreeCtrl, wxbRestorePanel::OnTreeExpanding)
209 EVT_TREE_MARKED_EVENT(TreeCtrl, wxbRestorePanel::OnTreeMarked)
210 EVT_BUTTON(TreeAdd, wxbRestorePanel::OnTreeAdd)
211 EVT_BUTTON(TreeRemove, wxbRestorePanel::OnTreeRemove)
212 EVT_BUTTON(TreeRefresh, wxbRestorePanel::OnTreeRefresh)
214 EVT_LIST_ITEM_ACTIVATED(ListCtrl, wxbRestorePanel::OnListActivated)
215 EVT_LIST_MARKED_EVENT(ListCtrl, wxbRestorePanel::OnListMarked)
216 EVT_LIST_ITEM_SELECTED(ListCtrl, wxbRestorePanel::OnListChanged)
217 EVT_LIST_ITEM_DESELECTED(ListCtrl, wxbRestorePanel::OnListChanged)
218 EVT_BUTTON(ListAdd, wxbRestorePanel::OnListAdd)
219 EVT_BUTTON(ListRemove, wxbRestorePanel::OnListRemove)
220 EVT_BUTTON(ListRefresh, wxbRestorePanel::OnListRefresh)
222 EVT_TEXT(ConfigWhere, wxbRestorePanel::OnConfigUpdated)
223 EVT_TEXT(ConfigWhen, wxbRestorePanel::OnConfigUpdated)
224 EVT_TEXT(ConfigPriority, wxbRestorePanel::OnConfigUpdated)
225 EVT_CHOICE(ConfigWhen, wxbRestorePanel::OnConfigUpdated)
226 EVT_CHOICE(ConfigReplace, wxbRestorePanel::OnConfigUpdated)
227 EVT_CHOICE(ConfigClient, wxbRestorePanel::OnConfigUpdated)
228 EVT_CHOICE(ConfigFileset, wxbRestorePanel::OnConfigUpdated)
229 EVT_CHOICE(ConfigStorage, wxbRestorePanel::OnConfigUpdated)
230 EVT_CHOICE(ConfigJobName, wxbRestorePanel::OnConfigUpdated)
231 EVT_CHOICE(ConfigPool, wxbRestorePanel::OnConfigUpdated)
233 EVT_BUTTON(ConfigOk, wxbRestorePanel::OnConfigOk)
234 EVT_BUTTON(ConfigApply, wxbRestorePanel::OnConfigApply)
235 EVT_BUTTON(ConfigCancel, wxbRestorePanel::OnConfigCancel)
239 * wxbRestorePanel constructor
241 wxbRestorePanel::wxbRestorePanel(wxWindow* parent): wxbPanel(parent) {
242 //pendingEvents = new wxbEventList(); //EVTQUEUE
243 //processing = false; //EVTQUEUE
246 imagelist = new wxImageList(16, 16, TRUE, 3);
247 imagelist->Add(wxIcon(unmarked_xpm));
248 imagelist->Add(wxIcon(marked_xpm));
249 imagelist->Add(wxIcon(partmarked_xpm));
251 wxFlexGridSizer* mainSizer = new wxFlexGridSizer(3, 1, 10, 10);
252 mainSizer->AddGrowableCol(0);
253 mainSizer->AddGrowableRow(1);
255 wxFlexGridSizer *firstSizer = new wxFlexGridSizer(1, 2, 10, 10);
257 firstSizer->AddGrowableCol(0);
258 firstSizer->AddGrowableRow(0);
260 start = new wxButton(this, RestoreStart, wxT("Enter restore mode"), wxDefaultPosition, wxSize(150, 30));
261 firstSizer->Add(start, 0, wxALIGN_CENTER_HORIZONTAL | wxALIGN_CENTER_VERTICAL, 10);
263 cancel = new wxButton(this, RestoreCancel, wxT("Cancel restore"), wxDefaultPosition, wxSize(150, 30));
264 firstSizer->Add(cancel, 0, wxALIGN_CENTER_HORIZONTAL | wxALIGN_RIGHT, 10);
268 /* clientChoice = new wxChoice(this, ClientChoice, wxDefaultPosition, wxSize(150, 30), 0, elist);
269 firstSizer->Add(clientChoice, 1, wxALIGN_CENTER_HORIZONTAL | wxALIGN_CENTER_VERTICAL, 10);
271 jobChoice = new wxChoice(this, -1, wxDefaultPosition, wxSize(150, 30), 0, elist);
272 firstSizer->Add(jobChoice, 1, wxALIGN_CENTER_HORIZONTAL | wxALIGN_CENTER_VERTICAL, 10);*/
274 mainSizer->Add(firstSizer, 1, wxEXPAND, 10);
276 treelistPanel = new wxSplitterWindow(this);
278 wxPanel* treePanel = new wxPanel(treelistPanel);
279 wxFlexGridSizer *treeSizer = new wxFlexGridSizer(2, 1, 0, 0);
280 treeSizer->AddGrowableCol(0);
281 treeSizer->AddGrowableRow(0);
283 tree = new wxbTreeCtrl(treePanel, this, TreeCtrl, wxDefaultPosition, wxSize(200,50));
284 tree->SetImageList(imagelist);
286 treeSizer->Add(tree, 1, wxEXPAND, 0);
288 wxBoxSizer *treeCtrlSizer = new wxBoxSizer(wxHORIZONTAL);
289 treeadd = new wxButton(treePanel, TreeAdd, wxT("Add"), wxDefaultPosition, wxSize(60, 25));
290 treeCtrlSizer->Add(treeadd, 0, wxLEFT | wxRIGHT, 3);
291 treeremove = new wxButton(treePanel, TreeRemove, wxT("Remove"), wxDefaultPosition, wxSize(60, 25));
292 treeCtrlSizer->Add(treeremove, 0, wxLEFT | wxRIGHT, 3);
293 treerefresh = new wxButton(treePanel, TreeRefresh, wxT("Refresh"), wxDefaultPosition, wxSize(60, 25));
294 treeCtrlSizer->Add(treerefresh, 0, wxLEFT | wxRIGHT, 3);
296 treeSizer->Add(treeCtrlSizer, 1, wxALIGN_CENTER_HORIZONTAL, 0);
298 treePanel->SetSizer(treeSizer);
300 wxPanel* listPanel = new wxPanel(treelistPanel);
301 wxFlexGridSizer *listSizer = new wxFlexGridSizer(2, 1, 0, 0);
302 listSizer->AddGrowableCol(0);
303 listSizer->AddGrowableRow(0);
305 list = new wxbListCtrl(listPanel, this, ListCtrl, wxDefaultPosition, wxSize(200,50));
306 //treelistSizer->Add(list, 1, wxEXPAND, 10);
308 list->SetImageList(imagelist, wxIMAGE_LIST_SMALL);
311 info.SetMask(wxLIST_MASK_TEXT | wxLIST_MASK_FORMAT);
312 info.SetText(wxT("M"));
313 info.SetAlign(wxLIST_FORMAT_CENTER);
314 list->InsertColumn(0, info);
316 info.SetText(wxT("Filename"));
317 info.SetAlign(wxLIST_FORMAT_LEFT);
318 list->InsertColumn(1, info);
320 info.SetText(wxT("Size"));
321 info.SetAlign(wxLIST_FORMAT_RIGHT);
322 list->InsertColumn(2, info);
324 info.SetText(wxT("Date"));
325 info.SetAlign(wxLIST_FORMAT_LEFT);
326 list->InsertColumn(3, info);
328 info.SetText(wxT("Perm."));
329 info.SetAlign(wxLIST_FORMAT_LEFT);
330 list->InsertColumn(4, info);
332 info.SetText(wxT("User"));
333 info.SetAlign(wxLIST_FORMAT_RIGHT);
334 list->InsertColumn(5, info);
336 info.SetText(wxT("Group"));
337 info.SetAlign(wxLIST_FORMAT_RIGHT);
338 list->InsertColumn(6, info);
340 listSizer->Add(list, 1, wxEXPAND, 0);
342 wxBoxSizer *listCtrlSizer = new wxBoxSizer(wxHORIZONTAL);
343 listadd = new wxButton(listPanel, ListAdd, wxT("Add"), wxDefaultPosition, wxSize(60, 25));
344 listCtrlSizer->Add(listadd, 0, wxLEFT | wxRIGHT, 5);
345 listremove = new wxButton(listPanel, ListRemove, wxT("Remove"), wxDefaultPosition, wxSize(60, 25));
346 listCtrlSizer->Add(listremove, 0, wxLEFT | wxRIGHT, 5);
347 listrefresh = new wxButton(listPanel, ListRefresh, wxT("Refresh"), wxDefaultPosition, wxSize(60, 25));
348 listCtrlSizer->Add(listrefresh, 0, wxLEFT | wxRIGHT, 5);
350 listSizer->Add(listCtrlSizer, 1, wxALIGN_CENTER_HORIZONTAL, 0);
352 listPanel->SetSizer(listSizer);
354 treelistPanel->SplitVertically(treePanel, listPanel, 210);
356 treelistPanel->SetMinimumPaneSize(210);
358 treelistPanel->Show(false);
360 wxbConfig* config = new wxbConfig();
361 config->Add(new wxbConfigParam(wxT("Job Name"), ConfigJobName, choice, 0, elist));
362 config->Add(new wxbConfigParam(wxT("Client"), ConfigClient, choice, 0, elist));
363 config->Add(new wxbConfigParam(wxT("Fileset"), ConfigFileset, choice, 0, elist));
364 config->Add(new wxbConfigParam(wxT("Pool"), ConfigPool, choice, 0, elist));
365 config->Add(new wxbConfigParam(wxT("Storage"), ConfigStorage, choice, 0, elist));
366 config->Add(new wxbConfigParam(wxT("Before"), ConfigWhen, choice, 0, elist));
368 configPanel = new wxbConfigPanel(this, config, wxT("Please configure parameters concerning files to restore :"), RestoreStart, RestoreCancel, -1);
370 configPanel->Show(true);
371 configPanel->Enable(false);
373 config = new wxbConfig();
374 config->Add(new wxbConfigParam(wxT("Job Name"), -1, text, wxT("")));
375 config->Add(new wxbConfigParam(wxT("Bootstrap"), -1, text, wxT("")));
376 config->Add(new wxbConfigParam(wxT("Where"), ConfigWhere, modifiableText, wxT("")));
377 wxString erlist[] = {wxT("always"), wxT("if newer"), wxT("if older"), wxT("never")};
378 config->Add(new wxbConfigParam(wxT("Replace"), ConfigReplace, choice, 4, erlist));
379 config->Add(new wxbConfigParam(wxT("Fileset"), ConfigFileset, choice, 0, erlist));
380 config->Add(new wxbConfigParam(wxT("Client"), ConfigClient, choice, 0, erlist));
381 config->Add(new wxbConfigParam(wxT("Storage"), ConfigStorage, choice, 0, erlist));
382 config->Add(new wxbConfigParam(wxT("When"), ConfigWhen, modifiableText, wxT("")));
383 config->Add(new wxbConfigParam(wxT("Priority"), ConfigPriority, modifiableText, wxT("")));
385 restorePanel = new wxbConfigPanel(this, config, wxT("Please configure parameters concerning files restoration :"), ConfigOk, ConfigCancel, ConfigApply);
387 restorePanel->Show(false);
389 centerSizer = new wxBoxSizer(wxHORIZONTAL);
390 //centerSizer->Add(treelistPanel, 1, wxEXPAND | wxADJUST_MINSIZE);
392 mainSizer->Add(centerSizer, 1, wxEXPAND, 10);
394 gauge = new wxGauge(this, -1, 1, wxDefaultPosition, wxSize(200,20));
396 mainSizer->Add(gauge, 1, wxEXPAND, 5);
398 gauge->Enable(false);
401 mainSizer->SetSizeHints(this);
405 for (int i = 0; i < 7; i++) {
406 list->SetColumnWidth(i, 70);
409 SetCursor(*wxSTANDARD_CURSOR);
411 markWhenCommandDone = false;
417 * wxbRestorePanel destructor
419 wxbRestorePanel::~wxbRestorePanel() {
423 /*----------------------------------------------------------------------------
424 wxbPanel overloadings
425 ----------------------------------------------------------------------------*/
427 wxString wxbRestorePanel::GetTitle() {
428 return wxT("Restore");
431 void wxbRestorePanel::EnablePanel(bool enable) {
433 if (status == disabled) {
434 SetStatus(activable);
442 /*----------------------------------------------------------------------------
443 Commands called by events handler
444 ----------------------------------------------------------------------------*/
446 /* The main button has been clicked */
447 void wxbRestorePanel::CmdStart() {
449 if (status == activable) {
450 wxbMainFrame::GetInstance()->SetStatusText(wxT("Getting parameters list."));
451 wxbDataTokenizer* dt = wxbUtils::WaitForEnd(wxT(".clients\n"), true, false);
454 configPanel->ClearRowChoices(wxT("Client"));
455 restorePanel->ClearRowChoices(wxT("Client"));
457 if (dt->GetCount() == 0) {
458 wxbMainFrame::GetInstance()->SetStatusText(wxT("Error : no clients returned by the director."));
462 for (i = 0; i < dt->GetCount(); i++) {
465 configPanel->AddRowChoice(wxT("Client"), str);
466 restorePanel->AddRowChoice(wxT("Client"), str);
476 dt = wxbUtils::WaitForEnd(wxT(".filesets\n"), true, false);
478 configPanel->ClearRowChoices(wxT("Fileset"));
479 restorePanel->ClearRowChoices(wxT("Fileset"));
481 if (dt->GetCount() == 0) {
482 wxbMainFrame::GetInstance()->SetStatusText(wxT("Error : no filesets returned by the director."));
486 for (i = 0; i < dt->GetCount(); i++) {
489 configPanel->AddRowChoice(wxT("Fileset"), str);
490 restorePanel->AddRowChoice(wxT("Fileset"), str);
500 dt = wxbUtils::WaitForEnd(wxT(".storage\n"), true, false);
502 configPanel->ClearRowChoices(wxT("Storage"));
503 restorePanel->ClearRowChoices(wxT("Storage"));
505 if (dt->GetCount() == 0) {
506 wxbMainFrame::GetInstance()->SetStatusText(wxT("Error : no storage returned by the director."));
510 for (i = 0; i < dt->GetCount(); i++) {
513 configPanel->AddRowChoice(wxT("Storage"), str);
514 restorePanel->AddRowChoice(wxT("Storage"), str);
524 dt = wxbUtils::WaitForEnd(wxT(".jobs\n"), true, false);
526 configPanel->ClearRowChoices(wxT("Job Name"));
528 if (dt->GetCount() == 0) {
529 wxbMainFrame::GetInstance()->SetStatusText(wxT("Error : no jobs returned by the director."));
533 for (i = 0; i < dt->GetCount(); i++) {
536 configPanel->AddRowChoice(wxT("Job Name"), str);
539 configPanel->SetRowString(wxT("Job Name"), wxT("RestoreFiles"));
548 dt = wxbUtils::WaitForEnd(wxT(".pools\n"), true, false);
550 configPanel->ClearRowChoices(wxT("Pool"));
552 if (dt->GetCount() == 0) {
553 wxbMainFrame::GetInstance()->SetStatusText(wxT("Error : no jobs returned by the director."));
557 for (i = 0; i < dt->GetCount(); i++) {
560 configPanel->AddRowChoice(wxT("Pool"), str);
574 wxbMainFrame::GetInstance()->SetStatusText(wxT("Please configure your restore parameters."));
576 else if (status == entered) {
577 /* if (clientChoice->GetStringSelection().Length() < 1) {
578 wxbMainFrame::GetInstance()->SetStatusText("Please select a client.");
581 if (jobChoice->GetStringSelection().Length() < 1) {
582 wxbMainFrame::GetInstance()->SetStatusText("Please select a restore date.");
585 wxbMainFrame::GetInstance()->SetStatusText(wxT("Building restore tree..."));
589 wxbTableParser* tableparser = new wxbTableParser();
590 wxbDataTokenizer* dt = new wxbDataTokenizer(false);
592 wxbMainFrame::GetInstance()->Send(wxString(wxT("restore")) <<
593 wxT(" client=\"") << configPanel->GetRowString(wxT("Client")) <<
594 wxT("\" fileset=\"") << configPanel->GetRowString(wxT("Fileset")) <<
595 wxT("\" pool=\"") << configPanel->GetRowString(wxT("Pool")) <<
596 wxT("\" storage=\"") << configPanel->GetRowString(wxT("Storage")) <<
597 wxT("\" before=\"") << configPanel->GetRowString(wxT("Before")) <<
599 //wxbUtils::WaitForPrompt("6\n");
601 /*wxbPromptParser *pp = wxbUtils::WaitForPrompt(wxString() << configPanel->GetRowString(wxT("Before")) << "\n", true);
602 int client = pp->getChoices()->Index(configPanel->GetRowString(wxT("Client")));
603 if (client == wxNOT_FOUND) {
604 wxbMainFrame::GetInstance()->SetStatusText("Failed to find the selected client.");
609 //wxbMainFrame::GetInstance()->Send(wxString() << configPanel->GetRowString(wxT("Before")) << "\n");
611 while (!tableparser->hasFinished() && !dt->hasFinished()) {
612 wxTheApp->Yield(true);
613 wxbUtils::MilliSleep(100);
618 if (dt->hasFinished() && !tableparser->hasFinished()) {
620 if (dt->GetCount() > 1) {
621 str = (*dt)[dt->GetCount()-2];
624 wxbMainFrame::GetInstance()->SetStatusText(wxString(wxT("Error while starting restore: ")) << str);
634 for (i = 0; i < tableparser->GetCount(); i++) {
635 str = (*tableparser)[i][2];
636 str.Replace(wxT(","), wxT(""));
637 if (str.ToLong(&l)) {
643 gauge->SetRange(tot);
645 /*wxbMainFrame::GetInstance()->Print(
646 wxString("[") << tot << "]", CS_DEBUG);*/
648 wxDateTime base = wxDateTime::Now();
652 unsigned int lastindex = 0;
659 newdate = wxDateTime::Now();
660 if (newdate.Subtract(base).GetMilliseconds() > 10 ) {
662 for (; lastindex < dt->GetCount(); lastindex++) {
663 if (((i1 = (*dt)[lastindex].Find(wxT("Building directory tree for JobId "))) >= 0) &&
664 ((i2 = (*dt)[lastindex].Find(wxT(" ..."))) > 0)) {
665 str = (*dt)[lastindex].Mid(i1+34, i2-(i1+34));
666 for (i = 0; i < tableparser->GetCount(); i++) {
667 if (str == (*tableparser)[i][0]) {
668 str = (*tableparser)[i][2];
669 str.Replace(wxT(","), wxT(""));
670 if (str.ToLong(&l)) {
673 var = (willdo-done)/50;
674 gauge->SetValue(done);
675 wxTheApp->Yield(true);
681 else if ((*dt)[lastindex] == wxT("+")) {
682 gauge->SetValue(gauge->GetValue()+var);
683 wxTheApp->Yield(true);
688 if (dt->hasFinished()) {
692 wxTheApp->Yield(true);
693 wxbUtils::MilliSleep(1);
696 gauge->SetValue(tot);
697 wxTheApp->Yield(true);
708 wxbUtils::WaitForEnd(wxT("unmark *\n"));
709 wxTreeItemId root = tree->AddRoot(configPanel->GetRowString(wxT("Client")), -1, -1, new wxbTreeItemData(wxT("/"), configPanel->GetRowString(wxT("Client")), 0));
710 currentTreeItem = root;
712 tree->SelectItem(root);
714 wxbMainFrame::GetInstance()->SetStatusText(wxT("Right click on a file or on a directory, or double-click on its mark to add it to the restore list."));
717 else if (status == choosing) {
721 wxbDataTokenizer* dt;
725 dt = new wxbDataTokenizer(true);
726 wxbUtils::WaitForPrompt(wxT("done\n"));
728 SetStatus(configuring);
730 for (i = 0; i < dt->GetCount(); i++) {
731 if ((j = (*dt)[i].Find(wxT(" files selected to be restored."))) > -1) {
732 (*dt)[i].Mid(0, j).ToLong(&totfilemessages);
736 if ((j = (*dt)[i].Find(wxT(" file selected to be restored."))) > -1) {
737 (*dt)[i].Mid(0, j).ToLong(&totfilemessages);
742 wxbMainFrame::GetInstance()->SetStatusText(
743 wxString(wxT("Please configure your restore (") )
744 << totfilemessages << wxT(" files selected to be restored)..."));
746 UpdateSecondConfig(dt);
751 restorePanel->EnableApply(false);
753 if (totfilemessages == 0) {
754 wxbMainFrame::GetInstance()->Print(wxT("Restore failed : no file selected.\n"), CS_DEBUG);
755 wxbMainFrame::GetInstance()->SetStatusText(wxT("Restore failed : no file selected."));
760 else if (status == configuring) {
761 cancel->Enable(false);
765 wxbMainFrame::GetInstance()->SetStatusText(wxT("Restoring, please wait..."));
767 wxbDataTokenizer* dt;
769 SetStatus(restoring);
770 dt = wxbUtils::WaitForEnd(wxT("yes\n"), true);
773 gauge->SetRange(totfilemessages);
777 for (i = 0; i < dt->GetCount(); i++) {
778 if ((j = (*dt)[i].Find(wxT("Job started. JobId="))) > -1) {
779 jobid = (*dt)[i].Mid(j+19);
780 wxbMainFrame::GetInstance()->SetStatusText(wxT("Restore started, jobid=") + jobid);
784 if ((j = (*dt)[i].Find(wxT("Job failed."))) > -1) {
785 wxbMainFrame::GetInstance()->Print(wxT("Restore failed, please look at messages.\n"), CS_DEBUG);
786 wxbMainFrame::GetInstance()->SetStatusText(wxT("Restore failed, please look at messages in console."));
791 if (jobid == wxT("")) {
792 wxbMainFrame::GetInstance()->Print(wxT("Failed to retrieve jobid.\n"), CS_DEBUG);
793 wxbMainFrame::GetInstance()->SetStatusText(wxT("Failed to retrieve jobid.\n"));
797 wxDateTime currenttime;
799 dt = wxbUtils::WaitForEnd(wxT("time\n"), true);
800 wxStringTokenizer ttkz((*dt)[0], wxT(" "), wxTOKEN_STRTOK);
801 if ((currenttime.ParseDate(ttkz.GetNextToken()) == NULL) || // Date
802 (currenttime.ParseTime(ttkz.GetNextToken()) == NULL)) { // Time
803 currenttime.SetYear(1990); // If parsing fails, set currenttime to a dummy date
806 currenttime -= wxTimeSpan::Seconds(30); //Adding a 30" tolerance
810 wxDateTime scheduledtime;
811 wxStringTokenizer stkz(restorePanel->GetRowString(wxT("When")), wxT(" "), wxTOKEN_STRTOK);
813 if ((scheduledtime.ParseDate(stkz.GetNextToken()) == NULL) || // Date
814 (scheduledtime.ParseTime(stkz.GetNextToken()) == NULL)) { // Time
815 scheduledtime.SetYear(2090); // If parsing fails, set scheduledtime to a dummy date
818 if (scheduledtime.Subtract(currenttime).IsLongerThan(wxTimeSpan::Seconds(150))) {
819 wxbMainFrame::GetInstance()->Print(wxT("Restore is scheduled in more than two minutes, wx-console will not wait for its completion.\n"), CS_DEBUG);
820 wxbMainFrame::GetInstance()->SetStatusText(wxT("Restore is scheduled in more than two minutes, wx-console will not wait for its completion."));
825 wxString cmd = wxString(wxT("list jobid=")) + jobid;
827 wxbTableParser* tableparser;
829 long filemessages = 0;
832 bool waitforever = false;
839 tableparser = wxbUtils::CreateAndWaitForParser(cmd);
841 status = (*tableparser)[0][7].GetChar(0);
844 wxbMainFrame::GetInstance()->SetStatusText(wxT("Restore job created, but not yet running."));
848 wxbMainFrame::GetInstance()->SetStatusText(
849 wxString(wxT("Restore job running, please wait (")) << filemessages <<
850 wxT(" of ") << totfilemessages << wxT(" files restored)..."));
854 wxbMainFrame::GetInstance()->SetStatusText(wxT("Restore job terminated successfully."));
855 wxbMainFrame::GetInstance()->Print(wxT("Restore job terminated successfully.\n"), CS_DEBUG);
859 case JS_ErrorTerminated:
860 wxbMainFrame::GetInstance()->SetStatusText(wxT("Restore job terminated in error, see messages in console."));
861 wxbMainFrame::GetInstance()->Print(wxT("Restore job terminated in error, see messages.\n"), CS_DEBUG);
866 wxbMainFrame::GetInstance()->SetStatusText(wxT("Restore job reported a non-fatal error."));
870 wxbMainFrame::GetInstance()->SetStatusText(wxT("Restore job reported a fatal error."));
875 wxbMainFrame::GetInstance()->SetStatusText(wxT("Restore job cancelled by user."));
876 wxbMainFrame::GetInstance()->Print(wxT("Restore job cancelled by user.\n"), CS_DEBUG);
881 wxbMainFrame::GetInstance()->SetStatusText(wxT("Restore job is waiting on File daemon."));
885 wxbMainFrame::GetInstance()->SetStatusText(wxT("Restore job is waiting for new media."));
888 case JS_WaitStoreRes:
889 wxbMainFrame::GetInstance()->SetStatusText(wxT("Restore job is waiting for storage resource."));
893 wxbMainFrame::GetInstance()->SetStatusText(wxT("Restore job is waiting for job resource."));
896 case JS_WaitClientRes:
897 wxbMainFrame::GetInstance()->SetStatusText(wxT("Restore job is waiting for Client resource."));
901 wxbMainFrame::GetInstance()->SetStatusText(wxT("Restore job is waiting for maximum jobs."));
904 case JS_WaitStartTime:
905 wxbMainFrame::GetInstance()->SetStatusText(wxT("Restore job is waiting for start time."));
908 case JS_WaitPriority:
909 wxbMainFrame::GetInstance()->SetStatusText(wxT("Restore job is waiting for higher priority jobs to finish."));
915 dt = wxbUtils::WaitForEnd(wxT(".messages\n"), true);
917 for (unsigned int i = 0; i < dt->GetCount(); i++) {
918 wxStringTokenizer tkz((*dt)[i], wxT(" "), wxTOKEN_STRTOK);
922 // Date Time name: perm ? user grp size date time
923 //04-Apr-2004 17:19 Tom-fd: -rwx------ 1 nicolas None 514967 2004-03-20 20:03:42 filename
925 if (datetime.ParseDate(tkz.GetNextToken()) != NULL) { // Date
926 if (datetime.ParseTime(tkz.GetNextToken()) != NULL) { // Time
927 if (tkz.GetNextToken().Last() == ':') { // name:
928 tkz.GetNextToken(); // perm
929 tkz.GetNextToken(); // ?
930 tkz.GetNextToken(); // user
931 tkz.GetNextToken(); // grp
932 tkz.GetNextToken(); // size
933 if (datetime.ParseDate(tkz.GetNextToken()) != NULL) { //date
934 if (datetime.ParseTime(tkz.GetNextToken()) != NULL) { //time
936 //wxbMainFrame::GetInstance()->Print(wxString("(") << filemessages << ")", CS_DEBUG);
937 gauge->SetValue(filemessages);
948 while (sw2.Time() < 10000) {
949 wxTheApp->Yield(true);
950 wxbUtils::MilliSleep(100);
957 if ((!waitforever) && (sw.Time() > 60000)) {
958 wxbMainFrame::GetInstance()->Print(wxT("The restore job has not been started within one minute, wx-console will not wait for its completion anymore.\n"), CS_DEBUG);
959 wxbMainFrame::GetInstance()->SetStatusText(wxT("The restore job has not been started within one minute, wx-console will not wait for its completion anymore."));
964 wxbUtils::WaitForEnd(wxT(".messages\n"));
966 gauge->SetValue(totfilemessages);
968 if (status == JS_Terminated) {
969 wxbMainFrame::GetInstance()->Print(wxT("Restore done successfully.\n"), CS_DEBUG);
970 wxbMainFrame::GetInstance()->SetStatusText(wxT("Restore done successfully."));
976 /* The cancel button has been clicked */
977 void wxbRestorePanel::CmdCancel() {
980 if (status == restoring) {
981 if (jobid != wxT("")) {
982 wxbMainFrame::GetInstance()->Send(wxString(wxT("cancel job=")) << jobid << wxT("\n"));
984 cancel->Enable(true);
989 while ((IsWorking()) && (cancelled != 2)) {
990 wxTheApp->Yield(true);
991 wxbUtils::MilliSleep(100);
992 if (sw.Time() > 30000) { /* 30 seconds timeout */
993 if (status == choosing) {
994 wxbMainFrame::GetInstance()->Send(wxT("quit\n"));
996 else if (status == configuring) {
997 wxbMainFrame::GetInstance()->Send(wxT("no\n"));
999 else if (status == restoring) {
1002 SetStatus(finished);
1003 wxbUtils::MilliSleep(1000);
1010 wxbMainFrame::GetInstance()->Send(wxT("quit\n"));
1013 wxbMainFrame::GetInstance()->Send(wxT("no\n"));
1018 wxbUtils::MilliSleep(1000);
1019 SetStatus(finished);
1022 /* Apply configuration changes */
1024 /* 1: Level (not appropriate)
1029 * 6: When (yes : "Please enter desired start time as YYYY-MM-DD HH:MM:SS (return for now):")
1030 * 7: Priority (yes : "Enter new Priority: (positive integer)")
1032 * 9: Where (yes : "Please enter path prefix for restore (/ for none):")
1033 * 10: Replace (yes : "Replace:\n 1: always\n 2: ifnewer\n 3: ifolder\n 4: never\n
1034 * Select replace option (1-4):")
1038 void wxbRestorePanel::CmdConfigApply() {
1039 if (cfgUpdated == 0) return;
1041 wxbMainFrame::GetInstance()->SetStatusText(wxT("Applying restore configuration changes..."));
1043 EnableConfig(false);
1045 wxbDataTokenizer* dt = NULL;
1047 bool failed = false;
1049 while (cfgUpdated > 0) {
1054 wxString def; //String to send if can't use our data
1055 if ((cfgUpdated >> ConfigWhere) & 1) {
1056 wxbUtils::WaitForPrompt(wxT("mod\n")); /* TODO: check results */
1057 wxbUtils::WaitForPrompt(wxT("9\n"));
1058 dt = new wxbDataTokenizer(true);
1059 wxbUtils::WaitForPrompt(restorePanel->GetRowString(wxT("Where")) + wxT("\n"));
1061 cfgUpdated = cfgUpdated & (~(1 << ConfigWhere));
1063 else if ((cfgUpdated >> ConfigReplace) & 1) {
1064 wxbUtils::WaitForPrompt(wxT("mod\n")); /* TODO: check results */
1065 wxbUtils::WaitForPrompt(wxT("10\n"));
1066 dt = new wxbDataTokenizer(true);
1067 wxbUtils::WaitForPrompt(wxString() << (restorePanel->GetRowSelection(wxT("Replace"))+1) << wxT("\n"));
1069 cfgUpdated = cfgUpdated & (~(1 << ConfigReplace));
1071 else if ((cfgUpdated >> ConfigWhen) & 1) {
1072 wxbUtils::WaitForPrompt(wxT("mod\n")); /* TODO: check results */
1073 wxbUtils::WaitForPrompt(wxT("6\n"));
1074 dt = new wxbDataTokenizer(true);
1075 wxbUtils::WaitForPrompt(restorePanel->GetRowString(wxT("When")) + wxT("\n"));
1077 cfgUpdated = cfgUpdated & (~(1 << ConfigWhen));
1079 else if ((cfgUpdated >> ConfigPriority) & 1) {
1080 wxbUtils::WaitForPrompt(wxT("mod\n")); /* TODO: check results */
1081 wxbUtils::WaitForPrompt(wxT("7\n"));
1082 dt = new wxbDataTokenizer(true);
1083 wxbUtils::WaitForPrompt(restorePanel->GetRowString(wxT("Priority")) + wxT("\n"));
1085 cfgUpdated = cfgUpdated & (~(1 << ConfigPriority));
1087 else if ((cfgUpdated >> ConfigClient) & 1) {
1088 wxbUtils::WaitForPrompt(wxT("mod\n")); /* TODO: check results */
1089 wxbPromptParser *pp = wxbUtils::WaitForPrompt(wxT("5\n"), true);
1090 int client = pp->getChoices()->Index(restorePanel->GetRowString(wxT("Client")));
1091 if (client == wxNOT_FOUND) {
1092 wxbMainFrame::GetInstance()->SetStatusText(wxT("Failed to find the selected client."));
1097 dt = new wxbDataTokenizer(true);
1098 wxbUtils::WaitForPrompt(wxString() << client << wxT("\n"));
1100 cfgUpdated = cfgUpdated & (~(1 << ConfigClient));
1102 else if ((cfgUpdated >> ConfigFileset) & 1) {
1103 wxbUtils::WaitForPrompt(wxT("mod\n")); /* TODO: check results */
1104 wxbPromptParser *pp = wxbUtils::WaitForPrompt(wxT("4\n"), true);
1105 int fileset = pp->getChoices()->Index(restorePanel->GetRowString(wxT("Fileset")));
1106 if (fileset == wxNOT_FOUND) {
1107 wxbMainFrame::GetInstance()->SetStatusText(wxT("Failed to find the selected fileset."));
1112 dt = new wxbDataTokenizer(true);
1113 wxbUtils::WaitForPrompt(wxString() << fileset << wxT("\n"));
1115 cfgUpdated = cfgUpdated & (~(1 << ConfigFileset));
1117 else if ((cfgUpdated >> ConfigStorage) & 1) {
1118 wxbUtils::WaitForPrompt(wxT("mod\n")); /* TODO: check results */
1119 wxbPromptParser *pp = wxbUtils::WaitForPrompt(wxT("2\n"), true);
1120 int fileset = pp->getChoices()->Index(restorePanel->GetRowString(wxT("Storage")));
1121 if (fileset == wxNOT_FOUND) {
1122 wxbMainFrame::GetInstance()->SetStatusText(wxT("Failed to find the selected storage."));
1127 dt = new wxbDataTokenizer(true);
1128 wxbUtils::WaitForPrompt(wxString() << fileset << wxT("\n"));
1130 cfgUpdated = cfgUpdated & (~(1 << ConfigFileset));
1138 for (i = 0; i < dt->GetCount(); i++) {
1139 if ((*dt)[i].Find(wxT("Run Restore job")) == 0) {
1144 if (i == dt->GetCount()) {
1146 dt = wxbUtils::WaitForEnd(def + wxT("\n"), true);
1150 UpdateSecondConfig(dt); /* TODO: Check result */
1155 wxbMainFrame::GetInstance()->SetStatusText(wxT("Restore configuration changes were applied."));
1161 /* Cancel restore */
1162 void wxbRestorePanel::CmdConfigCancel() {
1163 wxbUtils::WaitForEnd(wxT("no\n"));
1164 wxbMainFrame::GetInstance()->Print(wxT("Restore cancelled.\n"), CS_DEBUG);
1165 wxbMainFrame::GetInstance()->SetStatusText(wxT("Restore cancelled."));
1166 SetStatus(finished);
1169 /* List jobs for a specified client */
1170 void wxbRestorePanel::CmdListJobs() {
1171 if (status == entered) {
1172 configPanel->ClearRowChoices(wxT("Before"));
1173 /*wxbUtils::WaitForPrompt("query\n");
1174 wxbUtils::WaitForPrompt("6\n");*/
1175 wxbTableParser* tableparser = new wxbTableParser(false);
1176 wxbDataTokenizer* dt = wxbUtils::WaitForEnd(
1177 wxString(wxT(".backups client=")) + configPanel->GetRowString(wxT("Client")) + wxT("\n"), true);
1179 while (!tableparser->hasFinished()) {
1180 wxTheApp->Yield(true);
1181 wxbUtils::MilliSleep(100);
1184 if (!tableparser->GetCount() == 0) {
1185 for (unsigned int i = 0; i < dt->Count(); i++) {
1186 if ((*dt)[i].Find(wxT("No results to list.")) == 0) {
1187 configPanel->AddRowChoice(wxT("Before"), wxT("No backup found for this client."));
1188 configPanel->SetRowSelection(wxT("Before"), 0);
1189 configPanel->EnableApply(true); // Enabling the not existing apply button disables the ok button.
1194 else if (((*dt)[i].Find(wxT("ERROR")) > -1) || ((*dt)[i].Find(wxT("Query failed")) > -1)) {
1195 configPanel->AddRowChoice(wxT("Before"), wxT("Cannot get previous backups list, see console."));
1196 configPanel->SetRowSelection(wxT("Before"), 0);
1197 configPanel->EnableApply(true); // Enabling the not existing apply button disables the ok button.
1207 for (int i = tableparser->GetCount()-1; i > -1; i--) {
1208 wxString str = (*tableparser)[i][3];
1209 wxDateTime datetime;
1211 if ( ( (chr = datetime.ParseDate(str.GetData()) ) != NULL ) && ( datetime.ParseTime(++chr) != NULL ) ) {
1212 datetime += wxTimeSpan::Seconds(1);
1213 configPanel->AddRowChoice(wxT("Before"), datetime.Format(wxT("%Y-%m-%d %H:%M:%S")));
1219 configPanel->SetRowSelection(wxT("Before"), 0);
1220 configPanel->EnableApply(false); // Disabling the not existing apply button enables the ok button.
1224 /* List files and directories for a specified tree item */
1225 void wxbRestorePanel::CmdList(wxTreeItemId item) {
1226 if (status == choosing) {
1227 list->DeleteAllItems();
1232 UpdateTreeItem(item, true, false);
1234 if (list->GetItemCount() >= 1) {
1235 int firstwidth = list->GetSize().GetWidth();
1236 for (int i = 2; i < 7; i++) {
1237 list->SetColumnWidth(i, wxLIST_AUTOSIZE);
1238 firstwidth -= list->GetColumnWidth(i);
1241 list->SetColumnWidth(0, 18);
1243 list->SetColumnWidth(1, wxLIST_AUTOSIZE);
1244 if (list->GetColumnWidth(1) < firstwidth) {
1245 list->SetColumnWidth(1, firstwidth-25);
1251 /* Mark a treeitem (directory) or a listitem (file or directory) */
1252 void wxbRestorePanel::CmdMark(wxTreeItemId treeitem, long* listitems, int listsize, int state) {
1253 if (status == choosing) {
1254 wxbTreeItemData** itemdata;
1255 int itemdatasize = 0;
1256 if (listsize == 0) {
1257 itemdata = new wxbTreeItemData*[1];
1261 itemdata = new wxbTreeItemData*[listsize];
1262 itemdatasize = listsize;
1265 if (listitems != NULL) {
1266 for (int i = 0; i < listsize; i++) {
1267 itemdata[i] = (wxbTreeItemData*)list->GetItemData(listitems[i]);
1270 else if (treeitem.IsOk()) {
1271 itemdata[0] = (wxbTreeItemData*)tree->GetItemData(treeitem);
1278 if (itemdata[0] == NULL) { //Should never happen
1283 wxString dir = itemdata[0]->GetPath();
1286 if (dir != wxT("/")) {
1287 if (dir.GetChar(dir.Length()-1) == '/') {
1291 int i = dir.Find('/', TRUE);
1296 else { /* first dir below root */
1297 file = dir.Mid(i+1);
1298 dir = dir.Mid(0, i+1);
1307 bool marked = false;
1308 bool unmarked = false;
1310 for (int i = 0; i < itemdatasize; i++) {
1311 switch(itemdata[i]->GetMarked()) {
1325 if (marked && unmarked)
1341 wxbUtils::WaitForEnd(wxString(wxT("cd \"")) << dir << wxT("\"\n"));
1342 wxbUtils::WaitForEnd(wxString((state==1) ? wxT("mark") : wxT("unmark")) << wxT(" \"") << file << wxT("\"\n"));
1344 /* TODO: Check commands results */
1346 /*if ((dir == "/") && (file == "*")) {
1347 itemdata->SetMarked((itemdata->GetMarked() == 1) ? 0 : 1);
1350 if (listitems == NULL) { /* tree item state changed */
1351 SetTreeItemState(treeitem, state);
1352 /*treeitem = tree->GetSelection();
1353 UpdateTree(treeitem, true);
1354 treeitem = tree->GetItemParent(treeitem);*/
1357 for (int i = 0; i < listsize; i++) {
1358 SetListItemState(listitems[i], state);
1360 /*UpdateTree(treeitem, (tree->GetSelection() == treeitem));
1361 treeitem = tree->GetItemParent(treeitem);*/
1364 /*while (treeitem.IsOk()) {
1365 WaitForList(treeitem, false);
1366 treeitem = tree->GetItemParent(treeitem);
1373 /*----------------------------------------------------------------------------
1375 ----------------------------------------------------------------------------*/
1377 /* Run a dir command, and waits until result is fully received. */
1378 void wxbRestorePanel::UpdateTreeItem(wxTreeItemId item, bool updatelist, bool recurse) {
1379 // this->updatelist = updatelist;
1380 wxbDataTokenizer* dt;
1382 dt = wxbUtils::WaitForEnd(wxString(wxT("cd \"")) <<
1383 static_cast<wxbTreeItemData*>(tree->GetItemData(item))
1384 ->GetPath() << wxT("\"\n"), false);
1386 /* TODO: check command result */
1393 list->DeleteAllItems();
1394 dt = wxbUtils::WaitForEnd(wxT("dir\n"), true);
1398 for (unsigned int i = 0; i < dt->GetCount(); i++) {
1401 if (str.Find(wxT("cwd is:")) == 0) { // Sometimes cd command result "infiltrate" into listings.
1407 wxString* file = ParseList(str);
1412 wxTreeItemId treeid;
1414 if (file[8].GetChar(file[8].Length()-1) == '/') {
1417 #if wxCHECK_VERSION(2, 6, 0)
1418 wxTreeItemIdValue cookie;
1423 treeid = tree->GetFirstChild(item, cookie);
1425 bool updated = false;
1427 while (treeid.IsOk()) {
1428 itemStr = ((wxbTreeItemData*)tree->GetItemData(treeid))->GetName();
1429 if (file[8] == itemStr) {
1430 int stat = wxbTreeItemData::GetMarkedStatus(file[6]);
1431 if (static_cast<wxbTreeItemData*>(tree->GetItemData(treeid))->GetMarked() != stat) {
1432 tree->SetItemImage(treeid, stat, wxTreeItemIcon_Normal);
1433 tree->SetItemImage(treeid, stat, wxTreeItemIcon_Selected);
1434 static_cast<wxbTreeItemData*>(tree->GetItemData(treeid))->SetMarked(file[6]);
1436 if ((recurse) && (tree->IsExpanded(treeid))) {
1437 UpdateTreeItem(treeid, false, true);
1442 treeid = tree->GetNextChild(item, cookie);
1446 int img = wxbTreeItemData::GetMarkedStatus(file[6]);
1447 treeid = tree->AppendItem(item, wxbUtils::ConvertToPrintable(file[8]), img, img, new wxbTreeItemData(file[7], file[8], file[6]));
1452 long ind = list->InsertItem(list->GetItemCount(), wxbTreeItemData::GetMarkedStatus(file[6]));
1453 wxbTreeItemData* data = new wxbTreeItemData(file[7], file[8], file[6], ind);
1454 data->SetId(treeid);
1455 list->SetItemData(ind, (long)data);
1456 list->SetItem(ind, 1, wxbUtils::ConvertToPrintable(file[8])); // filename
1457 list->SetItem(ind, 2, file[4]); //Size
1458 list->SetItem(ind, 3, file[5]); //date
1459 list->SetItem(ind, 4, file[0]); //perm
1460 list->SetItem(ind, 5, file[2]); //user
1461 list->SetItem(ind, 6, file[3]); //grp
1473 /* Parse dir command results. */
1474 wxString* wxbRestorePanel::ParseList(wxString line) {
1475 /* See ls_output in dird/ua_tree.c */
1477 //drwxrwxrwx 111 root root 0 2004-04-03 14:35:21 f:/tocd/NVSU 1.00.00/
1478 //+ 10 + +i+ + 8 + + 8 ++ 8 + + 19 + *+ ->
1479 //0 12 i+15 i+24 i+32 i+42 i+62
1483 if (line.Length() < 63)
1486 wxString* ret = new wxString[9];
1488 ret[0] = line.Mid(0, 10).Trim();
1490 /* Column 1 has a variable width */
1491 i = line.find(' ', 14) - 14;
1492 ret[1] = line.Mid(12, 2+i).Trim();
1494 ret[2] = line.Mid(15+i, 8).Trim();
1495 ret[3] = line.Mid(24+i, 8).Trim();
1496 ret[4] = line.Mid(32+i, 8).Trim();
1497 ret[5] = line.Mid(42+i, 19).Trim();
1498 ret[6] = line.Mid(62+i, 1);
1499 ret[7] = line.Mid(63+i).Trim();
1501 if (ret[6] == wxT(" ")) ret[6] = wxT("");
1503 if (ret[7].GetChar(ret[7].Length()-1) == '/') {
1505 ret[8].RemoveLast();
1506 ret[8] = ret[7].Mid(ret[8].Find('/', true)+1);
1509 ret[8] = ret[7].Mid(ret[7].Find('/', true)+1);
1515 /* Sets a list item state, and update its parents and children if it is a directory */
1516 void wxbRestorePanel::SetListItemState(long listitem, int newstate) {
1517 wxbTreeItemData* itemdata = (wxbTreeItemData*)list->GetItemData(listitem);
1519 wxTreeItemId treeitem;
1521 itemdata->SetMarked(newstate);
1522 list->SetItemImage(listitem, newstate, 0); /* TODO: Find what these ints are for */
1523 list->SetItemImage(listitem, newstate, 1);
1525 if ((treeitem = itemdata->GetId()).IsOk()) {
1526 SetTreeItemState(treeitem, newstate);
1529 UpdateTreeItemState(tree->GetSelection());
1533 /* Sets a tree item state, and update its children, parents and list (if necessary) */
1534 void wxbRestorePanel::SetTreeItemState(wxTreeItemId item, int newstate) {
1535 #if wxCHECK_VERSION(2, 6, 0)
1536 wxTreeItemIdValue cookie;
1540 wxTreeItemId currentChild = tree->GetFirstChild(item, cookie);
1542 wxbTreeItemData* itemdata;
1544 while (currentChild.IsOk()) {
1545 itemdata = (wxbTreeItemData*)tree->GetItemData(currentChild);
1546 int state = itemdata->GetMarked();
1548 if (state != newstate) {
1549 itemdata->SetMarked(newstate);
1550 tree->SetItemImage(currentChild, newstate, wxTreeItemIcon_Normal);
1551 tree->SetItemImage(currentChild, newstate, wxTreeItemIcon_Selected);
1554 currentChild = tree->GetNextChild(item, cookie);
1557 itemdata = (wxbTreeItemData*)tree->GetItemData(item);
1558 itemdata->SetMarked(newstate);
1559 tree->SetItemImage(item, newstate, wxTreeItemIcon_Normal);
1560 tree->SetItemImage(item, newstate, wxTreeItemIcon_Selected);
1563 if (tree->GetSelection() == item) {
1564 for (long i = 0; i < list->GetItemCount(); i++) {
1565 list->SetItemImage(i, newstate, 0); /* TODO: Find what these ints are for */
1566 list->SetItemImage(i, newstate, 1);
1570 UpdateTreeItemState(tree->GetItemParent(item));
1573 /* Update a tree item state, and its parents' state */
1574 void wxbRestorePanel::UpdateTreeItemState(wxTreeItemId item) {
1581 #if wxCHECK_VERSION(2, 6, 0)
1582 wxTreeItemIdValue cookie;
1586 wxTreeItemId currentChild = tree->GetFirstChild(item, cookie);
1588 bool onechildmarked = false;
1589 bool onechildunmarked = false;
1591 while (currentChild.IsOk()) {
1592 state = ((wxbTreeItemData*)tree->GetItemData(currentChild))->GetMarked();
1595 onechildunmarked = true;
1598 onechildmarked = true;
1601 onechildmarked = true;
1602 onechildunmarked = true;
1606 if (onechildmarked && onechildunmarked) {
1610 currentChild = tree->GetNextChild(item, cookie);
1613 if (tree->GetSelection() == item) {
1614 for (long i = 0; i < list->GetItemCount(); i++) {
1615 state = ((wxbTreeItemData*)list->GetItemData(i))->GetMarked();
1619 onechildunmarked = true;
1622 onechildmarked = true;
1625 onechildmarked = true;
1626 onechildunmarked = true;
1630 if (onechildmarked && onechildunmarked) {
1638 if (onechildmarked && onechildunmarked) {
1641 else if (onechildmarked) {
1644 else if (onechildunmarked) {
1647 else { // no child, don't change anything
1648 UpdateTreeItemState(tree->GetItemParent(item));
1652 wxbTreeItemData* itemdata = (wxbTreeItemData*)tree->GetItemData(item);
1654 itemdata->SetMarked(state);
1655 tree->SetItemImage(item, state, wxTreeItemIcon_Normal);
1656 tree->SetItemImage(item, state, wxTreeItemIcon_Selected);
1658 UpdateTreeItemState(tree->GetItemParent(item));
1661 /* Refresh the whole tree. */
1662 void wxbRestorePanel::RefreshTree() {
1663 /* Save current selection */
1664 wxArrayString current;
1666 wxTreeItemId item = currentTreeItem;
1668 while ((item.IsOk()) && (item != tree->GetRootItem())) {
1669 current.Add(tree->GetItemText(item));
1670 item = tree->GetItemParent(item);
1673 /* Update the tree */
1674 UpdateTreeItem(tree->GetRootItem(), false, true);
1676 /* Reselect the former selected item */
1677 item = tree->GetRootItem();
1679 if (current.Count() == 0) {
1680 tree->SelectItem(item);
1686 for (int i = current.Count()-1; i >= 0; i--) {
1687 #if wxCHECK_VERSION(2, 6, 0)
1688 wxTreeItemIdValue cookie;
1692 wxTreeItemId currentChild = tree->GetFirstChild(item, cookie);
1696 while (currentChild.IsOk()) {
1697 if (((wxbTreeItemData*)tree->GetItemData(currentChild))->GetName() == current[i]) {
1698 item = currentChild;
1703 currentChild = tree->GetNextChild(item, cookie);
1709 UpdateTreeItem(item, true, false); /* Update the list */
1711 tree->SelectItem(item);
1714 void wxbRestorePanel::RefreshList() {
1715 if (currentTreeItem.IsOk()) {
1716 UpdateTreeItem(currentTreeItem, true, false); /* Update the list */
1720 /* Update first config, adapting settings to the job name selected */
1721 void wxbRestorePanel::UpdateFirstConfig() {
1722 configPanel->Enable(false);
1723 wxbDataTokenizer* dt = wxbUtils::WaitForEnd(wxString(wxT(".defaults job=")) + configPanel->GetRowString(wxT("Job Name")) + wxT("\n"), true, false);
1729 * where=/tmp/bacula-restores
1732 * fileset=Full Set */
1738 bool dolistjobs = false;
1740 for (i = 0; i < dt->GetCount(); i++) {
1742 if ((j = str.Find('=')) > -1) {
1743 name = str.Mid(0, j);
1744 if (name == wxT("pool")) {
1745 configPanel->SetRowString(wxT("Pool"), str.Mid(j+1));
1747 else if (name == wxT("client")) {
1749 if ((str != configPanel->GetRowString(wxT("Client"))) || (configPanel->GetRowString(wxT("Before")) == wxT(""))) {
1750 configPanel->SetRowString(wxT("Client"), str);
1754 else if (name == wxT("storage")) {
1755 configPanel->SetRowString(wxT("Storage"), str.Mid(j+1));
1757 else if (name == wxT("fileset")) {
1758 configPanel->SetRowString(wxT("Fileset"), str.Mid(j+1));
1766 //wxTheApp->Yield(false);
1769 configPanel->Enable(true);
1773 * Update second config.
1776 * JobName: RestoreFiles
1777 * Bootstrap: /var/lib/bacula/restore.bsr
1778 * Where: /tmp/bacula-restores
1783 * When: 2004-04-18 01:18:56
1785 * OK to run? (yes/mod/no):
1788 bool wxbRestorePanel::UpdateSecondConfig(wxbDataTokenizer* dt) {
1790 for (i = 0; i < dt->GetCount(); i++) {
1791 if ((*dt)[i].Find(wxT("Run Restore job")) == 0)
1795 if ((i + 10) > dt->GetCount()) {
1801 if ((k = (*dt)[++i].Find(wxT("JobName:"))) != 0) return false;
1802 restorePanel->SetRowString(wxT("Job Name"), (*dt)[i].Mid(10).Trim(false).RemoveLast());
1803 if ((k = (*dt)[++i].Find(wxT("Bootstrap:"))) != 0) return false;
1804 restorePanel->SetRowString(wxT("Bootstrap"), (*dt)[i].Mid(10).Trim(false).RemoveLast());
1805 if ((k = (*dt)[++i].Find(wxT("Where:"))) != 0) return false;
1806 restorePanel->SetRowString(wxT("Where"), (*dt)[i].Mid(10).Trim(false).RemoveLast());
1808 if ((k = (*dt)[++i].Find(wxT("Replace:"))) != 0) return false;
1809 wxString str = (*dt)[i].Mid(10).Trim(false).RemoveLast();
1810 if (str == wxT("always")) restorePanel->SetRowSelection(wxT("Replace"), 0);
1811 else if (str == wxT("ifnewer")) restorePanel->SetRowSelection(wxT("Replace"), 1);
1812 else if (str == wxT("ifolder")) restorePanel->SetRowSelection(wxT("Replace"), 2);
1813 else if (str == wxT("never")) restorePanel->SetRowSelection(wxT("Replace"), 3);
1814 else restorePanel->SetRowSelection(wxT("Replace"), 0);
1816 if ((k = (*dt)[++i].Find(wxT("FileSet:"))) != 0) return false;
1817 restorePanel->SetRowString(wxT("Fileset"), (*dt)[i].Mid(10).Trim(false).RemoveLast());
1818 if ((k = (*dt)[++i].Find(wxT("Client:"))) != 0) return false;
1819 restorePanel->SetRowString(wxT("Client"), (*dt)[i].Mid(10).Trim(false).RemoveLast());
1820 if ((k = (*dt)[++i].Find(wxT("Storage:"))) != 0) return false;
1821 restorePanel->SetRowString(wxT("Storage"), (*dt)[i].Mid(10).Trim(false).RemoveLast());
1822 if ((k = (*dt)[++i].Find(wxT("When:"))) != 0) return false;
1823 restorePanel->SetRowString(wxT("When"), (*dt)[i].Mid(10).Trim(false).RemoveLast());
1824 if ((k = (*dt)[++i].Find(wxT("Priority:"))) != 0) return false;
1825 restorePanel->SetRowString(wxT("Priority"), (*dt)[i].Mid(10).Trim(false).RemoveLast());
1828 restorePanel->Layout();
1833 /*----------------------------------------------------------------------------
1835 ----------------------------------------------------------------------------*/
1837 /* Set current status by enabling/disabling components */
1838 void wxbRestorePanel::SetStatus(status_enum newstatus) {
1839 switch (newstatus) {
1841 centerSizer->Remove(configPanel);
1842 centerSizer->Remove(restorePanel);
1843 centerSizer->Remove(treelistPanel);
1844 treelistPanel->Show(false);
1845 restorePanel->Show(false);
1846 centerSizer->Add(configPanel, 1, wxEXPAND);
1847 configPanel->Show(true);
1848 configPanel->Layout();
1849 centerSizer->Layout();
1851 start->SetLabel(wxT("Enter restore mode"));
1852 start->Enable(false);
1853 configPanel->Enable(false);
1854 tree->Enable(false);
1855 list->Enable(false);
1856 gauge->Enable(false);
1857 cancel->Enable(false);
1862 centerSizer->Remove(configPanel);
1863 centerSizer->Remove(restorePanel);
1864 centerSizer->Remove(treelistPanel);
1865 treelistPanel->Show(false);
1866 restorePanel->Show(false);
1867 centerSizer->Add(configPanel, 1, wxEXPAND);
1868 configPanel->Show(true);
1869 configPanel->Layout();
1870 centerSizer->Layout();
1872 tree->DeleteAllItems();
1873 list->DeleteAllItems();
1874 configPanel->ClearRowChoices(wxT("Client"));
1875 configPanel->ClearRowChoices(wxT("Before"));
1876 wxbMainFrame::GetInstance()->EnablePanels();
1877 newstatus = activable;
1880 start->SetLabel(wxT("Enter restore mode"));
1881 start->Enable(true);
1882 configPanel->Enable(false);
1883 tree->Enable(false);
1884 list->Enable(false);
1885 gauge->Enable(false);
1886 cancel->Enable(false);
1890 wxbMainFrame::GetInstance()->DisablePanels(this);
1892 start->Enable(false);
1893 //start->SetLabel("Choose files to restore");
1894 configPanel->Enable(true);
1895 tree->Enable(false);
1896 list->Enable(false);
1897 cancel->Enable(true);
1904 start->Enable(true);
1905 start->SetLabel(wxT("Restore"));
1906 centerSizer->Remove(configPanel);
1907 configPanel->Show(false);
1908 centerSizer->Add(treelistPanel, 1, wxEXPAND);
1909 treelistPanel->Show(true);
1910 treelistPanel->Layout();
1911 centerSizer->Layout();
1918 start->Enable(false);
1919 configPanel->Enable(false);
1920 tree->Enable(false);
1921 list->Enable(false);
1922 centerSizer->Remove(treelistPanel);
1923 treelistPanel->Show(false);
1924 centerSizer->Add(restorePanel, 1, wxEXPAND);
1925 restorePanel->Show(true);
1926 restorePanel->Layout();
1927 centerSizer->Layout();
1929 restorePanel->EnableApply(false);
1932 start->SetLabel(wxT("Restoring..."));
1933 gauge->Enable(true);
1935 start->Enable(false);
1936 configPanel->Enable(false);
1937 tree->Enable(false);
1938 list->Enable(false);
1945 /*----------------------------------------------------------------------------
1947 ----------------------------------------------------------------------------*/
1949 void wxbRestorePanel::SetWorking(bool working) {
1950 this->working = working;
1952 SetCursor(*wxHOURGLASS_CURSOR);
1953 // SetEvtHandlerEnabled(false); //EVTQUEUE
1955 // else if (!processing) { /* Empty event queue if we aren't already doing this */ //EVTQUEUE
1957 // processing = true; //EVTQUEUE
1958 SetCursor(*wxSTANDARD_CURSOR);
1959 // SetEvtHandlerEnabled(true); //EVTQUEUE
1960 /* wxNode *node = pendingEvents->First(); //EVTQUEUE
1962 wxEvent *event = (wxEvent *)node->Data();
1965 wxEvtHandler::ProcessEvent(*event);
1968 node = pendingEvents->First();
1970 processing = false;*/
1974 bool wxbRestorePanel::IsWorking() {
1975 return this->working;
1978 void wxbRestorePanel::EnableConfig(bool enable) {
1979 restorePanel->Enable(enable);
1982 /*----------------------------------------------------------------------------
1984 ----------------------------------------------------------------------------*/
1989 bool wxbRestorePanel::ProcessEvent(wxEvent& event) {
1990 if (IsWorking() || processing) {
1991 wxEvent *eventCopy = event.Clone();
1993 pendingEvents->Append(eventCopy);
1997 return wxEvtHandler::ProcessEvent(event);
2002 void wxbRestorePanel::OnCancel(wxCommandEvent& event) {
2003 cancel->Enable(false);
2004 SetCursor(*wxHOURGLASS_CURSOR);
2006 SetCursor(*wxSTANDARD_CURSOR);
2009 void wxbRestorePanel::OnStart(wxCommandEvent& event) {
2018 void wxbRestorePanel::OnTreeChanging(wxTreeEvent& event) {
2024 void wxbRestorePanel::OnTreeExpanding(wxTreeEvent& event) {
2030 //CmdList(event.GetItem());
2031 if (tree->GetSelection() != event.GetItem()) {
2032 tree->SelectItem(event.GetItem());
2037 void wxbRestorePanel::OnTreeChanged(wxTreeEvent& event) {
2041 if (currentTreeItem == event.GetItem()) {
2044 treeadd->Enable(false);
2045 treeremove->Enable(false);
2046 treerefresh->Enable(false);
2047 markWhenCommandDone = false;
2049 currentTreeItem = event.GetItem();
2050 CmdList(event.GetItem());
2051 if (markWhenCommandDone) {
2052 CmdMark(event.GetItem(), NULL, 0);
2056 if (event.GetItem().IsOk()) {
2057 int status = ((wxbTreeItemData*)tree->GetItemData(event.GetItem()))->GetMarked();
2058 treeadd->Enable(status != 1);
2059 treeremove->Enable(status != 0);
2061 treerefresh->Enable(true);
2064 void wxbRestorePanel::OnTreeMarked(wxbTreeMarkedEvent& event) {
2066 if (tree->GetSelection() == event.GetItem()) {
2067 markWhenCommandDone = !markWhenCommandDone;
2072 markWhenCommandDone = false;
2073 CmdMark(event.GetItem(), NULL, 0);
2074 if (markWhenCommandDone) {
2075 CmdMark(event.GetItem(), NULL, 0);
2080 if (event.GetItem().IsOk()) {
2081 int status = ((wxbTreeItemData*)tree->GetItemData(event.GetItem()))->GetMarked();
2082 treeadd->Enable(status != 1);
2083 treeremove->Enable(status != 0);
2087 void wxbRestorePanel::OnTreeAdd(wxCommandEvent& event) {
2092 if (currentTreeItem.IsOk()) {
2094 CmdMark(currentTreeItem, NULL, 0, 1);
2097 treeremove->Enable(1);
2102 void wxbRestorePanel::OnTreeRemove(wxCommandEvent& event) {
2107 if (currentTreeItem.IsOk()) {
2109 CmdMark(currentTreeItem, NULL, 0, 0);
2112 treeremove->Enable(0);
2117 void wxbRestorePanel::OnTreeRefresh(wxCommandEvent& event) {
2127 void wxbRestorePanel::OnListMarked(wxbListMarkedEvent& event) {
2132 if (list->GetSelectedItemCount() == 0) {
2138 long* items = new long[list->GetSelectedItemCount()];
2142 long item = list->GetNextItem(-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
2143 while (item != -1) {
2146 item = list->GetNextItem(item, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
2149 CmdMark(wxTreeItemId(), items, num);
2153 wxListEvent listevt;
2155 OnListChanged(listevt);
2162 void wxbRestorePanel::OnListActivated(wxListEvent& event) {
2167 long item = event.GetIndex();
2168 // long item = list->GetNextItem(-1, wxLIST_NEXT_ALL, wxLIST_STATE_FOCUSED);
2170 wxbTreeItemData* itemdata = (wxbTreeItemData*)list->GetItemData(item);
2171 wxString name = itemdata->GetName();
2176 #if wxCHECK_VERSION(2, 6, 0)
2177 wxTreeItemIdValue cookie;
2182 if (name.GetChar(name.Length()-1) == '/') {
2183 wxTreeItemId currentChild = tree->GetFirstChild(currentTreeItem, cookie);
2185 while (currentChild.IsOk()) {
2186 wxString name2 = ((wxbTreeItemData*)tree->GetItemData(currentChild))->GetName();
2187 if (name2 == name) {
2188 //tree->UnselectAll();
2190 tree->Expand(currentTreeItem);
2191 tree->SelectItem(currentChild);
2195 currentChild = tree->GetNextChild(currentTreeItem, cookie);
2202 void wxbRestorePanel::OnListChanged(wxListEvent& event) {
2207 listadd->Enable(false);
2208 listremove->Enable(false);
2210 bool marked = false;
2211 bool unmarked = false;
2213 long item = list->GetNextItem(-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
2214 while (item != -1) {
2215 switch (((wxbTreeItemData*)list->GetItemData(item))->GetMarked()) {
2228 // Should never happen
2230 if (marked && unmarked) break;
2231 item = list->GetNextItem(item, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
2234 listadd->Enable(unmarked);
2235 listremove->Enable(marked);
2238 void wxbRestorePanel::OnListAdd(wxCommandEvent& event) {
2245 long* items = new long[list->GetSelectedItemCount()];
2249 long item = list->GetNextItem(-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
2250 while (item != -1) {
2253 item = list->GetNextItem(item, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
2256 CmdMark(wxTreeItemId(), items, num, 1);
2263 listadd->Enable(false);
2264 listremove->Enable(true);
2267 void wxbRestorePanel::OnListRemove(wxCommandEvent& event) {
2274 long* items = new long[list->GetSelectedItemCount()];
2278 long item = list->GetNextItem(-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
2279 while (item != -1) {
2282 item = list->GetNextItem(item, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
2285 CmdMark(wxTreeItemId(), items, num, 0);
2292 listadd->Enable(true);
2293 listremove->Enable(false);
2296 void wxbRestorePanel::OnListRefresh(wxCommandEvent& event) {
2306 void wxbRestorePanel::OnConfigUpdated(wxCommandEvent& event) {
2307 if (status == entered) {
2308 if (event.GetId() == ConfigJobName) {
2313 UpdateFirstConfig();
2316 else if (event.GetId() == ConfigClient) {
2321 configPanel->Enable(false);
2323 configPanel->Enable(true);
2326 cfgUpdated = cfgUpdated | (1 << event.GetId());
2328 else if (status == configuring) {
2329 restorePanel->EnableApply(true);
2330 cfgUpdated = cfgUpdated | (1 << event.GetId());
2334 void wxbRestorePanel::OnConfigOk(wxCommandEvent& WXUNUSED(event)) {
2335 if (status != configuring) return;
2344 void wxbRestorePanel::OnConfigApply(wxCommandEvent& WXUNUSED(event)) {
2345 if (status != configuring) return;
2351 if (cfgUpdated == 0) {
2352 restorePanel->EnableApply(false);
2357 void wxbRestorePanel::OnConfigCancel(wxCommandEvent& WXUNUSED(event)) {
2358 if (status != configuring) return;