]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/wx-console/wxbrestorepanel.cpp
- wxbRestorePanel : Added functions to get/set working status
[bacula/bacula] / bacula / src / wx-console / wxbrestorepanel.cpp
1 /*
2  *
3  *   wxbPanel for restoring files
4  *
5  *    Nicolas Boichat, April-May 2004
6  *
7  */
8 /*
9    Copyright (C) 2004 Kern Sibbald and John Walker
10
11    This program is free software; you can redistribute it and/or
12    modify it under the terms of the GNU General Public License
13    as published by the Free Software Foundation; either version 2
14    of the License, or (at your option) any later version.
15
16    This program is distributed in the hope that it will be useful,
17    but WITHOUT ANY WARRANTY; without even the implied warranty of
18    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19    GNU General Public License for more details.
20
21    You should have received a copy of the GNU General Public License
22    along with this program; if not, write to the Free Software
23    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
24  */
25 /* Note concerning "done" output (modifiable marked with +)
26 Run Restore job
27 +JobName:    RestoreFiles
28 Bootstrap:  /var/lib/bacula/restore.bsr
29 +Where:      /tmp/bacula-restores
30 +Replace:    always
31 +FileSet:    Full Set
32 +Client:     tom-fd
33 +Storage:    File
34 +When:       2004-04-18 01:18:56
35 +Priority:   10
36 OK to run? (yes/mod/no):mod
37 Parameters to modify:
38      1: Level (not appropriate)
39      2: Storage (automatic ?)
40      3: Job (no)
41      4: FileSet (yes)
42      5: Client (yes : "The defined Client resources are:\n\t1: velours-fd\n\t2: tom-fd\nSelect Client (File daemon) resource (1-2):")
43      6: When (yes : "Please enter desired start time as YYYY-MM-DD HH:MM:SS (return for now):")
44      7: Priority (yes : "Enter new Priority: (positive integer)")
45      8: Bootstrap (?)
46      9: Where (yes : "Please enter path prefix for restore (/ for none):")
47     10: Replace (yes : "Replace:\n 1: always\n 2: ifnewer\n 3: ifolder\n 4: never\n 
48           Select replace option (1-4):")
49     11: JobId (no)
50 Select parameter to modify (1-11):
51        */
52
53 #include "wxbrestorepanel.h"
54
55 #include "wxbmainframe.h"
56
57 #include "csprint.h"
58
59 #include <wx/choice.h>
60 #include <wx/datetime.h>
61
62 #include <wx/timer.h>
63
64 #include "unmarked.xpm"
65 #include "marked.xpm"
66 #include "partmarked.xpm"
67
68 #include <wx/listimpl.cpp>
69
70 /* A macro named Yield is defined under MinGW */
71 #undef Yield
72
73 WX_DEFINE_LIST(wxbEventList);
74
75 /*
76  *  Class which is stored in the tree and in the list to keep informations
77  *  about the element.
78  */
79 class wxbTreeItemData : public wxTreeItemData {
80    public:
81       wxbTreeItemData(wxString path, wxString name, int marked, long listid = -1);
82       wxbTreeItemData(wxString path, wxString name, wxString marked, long listid = -1);
83       ~wxbTreeItemData();
84       wxString GetPath();
85       wxString GetName();
86       
87       int GetMarked();
88       void SetMarked(int marked);
89       void SetMarked(wxString marked);
90       
91       long GetListId();
92
93       static int GetMarkedStatus(wxString file);
94    private:
95       wxString* path; /* Full path */
96       wxString* name; /* File name */
97       int marked; /* 0 - Not Marked, 1 - Marked, 2 - Some file under is marked */
98       long listid; /* list ID : >-1 if this data is in the list (and/or on the tree) */
99 };
100
101 wxbTreeItemData::wxbTreeItemData(wxString path, wxString name, int marked, long listid): wxTreeItemData() {
102    this->path = new wxString(path);
103    this->name = new wxString(name);
104    this->marked = marked;
105    this->listid = listid;
106 }
107
108 wxbTreeItemData::wxbTreeItemData(wxString path, wxString name, wxString marked, long listid): wxTreeItemData() {
109    this->path = new wxString(path);
110    this->name = new wxString(name);
111    SetMarked(marked);
112    this->listid = listid;
113 }
114
115 wxbTreeItemData::~wxbTreeItemData() {
116    delete path;
117    delete name;
118 }
119
120 int wxbTreeItemData::GetMarked() {
121    return marked;
122 }
123
124 void wxbTreeItemData::SetMarked(wxString marked) {
125    if (marked == "*") {
126       this->marked = 1;
127    }
128    else if (marked == "+") {
129       this->marked = 2;
130    }
131    else {
132       this->marked = 0;
133    }
134 }
135
136 void wxbTreeItemData::SetMarked(int marked) {
137    this->marked = marked;
138 }
139
140 long wxbTreeItemData::GetListId() {
141    return listid;
142 }
143
144 wxString wxbTreeItemData::GetPath() {
145    return *path;
146 }
147
148 wxString wxbTreeItemData::GetName() {
149    return *name;
150 }
151
152 /*wxbTreeItemData* wxbTreeItemData::GetChild(wxString dirname) {
153    int marked = GetMarkedStatus(dirname);
154    return new wxbTreeItemData(path + (marked ? dirname.Mid(1) : dirname), marked);
155 }*/
156
157 int wxbTreeItemData::GetMarkedStatus(wxString file) {
158    if (file.Length() == 0)
159       return 0;
160    
161    switch (file.GetChar(0)) {
162        case '*':
163           return 1;
164        case '+':
165           return 2;
166        default:
167           return 0;
168     }
169 }
170
171 // ----------------------------------------------------------------------------
172 // event tables and other macros for wxWindows
173 // ----------------------------------------------------------------------------
174
175 enum
176 {
177    RestoreStart = 1,
178    RestoreCancel = 2,
179    TreeCtrl = 3,
180    ListCtrl = 4,
181    ConfigOk = 5,
182    ConfigApply = 6,
183    ConfigCancel = 7,
184    ConfigWhere = 8,
185    ConfigReplace = 9,
186    ConfigWhen = 10,
187    ConfigPriority = 11,
188    ConfigClient = 12,
189    ConfigFileset = 13,
190    ConfigStorage = 14,
191    ConfigJobName = 15,
192    ConfigPool = 16,
193    TreeAdd = 17,
194    TreeRemove = 18,
195    TreeRefresh = 19,
196    ListAdd = 20,
197    ListRemove = 21,
198    ListRefresh = 22
199 };
200
201 BEGIN_EVENT_TABLE(wxbRestorePanel, wxPanel)
202    EVT_BUTTON(RestoreStart, wxbRestorePanel::OnStart)
203    EVT_BUTTON(RestoreCancel, wxbRestorePanel::OnCancel)
204    
205    EVT_TREE_SEL_CHANGING(TreeCtrl, wxbRestorePanel::OnTreeChanging)
206    EVT_TREE_SEL_CHANGED(TreeCtrl, wxbRestorePanel::OnTreeChanged)
207    EVT_TREE_ITEM_EXPANDING(TreeCtrl, wxbRestorePanel::OnTreeExpanding)
208    EVT_TREE_MARKED_EVENT(TreeCtrl, wxbRestorePanel::OnTreeMarked)
209    EVT_BUTTON(TreeAdd, wxbRestorePanel::OnTreeAdd)
210    EVT_BUTTON(TreeRemove, wxbRestorePanel::OnTreeRemove)
211    EVT_BUTTON(TreeRefresh, wxbRestorePanel::OnTreeRefresh)
212
213    EVT_LIST_ITEM_ACTIVATED(ListCtrl, wxbRestorePanel::OnListActivated)
214    EVT_LIST_MARKED_EVENT(ListCtrl, wxbRestorePanel::OnListMarked)
215    EVT_LIST_ITEM_SELECTED(ListCtrl, wxbRestorePanel::OnListChanged)
216    EVT_LIST_ITEM_DESELECTED(ListCtrl, wxbRestorePanel::OnListChanged)
217    EVT_BUTTON(ListAdd, wxbRestorePanel::OnListAdd)
218    EVT_BUTTON(ListRemove, wxbRestorePanel::OnListRemove)
219    EVT_BUTTON(ListRefresh, wxbRestorePanel::OnListRefresh)
220   
221    EVT_TEXT(ConfigWhere, wxbRestorePanel::OnConfigUpdated)
222    EVT_TEXT(ConfigWhen, wxbRestorePanel::OnConfigUpdated)
223    EVT_TEXT(ConfigPriority, wxbRestorePanel::OnConfigUpdated)
224    EVT_CHOICE(ConfigWhen, wxbRestorePanel::OnConfigUpdated)
225    EVT_CHOICE(ConfigReplace, wxbRestorePanel::OnConfigUpdated)
226    EVT_CHOICE(ConfigClient, wxbRestorePanel::OnConfigUpdated)
227    EVT_CHOICE(ConfigFileset, wxbRestorePanel::OnConfigUpdated)
228    EVT_CHOICE(ConfigStorage, wxbRestorePanel::OnConfigUpdated)
229    EVT_CHOICE(ConfigJobName, wxbRestorePanel::OnConfigUpdated)
230    EVT_CHOICE(ConfigPool, wxbRestorePanel::OnConfigUpdated)
231    
232    EVT_BUTTON(ConfigOk, wxbRestorePanel::OnConfigOk)
233    EVT_BUTTON(ConfigApply, wxbRestorePanel::OnConfigApply)
234    EVT_BUTTON(ConfigCancel, wxbRestorePanel::OnConfigCancel)
235 END_EVENT_TABLE()
236
237 /*
238  *  wxbRestorePanel constructor
239  */
240 wxbRestorePanel::wxbRestorePanel(wxWindow* parent): wxbPanel(parent) {
241    //pendingEvents = new wxbEventList(); //EVTQUEUE
242    //processing = false; //EVTQUEUE
243    SetWorking(false);
244    
245    imagelist = new wxImageList(16, 16, TRUE, 3);
246    imagelist->Add(wxIcon(unmarked_xpm));
247    imagelist->Add(wxIcon(marked_xpm));
248    imagelist->Add(wxIcon(partmarked_xpm));
249
250    wxFlexGridSizer* mainSizer = new wxFlexGridSizer(3, 1, 10, 10);
251    mainSizer->AddGrowableCol(0);
252    mainSizer->AddGrowableRow(1);
253
254    wxFlexGridSizer *firstSizer = new wxFlexGridSizer(1, 2, 10, 10);
255
256    firstSizer->AddGrowableCol(0);
257    firstSizer->AddGrowableRow(0);
258
259    start = new wxButton(this, RestoreStart, "Enter restore mode", wxDefaultPosition, wxSize(150, 30));
260    firstSizer->Add(start, 0, wxALIGN_CENTER_HORIZONTAL | wxALIGN_CENTER_VERTICAL, 10);
261
262    cancel = new wxButton(this, RestoreCancel, "Cancel restore", wxDefaultPosition, wxSize(150, 30));
263    firstSizer->Add(cancel, 0, wxALIGN_CENTER_HORIZONTAL | wxALIGN_RIGHT, 10);
264
265    wxString elist[1];
266
267 /*   clientChoice = new wxChoice(this, ClientChoice, wxDefaultPosition, wxSize(150, 30), 0, elist);
268    firstSizer->Add(clientChoice, 1, wxALIGN_CENTER_HORIZONTAL | wxALIGN_CENTER_VERTICAL, 10);
269
270    jobChoice = new wxChoice(this, -1, wxDefaultPosition, wxSize(150, 30), 0, elist);
271    firstSizer->Add(jobChoice, 1, wxALIGN_CENTER_HORIZONTAL | wxALIGN_CENTER_VERTICAL, 10);*/
272
273    mainSizer->Add(firstSizer, 1, wxEXPAND, 10);
274
275    treelistPanel = new wxSplitterWindow(this);
276
277    wxPanel* treePanel = new wxPanel(treelistPanel);
278    wxFlexGridSizer *treeSizer = new wxFlexGridSizer(2, 1, 0, 0);
279    treeSizer->AddGrowableCol(0);
280    treeSizer->AddGrowableRow(0);
281
282    tree = new wxbTreeCtrl(treePanel, this, TreeCtrl, wxDefaultPosition, wxSize(200,50));  
283    tree->SetImageList(imagelist);
284    
285    treeSizer->Add(tree, 1, wxEXPAND, 0);
286    
287    wxBoxSizer *treeCtrlSizer = new wxBoxSizer(wxHORIZONTAL);
288    treeadd = new wxButton(treePanel, TreeAdd, "Add", wxDefaultPosition, wxSize(60, 25));
289    treeCtrlSizer->Add(treeadd, 0, wxLEFT | wxRIGHT, 3);
290    treeremove = new wxButton(treePanel, TreeRemove, "Remove", wxDefaultPosition, wxSize(60, 25));
291    treeCtrlSizer->Add(treeremove, 0, wxLEFT | wxRIGHT, 3);
292    treerefresh = new wxButton(treePanel, TreeRefresh, "Refresh", wxDefaultPosition, wxSize(60, 25));
293    treeCtrlSizer->Add(treerefresh, 0, wxLEFT | wxRIGHT, 3);
294    
295    treeSizer->Add(treeCtrlSizer, 1, wxALIGN_CENTER_HORIZONTAL, 0);
296    
297    treePanel->SetSizer(treeSizer);
298    
299    wxPanel* listPanel = new wxPanel(treelistPanel);
300    wxFlexGridSizer *listSizer = new wxFlexGridSizer(2, 1, 0, 0);
301    listSizer->AddGrowableCol(0);
302    listSizer->AddGrowableRow(0);
303    
304    list = new wxbListCtrl(listPanel, this, ListCtrl, wxDefaultPosition, wxSize(200,50));
305    //treelistSizer->Add(list, 1, wxEXPAND, 10);
306
307    list->SetImageList(imagelist, wxIMAGE_LIST_SMALL);
308
309    wxListItem info;
310    info.SetMask(wxLIST_MASK_TEXT | wxLIST_MASK_FORMAT);
311    info.SetText("M");
312    info.SetAlign(wxLIST_FORMAT_CENTER);
313    list->InsertColumn(0, info);
314    
315    info.SetText("Filename");
316    info.SetAlign(wxLIST_FORMAT_LEFT);
317    list->InsertColumn(1, info);
318
319    info.SetText("Size");
320    info.SetAlign(wxLIST_FORMAT_RIGHT);   
321    list->InsertColumn(2, info);
322
323    info.SetText("Date");
324    info.SetAlign(wxLIST_FORMAT_LEFT);
325    list->InsertColumn(3, info);
326
327    info.SetText("Perm.");
328    info.SetAlign(wxLIST_FORMAT_LEFT);
329    list->InsertColumn(4, info);
330    
331    info.SetText("User");
332    info.SetAlign(wxLIST_FORMAT_RIGHT);
333    list->InsertColumn(5, info);
334    
335    info.SetText("Group");
336    info.SetAlign(wxLIST_FORMAT_RIGHT);
337    list->InsertColumn(6, info);
338     
339    listSizer->Add(list, 1, wxEXPAND, 0);
340    
341    wxBoxSizer *listCtrlSizer = new wxBoxSizer(wxHORIZONTAL);
342    listadd = new wxButton(listPanel, ListAdd, "Add", wxDefaultPosition, wxSize(60, 25));
343    listCtrlSizer->Add(listadd, 0, wxLEFT | wxRIGHT, 5);
344    listremove = new wxButton(listPanel, ListRemove, "Remove", wxDefaultPosition, wxSize(60, 25));
345    listCtrlSizer->Add(listremove, 0, wxLEFT | wxRIGHT, 5);
346    listrefresh = new wxButton(listPanel, ListRefresh, "Refresh", wxDefaultPosition, wxSize(60, 25));
347    listCtrlSizer->Add(listrefresh, 0, wxLEFT | wxRIGHT, 5);
348    
349    listSizer->Add(listCtrlSizer, 1, wxALIGN_CENTER_HORIZONTAL, 0);
350    
351    listPanel->SetSizer(listSizer);
352    
353    treelistPanel->SplitVertically(treePanel, listPanel, 210);
354    
355    treelistPanel->SetMinimumPaneSize(210);
356      
357    treelistPanel->Show(false);
358    
359    wxbConfig* config = new wxbConfig();
360    config->Add(new wxbConfigParam("Job Name", ConfigJobName, choice, 0, elist));
361    config->Add(new wxbConfigParam("Client", ConfigClient, choice, 0, elist));
362    config->Add(new wxbConfigParam("Fileset", ConfigFileset, choice, 0, elist));
363    config->Add(new wxbConfigParam("Pool", ConfigPool, choice, 0, elist));
364    config->Add(new wxbConfigParam("Storage", ConfigStorage, choice, 0, elist));
365    config->Add(new wxbConfigParam("Before", ConfigWhen, choice, 0, elist));
366    
367    configPanel = new wxbConfigPanel(this, config, "Please configure parameters concerning files to restore :", RestoreStart, RestoreCancel, -1);
368    
369    configPanel->Show(true);
370    configPanel->Enable(false);
371    
372    config = new wxbConfig();
373    config->Add(new wxbConfigParam("Job Name", -1, text, ""));
374    config->Add(new wxbConfigParam("Bootstrap", -1, text, ""));
375    config->Add(new wxbConfigParam("Where", ConfigWhere, modifiableText, ""));
376    wxString erlist[] = {"always", "if newer", "if older", "never"};
377    config->Add(new wxbConfigParam("Replace", ConfigReplace, choice, 4, erlist));
378    config->Add(new wxbConfigParam("Fileset", ConfigFileset, choice, 0, erlist));
379    config->Add(new wxbConfigParam("Client", ConfigClient, choice, 0, erlist));
380    config->Add(new wxbConfigParam("Storage", ConfigStorage, choice, 0, erlist));
381    config->Add(new wxbConfigParam("When", ConfigWhen, modifiableText, ""));
382    config->Add(new wxbConfigParam("Priority", ConfigPriority, modifiableText, ""));
383    
384    restorePanel = new wxbConfigPanel(this, config, "Please configure parameters concerning files restoration :", ConfigOk, ConfigCancel, ConfigApply);
385     
386    restorePanel->Show(false);
387    
388    centerSizer = new wxBoxSizer(wxHORIZONTAL);
389    //centerSizer->Add(treelistPanel, 1, wxEXPAND | wxADJUST_MINSIZE);
390       
391    mainSizer->Add(centerSizer, 1, wxEXPAND, 10);
392
393    gauge = new wxGauge(this, -1, 1, wxDefaultPosition, wxSize(200,20));
394
395    mainSizer->Add(gauge, 1, wxEXPAND, 5);
396    gauge->SetValue(0);
397    gauge->Enable(false);
398
399    SetSizer(mainSizer);
400    mainSizer->SetSizeHints(this);
401
402    SetStatus(disabled);
403
404    for (int i = 0; i < 7; i++) {
405       list->SetColumnWidth(i, 70);
406    }
407
408    SetCursor(*wxSTANDARD_CURSOR);
409
410    markWhenListingDone = false;
411    
412    cancelled = 0;
413 }
414
415 /*
416  *  wxbRestorePanel destructor
417  */
418 wxbRestorePanel::~wxbRestorePanel() {
419    delete imagelist;
420 }
421
422 /*----------------------------------------------------------------------------
423    wxbPanel overloadings
424   ----------------------------------------------------------------------------*/
425
426 wxString wxbRestorePanel::GetTitle() {
427    return "Restore";
428 }
429
430 void wxbRestorePanel::EnablePanel(bool enable) {
431    if (enable) {
432       if (status == disabled) {
433          SetStatus(activable);
434       }
435    }
436    else {
437       SetStatus(disabled);
438    }
439 }
440
441 /*----------------------------------------------------------------------------
442    Commands called by events handler
443   ----------------------------------------------------------------------------*/
444
445 /* The main button has been clicked */
446 void wxbRestorePanel::CmdStart() {
447    unsigned int i;
448    if (status == activable) {
449       wxbMainFrame::GetInstance()->SetStatusText("Getting parameters list.");
450       wxbDataTokenizer* dt = WaitForEnd(".clients\n", true, false);
451       wxString str;
452
453       configPanel->ClearRowChoices("Client");
454       restorePanel->ClearRowChoices("Client");
455       
456       if (dt->GetCount() == 0) {
457          wxbMainFrame::GetInstance()->SetStatusText("Error : no clients returned by the director.");
458          return;
459       }
460       
461       for (i = 0; i < dt->GetCount(); i++) {
462          str = (*dt)[i];
463          str.RemoveLast();
464          configPanel->AddRowChoice("Client", str);
465          restorePanel->AddRowChoice("Client", str);
466       }
467           
468       delete dt;
469       
470       if (cancelled) {
471          cancelled = 2;
472          return;
473       }
474       
475       dt = WaitForEnd(".filesets\n", true, false);
476       
477       configPanel->ClearRowChoices("Fileset");
478       restorePanel->ClearRowChoices("Fileset");
479     
480       if (dt->GetCount() == 0) {
481          wxbMainFrame::GetInstance()->SetStatusText("Error : no filesets returned by the director.");
482          return;
483       }
484       
485       for (i = 0; i < dt->GetCount(); i++) {
486          str = (*dt)[i];
487          str.RemoveLast();
488          configPanel->AddRowChoice("Fileset", str);
489          restorePanel->AddRowChoice("Fileset", str);
490       }
491       
492       delete dt;
493       
494       if (cancelled) {
495          cancelled = 2;
496          return;
497       }
498       
499       dt = WaitForEnd(".storage\n", true, false);
500     
501       configPanel->ClearRowChoices("Storage");
502       restorePanel->ClearRowChoices("Storage");
503     
504       if (dt->GetCount() == 0) {
505          wxbMainFrame::GetInstance()->SetStatusText("Error : no storage returned by the director.");
506          return;
507       }
508       
509       for (i = 0; i < dt->GetCount(); i++) {
510          str = (*dt)[i];
511          str.RemoveLast();
512          configPanel->AddRowChoice("Storage", str);
513          restorePanel->AddRowChoice("Storage", str);
514       }
515       
516       delete dt;
517       
518       if (cancelled) {
519          cancelled = 2;
520          return;
521       }
522       
523       dt = WaitForEnd(".jobs\n", true, false);
524     
525       configPanel->ClearRowChoices("Job Name");
526     
527       if (dt->GetCount() == 0) {
528          wxbMainFrame::GetInstance()->SetStatusText("Error : no jobs returned by the director.");
529          return;
530       }
531       
532       for (i = 0; i < dt->GetCount(); i++) {
533          str = (*dt)[i];
534          str.RemoveLast();
535          configPanel->AddRowChoice("Job Name", str);
536       }
537       
538       configPanel->SetRowString("Job Name", "RestoreFiles");
539       
540       delete dt;
541       
542       if (cancelled) {
543          cancelled = 2;
544          return;
545       }
546       
547       dt = WaitForEnd(".pools\n", true, false);
548     
549       configPanel->ClearRowChoices("Pool");
550     
551       if (dt->GetCount() == 0) {
552          wxbMainFrame::GetInstance()->SetStatusText("Error : no jobs returned by the director.");
553          return;
554       }
555       
556       for (i = 0; i < dt->GetCount(); i++) {
557          str = (*dt)[i];
558          str.RemoveLast();
559          configPanel->AddRowChoice("Pool", str);
560       }
561          
562       delete dt; 
563       
564       if (cancelled) {
565          cancelled = 2;
566          return;
567       }
568
569       SetStatus(entered);
570
571       UpdateFirstConfig();
572            
573       wxbMainFrame::GetInstance()->SetStatusText("Please configure your restore parameters.");
574    }
575    else if (status == entered) {
576 /*      if (clientChoice->GetStringSelection().Length() < 1) {
577          wxbMainFrame::GetInstance()->SetStatusText("Please select a client.");
578          return;
579       }
580       if (jobChoice->GetStringSelection().Length() < 1) {
581          wxbMainFrame::GetInstance()->SetStatusText("Please select a restore date.");
582          return;
583       }*/
584       wxbMainFrame::GetInstance()->SetStatusText("Building restore tree...");
585       
586       SetStatus(choosing);
587       
588       WaitForPrompt(wxString("restore") <<
589          " client=\"" << configPanel->GetRowString("Client") <<
590          "\" fileset=\"" << configPanel->GetRowString("Fileset") <<
591          "\" pool=\"" << configPanel->GetRowString("Pool") <<
592          "\" storage=\"" << configPanel->GetRowString("Storage") << "\"\n");
593       WaitForPrompt("6\n");
594       //WaitForEnd();
595       /*wxbPromptParser *pp = WaitForPrompt(wxString() << configPanel->GetRowString("Before") << "\n", true);
596       int client = pp->getChoices()->Index(configPanel->GetRowString("Client"));
597       if (client == wxNOT_FOUND) {
598          wxbMainFrame::GetInstance()->SetStatusText("Failed to find the selected client.");
599          return;
600       }
601       delete pp;*/
602       
603       wxbTableParser* tableparser = new wxbTableParser();
604       wxbDataTokenizer* dt = new wxbDataTokenizer(true);
605       
606       wxbMainFrame::GetInstance()->Send(wxString() << configPanel->GetRowString("Before") << "\n");
607    
608       while (!tableparser->hasFinished() && !dt->hasFinished()) {
609          wxTheApp->Yield(true);
610          ::wxUsleep(100);
611       }
612       
613       wxString str;
614
615       if (dt->hasFinished() && !tableparser->hasFinished()) {
616          str = "";
617          if (dt->GetCount() > 1) {
618             str = (*dt)[dt->GetCount()-2];
619             str.RemoveLast();
620          }
621          wxbMainFrame::GetInstance()->SetStatusText(wxString("Error while starting restore: ") << str);
622          delete dt;
623          delete tableparser;
624          SetStatus(finished);
625          return;
626       }
627            
628       int tot = 0;
629       long l;
630       
631       for (i = 0; i < tableparser->GetCount(); i++) {
632          str = (*tableparser)[i][2];
633          str.Replace(",", "");
634          if (str.ToLong(&l)) {
635             tot += l;
636          }
637       }
638            
639       gauge->SetValue(0);
640       gauge->SetRange(tot);
641       
642       /*wxbMainFrame::GetInstance()->Print(
643                wxString("[") << tot << "]", CS_DEBUG);*/
644       
645       wxDateTime base = wxDateTime::Now();
646       wxDateTime newdate;
647       int done = 0;
648       int willdo = 0;
649       unsigned int lastindex = 0;
650       
651       int var = 0;
652       
653       while (!dt->hasFinished()) {
654          newdate = wxDateTime::Now();
655          if (newdate.Subtract(base).GetMilliseconds() > 10 ) {
656             base = newdate;
657             for (; lastindex < dt->GetCount(); lastindex++) {
658                if (((*dt)[lastindex].Find("Building directory tree for JobId ") == 0) && 
659                      ((i = (*dt)[lastindex].Find(" ...")) > 0)) {
660                   str = (*dt)[lastindex].Mid(34, i-34);
661                   for (i = 0; i < tableparser->GetCount(); i++) {
662                      if (str == (*tableparser)[i][0]) {
663                         str = (*tableparser)[i][2];
664                         str.Replace(",", "");
665                         if (str.ToLong(&l)) {
666                            done += willdo;
667                            willdo += l;
668                            var = (willdo-done)/3;
669                         }
670                         break;
671                      }
672                   }
673                }
674             }
675             
676             if (gauge->GetValue() <= done) {
677                gauge->SetValue(done);
678                if (var < 0)
679                   var = -var;
680             }
681             else if (gauge->GetValue() >= willdo) {
682                gauge->SetValue(willdo);
683                if (var > 0)
684                   var = -var;
685             }
686             
687             gauge->SetValue(gauge->GetValue()+var);
688             
689             /*wxbMainFrame::GetInstance()->Print(
690                wxString("[") << gauge->GetValue() << "/" << done
691                   << "-" << willdo << "]", CS_DEBUG);*/
692          }
693          wxTheApp->Yield(true);
694          ::wxUsleep(1);
695       }
696
697       gauge->SetValue(tot);
698       wxTheApp->Yield(true);
699       gauge->SetValue(0);
700       
701       delete dt;
702       delete tableparser;
703
704       if (cancelled) {
705          cancelled = 2;
706          return;
707       }
708
709       WaitForEnd("unmark *\n");
710       wxTreeItemId root = tree->AddRoot(configPanel->GetRowString("Client"), -1, -1, new wxbTreeItemData("/", configPanel->GetRowString("Client"), 0));
711       currentTreeItem = root;
712       tree->Refresh();
713       tree->SelectItem(root);
714       CmdList(root);
715       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.");
716       tree->Expand(root);
717    }
718    else if (status == choosing) {
719       EnableConfig(false);
720       
721       totfilemessages = 0;
722       wxbDataTokenizer* dt;
723            
724       int j;
725       
726       dt = new wxbDataTokenizer(true);
727       WaitForPrompt("done\n");
728
729       SetStatus(configuring);
730
731       for (i = 0; i < dt->GetCount(); i++) {
732          if ((j = (*dt)[i].Find(" files selected to be restored.")) > -1) {
733             (*dt)[i].Mid(0, j).ToLong(&totfilemessages);
734             break;
735          }
736
737          if ((j = (*dt)[i].Find(" file selected to be restored.")) > -1) {
738             (*dt)[i].Mid(0, j).ToLong(&totfilemessages);
739             break;
740          }
741       }
742       
743       wxbMainFrame::GetInstance()->SetStatusText(
744          wxString("Please configure your restore (") 
745             << totfilemessages <<  " files selected to be restored)...");
746       
747       UpdateSecondConfig(dt);
748       
749       delete dt;
750       
751       EnableConfig(true);
752       restorePanel->EnableApply(false);
753
754       if (totfilemessages == 0) {
755          wxbMainFrame::GetInstance()->Print("Restore failed : no file selected.\n", CS_DEBUG);
756          wxbMainFrame::GetInstance()->SetStatusText("Restore failed : no file selected.");
757          SetStatus(finished);
758          return;
759       }
760    }
761    else if (status == configuring) {
762       cancel->Enable(false);
763       jobid = "";
764       EnableConfig(false);
765     
766       wxbMainFrame::GetInstance()->SetStatusText("Restoring, please wait...");
767     
768       wxbDataTokenizer* dt;
769     
770       SetStatus(restoring);
771       WaitForEnd("yes\n");
772
773       gauge->SetValue(0);
774       gauge->SetRange(totfilemessages);
775
776       wxDateTime currenttime;
777       
778       dt = WaitForEnd("time\n", true);
779       wxStringTokenizer ttkz((*dt)[0], " ", wxTOKEN_STRTOK);
780       if ((currenttime.ParseDate(ttkz.GetNextToken()) == NULL) || // Date
781            (currenttime.ParseTime(ttkz.GetNextToken()) == NULL)) { // Time
782          currenttime.SetYear(1990); // If parsing fails, set currenttime to a dummy date
783       }
784       else {
785          currenttime -= wxTimeSpan::Seconds(30); //Adding a 30" tolerance
786       }
787       delete dt;
788     
789       wxDateTime scheduledtime;
790       wxStringTokenizer stkz(restorePanel->GetRowString("When"), " ", wxTOKEN_STRTOK);
791       
792       if ((scheduledtime.ParseDate(stkz.GetNextToken()) == NULL) || // Date
793            (scheduledtime.ParseTime(stkz.GetNextToken()) == NULL)) { // Time
794          scheduledtime.SetYear(2090); // If parsing fails, set scheduledtime to a dummy date
795       }
796
797       if (scheduledtime.Subtract(currenttime).IsLongerThan(wxTimeSpan::Seconds(150))) {
798          wxbMainFrame::GetInstance()->Print("Restore is scheduled in more than two minutes, wx-console will not wait for its completion.\n", CS_DEBUG);
799          wxbMainFrame::GetInstance()->SetStatusText("Restore is scheduled in more than two minutes, wx-console will not wait for its completion.");
800          SetStatus(finished);
801          return;
802       }
803
804       wxString cmd = "list jobid=";
805
806       wxString jobname = restorePanel->GetRowString("Job Name");
807
808       wxStopWatch sw;
809
810       wxbTableParser* tableparser;
811
812       while (true) {
813          tableparser = CreateAndWaitForParser("list jobs\n");
814          
815          wxDateTime jobtime;
816          
817          if (jobname == (*tableparser)[tableparser->GetCount()-1][1]) {
818             wxStringTokenizer jtkz((*tableparser)[tableparser->GetCount()-1][2], " ", wxTOKEN_STRTOK);
819             if ((jobtime.ParseDate(jtkz.GetNextToken()) != NULL) && // Date
820                   (jobtime.ParseTime(jtkz.GetNextToken()) != NULL)) { // Time
821                if (jobtime.IsLaterThan(currenttime)) {
822                   jobid = (*tableparser)[tableparser->GetCount()-1][0];
823                   cmd << jobid << "\n";
824                   delete tableparser;
825                   cancel->Enable(true);
826                   break;
827                }
828             }
829          }
830    
831          delete tableparser;
832          
833          wxStopWatch sw2;
834          while (sw2.Time() < 2000) {
835             wxTheApp->Yield(true);
836             ::wxUsleep(100);
837          }
838          if (sw.Time() > 60000) {
839             wxbMainFrame::GetInstance()->Print("The restore job has not been created within one minute, wx-console will not wait for its completion anymore.\n", CS_DEBUG);
840             wxbMainFrame::GetInstance()->SetStatusText("The restore job has not been created within one minute, wx-console will not wait for its completion anymore.");
841             SetStatus(finished);
842             cancel->Enable(true);
843             return;
844          }
845       }
846       
847       long filemessages = 0;
848
849       while (true) {
850          tableparser = CreateAndWaitForParser(cmd);
851          if ((*tableparser)[0][7] != "C") {
852             break;
853          }
854          delete tableparser;
855
856          dt = WaitForEnd("messages\n", true);
857          
858          for (unsigned int i = 0; i < dt->GetCount(); i++) {
859             wxStringTokenizer tkz((*dt)[i], " ", wxTOKEN_STRTOK);
860    
861             wxDateTime datetime;
862    
863             //   Date    Time   name:   perm      ?   user   grp      size    date     time
864             //04-Apr-2004 17:19 Tom-fd: -rwx------   1 nicolas  None     514967 2004-03-20 20:03:42  filename
865    
866             if (datetime.ParseDate(tkz.GetNextToken()) != NULL) { // Date
867                if (datetime.ParseTime(tkz.GetNextToken()) != NULL) { // Time
868                   if (tkz.GetNextToken().Last() == ':') { // name:
869                   tkz.GetNextToken(); // perm
870                   tkz.GetNextToken(); // ?
871                   tkz.GetNextToken(); // user
872                   tkz.GetNextToken(); // grp
873                   tkz.GetNextToken(); // size
874                   if (datetime.ParseDate(tkz.GetNextToken()) != NULL) { //date
875                         if (datetime.ParseTime(tkz.GetNextToken()) != NULL) { //time
876                            filemessages++;
877                            //wxbMainFrame::GetInstance()->Print(wxString("(") << filemessages << ")", CS_DEBUG);
878                            gauge->SetValue(filemessages);
879                         }
880                      }
881                   }
882                }
883             }
884          }
885          
886          delete dt;
887
888          wxbMainFrame::GetInstance()->SetStatusText(wxString("Restoring, please wait (") << filemessages << " of " << totfilemessages << " files done)...");
889
890          wxStopWatch sw2;
891          while (sw2.Time() < 10000) {  
892             wxTheApp->Yield(true);
893             ::wxUsleep(100);
894          }
895       }
896
897       WaitForEnd("messages\n");
898
899       gauge->SetValue(totfilemessages);
900
901       if ((*tableparser)[0][7] == "T") {
902          wxbMainFrame::GetInstance()->Print("Restore done successfully.\n", CS_DEBUG);
903          wxbMainFrame::GetInstance()->SetStatusText("Restore done successfully.");
904       }
905       else {
906          wxbMainFrame::GetInstance()->Print("Restore failed, please look at messages.\n", CS_DEBUG);
907          wxbMainFrame::GetInstance()->SetStatusText("Restore failed, please look at messages in console.");
908       }
909       delete tableparser;
910       SetStatus(finished);
911    }
912 }
913
914 /* The cancel button has been clicked */
915 void wxbRestorePanel::CmdCancel() {
916    cancelled = 1;
917    
918    if (status == restoring) {
919       if (jobid != "") {
920          wxbMainFrame::GetInstance()->Send(wxString("cancel job=") << jobid << "\n");
921       }
922       cancel->Enable(true);
923       return;
924    }
925    
926    wxStopWatch sw;
927    while ((IsWorking()) && (cancelled != 2)) {
928       wxTheApp->Yield(true);
929       ::wxUsleep(100);
930       if (sw.Time() > 30000) { /* 30 seconds timeout */
931          if (status == choosing) {
932             wxbMainFrame::GetInstance()->Send("quit\n");
933          }
934          else if (status == configuring) {
935             wxbMainFrame::GetInstance()->Send("no\n");
936          }
937          else if (status == restoring) {
938             
939          }
940          SetStatus(finished);
941          ::wxUsleep(1000);
942          return;
943       }
944    }
945    
946    switch (status) {
947    case choosing:
948       wxbMainFrame::GetInstance()->Send("quit\n");      
949       break;
950    case configuring:
951       wxbMainFrame::GetInstance()->Send("no\n");      
952       break;
953    default:
954       break;
955    }
956    ::wxUsleep(1000);
957    SetStatus(finished);
958 }
959
960 /* Apply configuration changes */
961
962 /*   1: Level (not appropriate)
963  *   2: Storage (yes)
964  *   3: Job (no)
965  *   4: FileSet (yes)
966  *   5: Client (yes)
967  *   6: When (yes : "Please enter desired start time as YYYY-MM-DD HH:MM:SS (return for now):")
968  *   7: Priority (yes : "Enter new Priority: (positive integer)")
969  *   8: Bootstrap (?)
970  *   9: Where (yes : "Please enter path prefix for restore (/ for none):")
971  *  10: Replace (yes : "Replace:\n 1: always\n 2: ifnewer\n 3: ifolder\n 4: never\n 
972  *         Select replace option (1-4):")
973  *  11: JobId (no)
974  */
975
976 void wxbRestorePanel::CmdConfigApply() {
977    if (cfgUpdated == 0) return;
978    
979    wxbMainFrame::GetInstance()->SetStatusText("Applying restore configuration changes...");
980    
981    EnableConfig(false);
982    
983    wxbDataTokenizer* dt = NULL;
984    
985    bool failed = false;
986    
987    while (cfgUpdated > 0) {
988       if (cancelled) {
989          cancelled = 2;
990          return;
991       }
992       wxString def; //String to send if can't use our data
993       if ((cfgUpdated >> ConfigWhere) & 1) {
994          WaitForPrompt("mod\n"); /* TODO: check results */
995          WaitForPrompt("9\n");
996          dt = new wxbDataTokenizer(true);
997          WaitForPrompt(restorePanel->GetRowString("Where") + "\n");
998          def = "/tmp";
999          cfgUpdated = cfgUpdated & (~(1 << ConfigWhere));
1000       }
1001       else if ((cfgUpdated >> ConfigReplace) & 1) {
1002          WaitForPrompt("mod\n"); /* TODO: check results */
1003          WaitForPrompt("10\n");
1004          dt = new wxbDataTokenizer(true);
1005          WaitForPrompt(wxString() << (restorePanel->GetRowSelection("Replace")+1) << "\n");
1006          def = "1";
1007          cfgUpdated = cfgUpdated & (~(1 << ConfigReplace));
1008       }
1009       else if ((cfgUpdated >> ConfigWhen) & 1) {
1010          WaitForPrompt("mod\n"); /* TODO: check results */
1011          WaitForPrompt("6\n");
1012          dt = new wxbDataTokenizer(true);
1013          WaitForPrompt(restorePanel->GetRowString("When") + "\n");
1014          def = "";
1015          cfgUpdated = cfgUpdated & (~(1 << ConfigWhen));
1016       }
1017       else if ((cfgUpdated >> ConfigPriority) & 1) {
1018          WaitForPrompt("mod\n"); /* TODO: check results */
1019          WaitForPrompt("7\n");
1020          dt = new wxbDataTokenizer(true);
1021          WaitForPrompt(restorePanel->GetRowString("Priority") + "\n");
1022          def = "10";
1023          cfgUpdated = cfgUpdated & (~(1 << ConfigPriority));
1024       }
1025       else if ((cfgUpdated >> ConfigClient) & 1) {
1026          WaitForPrompt("mod\n"); /* TODO: check results */
1027          wxbPromptParser *pp = WaitForPrompt("5\n", true);
1028          int client = pp->getChoices()->Index(restorePanel->GetRowString("Client"));
1029          if (client == wxNOT_FOUND) {
1030             wxbMainFrame::GetInstance()->SetStatusText("Failed to find the selected client.");
1031             failed = true;
1032             client = 1;
1033          }
1034          delete pp;
1035          dt = new wxbDataTokenizer(true);
1036          WaitForPrompt(wxString() << client << "\n");
1037          def = "1";
1038          cfgUpdated = cfgUpdated & (~(1 << ConfigClient));
1039       }
1040       else if ((cfgUpdated >> ConfigFileset) & 1) {
1041          WaitForPrompt("mod\n"); /* TODO: check results */
1042          wxbPromptParser *pp = WaitForPrompt("4\n", true);
1043          int fileset = pp->getChoices()->Index(restorePanel->GetRowString("Fileset"));
1044          if (fileset == wxNOT_FOUND) {
1045             wxbMainFrame::GetInstance()->SetStatusText("Failed to find the selected fileset.");
1046             failed = true;
1047             fileset = 1;
1048          }
1049          delete pp;
1050          dt = new wxbDataTokenizer(true);
1051          WaitForPrompt(wxString() << fileset << "\n");
1052          def = "1";
1053          cfgUpdated = cfgUpdated & (~(1 << ConfigFileset));
1054       }
1055       else if ((cfgUpdated >> ConfigStorage) & 1) {
1056          WaitForPrompt("mod\n"); /* TODO: check results */
1057          wxbPromptParser *pp = WaitForPrompt("2\n", true);
1058          int fileset = pp->getChoices()->Index(restorePanel->GetRowString("Storage"));
1059          if (fileset == wxNOT_FOUND) {
1060             wxbMainFrame::GetInstance()->SetStatusText("Failed to find the selected storage.");
1061             failed = true;
1062             fileset = 1;
1063          }
1064          delete pp;
1065          dt = new wxbDataTokenizer(true);
1066          WaitForPrompt(wxString() << fileset << "\n");
1067          def = "1";
1068          cfgUpdated = cfgUpdated & (~(1 << ConfigFileset));
1069       }
1070       else {
1071          cfgUpdated = 0;
1072          break;
1073       }
1074                  
1075       unsigned int i;
1076       for (i = 0; i < dt->GetCount(); i++) {
1077          if ((*dt)[i].Find("Run Restore job") == 0) {
1078             break;
1079          }
1080       }
1081       
1082       if (i == dt->GetCount()) {
1083          delete dt;   
1084          dt = WaitForEnd(def + "\n", true);
1085          failed = true;
1086       }
1087    }
1088    UpdateSecondConfig(dt); /* TODO: Check result */
1089    
1090    EnableConfig(true);
1091
1092    if (!failed) {
1093       wxbMainFrame::GetInstance()->SetStatusText("Restore configuration changes were applied.");
1094    }
1095
1096    delete dt;
1097 }
1098
1099 /* Cancel restore */
1100 void wxbRestorePanel::CmdConfigCancel() {
1101    WaitForEnd("no\n");
1102    wxbMainFrame::GetInstance()->Print("Restore cancelled.\n", CS_DEBUG);
1103    wxbMainFrame::GetInstance()->SetStatusText("Restore cancelled.");
1104    SetStatus(finished);
1105 }
1106
1107 /* List jobs for a specified client */
1108 void wxbRestorePanel::CmdListJobs() {
1109    if (status == entered) {
1110       configPanel->ClearRowChoices("Before");
1111       WaitForPrompt("query\n");
1112       WaitForPrompt("6\n");
1113       wxbTableParser* tableparser = CreateAndWaitForParser(configPanel->GetRowString("Client") + "\n");
1114
1115       for (int i = tableparser->GetCount()-1; i > -1; i--) {
1116          wxString str = (*tableparser)[i][3];
1117          wxDateTime datetime;
1118          const char* chr;
1119          if ( ( (chr = datetime.ParseDate(str.GetData()) ) != NULL ) && ( datetime.ParseTime(++chr) != NULL ) ) {
1120             datetime += wxTimeSpan::Seconds(1);
1121             //wxbMainFrame::GetInstance()->Print(wxString("-") << datetime.Format("%Y-%m-%d %H:%M:%S"), CS_DEBUG);
1122             configPanel->AddRowChoice("Before", datetime.Format("%Y-%m-%d %H:%M:%S"));
1123          }
1124          /*else {
1125          jobChoice->Append("Invalid");
1126          }*/
1127       }
1128       
1129       delete tableparser;
1130
1131       configPanel->SetRowSelection("Before", 0);
1132    }
1133 }
1134
1135 /* List files and directories for a specified tree item */
1136 void wxbRestorePanel::CmdList(wxTreeItemId item) {
1137    if (status == choosing) {
1138       list->DeleteAllItems();
1139
1140       if (!item.IsOk()) {
1141          return;
1142       }
1143       UpdateTreeItem(item, true, false);
1144     
1145       if (list->GetItemCount() >= 1) {
1146          int firstwidth = list->GetSize().GetWidth(); 
1147          for (int i = 2; i < 7; i++) {
1148             list->SetColumnWidth(i, wxLIST_AUTOSIZE);
1149             firstwidth -= list->GetColumnWidth(i);
1150          }
1151        
1152          list->SetColumnWidth(0, 18);
1153          firstwidth -= 18;
1154          list->SetColumnWidth(1, wxLIST_AUTOSIZE);
1155          if (list->GetColumnWidth(1) < firstwidth) {
1156             list->SetColumnWidth(1, firstwidth-25);
1157          }
1158       }
1159    }
1160 }
1161
1162 /* Mark a treeitem (directory) or a listitem (file or directory) */
1163 void wxbRestorePanel::CmdMark(wxTreeItemId treeitem, long* listitems, int listsize, int state) {
1164    if (status == choosing) {
1165       wxbTreeItemData** itemdata;
1166       int itemdatasize = 0;
1167       if (listsize == 0) {
1168          itemdata = new wxbTreeItemData*[1];
1169          itemdatasize = 1;
1170       }
1171       else {
1172          itemdata = new wxbTreeItemData*[listsize];
1173          itemdatasize = listsize;
1174       }
1175       
1176       if (listitems != NULL) {
1177          for (int i = 0; i < listsize; i++) {
1178             itemdata[i] = (wxbTreeItemData*)list->GetItemData(listitems[i]);
1179          }
1180       }
1181       else if (treeitem.IsOk()) {
1182          itemdata[0] = (wxbTreeItemData*)tree->GetItemData(treeitem);
1183       }
1184       else {
1185          delete[] itemdata;
1186          return;
1187       }
1188
1189       if (itemdata[0] == NULL) { //Should never happen
1190          delete[] itemdata;
1191          return;
1192       }
1193
1194       wxString dir = itemdata[0]->GetPath();
1195       wxString file;
1196
1197       if (dir != "/") {
1198          if (dir.GetChar(dir.Length()-1) == '/') {
1199             dir.RemoveLast();
1200          }
1201
1202          int i = dir.Find('/', TRUE);
1203          if (i == -1) {
1204             file = dir;
1205             dir = "/";
1206          }
1207          else { /* first dir below root */
1208             file = dir.Mid(i+1);
1209             dir = dir.Mid(0, i+1);
1210          }
1211       }
1212       else {
1213          dir = "/";
1214          file = "*";
1215       }
1216
1217       if (state == -1) {
1218          bool marked = false;
1219          bool unmarked = false;
1220          state = 0;
1221          for (int i = 0; i < itemdatasize; i++) {
1222             switch(itemdata[i]->GetMarked()) {
1223             case 0:
1224                unmarked = true;
1225                break;
1226             case 1:
1227                marked = true;
1228                break;
1229             case 2:
1230                marked = true;
1231                unmarked = true;
1232                break;
1233             default:
1234                break;
1235             }
1236             if (marked && unmarked)
1237                break;
1238          }
1239          if (marked) {
1240             if (unmarked) {
1241                state = 1;
1242             }
1243             else {
1244                state = 0;
1245             }
1246          }
1247          else {
1248             state = 1;
1249          }
1250       }
1251
1252       WaitForEnd(wxString("cd \"") << dir << "\"\n");
1253       WaitForEnd(wxString((state==1) ? "mark" : "unmark") << " \"" << file << "\"\n");
1254
1255       /* TODO: Check commands results */
1256
1257       /*if ((dir == "/") && (file == "*")) {
1258             itemdata->SetMarked((itemdata->GetMarked() == 1) ? 0 : 1);
1259       }*/
1260
1261       if (listitems == NULL) { /* tree item state changed */
1262          SetTreeItemState(treeitem, state);
1263          /*treeitem = tree->GetSelection();
1264          UpdateTree(treeitem, true);
1265          treeitem = tree->GetItemParent(treeitem);*/
1266       }
1267       else {
1268          for (int i = 0; i < listsize; i++) {
1269             SetListItemState(listitems[i], state);
1270          }
1271          /*UpdateTree(treeitem, (tree->GetSelection() == treeitem));
1272          treeitem = tree->GetItemParent(treeitem);*/
1273       }
1274
1275       /*while (treeitem.IsOk()) {
1276          WaitForList(treeitem, false);
1277          treeitem = tree->GetItemParent(treeitem);
1278       }*/
1279       
1280       delete[] itemdata;
1281    }
1282 }
1283
1284 /*----------------------------------------------------------------------------
1285    General functions
1286   ----------------------------------------------------------------------------*/
1287
1288 /* Parse a table in tableParser */
1289 wxbTableParser* wxbRestorePanel::CreateAndWaitForParser(wxString cmd) {
1290    wxbTableParser* tableParser = new wxbTableParser();
1291
1292    wxbMainFrame::GetInstance()->Send(cmd);
1293
1294    //time_t base = wxDateTime::Now().GetTicks();
1295    while (!tableParser->hasFinished()) {
1296       //innerThread->Yield();
1297       wxTheApp->Yield(true);
1298       ::wxUsleep(100);
1299       //if (base+15 < wxDateTime::Now().GetTicks()) break;
1300    }
1301    return tableParser;
1302 }
1303
1304 /* Run a command, and waits until prompt result is fully received,
1305  * if keepresults is true, returns a valid pointer to a wxbPromptParser
1306  * containing the data. */
1307 wxbPromptParser* wxbRestorePanel::WaitForPrompt(wxString cmd, bool keepresults) {
1308    wxbPromptParser* promptParser = new wxbPromptParser();
1309    
1310    wxbMainFrame::GetInstance()->Send(cmd);
1311     
1312    //time_t base = wxDateTime::Now().GetTicks();
1313    while (!promptParser->hasFinished()) {
1314       //innerThread->Yield();
1315       wxTheApp->Yield(true);
1316       ::wxUsleep(100);
1317       //if (base+15 < wxDateTime::Now().GetTicks()) break;
1318    }
1319      
1320    if (keepresults) {
1321       return promptParser;
1322    }
1323    else {
1324       delete promptParser;
1325       return NULL;
1326    }  
1327 }
1328
1329 /* Run a command, and waits until result is fully received. */
1330 wxbDataTokenizer* wxbRestorePanel::WaitForEnd(wxString cmd, bool keepresults, bool linebyline) {
1331    wxbDataTokenizer* datatokenizer = new wxbDataTokenizer(linebyline);
1332
1333    wxbMainFrame::GetInstance()->Send(cmd);
1334    
1335    //wxbMainFrame::GetInstance()->Print("(<WFE)", CS_DEBUG);
1336    
1337    //time_t base = wxDateTime::Now().GetTicks();
1338    while (!datatokenizer->hasFinished()) {
1339       //innerThread->Yield();
1340       wxTheApp->Yield(true);
1341       ::wxUsleep(100);
1342       //if (base+15 < wxDateTime::Now().GetTicks()) break;
1343    }
1344    
1345    //wxbMainFrame::GetInstance()->Print("(>WFE)", CS_DEBUG);
1346    
1347    if (keepresults) {
1348       return datatokenizer;
1349    }
1350    else {
1351       delete datatokenizer;
1352       return NULL;
1353    }
1354 }
1355
1356 /* Run a dir command, and waits until result is fully received. */
1357 void wxbRestorePanel::UpdateTreeItem(wxTreeItemId item, bool updatelist, bool recurse) {
1358 //   this->updatelist = updatelist;
1359    wxbDataTokenizer* dt;
1360
1361    dt = WaitForEnd(wxString("cd \"") << 
1362       static_cast<wxbTreeItemData*>(tree->GetItemData(item))
1363          ->GetPath() << "\"\n", false);
1364
1365    /* TODO: check command result */
1366    
1367    //delete dt;
1368
1369    status = listing;
1370
1371    if (updatelist)
1372       list->DeleteAllItems();
1373    dt = WaitForEnd("dir\n", true);
1374    
1375    wxString str;
1376    
1377    for (unsigned int i = 0; i < dt->GetCount(); i++) {
1378       str = (*dt)[i];
1379       
1380       if (str.Find("cwd is:") == 0) { // Sometimes cd command result "infiltrate" into listings.
1381          break;
1382       }
1383
1384       str.RemoveLast();
1385
1386       wxString* file = ParseList(str);
1387       
1388       if (file == NULL)
1389             break;
1390
1391       wxTreeItemId treeid;
1392
1393       if (file[8].GetChar(file[8].Length()-1) == '/') {
1394          wxString itemStr;
1395
1396          long cookie;
1397          treeid = tree->GetFirstChild(item, cookie);
1398
1399          bool updated = false;
1400
1401          while (treeid.IsOk()) {
1402             itemStr = tree->GetItemText(treeid);
1403             if (file[8] == itemStr) {
1404                int stat = wxbTreeItemData::GetMarkedStatus(file[6]);
1405                if (static_cast<wxbTreeItemData*>(tree->GetItemData(treeid))->GetMarked() != stat) {
1406                   tree->SetItemImage(treeid, stat, wxTreeItemIcon_Normal);
1407                   tree->SetItemImage(treeid, stat, wxTreeItemIcon_Selected);
1408                   static_cast<wxbTreeItemData*>(tree->GetItemData(treeid))->SetMarked(file[6]);
1409                }
1410                if ((recurse) && (tree->IsExpanded(treeid))) {
1411                   UpdateTreeItem(treeid, false, true);
1412                }
1413                updated = true;
1414                break;
1415             }
1416             treeid = tree->GetNextChild(item, cookie);
1417          }
1418
1419          if (!updated) {
1420             int img = wxbTreeItemData::GetMarkedStatus(file[6]);
1421             treeid = tree->AppendItem(item, file[8], img, img, new wxbTreeItemData(file[7], file[8], file[6]));
1422          }
1423       }
1424
1425       if (updatelist) {
1426          long ind = list->InsertItem(list->GetItemCount(), wxbTreeItemData::GetMarkedStatus(file[6]));
1427          wxbTreeItemData* data = new wxbTreeItemData(file[7], file[8], file[6], ind);
1428          data->SetId(treeid);
1429          list->SetItemData(ind, (long)data);
1430          list->SetItem(ind, 1, file[8]); // filename
1431          list->SetItem(ind, 2, file[4]); //Size
1432          list->SetItem(ind, 3, file[5]); //date
1433          list->SetItem(ind, 4, file[0]); //perm
1434          list->SetItem(ind, 5, file[2]); //user
1435          list->SetItem(ind, 6, file[3]); //grp
1436       }
1437
1438       delete[] file;
1439    }
1440    
1441    delete dt;
1442    
1443    tree->Refresh();
1444    status = choosing;
1445 }
1446
1447 /* Parse dir command results. */
1448 wxString* wxbRestorePanel::ParseList(wxString line) {
1449    //drwx------  11 1003    42949672      0  2001-07-30 16:45:14 *filename
1450    //+ 10    ++ 4++   10   ++   8  ++   8  + +      19         + *+ ->
1451    //0       10  14         24      32       42                  62
1452
1453    if (line.Length() < 63)
1454       return NULL;
1455
1456    wxString* ret = new wxString[9];
1457
1458    ret[0] = line.Mid(0, 10).Trim();
1459    ret[1] = line.Mid(10, 4).Trim();
1460    ret[2] = line.Mid(14, 10).Trim();
1461    ret[3] = line.Mid(24, 8).Trim();
1462    ret[4] = line.Mid(32, 8).Trim();
1463    ret[5] = line.Mid(42, 19).Trim();
1464    ret[6] = line.Mid(62, 1);
1465    ret[7] = line.Mid(63).Trim();
1466
1467    if (ret[6] == " ") ret[6] = "";
1468
1469    if (ret[7].GetChar(ret[7].Length()-1) == '/') {
1470       ret[8] = ret[7];
1471       ret[8].RemoveLast();
1472       ret[8] = ret[7].Mid(ret[8].Find('/', true)+1);
1473    }
1474    else {
1475       ret[8] = ret[7].Mid(ret[7].Find('/', true)+1);
1476    }
1477
1478    return ret;
1479 }
1480
1481 /* Sets a list item state, and update its parents and children if it is a directory */
1482 void wxbRestorePanel::SetListItemState(long listitem, int newstate) {
1483    wxbTreeItemData* itemdata = (wxbTreeItemData*)list->GetItemData(listitem);
1484    
1485    wxTreeItemId treeitem;
1486    
1487    itemdata->SetMarked(newstate);
1488    list->SetItemImage(listitem, newstate, 0); /* TODO: Find what these ints are for */
1489    list->SetItemImage(listitem, newstate, 1);
1490       
1491    if ((treeitem = itemdata->GetId()).IsOk()) {
1492       SetTreeItemState(treeitem, newstate);
1493    }
1494    else {
1495       UpdateTreeItemState(tree->GetSelection());
1496    }
1497 }
1498
1499 /* Sets a tree item state, and update its children, parents and list (if necessary) */
1500 void wxbRestorePanel::SetTreeItemState(wxTreeItemId item, int newstate) {
1501    long cookie;
1502    wxTreeItemId currentChild = tree->GetFirstChild(item, cookie);
1503
1504    wxbTreeItemData* itemdata;
1505
1506    while (currentChild.IsOk()) {
1507       itemdata = (wxbTreeItemData*)tree->GetItemData(currentChild);
1508       int state = itemdata->GetMarked();
1509       
1510       if (state != newstate) {
1511          itemdata->SetMarked(newstate);
1512          tree->SetItemImage(currentChild, newstate, wxTreeItemIcon_Normal);
1513          tree->SetItemImage(currentChild, newstate, wxTreeItemIcon_Selected);
1514       }
1515       
1516       currentChild = tree->GetNextChild(item, cookie);
1517    }
1518      
1519    itemdata = (wxbTreeItemData*)tree->GetItemData(item);  
1520    itemdata->SetMarked(newstate);
1521    tree->SetItemImage(item, newstate, wxTreeItemIcon_Normal);
1522    tree->SetItemImage(item, newstate, wxTreeItemIcon_Selected);
1523    tree->Refresh();
1524    
1525    if (tree->GetSelection() == item) {
1526       for (long i = 0; i < list->GetItemCount(); i++) {
1527          list->SetItemImage(i, newstate, 0); /* TODO: Find what these ints are for */
1528          list->SetItemImage(i, newstate, 1);
1529       }
1530    }
1531    
1532    UpdateTreeItemState(tree->GetItemParent(item));
1533 }
1534
1535 /* Update a tree item state, and its parents' state */
1536 void wxbRestorePanel::UpdateTreeItemState(wxTreeItemId item) {  
1537    if (!item.IsOk()) {
1538       return;
1539    }
1540    
1541    int state = 0;
1542        
1543    long cookie;
1544    wxTreeItemId currentChild = tree->GetFirstChild(item, cookie);
1545
1546    bool onechildmarked = false;
1547    bool onechildunmarked = false;
1548
1549    while (currentChild.IsOk()) {
1550       state = ((wxbTreeItemData*)tree->GetItemData(currentChild))->GetMarked();
1551       switch (state) {
1552       case 0:
1553          onechildunmarked = true;
1554          break;
1555       case 1:
1556          onechildmarked = true;
1557          break;
1558       case 2:
1559          onechildmarked = true;
1560          onechildunmarked = true;
1561          break;
1562       }
1563       
1564       if (onechildmarked && onechildunmarked) {
1565          break;
1566       }
1567       
1568       currentChild = tree->GetNextChild(item, cookie);
1569    }
1570    
1571    if (tree->GetSelection() == item) {
1572       for (long i = 0; i < list->GetItemCount(); i++) {
1573          state = ((wxbTreeItemData*)list->GetItemData(i))->GetMarked();
1574          
1575          switch (state) {
1576          case 0:
1577             onechildunmarked = true;
1578             break;
1579          case 1:
1580             onechildmarked = true;
1581             break;
1582          case 2:
1583             onechildmarked = true;
1584             onechildunmarked = true;
1585             break;
1586          }
1587          
1588          if (onechildmarked && onechildunmarked) {
1589             break;
1590          }
1591       }
1592    }
1593    
1594    state = 0;
1595    
1596    if (onechildmarked && onechildunmarked) {
1597       state = 2;
1598    }
1599    else if (onechildmarked) {
1600       state = 1;
1601    }
1602    else if (onechildunmarked) {
1603       state = 0;
1604    }
1605    else { // no child, don't change anything
1606       UpdateTreeItemState(tree->GetItemParent(item));
1607       return;
1608    }
1609    
1610    wxbTreeItemData* itemdata = (wxbTreeItemData*)tree->GetItemData(item);
1611       
1612    itemdata->SetMarked(state);
1613    tree->SetItemImage(item, state, wxTreeItemIcon_Normal);
1614    tree->SetItemImage(item, state, wxTreeItemIcon_Selected);
1615    
1616    UpdateTreeItemState(tree->GetItemParent(item));
1617 }
1618
1619 /* Refresh the whole tree. */
1620 void wxbRestorePanel::RefreshTree() {
1621    /* Save current selection */
1622    wxArrayString current;
1623    
1624    wxTreeItemId item = currentTreeItem;
1625    
1626    while ((item.IsOk()) && (item != tree->GetRootItem())) {
1627       current.Add(tree->GetItemText(item));
1628       item = tree->GetItemParent(item);
1629    }
1630
1631    /* Update the tree */
1632    UpdateTreeItem(tree->GetRootItem(), false, true);
1633
1634    /* Reselect the former selected item */   
1635    item = tree->GetRootItem();
1636    
1637    if (current.Count() == 0) {
1638       tree->SelectItem(item);
1639       return;
1640    }
1641    
1642    bool match;
1643    
1644    for (int i = current.Count()-1; i >= 0; i--) {
1645       long cookie;
1646       wxTreeItemId currentChild = tree->GetFirstChild(item, cookie);
1647       
1648       match = false;
1649       
1650       while (currentChild.IsOk()) {
1651          if (tree->GetItemText(currentChild) == current[i]) {
1652             item = currentChild;
1653             match = true;
1654             break;
1655          }
1656    
1657          currentChild = tree->GetNextChild(item, cookie);
1658       }
1659       
1660       if (!match) break;
1661    }
1662    
1663    UpdateTreeItem(item, true, false); /* Update the list */
1664    
1665    tree->SelectItem(item);
1666 }
1667
1668 void wxbRestorePanel::RefreshList() {
1669    if (currentTreeItem.IsOk()) {
1670       UpdateTreeItem(currentTreeItem, true, false); /* Update the list */
1671    }
1672 }
1673
1674 /* Update first config, adapting settings to the job name selected */
1675 void wxbRestorePanel::UpdateFirstConfig() {
1676    configPanel->Enable(false);
1677    wxbDataTokenizer* dt = WaitForEnd(wxString(".defaults job=") + configPanel->GetRowString("Job Name") + "\n", true, false);
1678    /* job=RestoreFiles
1679     * pool=Default
1680     * messages=Standard
1681     * client=***
1682     * storage=File
1683     * where=/tmp/bacula-restores
1684     * level=0
1685     * type=Restore
1686     * fileset=Full Set */
1687    
1688    wxString name, str;
1689    unsigned int i;
1690    int j;
1691    wxString client;
1692    bool dolistjobs = false;
1693    
1694    for (i = 0; i < dt->GetCount(); i++) {
1695       str = (*dt)[i];
1696       if ((j = str.Find('=')) > -1) {
1697          name = str.Mid(0, j);
1698          if (name == "pool") {
1699             configPanel->SetRowString("Pool", str.Mid(j+1));
1700          }
1701          else if (name == "client") {
1702             str = str.Mid(j+1);
1703             if ((str != configPanel->GetRowString("Client")) || (configPanel->GetRowString("Before") == "")) {
1704                configPanel->SetRowString("Client", str);
1705                dolistjobs = true;
1706             }
1707          }
1708          else if (name == "storage") {
1709             configPanel->SetRowString("Storage", str.Mid(j+1));
1710          }
1711          else if (name == "fileset") {
1712             configPanel->SetRowString("Fileset", str.Mid(j+1));
1713          }
1714       }
1715    }
1716       
1717    delete dt;
1718    
1719    if (dolistjobs) {
1720       //wxTheApp->Yield(false);
1721       CmdListJobs();
1722    }
1723    configPanel->Enable(true);
1724 }
1725
1726 /* 
1727  * Update second config.
1728  * 
1729  * Run Restore job
1730  * JobName:    RestoreFiles
1731  * Bootstrap:  /var/lib/bacula/restore.bsr
1732  * Where:      /tmp/bacula-restores
1733  * Replace:    always
1734  * FileSet:    Full Set
1735  * Client:     tom-fd
1736  * Storage:    File
1737  * When:       2004-04-18 01:18:56
1738  * Priority:   10
1739  * OK to run? (yes/mod/no):
1740  * 
1741  */
1742 bool wxbRestorePanel::UpdateSecondConfig(wxbDataTokenizer* dt) {
1743    unsigned int i;
1744    for (i = 0; i < dt->GetCount(); i++) {
1745       if ((*dt)[i].Find("Run Restore job") == 0)
1746          break;
1747    }
1748    
1749    if ((i + 10) > dt->GetCount()) {
1750       return false;
1751    }
1752    
1753    int k;
1754    
1755    if ((k = (*dt)[++i].Find("JobName:")) != 0) return false;
1756    restorePanel->SetRowString("Job Name", (*dt)[i].Mid(10).Trim(false).RemoveLast());
1757    if ((k = (*dt)[++i].Find("Bootstrap:")) != 0) return false;
1758    restorePanel->SetRowString("Bootstrap", (*dt)[i].Mid(10).Trim(false).RemoveLast());
1759    if ((k = (*dt)[++i].Find("Where:")) != 0) return false;
1760    restorePanel->SetRowString("Where", (*dt)[i].Mid(10).Trim(false).RemoveLast());
1761    
1762    if ((k = (*dt)[++i].Find("Replace:")) != 0) return false;
1763    wxString str = (*dt)[i].Mid(10).Trim(false).RemoveLast();
1764    if (str == "always") restorePanel->SetRowSelection("Replace", 0);
1765    else if (str == "ifnewer") restorePanel->SetRowSelection("Replace", 1);
1766    else if (str == "ifolder") restorePanel->SetRowSelection("Replace", 2);
1767    else if (str == "never") restorePanel->SetRowSelection("Replace", 3);
1768    else restorePanel->SetRowSelection("Replace", 0);
1769
1770    if ((k = (*dt)[++i].Find("FileSet:")) != 0) return false;
1771    restorePanel->SetRowString("Fileset", (*dt)[i].Mid(10).Trim(false).RemoveLast());
1772    if ((k = (*dt)[++i].Find("Client:")) != 0) return false;
1773    restorePanel->SetRowString("Client", (*dt)[i].Mid(10).Trim(false).RemoveLast());
1774    if ((k = (*dt)[++i].Find("Storage:")) != 0) return false;
1775    restorePanel->SetRowString("Storage", (*dt)[i].Mid(10).Trim(false).RemoveLast());
1776    if ((k = (*dt)[++i].Find("When:")) != 0) return false;
1777    restorePanel->SetRowString("When", (*dt)[i].Mid(10).Trim(false).RemoveLast());
1778    if ((k = (*dt)[++i].Find("Priority:")) != 0) return false;
1779    restorePanel->SetRowString("Priority", (*dt)[i].Mid(10).Trim(false).RemoveLast());
1780    cfgUpdated = 0;
1781    
1782    restorePanel->Layout();
1783    
1784    return true;
1785 }
1786
1787 /*----------------------------------------------------------------------------
1788    Status function
1789   ----------------------------------------------------------------------------*/
1790
1791 /* Set current status by enabling/disabling components */
1792 void wxbRestorePanel::SetStatus(status_enum newstatus) {
1793    switch (newstatus) {
1794    case disabled:
1795       centerSizer->Remove(configPanel);
1796       centerSizer->Remove(restorePanel);
1797       centerSizer->Remove(treelistPanel);
1798       treelistPanel->Show(false);
1799       restorePanel->Show(false);
1800       centerSizer->Add(configPanel, 1, wxEXPAND);
1801       configPanel->Show(true);
1802       configPanel->Layout();
1803       centerSizer->Layout();
1804       this->Layout();
1805       start->SetLabel("Enter restore mode");
1806       start->Enable(false);
1807       configPanel->Enable(false);
1808       tree->Enable(false);
1809       list->Enable(false);
1810       gauge->Enable(false);
1811       cancel->Enable(false);
1812       cfgUpdated = 0;
1813       cancelled = 0;
1814       break;
1815    case finished:
1816       centerSizer->Remove(configPanel);
1817       centerSizer->Remove(restorePanel);
1818       centerSizer->Remove(treelistPanel);
1819       treelistPanel->Show(false);
1820       restorePanel->Show(false);
1821       centerSizer->Add(configPanel, 1, wxEXPAND);
1822       configPanel->Show(true);
1823       configPanel->Layout();
1824       centerSizer->Layout();
1825       this->Layout();
1826       tree->DeleteAllItems();
1827       list->DeleteAllItems();
1828       configPanel->ClearRowChoices("Client");
1829       configPanel->ClearRowChoices("Before");
1830       wxbMainFrame::GetInstance()->EnablePanels();
1831       newstatus = activable;
1832    case activable:
1833       cancelled = 0;
1834       start->SetLabel("Enter restore mode");
1835       start->Enable(true);
1836       configPanel->Enable(false);
1837       tree->Enable(false);
1838       list->Enable(false);
1839       gauge->Enable(false);
1840       cancel->Enable(false);
1841       cfgUpdated = 0;
1842       break;
1843    case entered:
1844       wxbMainFrame::GetInstance()->DisablePanels(this);
1845       gauge->SetValue(0);
1846       start->Enable(false);
1847       //start->SetLabel("Choose files to restore");
1848       configPanel->Enable(true);
1849       tree->Enable(false);
1850       list->Enable(false);
1851       cancel->Enable(true);
1852       cfgUpdated = 0;
1853       break;
1854    case listing:
1855       
1856       break;
1857    case choosing:
1858       start->Enable(true);
1859       start->SetLabel("Restore");
1860       centerSizer->Remove(configPanel);
1861       configPanel->Show(false);
1862       centerSizer->Add(treelistPanel, 1, wxEXPAND);
1863       treelistPanel->Show(true);
1864       treelistPanel->Layout();
1865       centerSizer->Layout();
1866       this->Layout();
1867       tree->Enable(true);
1868       list->Enable(true);
1869       SetWorking(false);
1870       break;
1871    case configuring:
1872       start->Enable(false);
1873       configPanel->Enable(false);
1874       tree->Enable(false);
1875       list->Enable(false);
1876       centerSizer->Remove(treelistPanel);
1877       treelistPanel->Show(false);
1878       centerSizer->Add(restorePanel, 1, wxEXPAND);
1879       restorePanel->Show(true);
1880       restorePanel->Layout();
1881       centerSizer->Layout();
1882       this->Layout();
1883       restorePanel->EnableApply(false);
1884       break;
1885    case restoring:
1886       start->SetLabel("Restoring...");
1887       gauge->Enable(true);
1888       gauge->SetValue(0);
1889       start->Enable(false);
1890       configPanel->Enable(false);
1891       tree->Enable(false);
1892       list->Enable(false);
1893       SetWorking(true);
1894       break;
1895    }
1896    status = newstatus;
1897 }
1898
1899 /*----------------------------------------------------------------------------
1900    UI related
1901   ----------------------------------------------------------------------------*/
1902
1903 void wxbRestorePanel::SetWorking(bool working) {
1904    this->working = working;
1905    if (working) {
1906       SetCursor(*wxHOURGLASS_CURSOR);
1907 //      SetEvtHandlerEnabled(false); //EVTQUEUE
1908    }
1909 //   else if (!processing) { /* Empty event queue if we aren't already doing this */ //EVTQUEUE
1910    else {
1911 //      processing = true; //EVTQUEUE
1912       SetCursor(*wxSTANDARD_CURSOR);
1913 //      SetEvtHandlerEnabled(true); //EVTQUEUE
1914 /*      wxNode *node = pendingEvents->First(); //EVTQUEUE
1915       while ( node ) {
1916          wxEvent *event = (wxEvent *)node->Data();
1917          delete node;
1918    
1919          wxEvtHandler::ProcessEvent(*event);
1920          delete event;
1921    
1922          node = pendingEvents->First();
1923       }
1924       processing = false;*/
1925    }
1926 }
1927
1928 bool wxbRestorePanel::IsWorking() {
1929    return this->working;
1930 }
1931
1932 void wxbRestorePanel::EnableConfig(bool enable) {
1933    restorePanel->Enable(enable);
1934 }
1935
1936 /*----------------------------------------------------------------------------
1937    Event handling
1938   ----------------------------------------------------------------------------*/
1939
1940
1941 //EVTQUEUE
1942 /*
1943 bool wxbRestorePanel::ProcessEvent(wxEvent& event) {
1944    if (IsWorking() || processing) {
1945       wxEvent *eventCopy = event.Clone();
1946       
1947       pendingEvents->Append(eventCopy);
1948       return TRUE;
1949    }
1950    else {
1951       return wxEvtHandler::ProcessEvent(event);
1952    }
1953 }
1954 */
1955
1956 void wxbRestorePanel::OnCancel(wxCommandEvent& event) {
1957    cancel->Enable(false);
1958    SetCursor(*wxHOURGLASS_CURSOR);
1959    CmdCancel();
1960    SetCursor(*wxSTANDARD_CURSOR);
1961 }
1962
1963 void wxbRestorePanel::OnStart(wxCommandEvent& event) {
1964    if (IsWorking()) {
1965       AddPendingEvent(event);
1966       return;
1967    }
1968    SetWorking(true);
1969    CmdStart();
1970    SetWorking(false);
1971 }
1972
1973 void wxbRestorePanel::OnTreeChanging(wxTreeEvent& event) {
1974    if (IsWorking()) {
1975       AddPendingEvent(event);
1976       event.Veto();
1977    }
1978 }
1979
1980 void wxbRestorePanel::OnTreeExpanding(wxTreeEvent& event) {
1981    if (IsWorking()) {
1982       AddPendingEvent(event);
1983       event.Veto();
1984       return;
1985    }
1986    //working = true;
1987    //CmdList(event.GetItem());
1988    if (tree->GetSelection() != event.GetItem()) {
1989       tree->SelectItem(event.GetItem());
1990    }
1991    //working = false;
1992 }
1993
1994 void wxbRestorePanel::OnTreeChanged(wxTreeEvent& event) {
1995    if (IsWorking()) {
1996       AddPendingEvent(event);
1997       return;
1998    }
1999    if (currentTreeItem == event.GetItem()) {
2000       return;
2001    }
2002    treeadd->Enable(false);
2003    treeremove->Enable(false);
2004    treerefresh->Enable(false);
2005    markWhenListingDone = false;
2006    SetWorking(true);
2007    currentTreeItem = event.GetItem();
2008    CmdList(event.GetItem());
2009    if (markWhenListingDone) {
2010       CmdMark(event.GetItem(), NULL, 0);
2011       tree->Refresh();
2012    }
2013    SetWorking(false);
2014    if (event.GetItem().IsOk()) {
2015       int status = ((wxbTreeItemData*)tree->GetItemData(event.GetItem()))->GetMarked();
2016       treeadd->Enable(status != 1);
2017       treeremove->Enable(status != 0);
2018    }
2019    treerefresh->Enable(true);
2020 }
2021
2022 void wxbRestorePanel::OnTreeMarked(wxbTreeMarkedEvent& event) {
2023    csprint("Tree marked", CS_DEBUG);
2024    if (IsWorking()) {
2025       if (tree->GetSelection() == event.GetItem()) {
2026          markWhenListingDone = !markWhenListingDone;
2027       }
2028       AddPendingEvent(event);
2029       return;
2030    }
2031    SetWorking(true);
2032    CmdMark(event.GetItem(), NULL, 0);
2033    //event.Skip();
2034    tree->Refresh();
2035    SetWorking(false);
2036    if (event.GetItem().IsOk()) {
2037       int status = ((wxbTreeItemData*)tree->GetItemData(event.GetItem()))->GetMarked();
2038       treeadd->Enable(status != 1);
2039       treeremove->Enable(status != 0);
2040    }
2041 }
2042
2043 void wxbRestorePanel::OnTreeAdd(wxCommandEvent& event) {
2044    if (IsWorking()) {
2045       AddPendingEvent(event);
2046       return;
2047    }
2048    
2049    if (currentTreeItem.IsOk()) {
2050       SetWorking(true);
2051       CmdMark(currentTreeItem, NULL, 0, 1);
2052       tree->Refresh();
2053       treeadd->Enable(0);
2054       treeremove->Enable(1);
2055       SetWorking(false);
2056    }
2057 }
2058
2059 void wxbRestorePanel::OnTreeRemove(wxCommandEvent& event) {
2060    if (IsWorking()) {
2061       AddPendingEvent(event);
2062       return;
2063    }
2064    
2065    if (currentTreeItem.IsOk()) {
2066       SetWorking(true);
2067       CmdMark(currentTreeItem, NULL, 0, 0);
2068       tree->Refresh();
2069       treeadd->Enable(1);
2070       treeremove->Enable(0);
2071       SetWorking(false);
2072    }
2073 }
2074
2075 void wxbRestorePanel::OnTreeRefresh(wxCommandEvent& event) {
2076    if (IsWorking()) {
2077       AddPendingEvent(event);
2078       return;
2079    }
2080    
2081    SetWorking(true);
2082    RefreshTree();
2083    SetWorking(false);
2084 }
2085
2086 void wxbRestorePanel::OnListMarked(wxbListMarkedEvent& event) {
2087    if (IsWorking()) {
2088       AddPendingEvent(event);
2089       //event.Skip();
2090       return;
2091    }
2092    
2093    if (list->GetSelectedItemCount() == 0) {
2094       return;
2095    }
2096    
2097    SetWorking(true);  
2098    
2099    long* items = new long[list->GetSelectedItemCount()];
2100    
2101    int num = 0;
2102    
2103    long item = list->GetNextItem(-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
2104    while (item != -1) {
2105       items[num] = item;
2106       num++;
2107       item = list->GetNextItem(item, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
2108    }
2109      
2110    CmdMark(wxTreeItemId(), items, num);
2111    
2112    delete[] items;
2113    
2114    wxListEvent listevt;
2115    
2116    OnListChanged(listevt);
2117    
2118    event.Skip();
2119    tree->Refresh();
2120    SetWorking(false);
2121 }
2122
2123 void wxbRestorePanel::OnListActivated(wxListEvent& event) {
2124    if (IsWorking()) {
2125       AddPendingEvent(event);
2126       //event.Skip();
2127       return;
2128    }
2129    SetWorking(true);
2130    long item = event.GetIndex();
2131 //   long item = list->GetNextItem(-1, wxLIST_NEXT_ALL, wxLIST_STATE_FOCUSED);
2132    if (item > -1) {
2133       wxbTreeItemData* itemdata = (wxbTreeItemData*)list->GetItemData(item);
2134       wxString name = itemdata->GetName();
2135       event.Skip();
2136
2137       wxString itemStr;
2138
2139       long cookie;
2140
2141       if (name.GetChar(name.Length()-1) == '/') {
2142          wxTreeItemId currentChild = tree->GetFirstChild(currentTreeItem, cookie);
2143
2144          while (currentChild.IsOk()) {
2145             wxString name2 = tree->GetItemText(currentChild);
2146             if (name2 == name) {
2147                //tree->UnselectAll();
2148                SetWorking(false);
2149                tree->Expand(currentTreeItem);
2150                tree->SelectItem(currentChild);
2151                //tree->Refresh();
2152                return;
2153             }
2154             currentChild = tree->GetNextChild(currentTreeItem, cookie);
2155          }
2156       }
2157    }
2158    SetWorking(false);
2159 }
2160
2161 void wxbRestorePanel::OnListChanged(wxListEvent& event) {
2162    if (IsWorking()) {
2163       AddPendingEvent(event);
2164       return;
2165    }
2166  
2167    listadd->Enable(false);
2168    listremove->Enable(false);
2169    
2170    bool marked = false;
2171    bool unmarked = false;
2172    
2173    long item = list->GetNextItem(-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
2174    while (item != -1) {
2175       switch (((wxbTreeItemData*)list->GetItemData(item))->GetMarked()) {
2176       case 0:
2177          unmarked = true;
2178          break;
2179       case 1:
2180          marked = true;
2181          break;
2182       case 2:
2183          marked = true;
2184          unmarked = true;
2185          break;
2186       default:
2187          break;
2188          // Should never happen
2189       }
2190       if (marked && unmarked) break;
2191       item = list->GetNextItem(item, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
2192    }
2193    
2194    listadd->Enable(unmarked);
2195    listremove->Enable(marked);
2196 }
2197
2198 void wxbRestorePanel::OnListAdd(wxCommandEvent& event) {
2199    if (IsWorking()) {
2200       AddPendingEvent(event);
2201       return;
2202    }
2203    
2204    SetWorking(true);
2205    
2206    long* items = new long[list->GetSelectedItemCount()];
2207    
2208    int num = 0;
2209    
2210    long item = list->GetNextItem(-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
2211    while (item != -1) {
2212       items[num] = item;
2213       num++;
2214       item = list->GetNextItem(item, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
2215    }
2216      
2217    CmdMark(wxTreeItemId(), items, num, 1);
2218    
2219    delete[] items;
2220    
2221    tree->Refresh();
2222    SetWorking(false);
2223    
2224    listadd->Enable(false);
2225    listremove->Enable(true);
2226 }
2227
2228 void wxbRestorePanel::OnListRemove(wxCommandEvent& event) {
2229    if (IsWorking()) {
2230       AddPendingEvent(event);
2231       return;
2232    }
2233    
2234    SetWorking(true);
2235    
2236    long* items = new long[list->GetSelectedItemCount()];
2237    
2238    int num = 0;
2239    
2240    long item = list->GetNextItem(-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
2241    while (item != -1) {
2242       items[num] = item;
2243       num++;
2244       item = list->GetNextItem(item, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
2245    }
2246      
2247    CmdMark(wxTreeItemId(), items, num, 0);
2248    
2249    delete[] items;
2250    
2251    tree->Refresh();
2252    SetWorking(false);
2253    
2254    listadd->Enable(true);
2255    listremove->Enable(false);
2256 }
2257
2258 void wxbRestorePanel::OnListRefresh(wxCommandEvent& event) {
2259    if (IsWorking()) {
2260       AddPendingEvent(event);
2261       return;
2262    }
2263    
2264    SetWorking(true);
2265    RefreshList();
2266    SetWorking(false);
2267 }
2268
2269 void wxbRestorePanel::OnConfigUpdated(wxCommandEvent& event) {
2270    if (status == entered) {
2271       if (event.GetId() == ConfigJobName) {
2272          if (IsWorking()) {
2273             return;
2274          }
2275          SetWorking(true);
2276          UpdateFirstConfig();
2277          SetWorking(false);
2278       }
2279       else if (event.GetId() == ConfigClient) {
2280          if (IsWorking()) {
2281             return;
2282          }
2283          SetWorking(true);
2284          configPanel->Enable(false);
2285          CmdListJobs();
2286          configPanel->Enable(true);
2287          SetWorking(false);
2288       }
2289       cfgUpdated = cfgUpdated | (1 << event.GetId());
2290    }
2291    else if (status == configuring) {
2292       restorePanel->EnableApply(true);
2293       cfgUpdated = cfgUpdated | (1 << event.GetId());
2294    }
2295 }
2296
2297 void wxbRestorePanel::OnConfigOk(wxCommandEvent& WXUNUSED(event)) {
2298    if (status != configuring) return;
2299    if (IsWorking()) {
2300       return;
2301    }
2302    SetWorking(true);
2303    CmdStart();
2304    SetWorking(false);
2305 }
2306
2307 void wxbRestorePanel::OnConfigApply(wxCommandEvent& WXUNUSED(event)) {
2308    if (status != configuring) return;
2309    if (IsWorking()) {
2310       return;
2311    }
2312    SetWorking(true);
2313    CmdConfigApply();
2314    if (cfgUpdated == 0) {
2315       restorePanel->EnableApply(false);
2316    }
2317    SetWorking(false);  
2318 }
2319
2320 void wxbRestorePanel::OnConfigCancel(wxCommandEvent& WXUNUSED(event)) {
2321    if (status != configuring) return;
2322    if (IsWorking()) {
2323       return;
2324    }
2325    SetWorking(true);
2326    CmdConfigCancel();
2327    SetWorking(false);
2328 }
2329