]> git.sur5r.net Git - bacula/bacula/blobdiff - bacula/src/wx-console/wxbrestorepanel.cpp
- wxbHistoryTextCtrl : Created a new text control that keep an history
[bacula/bacula] / bacula / src / wx-console / wxbrestorepanel.cpp
index fcefcacdd6dc0cb07b68c20a636410694e582d8d..e058f5918d1cc2fdfa99960a900328563b5a7248 100644 (file)
@@ -1,3 +1,10 @@
+/*
+ *
+ *   wxbPanel for restoring files
+ *
+ *    Nicolas Boichat, April-May 2004
+ *
+ */
 /*
    Copyright (C) 2004 Kern Sibbald and John Walker
 
  */
 /* Note concerning "done" output (modifiable marked with +)
 Run Restore job
-JobName:    RestoreFiles
++JobName:    RestoreFiles
 Bootstrap:  /var/lib/bacula/restore.bsr
 +Where:      /tmp/bacula-restores
 +Replace:    always
-FileSet:    Full Set
-Client:     tom-fd
-Storage:    File
++FileSet:    Full Set
++Client:     tom-fd
++Storage:    File
 +When:       2004-04-18 01:18:56
 +Priority:   10
 OK to run? (yes/mod/no):mod
@@ -31,8 +38,8 @@ Parameters to modify:
      1: Level (not appropriate)
      2: Storage (automatic ?)
      3: Job (no)
-     4: FileSet (no)
-     5: Client (no)
+     4: FileSet (yes)
+     5: Client (yes : "The defined Client resources are:\n\t1: velours-fd\n\t2: tom-fd\nSelect Client (File daemon) resource (1-2):")
      6: When (yes : "Please enter desired start time as YYYY-MM-DD HH:MM:SS (return for now):")
      7: Priority (yes : "Enter new Priority: (positive integer)")
      8: Bootstrap (?)
@@ -52,13 +59,19 @@ Select parameter to modify (1-11):
 #include <wx/choice.h>
 #include <wx/datetime.h>
 
+#include <wx/timer.h>
+
 #include "unmarked.xpm"
 #include "marked.xpm"
 #include "partmarked.xpm"
 
+#include <wx/listimpl.cpp>
+
 /* A macro named Yield is defined under MinGW */
 #undef Yield
 
+WX_DEFINE_LIST(wxbEventList);
+
 /*
  *  Class which is stored in the tree and in the list to keep informations
  *  about the element.
@@ -162,49 +175,73 @@ int wxbTreeItemData::GetMarkedStatus(wxString file) {
 enum
 {
    RestoreStart = 1,
-   TreeCtrl = 2,
-   ListCtrl = 3,
-   ClientChoice = 4,
+   RestoreCancel = 2,
+   TreeCtrl = 3,
+   ListCtrl = 4,
    ConfigOk = 5,
    ConfigApply = 6,
    ConfigCancel = 7,
    ConfigWhere = 8,
    ConfigReplace = 9,
    ConfigWhen = 10,
-   ConfigPriority = 11
+   ConfigPriority = 11,
+   ConfigClient = 12,
+   ConfigFileset = 13,
+   ConfigStorage = 14,
+   ConfigJobName = 15,
+   ConfigPool = 16,
+   TreeAdd = 17,
+   TreeRemove = 18,
+   TreeRefresh = 19,
+   ListAdd = 20,
+   ListRemove = 21,
+   ListRefresh = 22
 };
 
 BEGIN_EVENT_TABLE(wxbRestorePanel, wxPanel)
    EVT_BUTTON(RestoreStart, wxbRestorePanel::OnStart)
-   EVT_CHOICE(ClientChoice, wxbRestorePanel::OnClientChoiceChanged)   
+   EVT_BUTTON(RestoreCancel, wxbRestorePanel::OnCancel)
    
    EVT_TREE_SEL_CHANGING(TreeCtrl, wxbRestorePanel::OnTreeChanging)
    EVT_TREE_SEL_CHANGED(TreeCtrl, wxbRestorePanel::OnTreeChanged)
    EVT_TREE_ITEM_EXPANDING(TreeCtrl, wxbRestorePanel::OnTreeExpanding)
+   EVT_TREE_MARKED_EVENT(TreeCtrl, wxbRestorePanel::OnTreeMarked)
+   EVT_BUTTON(TreeAdd, wxbRestorePanel::OnTreeAdd)
+   EVT_BUTTON(TreeRemove, wxbRestorePanel::OnTreeRemove)
+   EVT_BUTTON(TreeRefresh, wxbRestorePanel::OnTreeRefresh)
+
    EVT_LIST_ITEM_ACTIVATED(ListCtrl, wxbRestorePanel::OnListActivated)
-     
-   /*EVT_TREE_MARKED_EVENT(wxID_ANY, wxbRestorePanel::OnTreeMarked)
-   EVT_LIST_MARKED_EVENT(wxID_ANY, wxbRestorePanel::OnListMarked)*/
+   EVT_LIST_MARKED_EVENT(ListCtrl, wxbRestorePanel::OnListMarked)
+   EVT_LIST_ITEM_SELECTED(ListCtrl, wxbRestorePanel::OnListChanged)
+   EVT_LIST_ITEM_DESELECTED(ListCtrl, wxbRestorePanel::OnListChanged)
+   EVT_BUTTON(ListAdd, wxbRestorePanel::OnListAdd)
+   EVT_BUTTON(ListRemove, wxbRestorePanel::OnListRemove)
+   EVT_BUTTON(ListRefresh, wxbRestorePanel::OnListRefresh)
   
    EVT_TEXT(ConfigWhere, wxbRestorePanel::OnConfigUpdated)
    EVT_TEXT(ConfigWhen, wxbRestorePanel::OnConfigUpdated)
    EVT_TEXT(ConfigPriority, wxbRestorePanel::OnConfigUpdated)
+   EVT_CHOICE(ConfigWhen, wxbRestorePanel::OnConfigUpdated)
    EVT_CHOICE(ConfigReplace, wxbRestorePanel::OnConfigUpdated)
+   EVT_CHOICE(ConfigClient, wxbRestorePanel::OnConfigUpdated)
+   EVT_CHOICE(ConfigFileset, wxbRestorePanel::OnConfigUpdated)
+   EVT_CHOICE(ConfigStorage, wxbRestorePanel::OnConfigUpdated)
+   EVT_CHOICE(ConfigJobName, wxbRestorePanel::OnConfigUpdated)
+   EVT_CHOICE(ConfigPool, wxbRestorePanel::OnConfigUpdated)
    
    EVT_BUTTON(ConfigOk, wxbRestorePanel::OnConfigOk)
    EVT_BUTTON(ConfigApply, wxbRestorePanel::OnConfigApply)
    EVT_BUTTON(ConfigCancel, wxbRestorePanel::OnConfigCancel)
 END_EVENT_TABLE()
 
-BEGIN_EVENT_TABLE(wxbTreeListPanel, wxPanel)
-   EVT_TREE_MARKED_EVENT(wxID_ANY, wxbTreeListPanel::OnTreeMarked)
-   EVT_LIST_MARKED_EVENT(wxID_ANY, wxbTreeListPanel::OnListMarked)   
-END_EVENT_TABLE()
-
 /*
  *  wxbRestorePanel constructor
  */
 wxbRestorePanel::wxbRestorePanel(wxWindow* parent): wxbPanel(parent) {
+   //pendingEvents = new wxbEventList(); //EVTQUEUE
+   //processing = false; //EVTQUEUE
+   SetWorking(false);
+   
    imagelist = new wxImageList(16, 16, TRUE, 3);
    imagelist->Add(wxIcon(unmarked_xpm));
    imagelist->Add(wxIcon(marked_xpm));
@@ -214,32 +251,58 @@ wxbRestorePanel::wxbRestorePanel(wxWindow* parent): wxbPanel(parent) {
    mainSizer->AddGrowableCol(0);
    mainSizer->AddGrowableRow(1);
 
-   wxBoxSizer *firstSizer = new wxBoxSizer(wxHORIZONTAL);
+   wxFlexGridSizer *firstSizer = new wxFlexGridSizer(1, 2, 10, 10);
+
+   firstSizer->AddGrowableCol(0);
+   firstSizer->AddGrowableRow(0);
 
    start = new wxButton(this, RestoreStart, "Enter restore mode", wxDefaultPosition, wxSize(150, 30));
-   firstSizer->Add(start, 1, wxALIGN_CENTER_HORIZONTAL | wxALIGN_CENTER_VERTICAL, 10);
+   firstSizer->Add(start, 0, wxALIGN_CENTER_HORIZONTAL | wxALIGN_CENTER_VERTICAL, 10);
+
+   cancel = new wxButton(this, RestoreCancel, "Cancel restore", wxDefaultPosition, wxSize(150, 30));
+   firstSizer->Add(cancel, 0, wxALIGN_CENTER_HORIZONTAL | wxALIGN_RIGHT, 10);
 
-   wxString* elist = new wxString[1];
+   wxString elist[1];
 
-   clientChoice = new wxChoice(this, ClientChoice, wxDefaultPosition, wxSize(150, 30), 0, elist);
+/*   clientChoice = new wxChoice(this, ClientChoice, wxDefaultPosition, wxSize(150, 30), 0, elist);
    firstSizer->Add(clientChoice, 1, wxALIGN_CENTER_HORIZONTAL | wxALIGN_CENTER_VERTICAL, 10);
 
    jobChoice = new wxChoice(this, -1, wxDefaultPosition, wxSize(150, 30), 0, elist);
-   firstSizer->Add(jobChoice, 1, wxALIGN_CENTER_HORIZONTAL | wxALIGN_CENTER_VERTICAL, 10);
+   firstSizer->Add(jobChoice, 1, wxALIGN_CENTER_HORIZONTAL | wxALIGN_CENTER_VERTICAL, 10);*/
 
-   mainSizer->Add(firstSizer, 1, wxALIGN_CENTER_HORIZONTAL | wxALIGN_CENTER_VERTICAL, 10);
+   mainSizer->Add(firstSizer, 1, wxEXPAND, 10);
 
-   treelistPanel = new wxbTreeListPanel(this);
-   
-   wxFlexGridSizer* treelistSizer = new wxFlexGridSizer(1, 2, 10, 10);
+   treelistPanel = new wxSplitterWindow(this);
 
-   tree = new wxbTreeCtrl(treelistPanel, TreeCtrl, wxDefaultPosition, wxSize(200,50));
-   treelistSizer->Add(tree, 1, wxALIGN_CENTER_HORIZONTAL | wxALIGN_CENTER_VERTICAL | wxEXPAND, 10);
+   wxPanel* treePanel = new wxPanel(treelistPanel);
+   wxFlexGridSizer *treeSizer = new wxFlexGridSizer(2, 1, 0, 0);
+   treeSizer->AddGrowableCol(0);
+   treeSizer->AddGrowableRow(0);
 
+   tree = new wxbTreeCtrl(treePanel, this, TreeCtrl, wxDefaultPosition, wxSize(200,50));  
    tree->SetImageList(imagelist);
    
-   list = new wxbListCtrl(treelistPanel, ListCtrl, wxDefaultPosition, wxDefaultSize);
-   treelistSizer->Add(list, 1, wxALIGN_CENTER_HORIZONTAL | wxALIGN_CENTER_VERTICAL | wxEXPAND, 10);
+   treeSizer->Add(tree, 1, wxEXPAND, 0);
+   
+   wxBoxSizer *treeCtrlSizer = new wxBoxSizer(wxHORIZONTAL);
+   treeadd = new wxButton(treePanel, TreeAdd, "Add", wxDefaultPosition, wxSize(60, 25));
+   treeCtrlSizer->Add(treeadd, 0, wxLEFT | wxRIGHT, 3);
+   treeremove = new wxButton(treePanel, TreeRemove, "Remove", wxDefaultPosition, wxSize(60, 25));
+   treeCtrlSizer->Add(treeremove, 0, wxLEFT | wxRIGHT, 3);
+   treerefresh = new wxButton(treePanel, TreeRefresh, "Refresh", wxDefaultPosition, wxSize(60, 25));
+   treeCtrlSizer->Add(treerefresh, 0, wxLEFT | wxRIGHT, 3);
+   
+   treeSizer->Add(treeCtrlSizer, 1, wxALIGN_CENTER_HORIZONTAL, 0);
+   
+   treePanel->SetSizer(treeSizer);
+   
+   wxPanel* listPanel = new wxPanel(treelistPanel);
+   wxFlexGridSizer *listSizer = new wxFlexGridSizer(2, 1, 0, 0);
+   listSizer->AddGrowableCol(0);
+   listSizer->AddGrowableRow(0);
+   
+   list = new wxbListCtrl(listPanel, this, ListCtrl, wxDefaultPosition, wxSize(200,50));
+   //treelistSizer->Add(list, 1, wxEXPAND, 10);
 
    list->SetImageList(imagelist, wxIMAGE_LIST_SMALL);
 
@@ -272,76 +335,59 @@ wxbRestorePanel::wxbRestorePanel(wxWindow* parent): wxbPanel(parent) {
    info.SetText("Group");
    info.SetAlign(wxLIST_FORMAT_RIGHT);
    list->InsertColumn(6, info);
+    
+   listSizer->Add(list, 1, wxEXPAND, 0);
    
-   treelistSizer->AddGrowableCol(1);
-   treelistSizer->AddGrowableRow(0);
-   
-   treelistPanel->SetSizer(treelistSizer);
-   treelistSizer->SetSizeHints(treelistPanel);
-   
-   restorePanel = new wxPanel(this, -1);
-   
-   wxBoxSizer* restoreSizer = new wxBoxSizer(wxVERTICAL);
-   
-   wxGridSizer* cfgSizer = new wxGridSizer(9, 2, 5, 5);
-   
-   cfgJobname = new wxStaticText(restorePanel, -1, "  ", wxDefaultPosition, wxSize(150, 15), wxALIGN_LEFT);
-   cfgBootstrap = new wxStaticText(restorePanel, -1, "  ", wxDefaultPosition, wxSize(150, 15), wxALIGN_LEFT);
-   cfgWhere = new wxTextCtrl(restorePanel, ConfigWhere, "", wxDefaultPosition, wxSize(150, 15));
-   elist = new wxString[4];
-   elist[0] = "always";
-   elist[1] = "ifnewer";
-   elist[2] = "ifolder";
-   elist[3] = "never";
-   cfgReplace = new wxChoice(restorePanel, ConfigReplace, wxDefaultPosition, wxSize(150, 15), 4, elist);
-   cfgFileset = new wxStaticText(restorePanel, -1, "  ", wxDefaultPosition, wxSize(150, 15), wxALIGN_LEFT);
-   cfgClient = new wxStaticText(restorePanel, -1, "  ", wxDefaultPosition, wxSize(150, 15), wxALIGN_LEFT);
-   cfgStorage = new wxStaticText(restorePanel, -1, "  ", wxDefaultPosition, wxSize(150, 15), wxALIGN_LEFT);
-   cfgWhen = new wxTextCtrl(restorePanel, ConfigWhen, "0000-00-00 00:00:00", wxDefaultPosition, wxSize(150, 15));
-   cfgPriority = new wxTextCtrl(restorePanel, ConfigPriority, "", wxDefaultPosition, wxSize(50, 15));
-   
-   cfgSizer->Add(new wxStaticText(restorePanel, -1, "Job Name: ", wxDefaultPosition, wxSize(150, 15), wxALIGN_RIGHT), 1, wxEXPAND);
-   cfgSizer->Add(cfgJobname, 1, wxEXPAND);
-   cfgSizer->Add(new wxStaticText(restorePanel, -1, "Bootstrap: ", wxDefaultPosition, wxSize(150, 15), wxALIGN_RIGHT), 1, wxEXPAND);
-   cfgSizer->Add(cfgBootstrap, 1, wxEXPAND);
-   cfgSizer->Add(new wxStaticText(restorePanel, -1, "Where: ", wxDefaultPosition, wxSize(150, 15), wxALIGN_RIGHT), 1, wxEXPAND);
-   cfgSizer->Add(cfgWhere, 1, wxEXPAND);
-   cfgSizer->Add(new wxStaticText(restorePanel, -1, "Replace: ", wxDefaultPosition, wxSize(150, 15), wxALIGN_RIGHT), 1, wxEXPAND);
-   cfgSizer->Add(cfgReplace, 1, wxEXPAND);
-   cfgSizer->Add(new wxStaticText(restorePanel, -1, "Fileset: ", wxDefaultPosition, wxSize(150, 15), wxALIGN_RIGHT), 1, wxEXPAND);
-   cfgSizer->Add(cfgFileset, 1, wxEXPAND);
-   cfgSizer->Add(new wxStaticText(restorePanel, -1, "Client: ", wxDefaultPosition, wxSize(150, 15), wxALIGN_RIGHT), 1, wxEXPAND);
-   cfgSizer->Add(cfgClient, 1, wxEXPAND);
-   cfgSizer->Add(new wxStaticText(restorePanel, -1, "Storage: ", wxDefaultPosition, wxSize(150, 15), wxALIGN_RIGHT), 1, wxEXPAND);
-   cfgSizer->Add(cfgStorage, 1, wxEXPAND);
-   cfgSizer->Add(new wxStaticText(restorePanel, -1, "When: ", wxDefaultPosition, wxSize(150, 15), wxALIGN_RIGHT), 1, wxEXPAND);
-   cfgSizer->Add(cfgWhen, 1, wxEXPAND);
-   cfgSizer->Add(new wxStaticText(restorePanel, -1, "Priority: ", wxDefaultPosition, wxSize(150, 15), wxALIGN_RIGHT), 1, wxEXPAND);
-   cfgSizer->Add(cfgPriority, 1, wxEXPAND);
-      
-   restoreSizer->Add(cfgSizer, 1, wxALIGN_CENTER_HORIZONTAL | wxALIGN_CENTER_VERTICAL | wxALL, 5);
+   wxBoxSizer *listCtrlSizer = new wxBoxSizer(wxHORIZONTAL);
+   listadd = new wxButton(listPanel, ListAdd, "Add", wxDefaultPosition, wxSize(60, 25));
+   listCtrlSizer->Add(listadd, 0, wxLEFT | wxRIGHT, 5);
+   listremove = new wxButton(listPanel, ListRemove, "Remove", wxDefaultPosition, wxSize(60, 25));
+   listCtrlSizer->Add(listremove, 0, wxLEFT | wxRIGHT, 5);
+   listrefresh = new wxButton(listPanel, ListRefresh, "Refresh", wxDefaultPosition, wxSize(60, 25));
+   listCtrlSizer->Add(listrefresh, 0, wxLEFT | wxRIGHT, 5);
    
-   wxBoxSizer* restoreBottomSizer = new wxBoxSizer(wxHORIZONTAL);
+   listSizer->Add(listCtrlSizer, 1, wxALIGN_CENTER_HORIZONTAL, 0);
    
-   cfgOk = new wxButton(restorePanel, ConfigOk, "OK", wxDefaultPosition, wxSize(70, 25));
-   restoreBottomSizer->Add(cfgOk, 1, wxALIGN_CENTER_VERTICAL | wxRIGHT, 10);
-
-   cfgApply = new wxButton(restorePanel, ConfigApply, "Apply", wxDefaultPosition, wxSize(70, 25));
-   restoreBottomSizer->Add(cfgApply, 1, wxALIGN_CENTER_VERTICAL | wxLEFT | wxRIGHT, 10);
-
-   cfgCancel = new wxButton(restorePanel, ConfigCancel, "Cancel", wxDefaultPosition, wxSize(70, 25));
-   restoreBottomSizer->Add(cfgCancel, 1, wxALIGN_CENTER_VERTICAL | wxLEFT, 10);
+   listPanel->SetSizer(listSizer);
    
-   restoreSizer->Add(restoreBottomSizer, 0, wxALIGN_CENTER_HORIZONTAL | wxALIGN_CENTER_VERTICAL | wxALL, 5);
+   treelistPanel->SplitVertically(treePanel, listPanel, 210);
    
-   restorePanel->SetSizer(restoreSizer);
-   restoreSizer->SetSizeHints(restorePanel);
+   treelistPanel->SetMinimumPaneSize(210);
+     
+   treelistPanel->Show(false);
    
+   wxbConfig* config = new wxbConfig();
+   config->Add(new wxbConfigParam("Job Name", ConfigJobName, choice, 0, elist));
+   config->Add(new wxbConfigParam("Client", ConfigClient, choice, 0, elist));
+   config->Add(new wxbConfigParam("Fileset", ConfigFileset, choice, 0, elist));
+   config->Add(new wxbConfigParam("Pool", ConfigPool, choice, 0, elist));
+   config->Add(new wxbConfigParam("Storage", ConfigStorage, choice, 0, elist));
+   config->Add(new wxbConfigParam("Before", ConfigWhen, choice, 0, elist));
+   
+   configPanel = new wxbConfigPanel(this, config, "Please configure parameters concerning files to restore :", RestoreStart, RestoreCancel, -1);
+   
+   configPanel->Show(true);
+   configPanel->Enable(false);
+   
+   config = new wxbConfig();
+   config->Add(new wxbConfigParam("Job Name", -1, text, ""));
+   config->Add(new wxbConfigParam("Bootstrap", -1, text, ""));
+   config->Add(new wxbConfigParam("Where", ConfigWhere, modifiableText, ""));
+   wxString erlist[] = {"always", "if newer", "if older", "never"};
+   config->Add(new wxbConfigParam("Replace", ConfigReplace, choice, 4, erlist));
+   config->Add(new wxbConfigParam("Fileset", ConfigFileset, choice, 0, erlist));
+   config->Add(new wxbConfigParam("Client", ConfigClient, choice, 0, erlist));
+   config->Add(new wxbConfigParam("Storage", ConfigStorage, choice, 0, erlist));
+   config->Add(new wxbConfigParam("When", ConfigWhen, modifiableText, ""));
+   config->Add(new wxbConfigParam("Priority", ConfigPriority, modifiableText, ""));
+   
+   restorePanel = new wxbConfigPanel(this, config, "Please configure parameters concerning files restoration :", ConfigOk, ConfigCancel, ConfigApply);
+    
    restorePanel->Show(false);
    
    centerSizer = new wxBoxSizer(wxHORIZONTAL);
-   //centerSizer->Add(treelistSizer, 1, wxEXPAND);
-   
+   //centerSizer->Add(treelistPanel, 1, wxEXPAND | wxADJUST_MINSIZE);
+      
    mainSizer->Add(centerSizer, 1, wxEXPAND, 10);
 
    gauge = new wxGauge(this, -1, 1, wxDefaultPosition, wxSize(200,20));
@@ -355,13 +401,15 @@ wxbRestorePanel::wxbRestorePanel(wxWindow* parent): wxbPanel(parent) {
 
    SetStatus(disabled);
 
-   jobChoice->Enable(false);
-
    for (int i = 0; i < 7; i++) {
       list->SetColumnWidth(i, 70);
    }
 
-   working = false;
+   SetCursor(*wxSTANDARD_CURSOR);
+
+   markWhenListingDone = false;
+   
+   cancelled = 0;
 }
 
 /*
@@ -396,62 +444,291 @@ void wxbRestorePanel::EnablePanel(bool enable) {
 
 /* The main button has been clicked */
 void wxbRestorePanel::CmdStart() {
+   unsigned int i;
    if (status == activable) {
-      wxbTableParser* tableparser = CreateAndWaitForParser("list clients\n");
+      wxbMainFrame::GetInstance()->SetStatusText("Getting parameters list.");
+      wxbDataTokenizer* dt = wxbUtils::WaitForEnd(".clients\n", true, false);
+      wxString str;
 
-      clientChoice->Clear();
-      for (unsigned int i = 0; i < tableparser->size(); i++) {
-         long* j = new long;
-         (*tableparser)[i][0].ToLong(j);
-         clientChoice->Append((*tableparser)[i][1], (void*)j);
+      configPanel->ClearRowChoices("Client");
+      restorePanel->ClearRowChoices("Client");
+      
+      if (dt->GetCount() == 0) {
+         wxbMainFrame::GetInstance()->SetStatusText("Error : no clients returned by the director.");
+         return;
       }
       
-      delete tableparser;
+      for (i = 0; i < dt->GetCount(); i++) {
+         str = (*dt)[i];
+         str.RemoveLast();
+         configPanel->AddRowChoice("Client", str);
+         restorePanel->AddRowChoice("Client", str);
+      }
+          
+      delete dt;
+      
+      if (cancelled) {
+         cancelled = 2;
+         return;
+      }
+      
+      dt = wxbUtils::WaitForEnd(".filesets\n", true, false);
+      
+      configPanel->ClearRowChoices("Fileset");
+      restorePanel->ClearRowChoices("Fileset");
+    
+      if (dt->GetCount() == 0) {
+         wxbMainFrame::GetInstance()->SetStatusText("Error : no filesets returned by the director.");
+         return;
+      }
+      
+      for (i = 0; i < dt->GetCount(); i++) {
+         str = (*dt)[i];
+         str.RemoveLast();
+         configPanel->AddRowChoice("Fileset", str);
+         restorePanel->AddRowChoice("Fileset", str);
+      }
+      
+      delete dt;
+      
+      if (cancelled) {
+         cancelled = 2;
+         return;
+      }
+      
+      dt = wxbUtils::WaitForEnd(".storage\n", true, false);
+    
+      configPanel->ClearRowChoices("Storage");
+      restorePanel->ClearRowChoices("Storage");
+    
+      if (dt->GetCount() == 0) {
+         wxbMainFrame::GetInstance()->SetStatusText("Error : no storage returned by the director.");
+         return;
+      }
+      
+      for (i = 0; i < dt->GetCount(); i++) {
+         str = (*dt)[i];
+         str.RemoveLast();
+         configPanel->AddRowChoice("Storage", str);
+         restorePanel->AddRowChoice("Storage", str);
+      }
+      
+      delete dt;
+      
+      if (cancelled) {
+         cancelled = 2;
+         return;
+      }
+      
+      dt = wxbUtils::WaitForEnd(".jobs\n", true, false);
+    
+      configPanel->ClearRowChoices("Job Name");
+    
+      if (dt->GetCount() == 0) {
+         wxbMainFrame::GetInstance()->SetStatusText("Error : no jobs returned by the director.");
+         return;
+      }
+      
+      for (i = 0; i < dt->GetCount(); i++) {
+         str = (*dt)[i];
+         str.RemoveLast();
+         configPanel->AddRowChoice("Job Name", str);
+      }
+      
+      configPanel->SetRowString("Job Name", "RestoreFiles");
+      
+      delete dt;
+      
+      if (cancelled) {
+         cancelled = 2;
+         return;
+      }
+      
+      dt = wxbUtils::WaitForEnd(".pools\n", true, false);
+    
+      configPanel->ClearRowChoices("Pool");
+    
+      if (dt->GetCount() == 0) {
+         wxbMainFrame::GetInstance()->SetStatusText("Error : no jobs returned by the director.");
+         return;
+      }
+      
+      for (i = 0; i < dt->GetCount(); i++) {
+         str = (*dt)[i];
+         str.RemoveLast();
+         configPanel->AddRowChoice("Pool", str);
+      }
+         
+      delete dt; 
+      
+      if (cancelled) {
+         cancelled = 2;
+         return;
+      }
 
       SetStatus(entered);
+
+      UpdateFirstConfig();
+           
+      wxbMainFrame::GetInstance()->SetStatusText("Please configure your restore parameters.");
    }
    else if (status == entered) {
-      if (jobChoice->GetStringSelection().Length() < 1) {
+/*      if (clientChoice->GetStringSelection().Length() < 1) {
          wxbMainFrame::GetInstance()->SetStatusText("Please select a client.");
          return;
       }
-      WaitForEnd("restore\n");
-      WaitForEnd("6\n");
-      WaitForEnd(wxString() << jobChoice->GetStringSelection() << "\n");
-      WaitForEnd(wxString() << *((long*)clientChoice->GetClientData(clientChoice->GetSelection())) << "\n");
-      WaitForEnd("unmark *\n");
+      if (jobChoice->GetStringSelection().Length() < 1) {
+         wxbMainFrame::GetInstance()->SetStatusText("Please select a restore date.");
+         return;
+      }*/
+      wxbMainFrame::GetInstance()->SetStatusText("Building restore tree...");
+      
       SetStatus(choosing);
-      wxTreeItemId root = tree->AddRoot(clientChoice->GetStringSelection(), -1, -1, new wxbTreeItemData("/", clientChoice->GetStringSelection(), 0));
-      tree->Refresh();
-      UpdateTreeItem(root, true);
-      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.");
-      tree->Expand(root);
-   }
-   else if (status == choosing) {
-      SetStatus(configuring);
-      wxbMainFrame::GetInstance()->SetStatusText("Restoring, please wait...");
+      
+      wxbUtils::WaitForPrompt(wxString("restore") <<
+         " client=\"" << configPanel->GetRowString("Client") <<
+         "\" fileset=\"" << configPanel->GetRowString("Fileset") <<
+         "\" pool=\"" << configPanel->GetRowString("Pool") <<
+         "\" storage=\"" << configPanel->GetRowString("Storage") << "\"\n");
+      wxbUtils::WaitForPrompt("6\n");
+      //WaitForEnd();
+      /*wxbPromptParser *pp = wxbUtils::WaitForPrompt(wxString() << configPanel->GetRowString("Before") << "\n", true);
+      int client = pp->getChoices()->Index(configPanel->GetRowString("Client"));
+      if (client == wxNOT_FOUND) {
+         wxbMainFrame::GetInstance()->SetStatusText("Failed to find the selected client.");
+         return;
+      }
+      delete pp;*/
+      
+      wxbTableParser* tableparser = new wxbTableParser();
+      wxbDataTokenizer* dt = new wxbDataTokenizer(true);
+      
+      wxbMainFrame::GetInstance()->Send(wxString() << configPanel->GetRowString("Before") << "\n");
+   
+      while (!tableparser->hasFinished() && !dt->hasFinished()) {
+         wxTheApp->Yield(true);
+         ::wxUsleep(100);
+      }
+      
+      wxString str;
 
-      totfilemessages = 0;
-      wxbDataTokenizer* dt;
+      if (dt->hasFinished() && !tableparser->hasFinished()) {
+         str = "";
+         if (dt->GetCount() > 1) {
+            str = (*dt)[dt->GetCount()-2];
+            str.RemoveLast();
+         }
+         wxbMainFrame::GetInstance()->SetStatusText(wxString("Error while starting restore: ") << str);
+         delete dt;
+         delete tableparser;
+         SetStatus(finished);
+         return;
+      }
+           
+      int tot = 0;
+      long l;
       
-      dt = WaitForEnd("estimate\n", true);
+      for (i = 0; i < tableparser->GetCount(); i++) {
+         str = (*tableparser)[i][2];
+         str.Replace(",", "");
+         if (str.ToLong(&l)) {
+            tot += l;
+         }
+      }
+           
+      gauge->SetValue(0);
+      gauge->SetRange(tot);
       
-      int j, k;
-          
-      for (unsigned int i = 0; i < dt->GetCount(); i++) {
-         /* 15847 total files; 1 marked to be restored; 1,034 bytes. */
-         if ((j = (*dt)[i].Find(" marked to be restored;")) > -1) {
-            k = (*dt)[i].Find("; ");
-            (*dt)[i].Mid(k+2, j).ToLong(&totfilemessages);
-            break;
+      /*wxbMainFrame::GetInstance()->Print(
+               wxString("[") << tot << "]", CS_DEBUG);*/
+      
+      wxDateTime base = wxDateTime::Now();
+      wxDateTime newdate;
+      int done = 0;
+      int willdo = 0;
+      unsigned int lastindex = 0;
+      
+      int var = 0;
+      
+      while (!dt->hasFinished()) {
+         newdate = wxDateTime::Now();
+         if (newdate.Subtract(base).GetMilliseconds() > 10 ) {
+            base = newdate;
+            for (; lastindex < dt->GetCount(); lastindex++) {
+               if (((*dt)[lastindex].Find("Building directory tree for JobId ") == 0) && 
+                     ((i = (*dt)[lastindex].Find(" ...")) > 0)) {
+                  str = (*dt)[lastindex].Mid(34, i-34);
+                  for (i = 0; i < tableparser->GetCount(); i++) {
+                     if (str == (*tableparser)[i][0]) {
+                        str = (*tableparser)[i][2];
+                        str.Replace(",", "");
+                        if (str.ToLong(&l)) {
+                           done += willdo;
+                           willdo += l;
+                           var = (willdo-done)/3;
+                        }
+                        break;
+                     }
+                  }
+               }
+            }
+            
+            if (gauge->GetValue() <= done) {
+               gauge->SetValue(done);
+               if (var < 0)
+                  var = -var;
+            }
+            else if (gauge->GetValue() >= willdo) {
+               gauge->SetValue(willdo);
+               if (var > 0)
+                  var = -var;
+            }
+            
+            gauge->SetValue(gauge->GetValue()+var);
+            
+            /*wxbMainFrame::GetInstance()->Print(
+               wxString("[") << gauge->GetValue() << "/" << done
+                  << "-" << willdo << "]", CS_DEBUG);*/
          }
+         wxTheApp->Yield(true);
+         ::wxUsleep(1);
       }
+
+      gauge->SetValue(tot);
+      wxTheApp->Yield(true);
+      gauge->SetValue(0);
       
       delete dt;
+      delete tableparser;
+
+      if (cancelled) {
+         cancelled = 2;
+         return;
+      }
+
+      wxbUtils::WaitForEnd("unmark *\n");
+      wxTreeItemId root = tree->AddRoot(configPanel->GetRowString("Client"), -1, -1, new wxbTreeItemData("/", configPanel->GetRowString("Client"), 0));
+      currentTreeItem = root;
+      tree->Refresh();
+      tree->SelectItem(root);
+      CmdList(root);
+      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.");
+      tree->Expand(root);
+   }
+   else if (status == choosing) {
+      EnableConfig(false);
+      
+      totfilemessages = 0;
+      wxbDataTokenizer* dt;
+           
+      int j;
       
-      dt = WaitForEnd("done\n", true);
+      dt = new wxbDataTokenizer(true);
+      wxbUtils::WaitForPrompt("done\n");
+
+      SetStatus(configuring);
 
-      for (unsigned int i = 0; i < dt->GetCount(); i++) {
+      for (i = 0; i < dt->GetCount(); i++) {
          if ((j = (*dt)[i].Find(" files selected to be restored.")) > -1) {
             (*dt)[i].Mid(0, j).ToLong(&totfilemessages);
             break;
@@ -463,9 +740,16 @@ void wxbRestorePanel::CmdStart() {
          }
       }
       
-      UpdateConfig(dt);
+      wxbMainFrame::GetInstance()->SetStatusText(
+         wxString("Please configure your restore (") 
+            << totfilemessages <<  " files selected to be restored)...");
+      
+      UpdateSecondConfig(dt);
       
       delete dt;
+      
+      EnableConfig(true);
+      restorePanel->EnableApply(false);
 
       if (totfilemessages == 0) {
          wxbMainFrame::GetInstance()->Print("Restore failed : no file selected.\n", CS_DEBUG);
@@ -475,32 +759,101 @@ void wxbRestorePanel::CmdStart() {
       }
    }
    else if (status == configuring) {
+      cancel->Enable(false);
+      jobid = "";
+      EnableConfig(false);
+    
+      wxbMainFrame::GetInstance()->SetStatusText("Restoring, please wait...");
+    
       wxbDataTokenizer* dt;
     
       SetStatus(restoring);
-      WaitForEnd("yes\n");
+      wxbUtils::WaitForEnd("yes\n");
 
       gauge->SetValue(0);
       gauge->SetRange(totfilemessages);
 
+      wxDateTime currenttime;
+      
+      dt = wxbUtils::WaitForEnd("time\n", true);
+      wxStringTokenizer ttkz((*dt)[0], " ", wxTOKEN_STRTOK);
+      if ((currenttime.ParseDate(ttkz.GetNextToken()) == NULL) || // Date
+           (currenttime.ParseTime(ttkz.GetNextToken()) == NULL)) { // Time
+         currenttime.SetYear(1990); // If parsing fails, set currenttime to a dummy date
+      }
+      else {
+         currenttime -= wxTimeSpan::Seconds(30); //Adding a 30" tolerance
+      }
+      delete dt;
+    
+      wxDateTime scheduledtime;
+      wxStringTokenizer stkz(restorePanel->GetRowString("When"), " ", wxTOKEN_STRTOK);
+      
+      if ((scheduledtime.ParseDate(stkz.GetNextToken()) == NULL) || // Date
+           (scheduledtime.ParseTime(stkz.GetNextToken()) == NULL)) { // Time
+         scheduledtime.SetYear(2090); // If parsing fails, set scheduledtime to a dummy date
+      }
+
+      if (scheduledtime.Subtract(currenttime).IsLongerThan(wxTimeSpan::Seconds(150))) {
+         wxbMainFrame::GetInstance()->Print("Restore is scheduled in more than two minutes, wx-console will not wait for its completion.\n", CS_DEBUG);
+         wxbMainFrame::GetInstance()->SetStatusText("Restore is scheduled in more than two minutes, wx-console will not wait for its completion.");
+         SetStatus(finished);
+         return;
+      }
+
       wxString cmd = "list jobid=";
 
-      wxbTableParser* tableparser = CreateAndWaitForParser("list jobs\n");
-        /* TODO (#1#): Check more carefully which job we just have run. */
-      cmd << (*tableparser)[tableparser->size()-1][0] << "\n";
+      wxString jobname = restorePanel->GetRowString("Job Name");
 
-      delete tableparser;
+      wxStopWatch sw;
+
+      wxbTableParser* tableparser;
 
-      filemessages = 0;
+      while (true) {
+         tableparser = wxbUtils::CreateAndWaitForParser("list jobs\n");
+         
+         wxDateTime jobtime;
+         
+         if (jobname == (*tableparser)[tableparser->GetCount()-1][1]) {
+            wxStringTokenizer jtkz((*tableparser)[tableparser->GetCount()-1][2], " ", wxTOKEN_STRTOK);
+            if ((jobtime.ParseDate(jtkz.GetNextToken()) != NULL) && // Date
+                  (jobtime.ParseTime(jtkz.GetNextToken()) != NULL)) { // Time
+               if (jobtime.IsLaterThan(currenttime)) {
+                  jobid = (*tableparser)[tableparser->GetCount()-1][0];
+                  cmd << jobid << "\n";
+                  delete tableparser;
+                  cancel->Enable(true);
+                  break;
+               }
+            }
+         }
+   
+         delete tableparser;
+         
+         wxStopWatch sw2;
+         while (sw2.Time() < 2000) {
+            wxTheApp->Yield(true);
+            ::wxUsleep(100);
+         }
+         if (sw.Time() > 60000) {
+            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);
+            wxbMainFrame::GetInstance()->SetStatusText("The restore job has not been created within one minute, wx-console will not wait for its completion anymore.");
+            SetStatus(finished);
+            cancel->Enable(true);
+            return;
+         }
+      }
+      
+      long filemessages = 0;
 
       while (true) {
-         tableparser = CreateAndWaitForParser(cmd);
+         tableparser = wxbUtils::CreateAndWaitForParser(cmd);
          if ((*tableparser)[0][7] != "C") {
             break;
          }
          delete tableparser;
 
-         dt = WaitForEnd("messages\n", true);
+         dt = wxbUtils::WaitForEnd("messages\n", true);
          
          for (unsigned int i = 0; i < dt->GetCount(); i++) {
             wxStringTokenizer tkz((*dt)[i], " ", wxTOKEN_STRTOK);
@@ -534,13 +887,14 @@ void wxbRestorePanel::CmdStart() {
 
          wxbMainFrame::GetInstance()->SetStatusText(wxString("Restoring, please wait (") << filemessages << " of " << totfilemessages << " files done)...");
 
-         time_t start = wxDateTime::Now().GetTicks();
-         while (((wxDateTime::Now().GetTicks())-start) < 3) {
-            wxTheApp->Yield();
+         wxStopWatch sw2;
+         while (sw2.Time() < 10000) {  
+            wxTheApp->Yield(true);
+            ::wxUsleep(100);
          }
       }
 
-      WaitForEnd("messages\n");
+      wxbUtils::WaitForEnd("messages\n");
 
       gauge->SetValue(totfilemessages);
 
@@ -557,13 +911,59 @@ void wxbRestorePanel::CmdStart() {
    }
 }
 
+/* The cancel button has been clicked */
+void wxbRestorePanel::CmdCancel() {
+   cancelled = 1;
+   
+   if (status == restoring) {
+      if (jobid != "") {
+         wxbMainFrame::GetInstance()->Send(wxString("cancel job=") << jobid << "\n");
+      }
+      cancel->Enable(true);
+      return;
+   }
+   
+   wxStopWatch sw;
+   while ((IsWorking()) && (cancelled != 2)) {
+      wxTheApp->Yield(true);
+      ::wxUsleep(100);
+      if (sw.Time() > 30000) { /* 30 seconds timeout */
+         if (status == choosing) {
+            wxbMainFrame::GetInstance()->Send("quit\n");
+         }
+         else if (status == configuring) {
+            wxbMainFrame::GetInstance()->Send("no\n");
+         }
+         else if (status == restoring) {
+            
+         }
+         SetStatus(finished);
+         ::wxUsleep(1000);
+         return;
+      }
+   }
+   
+   switch (status) {
+   case choosing:
+      wxbMainFrame::GetInstance()->Send("quit\n");      
+      break;
+   case configuring:
+      wxbMainFrame::GetInstance()->Send("no\n");      
+      break;
+   default:
+      break;
+   }
+   ::wxUsleep(1000);
+   SetStatus(finished);
+}
+
 /* Apply configuration changes */
 
 /*   1: Level (not appropriate)
- *   2: Storage (automatic ?)
+ *   2: Storage (yes)
  *   3: Job (no)
- *   4: FileSet (no)
- *   5: Client (no)
+ *   4: FileSet (yes)
+ *   5: Client (yes)
  *   6: When (yes : "Please enter desired start time as YYYY-MM-DD HH:MM:SS (return for now):")
  *   7: Priority (yes : "Enter new Priority: (positive integer)")
  *   8: Bootstrap (?)
@@ -576,62 +976,129 @@ void wxbRestorePanel::CmdStart() {
 void wxbRestorePanel::CmdConfigApply() {
    if (cfgUpdated == 0) return;
    
+   wxbMainFrame::GetInstance()->SetStatusText("Applying restore configuration changes...");
+   
+   EnableConfig(false);
+   
    wxbDataTokenizer* dt = NULL;
+   
+   bool failed = false;
+   
    while (cfgUpdated > 0) {
+      if (cancelled) {
+         cancelled = 2;
+         return;
+      }
       wxString def; //String to send if can't use our data
       if ((cfgUpdated >> ConfigWhere) & 1) {
-         WaitForEnd("mod\n"); /* TODO: check results */
-         WaitForEnd("9\n");
-         dt = WaitForEnd(cfgWhere->GetValue() + "\n", true);
+         wxbUtils::WaitForPrompt("mod\n"); /* TODO: check results */
+         wxbUtils::WaitForPrompt("9\n");
+         dt = new wxbDataTokenizer(true);
+         wxbUtils::WaitForPrompt(restorePanel->GetRowString("Where") + "\n");
          def = "/tmp";
          cfgUpdated = cfgUpdated & (~(1 << ConfigWhere));
       }
       else if ((cfgUpdated >> ConfigReplace) & 1) {
-         WaitForEnd("mod\n"); /* TODO: check results */
-         WaitForEnd("10\n");
-         dt = WaitForEnd(wxString() << (cfgReplace->GetSelection()+1) << "\n", true);
+         wxbUtils::WaitForPrompt("mod\n"); /* TODO: check results */
+         wxbUtils::WaitForPrompt("10\n");
+         dt = new wxbDataTokenizer(true);
+         wxbUtils::WaitForPrompt(wxString() << (restorePanel->GetRowSelection("Replace")+1) << "\n");
          def = "1";
          cfgUpdated = cfgUpdated & (~(1 << ConfigReplace));
       }
       else if ((cfgUpdated >> ConfigWhen) & 1) {
-         WaitForEnd("mod\n"); /* TODO: check results */
-         WaitForEnd("6\n");
-         dt = WaitForEnd(cfgWhen->GetValue() + "\n", true);
+         wxbUtils::WaitForPrompt("mod\n"); /* TODO: check results */
+         wxbUtils::WaitForPrompt("6\n");
+         dt = new wxbDataTokenizer(true);
+         wxbUtils::WaitForPrompt(restorePanel->GetRowString("When") + "\n");
          def = "";
          cfgUpdated = cfgUpdated & (~(1 << ConfigWhen));
       }
       else if ((cfgUpdated >> ConfigPriority) & 1) {
-         WaitForEnd("mod\n"); /* TODO: check results */
-         WaitForEnd("7\n");
-         dt = WaitForEnd(cfgPriority->GetValue() + "\n", true);
+         wxbUtils::WaitForPrompt("mod\n"); /* TODO: check results */
+         wxbUtils::WaitForPrompt("7\n");
+         dt = new wxbDataTokenizer(true);
+         wxbUtils::WaitForPrompt(restorePanel->GetRowString("Priority") + "\n");
          def = "10";
          cfgUpdated = cfgUpdated & (~(1 << ConfigPriority));
       }
+      else if ((cfgUpdated >> ConfigClient) & 1) {
+         wxbUtils::WaitForPrompt("mod\n"); /* TODO: check results */
+         wxbPromptParser *pp = wxbUtils::WaitForPrompt("5\n", true);
+         int client = pp->getChoices()->Index(restorePanel->GetRowString("Client"));
+         if (client == wxNOT_FOUND) {
+            wxbMainFrame::GetInstance()->SetStatusText("Failed to find the selected client.");
+            failed = true;
+            client = 1;
+         }
+         delete pp;
+         dt = new wxbDataTokenizer(true);
+         wxbUtils::WaitForPrompt(wxString() << client << "\n");
+         def = "1";
+         cfgUpdated = cfgUpdated & (~(1 << ConfigClient));
+      }
+      else if ((cfgUpdated >> ConfigFileset) & 1) {
+         wxbUtils::WaitForPrompt("mod\n"); /* TODO: check results */
+         wxbPromptParser *pp = wxbUtils::WaitForPrompt("4\n", true);
+         int fileset = pp->getChoices()->Index(restorePanel->GetRowString("Fileset"));
+         if (fileset == wxNOT_FOUND) {
+            wxbMainFrame::GetInstance()->SetStatusText("Failed to find the selected fileset.");
+            failed = true;
+            fileset = 1;
+         }
+         delete pp;
+         dt = new wxbDataTokenizer(true);
+         wxbUtils::WaitForPrompt(wxString() << fileset << "\n");
+         def = "1";
+         cfgUpdated = cfgUpdated & (~(1 << ConfigFileset));
+      }
+      else if ((cfgUpdated >> ConfigStorage) & 1) {
+         wxbUtils::WaitForPrompt("mod\n"); /* TODO: check results */
+         wxbPromptParser *pp = wxbUtils::WaitForPrompt("2\n", true);
+         int fileset = pp->getChoices()->Index(restorePanel->GetRowString("Storage"));
+         if (fileset == wxNOT_FOUND) {
+            wxbMainFrame::GetInstance()->SetStatusText("Failed to find the selected storage.");
+            failed = true;
+            fileset = 1;
+         }
+         delete pp;
+         dt = new wxbDataTokenizer(true);
+         wxbUtils::WaitForPrompt(wxString() << fileset << "\n");
+         def = "1";
+         cfgUpdated = cfgUpdated & (~(1 << ConfigFileset));
+      }
       else {
          cfgUpdated = 0;
          break;
       }
-      
+                 
       unsigned int i;
       for (i = 0; i < dt->GetCount(); i++) {
-         if ((*dt)[i].Find("Run Restore job")) {
+         if ((*dt)[i].Find("Run Restore job") == 0) {
             break;
          }
       }
       
-      if (i == (dt->GetCount()-1)) {
+      if (i == dt->GetCount()) {
          delete dt;   
-         dt = WaitForEnd(def + "\n");
+         dt = wxbUtils::WaitForEnd(def + "\n", true);
+         failed = true;
       }
    }
-   UpdateConfig(dt); /* TODO: Check result */
-      
+   UpdateSecondConfig(dt); /* TODO: Check result */
+   
+   EnableConfig(true);
+
+   if (!failed) {
+      wxbMainFrame::GetInstance()->SetStatusText("Restore configuration changes were applied.");
+   }
+
    delete dt;
 }
 
 /* Cancel restore */
 void wxbRestorePanel::CmdConfigCancel() {
-   WaitForEnd("no\n");
+   wxbUtils::WaitForEnd("no\n");
    wxbMainFrame::GetInstance()->Print("Restore cancelled.\n", CS_DEBUG);
    wxbMainFrame::GetInstance()->SetStatusText("Restore cancelled.");
    SetStatus(finished);
@@ -640,19 +1107,19 @@ void wxbRestorePanel::CmdConfigCancel() {
 /* List jobs for a specified client */
 void wxbRestorePanel::CmdListJobs() {
    if (status == entered) {
-      jobChoice->Clear();
-      WaitForEnd("query\n");
-      WaitForEnd("6\n");
-      wxbTableParser* tableparser = CreateAndWaitForParser(clientChoice->GetString(clientChoice->GetSelection()) + "\n");
+      configPanel->ClearRowChoices("Before");
+      wxbUtils::WaitForPrompt("query\n");
+      wxbUtils::WaitForPrompt("6\n");
+      wxbTableParser* tableparser = wxbUtils::CreateAndWaitForParser(configPanel->GetRowString("Client") + "\n");
 
-      for (int i = tableparser->size()-1; i > -1; i--) {
+      for (int i = tableparser->GetCount()-1; i > -1; i--) {
          wxString str = (*tableparser)[i][3];
          wxDateTime datetime;
          const char* chr;
          if ( ( (chr = datetime.ParseDate(str.GetData()) ) != NULL ) && ( datetime.ParseTime(++chr) != NULL ) ) {
-            datetime = datetime.GetTicks() + 1;
+            datetime += wxTimeSpan::Seconds(1);
             //wxbMainFrame::GetInstance()->Print(wxString("-") << datetime.Format("%Y-%m-%d %H:%M:%S"), CS_DEBUG);
-            jobChoice->Append(datetime.Format("%Y-%m-%d %H:%M:%S"));
+            configPanel->AddRowChoice("Before", datetime.Format("%Y-%m-%d %H:%M:%S"));
          }
          /*else {
          jobChoice->Append("Invalid");
@@ -661,7 +1128,7 @@ void wxbRestorePanel::CmdListJobs() {
       
       delete tableparser;
 
-      jobChoice->SetSelection(0);
+      configPanel->SetRowSelection("Before", 0);
    }
 }
 
@@ -673,9 +1140,9 @@ void wxbRestorePanel::CmdList(wxTreeItemId item) {
       if (!item.IsOk()) {
          return;
       }
-      UpdateTreeItem(item, (tree->GetSelection() == item));
+      UpdateTreeItem(item, true, false);
     
-      if (list->GetItemCount() > 1) {
+      if (list->GetItemCount() >= 1) {
          int firstwidth = list->GetSize().GetWidth(); 
          for (int i = 2; i < 7; i++) {
             list->SetColumnWidth(i, wxLIST_AUTOSIZE);
@@ -686,30 +1153,45 @@ void wxbRestorePanel::CmdList(wxTreeItemId item) {
          firstwidth -= 18;
          list->SetColumnWidth(1, wxLIST_AUTOSIZE);
          if (list->GetColumnWidth(1) < firstwidth) {
-            list->SetColumnWidth(1, firstwidth-20);
+            list->SetColumnWidth(1, firstwidth-25);
          }
       }
    }
 }
 
 /* Mark a treeitem (directory) or a listitem (file or directory) */
-void wxbRestorePanel::CmdMark(wxTreeItemId treeitem, long listitem) {
+void wxbRestorePanel::CmdMark(wxTreeItemId treeitem, long* listitems, int listsize, int state) {
    if (status == choosing) {
-      wxbTreeItemData* itemdata = NULL;
-      if (listitem != -1) {
-         itemdata = (wxbTreeItemData*)list->GetItemData(listitem);
+      wxbTreeItemData** itemdata;
+      int itemdatasize = 0;
+      if (listsize == 0) {
+         itemdata = new wxbTreeItemData*[1];
+         itemdatasize = 1;
+      }
+      else {
+         itemdata = new wxbTreeItemData*[listsize];
+         itemdatasize = listsize;
+      }
+      
+      if (listitems != NULL) {
+         for (int i = 0; i < listsize; i++) {
+            itemdata[i] = (wxbTreeItemData*)list->GetItemData(listitems[i]);
+         }
       }
       else if (treeitem.IsOk()) {
-         itemdata = (wxbTreeItemData*)tree->GetItemData(treeitem);
+         itemdata[0] = (wxbTreeItemData*)tree->GetItemData(treeitem);
       }
       else {
+         delete[] itemdata;
          return;
       }
 
-      if (itemdata == NULL) //Should never happen
+      if (itemdata[0] == NULL) { //Should never happen
+         delete[] itemdata;
          return;
+      }
 
-      wxString dir = itemdata->GetPath();
+      wxString dir = itemdata[0]->GetPath();
       wxString file;
 
       if (dir != "/") {
@@ -732,8 +1214,43 @@ void wxbRestorePanel::CmdMark(wxTreeItemId treeitem, long listitem) {
          file = "*";
       }
 
-      WaitForEnd(wxString("cd ") << dir << "\n");
-      WaitForEnd(wxString((itemdata->GetMarked() == 1) ? "unmark " : "mark ") << file << "\n");
+      if (state == -1) {
+         bool marked = false;
+         bool unmarked = false;
+         state = 0;
+         for (int i = 0; i < itemdatasize; i++) {
+            switch(itemdata[i]->GetMarked()) {
+            case 0:
+               unmarked = true;
+               break;
+            case 1:
+               marked = true;
+               break;
+            case 2:
+               marked = true;
+               unmarked = true;
+               break;
+            default:
+               break;
+            }
+            if (marked && unmarked)
+               break;
+         }
+         if (marked) {
+            if (unmarked) {
+               state = 1;
+            }
+            else {
+               state = 0;
+            }
+         }
+         else {
+            state = 1;
+         }
+      }
+
+      wxbUtils::WaitForEnd(wxString("cd \"") << dir << "\"\n");
+      wxbUtils::WaitForEnd(wxString((state==1) ? "mark" : "unmark") << " \"" << file << "\"\n");
 
       /* TODO: Check commands results */
 
@@ -741,14 +1258,16 @@ void wxbRestorePanel::CmdMark(wxTreeItemId treeitem, long listitem) {
             itemdata->SetMarked((itemdata->GetMarked() == 1) ? 0 : 1);
       }*/
 
-      if (listitem == -1) { /* tree item state changed */
-         SetTreeItemState(treeitem, (itemdata->GetMarked() == 1) ? 0 : 1);
+      if (listitems == NULL) { /* tree item state changed */
+         SetTreeItemState(treeitem, state);
          /*treeitem = tree->GetSelection();
          UpdateTree(treeitem, true);
          treeitem = tree->GetItemParent(treeitem);*/
       }
       else {
-         SetListItemState(listitem, (itemdata->GetMarked() == 1) ? 0 : 1);
+         for (int i = 0; i < listsize; i++) {
+            SetListItemState(listitems[i], state);
+         }
          /*UpdateTree(treeitem, (tree->GetSelection() == treeitem));
          treeitem = tree->GetItemParent(treeitem);*/
       }
@@ -757,6 +1276,8 @@ void wxbRestorePanel::CmdMark(wxTreeItemId treeitem, long listitem) {
          WaitForList(treeitem, false);
          treeitem = tree->GetItemParent(treeitem);
       }*/
+      
+      delete[] itemdata;
    }
 }
 
@@ -764,67 +1285,24 @@ void wxbRestorePanel::CmdMark(wxTreeItemId treeitem, long listitem) {
    General functions
   ----------------------------------------------------------------------------*/
 
-/* Parse a table in tableParser */
-wxbTableParser* wxbRestorePanel::CreateAndWaitForParser(wxString cmd) {
-   wxbTableParser* tableParser = new wxbTableParser();
-
-   wxbMainFrame::GetInstance()->Send(cmd);
-
-   //time_t base = wxDateTime::Now().GetTicks();
-   while (!tableParser->hasFinished()) {
-      //innerThread->Yield();
-      wxTheApp->Yield();
-      //if (base+15 < wxDateTime::Now().GetTicks()) break;
-   }
-   return tableParser;
-}
-
-/* Run a command, and waits until result is fully received. */
-wxbDataTokenizer* wxbRestorePanel::WaitForEnd(wxString cmd, bool keepresults) {
-   wxbDataTokenizer* datatokenizer = new wxbDataTokenizer();
-
-   wxbMainFrame::GetInstance()->Send(cmd);
-   
-   //wxbMainFrame::GetInstance()->Print("(<WFE)", CS_DEBUG);
-   
-   //time_t base = wxDateTime::Now().GetTicks();
-   while (!datatokenizer->hasFinished()) {
-      //innerThread->Yield();
-      wxTheApp->Yield();
-      //if (base+15 < wxDateTime::Now().GetTicks()) break;
-   }
-   
-   //wxbMainFrame::GetInstance()->Print("(>WFE)", CS_DEBUG);
-   
-   if (keepresults) {
-      return datatokenizer;
-   }
-   else {
-      delete datatokenizer;
-      return NULL;
-   }
-}
-
 /* Run a dir command, and waits until result is fully received. */
-void wxbRestorePanel::UpdateTreeItem(wxTreeItemId item, bool updatelist) {
+void wxbRestorePanel::UpdateTreeItem(wxTreeItemId item, bool updatelist, bool recurse) {
 //   this->updatelist = updatelist;
-   currentTreeItem = item;
-
    wxbDataTokenizer* dt;
 
-   dt = WaitForEnd(wxString("cd \"") << 
-      static_cast<wxbTreeItemData*>(tree->GetItemData(currentTreeItem))
+   dt = wxbUtils::WaitForEnd(wxString("cd \"") << 
+      static_cast<wxbTreeItemData*>(tree->GetItemData(item))
          ->GetPath() << "\"\n", false);
 
    /* TODO: check command result */
    
    //delete dt;
 
-   SetStatus(listing);
+   status = listing;
 
    if (updatelist)
       list->DeleteAllItems();
-   dt = WaitForEnd("dir\n", true);
+   dt = wxbUtils::WaitForEnd("dir\n", true);
    
    wxString str;
    
@@ -848,7 +1326,7 @@ void wxbRestorePanel::UpdateTreeItem(wxTreeItemId item, bool updatelist) {
          wxString itemStr;
 
          long cookie;
-         treeid = tree->GetFirstChild(currentTreeItem, cookie);
+         treeid = tree->GetFirstChild(item, cookie);
 
          bool updated = false;
 
@@ -861,15 +1339,18 @@ void wxbRestorePanel::UpdateTreeItem(wxTreeItemId item, bool updatelist) {
                   tree->SetItemImage(treeid, stat, wxTreeItemIcon_Selected);
                   static_cast<wxbTreeItemData*>(tree->GetItemData(treeid))->SetMarked(file[6]);
                }
+               if ((recurse) && (tree->IsExpanded(treeid))) {
+                  UpdateTreeItem(treeid, false, true);
+               }
                updated = true;
                break;
             }
-            treeid = tree->GetNextChild(currentTreeItem, cookie);
+            treeid = tree->GetNextChild(item, cookie);
          }
 
          if (!updated) {
             int img = wxbTreeItemData::GetMarkedStatus(file[6]);
-            treeid = tree->AppendItem(currentTreeItem, file[8], img, img, new wxbTreeItemData(file[7], file[8], file[6]));
+            treeid = tree->AppendItem(item, file[8], img, img, new wxbTreeItemData(file[7], file[8], file[6]));
          }
       }
 
@@ -892,14 +1373,16 @@ void wxbRestorePanel::UpdateTreeItem(wxTreeItemId item, bool updatelist) {
    delete dt;
    
    tree->Refresh();
-   SetStatus(choosing);
+   status = choosing;
 }
 
 /* Parse dir command results. */
 wxString* wxbRestorePanel::ParseList(wxString line) {
-   //drwx------  11 1003    42949672      0  2001-07-30 16:45:14 *filename
-   //+ 10    ++ 4++   10   ++   8  ++   8  + +      19         + *+ ->
-   //0       10  14         24      32       42                  62
+   /* See ls_output in dird/ua_tree.c */
+  
+   //drwxrwxrwx   1 root     root           0  2004-04-03 14:35:21  f:/tocd/NVSU 1.00.00/
+   //+ 10     +  ++ +   8  + +   8  ++   8  +  +      19         + *+ ->
+   //0           12 15       24      32        42                  62
 
    if (line.Length() < 63)
       return NULL;
@@ -907,8 +1390,8 @@ wxString* wxbRestorePanel::ParseList(wxString line) {
    wxString* ret = new wxString[9];
 
    ret[0] = line.Mid(0, 10).Trim();
-   ret[1] = line.Mid(10, 4).Trim();
-   ret[2] = line.Mid(14, 10).Trim();
+   ret[1] = line.Mid(12, 2).Trim();
+   ret[2] = line.Mid(15, 8).Trim();
    ret[3] = line.Mid(24, 8).Trim();
    ret[4] = line.Mid(32, 8).Trim();
    ret[5] = line.Mid(42, 19).Trim();
@@ -1067,27 +1550,115 @@ void wxbRestorePanel::UpdateTreeItemState(wxTreeItemId item) {
    UpdateTreeItemState(tree->GetItemParent(item));
 }
 
-/* 
- * Refresh a tree item, and all its childs, 
- * by asking the director for new lists 
- */
-void wxbRestorePanel::RefreshTree(wxTreeItemId item) {
-/*   UpdateTreeItem(item, updatelist);*/
+/* Refresh the whole tree. */
+void wxbRestorePanel::RefreshTree() {
+   /* Save current selection */
+   wxArrayString current;
+   
+   wxTreeItemId item = currentTreeItem;
+   
+   while ((item.IsOk()) && (item != tree->GetRootItem())) {
+      current.Add(tree->GetItemText(item));
+      item = tree->GetItemParent(item);
+   }
 
-   /* Update all child which are not collapsed */
-/*   long cookie;
-   wxTreeItemId currentChild = tree->GetFirstChild(item, cookie);
+   /* Update the tree */
+   UpdateTreeItem(tree->GetRootItem(), false, true);
 
-   while (currentChild.IsOk()) {
-      if (tree->IsExpanded(currentChild))
-         UpdateTree(currentChild, false);
+   /* Reselect the former selected item */   
+   item = tree->GetRootItem();
+   
+   if (current.Count() == 0) {
+      tree->SelectItem(item);
+      return;
+   }
+   
+   bool match;
+   
+   for (int i = current.Count()-1; i >= 0; i--) {
+      long cookie;
+      wxTreeItemId currentChild = tree->GetFirstChild(item, cookie);
+      
+      match = false;
+      
+      while (currentChild.IsOk()) {
+         if (tree->GetItemText(currentChild) == current[i]) {
+            item = currentChild;
+            match = true;
+            break;
+         }
+   
+         currentChild = tree->GetNextChild(item, cookie);
+      }
+      
+      if (!match) break;
+   }
+   
+   UpdateTreeItem(item, true, false); /* Update the list */
+   
+   tree->SelectItem(item);
+}
 
-      currentChild = tree->GetNextChild(item, cookie);
-   }*/
+void wxbRestorePanel::RefreshList() {
+   if (currentTreeItem.IsOk()) {
+      UpdateTreeItem(currentTreeItem, true, false); /* Update the list */
+   }
+}
+
+/* Update first config, adapting settings to the job name selected */
+void wxbRestorePanel::UpdateFirstConfig() {
+   configPanel->Enable(false);
+   wxbDataTokenizer* dt = wxbUtils::WaitForEnd(wxString(".defaults job=") + configPanel->GetRowString("Job Name") + "\n", true, false);
+   /* job=RestoreFiles
+    * pool=Default
+    * messages=Standard
+    * client=***
+    * storage=File
+    * where=/tmp/bacula-restores
+    * level=0
+    * type=Restore
+    * fileset=Full Set */
+   
+   wxString name, str;
+   unsigned int i;
+   int j;
+   wxString client;
+   bool dolistjobs = false;
+   
+   for (i = 0; i < dt->GetCount(); i++) {
+      str = (*dt)[i];
+      if ((j = str.Find('=')) > -1) {
+         name = str.Mid(0, j);
+         if (name == "pool") {
+            configPanel->SetRowString("Pool", str.Mid(j+1));
+         }
+         else if (name == "client") {
+            str = str.Mid(j+1);
+            if ((str != configPanel->GetRowString("Client")) || (configPanel->GetRowString("Before") == "")) {
+               configPanel->SetRowString("Client", str);
+               dolistjobs = true;
+            }
+         }
+         else if (name == "storage") {
+            configPanel->SetRowString("Storage", str.Mid(j+1));
+         }
+         else if (name == "fileset") {
+            configPanel->SetRowString("Fileset", str.Mid(j+1));
+         }
+      }
+   }
+      
+   delete dt;
+   
+   if (dolistjobs) {
+      //wxTheApp->Yield(false);
+      CmdListJobs();
+   }
+   configPanel->Enable(true);
 }
 
 /* 
- * Update config.
+ * Update second config.
  * 
  * Run Restore job
  * JobName:    RestoreFiles
@@ -1102,7 +1673,7 @@ void wxbRestorePanel::RefreshTree(wxTreeItemId item) {
  * OK to run? (yes/mod/no):
  * 
  */
-bool wxbRestorePanel::UpdateConfig(wxbDataTokenizer* dt) {
+bool wxbRestorePanel::UpdateSecondConfig(wxbDataTokenizer* dt) {
    unsigned int i;
    for (i = 0; i < dt->GetCount(); i++) {
       if ((*dt)[i].Find("Run Restore job") == 0)
@@ -1116,30 +1687,30 @@ bool wxbRestorePanel::UpdateConfig(wxbDataTokenizer* dt) {
    int k;
    
    if ((k = (*dt)[++i].Find("JobName:")) != 0) return false;
-   cfgJobname->SetLabel((*dt)[i].Mid(10).Trim(false).RemoveLast());
+   restorePanel->SetRowString("Job Name", (*dt)[i].Mid(10).Trim(false).RemoveLast());
    if ((k = (*dt)[++i].Find("Bootstrap:")) != 0) return false;
-   cfgBootstrap->SetLabel((*dt)[i].Mid(10).Trim(false).RemoveLast());
+   restorePanel->SetRowString("Bootstrap", (*dt)[i].Mid(10).Trim(false).RemoveLast());
    if ((k = (*dt)[++i].Find("Where:")) != 0) return false;
-   cfgWhere->SetValue((*dt)[i].Mid(10).Trim(false).RemoveLast());
+   restorePanel->SetRowString("Where", (*dt)[i].Mid(10).Trim(false).RemoveLast());
    
    if ((k = (*dt)[++i].Find("Replace:")) != 0) return false;
    wxString str = (*dt)[i].Mid(10).Trim(false).RemoveLast();
-   if (str == "always") cfgReplace->SetSelection(0);
-   else if (str == "ifnewer") cfgReplace->SetSelection(1);
-   else if (str == "ifolder") cfgReplace->SetSelection(2);
-   else if (str == "never") cfgReplace->SetSelection(3);
-   else cfgReplace->SetSelection(0);
-   
+   if (str == "always") restorePanel->SetRowSelection("Replace", 0);
+   else if (str == "ifnewer") restorePanel->SetRowSelection("Replace", 1);
+   else if (str == "ifolder") restorePanel->SetRowSelection("Replace", 2);
+   else if (str == "never") restorePanel->SetRowSelection("Replace", 3);
+   else restorePanel->SetRowSelection("Replace", 0);
+
    if ((k = (*dt)[++i].Find("FileSet:")) != 0) return false;
-   cfgFileset->SetLabel((*dt)[i].Mid(10).Trim(false).RemoveLast());
+   restorePanel->SetRowString("Fileset", (*dt)[i].Mid(10).Trim(false).RemoveLast());
    if ((k = (*dt)[++i].Find("Client:")) != 0) return false;
-   cfgClient->SetLabel((*dt)[i].Mid(10).Trim(false).RemoveLast());
+   restorePanel->SetRowString("Client", (*dt)[i].Mid(10).Trim(false).RemoveLast());
    if ((k = (*dt)[++i].Find("Storage:")) != 0) return false;
-   cfgStorage->SetLabel((*dt)[i].Mid(10).Trim(false).RemoveLast());
+   restorePanel->SetRowString("Storage", (*dt)[i].Mid(10).Trim(false).RemoveLast());
    if ((k = (*dt)[++i].Find("When:")) != 0) return false;
-   cfgWhen->SetValue((*dt)[i].Mid(10).Trim(false).RemoveLast());
+   restorePanel->SetRowString("When", (*dt)[i].Mid(10).Trim(false).RemoveLast());
    if ((k = (*dt)[++i].Find("Priority:")) != 0) return false;
-   cfgPriority->SetValue((*dt)[i].Mid(10).Trim(false).RemoveLast());
+   restorePanel->SetRowString("Priority", (*dt)[i].Mid(10).Trim(false).RemoveLast());
    cfgUpdated = 0;
    
    restorePanel->Layout();
@@ -1155,65 +1726,85 @@ bool wxbRestorePanel::UpdateConfig(wxbDataTokenizer* dt) {
 void wxbRestorePanel::SetStatus(status_enum newstatus) {
    switch (newstatus) {
    case disabled:
+      centerSizer->Remove(configPanel);
       centerSizer->Remove(restorePanel);
       centerSizer->Remove(treelistPanel);
+      treelistPanel->Show(false);
       restorePanel->Show(false);
-      centerSizer->Add(treelistPanel, 1, wxEXPAND);
-      treelistPanel->Show(true);
+      centerSizer->Add(configPanel, 1, wxEXPAND);
+      configPanel->Show(true);
+      configPanel->Layout();
       centerSizer->Layout();
+      this->Layout();
       start->SetLabel("Enter restore mode");
       start->Enable(false);
-      clientChoice->Enable(false);
-      jobChoice->Enable(false);
+      configPanel->Enable(false);
       tree->Enable(false);
       list->Enable(false);
       gauge->Enable(false);
+      cancel->Enable(false);
+      cfgUpdated = 0;
+      cancelled = 0;
       break;
    case finished:
+      centerSizer->Remove(configPanel);
       centerSizer->Remove(restorePanel);
+      centerSizer->Remove(treelistPanel);
+      treelistPanel->Show(false);
       restorePanel->Show(false);
-      centerSizer->Add(treelistPanel, 1, wxEXPAND);
-      treelistPanel->Show(true);
+      centerSizer->Add(configPanel, 1, wxEXPAND);
+      configPanel->Show(true);
+      configPanel->Layout();
       centerSizer->Layout();
+      this->Layout();
       tree->DeleteAllItems();
       list->DeleteAllItems();
-      clientChoice->Clear();
-      jobChoice->Clear();
+      configPanel->ClearRowChoices("Client");
+      configPanel->ClearRowChoices("Before");
       wxbMainFrame::GetInstance()->EnablePanels();
       newstatus = activable;
    case activable:
+      cancelled = 0;
       start->SetLabel("Enter restore mode");
       start->Enable(true);
-      clientChoice->Enable(false);
-      jobChoice->Enable(false);
+      configPanel->Enable(false);
       tree->Enable(false);
       list->Enable(false);
       gauge->Enable(false);
+      cancel->Enable(false);
+      cfgUpdated = 0;
       break;
    case entered:
       wxbMainFrame::GetInstance()->DisablePanels(this);
       gauge->SetValue(0);
-      start->SetLabel("Choose files to restore");
-      clientChoice->Enable(true);
-      jobChoice->Enable(true);
+      start->Enable(false);
+      //start->SetLabel("Choose files to restore");
+      configPanel->Enable(true);
       tree->Enable(false);
       list->Enable(false);
+      cancel->Enable(true);
+      cfgUpdated = 0;
       break;
    case listing:
       
       break;
    case choosing:
+      start->Enable(true);
       start->SetLabel("Restore");
-      clientChoice->Enable(false);
-      jobChoice->Enable(false);
+      centerSizer->Remove(configPanel);
+      configPanel->Show(false);
+      centerSizer->Add(treelistPanel, 1, wxEXPAND);
+      treelistPanel->Show(true);
+      treelistPanel->Layout();
+      centerSizer->Layout();
+      this->Layout();
       tree->Enable(true);
       list->Enable(true);
-      working = false;
+      SetWorking(false);
       break;
    case configuring:
       start->Enable(false);
-      clientChoice->Enable(false);
-      jobChoice->Enable(false);
+      configPanel->Enable(false);
       tree->Enable(false);
       list->Enable(false);
       centerSizer->Remove(treelistPanel);
@@ -1222,57 +1813,107 @@ void wxbRestorePanel::SetStatus(status_enum newstatus) {
       restorePanel->Show(true);
       restorePanel->Layout();
       centerSizer->Layout();
-      cfgApply->Enable(false);
-      cfgOk->Enable(true);
+      this->Layout();
+      restorePanel->EnableApply(false);
       break;
    case restoring:
       start->SetLabel("Restoring...");
       gauge->Enable(true);
       gauge->SetValue(0);
       start->Enable(false);
-      clientChoice->Enable(false);
-      jobChoice->Enable(false);
+      configPanel->Enable(false);
       tree->Enable(false);
       list->Enable(false);
-      working = true;
+      SetWorking(true);
       break;
    }
    status = newstatus;
 }
 
 /*----------------------------------------------------------------------------
-   Event handling
+   UI related
   ----------------------------------------------------------------------------*/
 
-void wxbRestorePanel::OnClientChoiceChanged(wxCommandEvent& event) {
+void wxbRestorePanel::SetWorking(bool working) {
+   this->working = working;
    if (working) {
-      return;
+      SetCursor(*wxHOURGLASS_CURSOR);
+//      SetEvtHandlerEnabled(false); //EVTQUEUE
+   }
+//   else if (!processing) { /* Empty event queue if we aren't already doing this */ //EVTQUEUE
+   else {
+//      processing = true; //EVTQUEUE
+      SetCursor(*wxSTANDARD_CURSOR);
+//      SetEvtHandlerEnabled(true); //EVTQUEUE
+/*      wxNode *node = pendingEvents->First(); //EVTQUEUE
+      while ( node ) {
+         wxEvent *event = (wxEvent *)node->Data();
+         delete node;
+   
+         wxEvtHandler::ProcessEvent(*event);
+         delete event;
+   
+         node = pendingEvents->First();
+      }
+      processing = false;*/
    }
-   working = true;
-   clientChoice->Enable(false);
-   CmdListJobs();
-   clientChoice->Enable(true);
-   jobChoice->Refresh();
-   working = false;
 }
 
-void wxbRestorePanel::OnStart(wxEvent& WXUNUSED(event)) {
-   if (working) {
+bool wxbRestorePanel::IsWorking() {
+   return this->working;
+}
+
+void wxbRestorePanel::EnableConfig(bool enable) {
+   restorePanel->Enable(enable);
+}
+
+/*----------------------------------------------------------------------------
+   Event handling
+  ----------------------------------------------------------------------------*/
+
+
+//EVTQUEUE
+/*
+bool wxbRestorePanel::ProcessEvent(wxEvent& event) {
+   if (IsWorking() || processing) {
+      wxEvent *eventCopy = event.Clone();
+      
+      pendingEvents->Append(eventCopy);
+      return TRUE;
+   }
+   else {
+      return wxEvtHandler::ProcessEvent(event);
+   }
+}
+*/
+
+void wxbRestorePanel::OnCancel(wxCommandEvent& event) {
+   cancel->Enable(false);
+   SetCursor(*wxHOURGLASS_CURSOR);
+   CmdCancel();
+   SetCursor(*wxSTANDARD_CURSOR);
+}
+
+void wxbRestorePanel::OnStart(wxCommandEvent& event) {
+   if (IsWorking()) {
+      AddPendingEvent(event);
       return;
    }
-   working = true;
+   SetWorking(true);
    CmdStart();
-   working = false;
+   SetWorking(false);
 }
 
 void wxbRestorePanel::OnTreeChanging(wxTreeEvent& event) {
-   if (working) {
+   if (IsWorking()) {
+      AddPendingEvent(event);
       event.Veto();
    }
 }
 
 void wxbRestorePanel::OnTreeExpanding(wxTreeEvent& event) {
-   if (working) {
+   if (IsWorking()) {
+      AddPendingEvent(event);
       event.Veto();
       return;
    }
@@ -1285,48 +1926,143 @@ void wxbRestorePanel::OnTreeExpanding(wxTreeEvent& event) {
 }
 
 void wxbRestorePanel::OnTreeChanged(wxTreeEvent& event) {
-   if (working) {
+   if (IsWorking()) {
+      AddPendingEvent(event);
       return;
    }
-
-   working = true;
+   if (currentTreeItem == event.GetItem()) {
+      return;
+   }
+   treeadd->Enable(false);
+   treeremove->Enable(false);
+   treerefresh->Enable(false);
+   markWhenListingDone = false;
+   SetWorking(true);
+   currentTreeItem = event.GetItem();
    CmdList(event.GetItem());
-   working = false;
+   if (markWhenListingDone) {
+      CmdMark(event.GetItem(), NULL, 0);
+      tree->Refresh();
+   }
+   SetWorking(false);
+   if (event.GetItem().IsOk()) {
+      int status = ((wxbTreeItemData*)tree->GetItemData(event.GetItem()))->GetMarked();
+      treeadd->Enable(status != 1);
+      treeremove->Enable(status != 0);
+   }
+   treerefresh->Enable(true);
 }
 
 void wxbRestorePanel::OnTreeMarked(wxbTreeMarkedEvent& event) {
-   if (working) {
-      //event.Skip();
+   csprint("Tree marked", CS_DEBUG);
+   if (IsWorking()) {
+      if (tree->GetSelection() == event.GetItem()) {
+         markWhenListingDone = !markWhenListingDone;
+      }
+      AddPendingEvent(event);
       return;
    }
-   working = true;
-   CmdMark(event.GetItem(), -1);
+   SetWorking(true);
+   CmdMark(event.GetItem(), NULL, 0);
    //event.Skip();
    tree->Refresh();
-   working = false;
+   SetWorking(false);
+   if (event.GetItem().IsOk()) {
+      int status = ((wxbTreeItemData*)tree->GetItemData(event.GetItem()))->GetMarked();
+      treeadd->Enable(status != 1);
+      treeremove->Enable(status != 0);
+   }
+}
+
+void wxbRestorePanel::OnTreeAdd(wxCommandEvent& event) {
+   if (IsWorking()) {
+      AddPendingEvent(event);
+      return;
+   }
+   
+   if (currentTreeItem.IsOk()) {
+      SetWorking(true);
+      CmdMark(currentTreeItem, NULL, 0, 1);
+      tree->Refresh();
+      treeadd->Enable(0);
+      treeremove->Enable(1);
+      SetWorking(false);
+   }
+}
+
+void wxbRestorePanel::OnTreeRemove(wxCommandEvent& event) {
+   if (IsWorking()) {
+      AddPendingEvent(event);
+      return;
+   }
+   
+   if (currentTreeItem.IsOk()) {
+      SetWorking(true);
+      CmdMark(currentTreeItem, NULL, 0, 0);
+      tree->Refresh();
+      treeadd->Enable(1);
+      treeremove->Enable(0);
+      SetWorking(false);
+   }
+}
+
+void wxbRestorePanel::OnTreeRefresh(wxCommandEvent& event) {
+   if (IsWorking()) {
+      AddPendingEvent(event);
+      return;
+   }
+   
+   SetWorking(true);
+   RefreshTree();
+   SetWorking(false);
 }
 
 void wxbRestorePanel::OnListMarked(wxbListMarkedEvent& event) {
-   if (working) {
+   if (IsWorking()) {
+      AddPendingEvent(event);
       //event.Skip();
       return;
    }
-   working = true;
-   //long item = event.GetId(); 
-   long item = list->GetNextItem(-1, wxLIST_NEXT_ALL, wxLIST_STATE_FOCUSED);
-   CmdMark(wxTreeItemId(), item);
+   
+   if (list->GetSelectedItemCount() == 0) {
+      return;
+   }
+   
+   SetWorking(true);  
+   
+   long* items = new long[list->GetSelectedItemCount()];
+   
+   int num = 0;
+   
+   long item = list->GetNextItem(-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
+   while (item != -1) {
+      items[num] = item;
+      num++;
+      item = list->GetNextItem(item, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
+   }
+     
+   CmdMark(wxTreeItemId(), items, num);
+   
+   delete[] items;
+   
+   wxListEvent listevt;
+   
+   OnListChanged(listevt);
+   
    event.Skip();
    tree->Refresh();
-   working = false;
+   SetWorking(false);
 }
 
 void wxbRestorePanel::OnListActivated(wxListEvent& event) {
-   if (working) {
+   if (IsWorking()) {
+      AddPendingEvent(event);
       //event.Skip();
       return;
    }
-   working = true;
-   long item = list->GetNextItem(-1, wxLIST_NEXT_ALL, wxLIST_STATE_FOCUSED);
+   SetWorking(true);
+   long item = event.GetIndex();
+//   long item = list->GetNextItem(-1, wxLIST_NEXT_ALL, wxLIST_STATE_FOCUSED);
    if (item > -1) {
       wxbTreeItemData* itemdata = (wxbTreeItemData*)list->GetItemData(item);
       wxString name = itemdata->GetName();
@@ -1343,7 +2079,7 @@ void wxbRestorePanel::OnListActivated(wxListEvent& event) {
             wxString name2 = tree->GetItemText(currentChild);
             if (name2 == name) {
                //tree->UnselectAll();
-               working = false;
+               SetWorking(false);
                tree->Expand(currentTreeItem);
                tree->SelectItem(currentChild);
                //tree->Refresh();
@@ -1353,61 +2089,175 @@ void wxbRestorePanel::OnListActivated(wxListEvent& event) {
          }
       }
    }
-   working = false;
+   SetWorking(false);
+}
+
+void wxbRestorePanel::OnListChanged(wxListEvent& event) {
+   if (IsWorking()) {
+      AddPendingEvent(event);
+      return;
+   }
+   listadd->Enable(false);
+   listremove->Enable(false);
+   
+   bool marked = false;
+   bool unmarked = false;
+   
+   long item = list->GetNextItem(-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
+   while (item != -1) {
+      switch (((wxbTreeItemData*)list->GetItemData(item))->GetMarked()) {
+      case 0:
+         unmarked = true;
+         break;
+      case 1:
+         marked = true;
+         break;
+      case 2:
+         marked = true;
+         unmarked = true;
+         break;
+      default:
+         break;
+         // Should never happen
+      }
+      if (marked && unmarked) break;
+      item = list->GetNextItem(item, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
+   }
+   
+   listadd->Enable(unmarked);
+   listremove->Enable(marked);
+}
+
+void wxbRestorePanel::OnListAdd(wxCommandEvent& event) {
+   if (IsWorking()) {
+      AddPendingEvent(event);
+      return;
+   }
+   
+   SetWorking(true);
+   
+   long* items = new long[list->GetSelectedItemCount()];
+   
+   int num = 0;
+   
+   long item = list->GetNextItem(-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
+   while (item != -1) {
+      items[num] = item;
+      num++;
+      item = list->GetNextItem(item, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
+   }
+     
+   CmdMark(wxTreeItemId(), items, num, 1);
+   
+   delete[] items;
+   
+   tree->Refresh();
+   SetWorking(false);
+   
+   listadd->Enable(false);
+   listremove->Enable(true);
+}
+
+void wxbRestorePanel::OnListRemove(wxCommandEvent& event) {
+   if (IsWorking()) {
+      AddPendingEvent(event);
+      return;
+   }
+   
+   SetWorking(true);
+   
+   long* items = new long[list->GetSelectedItemCount()];
+   
+   int num = 0;
+   
+   long item = list->GetNextItem(-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
+   while (item != -1) {
+      items[num] = item;
+      num++;
+      item = list->GetNextItem(item, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
+   }
+     
+   CmdMark(wxTreeItemId(), items, num, 0);
+   
+   delete[] items;
+   
+   tree->Refresh();
+   SetWorking(false);
+   
+   listadd->Enable(true);
+   listremove->Enable(false);
+}
+
+void wxbRestorePanel::OnListRefresh(wxCommandEvent& event) {
+   if (IsWorking()) {
+      AddPendingEvent(event);
+      return;
+   }
+   
+   SetWorking(true);
+   RefreshList();
+   SetWorking(false);
 }
 
 void wxbRestorePanel::OnConfigUpdated(wxCommandEvent& event) {
-   if (status != configuring) return;
-   cfgApply->Enable(true);
-   cfgOk->Enable(false);
-   cfgUpdated = cfgUpdated | (1 << event.GetId());
+   if (status == entered) {
+      if (event.GetId() == ConfigJobName) {
+         if (IsWorking()) {
+            return;
+         }
+         SetWorking(true);
+         UpdateFirstConfig();
+         SetWorking(false);
+      }
+      else if (event.GetId() == ConfigClient) {
+         if (IsWorking()) {
+            return;
+         }
+         SetWorking(true);
+         configPanel->Enable(false);
+         CmdListJobs();
+         configPanel->Enable(true);
+         SetWorking(false);
+      }
+      cfgUpdated = cfgUpdated | (1 << event.GetId());
+   }
+   else if (status == configuring) {
+      restorePanel->EnableApply(true);
+      cfgUpdated = cfgUpdated | (1 << event.GetId());
+   }
 }
 
-void wxbRestorePanel::OnConfigOk(wxEvent& WXUNUSED(event)) {
+void wxbRestorePanel::OnConfigOk(wxCommandEvent& WXUNUSED(event)) {
    if (status != configuring) return;
-   if (working) {
+   if (IsWorking()) {
       return;
    }
-   working = true;
+   SetWorking(true);
    CmdStart();
-   working = false;
+   SetWorking(false);
 }
 
-void wxbRestorePanel::OnConfigApply(wxEvent& WXUNUSED(event)) {
+void wxbRestorePanel::OnConfigApply(wxCommandEvent& WXUNUSED(event)) {
    if (status != configuring) return;
-   if (working) {
+   if (IsWorking()) {
       return;
    }
-   working = true;
+   SetWorking(true);
    CmdConfigApply();
    if (cfgUpdated == 0) {
-      cfgApply->Enable(false);
-      cfgOk->Enable(true);
+      restorePanel->EnableApply(false);
    }
-   working = false;  
+   SetWorking(false);  
 }
 
-void wxbRestorePanel::OnConfigCancel(wxEvent& WXUNUSED(event)) {
+void wxbRestorePanel::OnConfigCancel(wxCommandEvent& WXUNUSED(event)) {
    if (status != configuring) return;
-   if (working) {
+   if (IsWorking()) {
       return;
    }
-   working = true;
+   SetWorking(true);
    CmdConfigCancel();
-   working = false;
-}
-
-/* TODO : correct that bad implementation of tree marked event forwarding */
-
-wxbTreeListPanel::wxbTreeListPanel(wxbRestorePanel* parent): wxPanel(parent, -1) {
-   this->parent = parent;
-}
-
-void wxbTreeListPanel::OnTreeMarked(wxbTreeMarkedEvent& event) {
-   parent->OnTreeMarked(event);
-}
-
-void wxbTreeListPanel::OnListMarked(wxbListMarkedEvent& event) {
-   parent->OnListMarked(event);
+   SetWorking(false);
 }