3 * wxbPanel for restoring files
5 * Nicolas Boichat, April-May 2004
9 Copyright (C) 2004 Kern Sibbald and John Walker
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.
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.
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.
25 /* Note concerning "done" output (modifiable marked with +)
27 +JobName: RestoreFiles
28 Bootstrap: /var/lib/bacula/restore.bsr
29 +Where: /tmp/bacula-restores
34 +When: 2004-04-18 01:18:56
36 OK to run? (yes/mod/no):mod
38 1: Level (not appropriate)
39 2: Storage (automatic ?)
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)")
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):")
50 Select parameter to modify (1-11):
53 #include "wxbrestorepanel.h"
55 #include "wxbmainframe.h"
59 #include <wx/choice.h>
60 #include <wx/datetime.h>
64 #include "unmarked.xpm"
66 #include "partmarked.xpm"
68 #include <wx/listimpl.cpp>
70 /* A macro named Yield is defined under MinGW */
73 WX_DEFINE_LIST(wxbEventList);
76 * Class which is stored in the tree and in the list to keep informations
79 class wxbTreeItemData : public wxTreeItemData {
81 wxbTreeItemData(wxString path, wxString name, int marked, long listid = -1);
82 wxbTreeItemData(wxString path, wxString name, wxString marked, long listid = -1);
88 void SetMarked(int marked);
89 void SetMarked(wxString marked);
93 static int GetMarkedStatus(wxString file);
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) */
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;
108 wxbTreeItemData::wxbTreeItemData(wxString path, wxString name, wxString marked, long listid): wxTreeItemData() {
109 this->path = new wxString(path);
110 this->name = new wxString(name);
112 this->listid = listid;
115 wxbTreeItemData::~wxbTreeItemData() {
120 int wxbTreeItemData::GetMarked() {
124 void wxbTreeItemData::SetMarked(wxString marked) {
128 else if (marked == "+") {
136 void wxbTreeItemData::SetMarked(int marked) {
137 this->marked = marked;
140 long wxbTreeItemData::GetListId() {
144 wxString wxbTreeItemData::GetPath() {
148 wxString wxbTreeItemData::GetName() {
152 /*wxbTreeItemData* wxbTreeItemData::GetChild(wxString dirname) {
153 int marked = GetMarkedStatus(dirname);
154 return new wxbTreeItemData(path + (marked ? dirname.Mid(1) : dirname), marked);
157 int wxbTreeItemData::GetMarkedStatus(wxString file) {
158 if (file.Length() == 0)
161 switch (file.GetChar(0)) {
171 // ----------------------------------------------------------------------------
172 // event tables and other macros for wxWindows
173 // ----------------------------------------------------------------------------
201 BEGIN_EVENT_TABLE(wxbRestorePanel, wxPanel)
202 EVT_BUTTON(RestoreStart, wxbRestorePanel::OnStart)
203 EVT_BUTTON(RestoreCancel, wxbRestorePanel::OnCancel)
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)
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)
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)
232 EVT_BUTTON(ConfigOk, wxbRestorePanel::OnConfigOk)
233 EVT_BUTTON(ConfigApply, wxbRestorePanel::OnConfigApply)
234 EVT_BUTTON(ConfigCancel, wxbRestorePanel::OnConfigCancel)
238 * wxbRestorePanel constructor
240 wxbRestorePanel::wxbRestorePanel(wxWindow* parent): wxbPanel(parent) {
241 //pendingEvents = new wxbEventList(); //EVTQUEUE
242 //processing = false; //EVTQUEUE
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));
250 wxFlexGridSizer* mainSizer = new wxFlexGridSizer(3, 1, 10, 10);
251 mainSizer->AddGrowableCol(0);
252 mainSizer->AddGrowableRow(1);
254 wxFlexGridSizer *firstSizer = new wxFlexGridSizer(1, 2, 10, 10);
256 firstSizer->AddGrowableCol(0);
257 firstSizer->AddGrowableRow(0);
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);
262 cancel = new wxButton(this, RestoreCancel, "Cancel restore", wxDefaultPosition, wxSize(150, 30));
263 firstSizer->Add(cancel, 0, wxALIGN_CENTER_HORIZONTAL | wxALIGN_RIGHT, 10);
267 /* clientChoice = new wxChoice(this, ClientChoice, wxDefaultPosition, wxSize(150, 30), 0, elist);
268 firstSizer->Add(clientChoice, 1, wxALIGN_CENTER_HORIZONTAL | wxALIGN_CENTER_VERTICAL, 10);
270 jobChoice = new wxChoice(this, -1, wxDefaultPosition, wxSize(150, 30), 0, elist);
271 firstSizer->Add(jobChoice, 1, wxALIGN_CENTER_HORIZONTAL | wxALIGN_CENTER_VERTICAL, 10);*/
273 mainSizer->Add(firstSizer, 1, wxEXPAND, 10);
275 treelistPanel = new wxSplitterWindow(this);
277 wxPanel* treePanel = new wxPanel(treelistPanel);
278 wxFlexGridSizer *treeSizer = new wxFlexGridSizer(2, 1, 0, 0);
279 treeSizer->AddGrowableCol(0);
280 treeSizer->AddGrowableRow(0);
282 tree = new wxbTreeCtrl(treePanel, this, TreeCtrl, wxDefaultPosition, wxSize(200,50));
283 tree->SetImageList(imagelist);
285 treeSizer->Add(tree, 1, wxEXPAND, 0);
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);
295 treeSizer->Add(treeCtrlSizer, 1, wxALIGN_CENTER_HORIZONTAL, 0);
297 treePanel->SetSizer(treeSizer);
299 wxPanel* listPanel = new wxPanel(treelistPanel);
300 wxFlexGridSizer *listSizer = new wxFlexGridSizer(2, 1, 0, 0);
301 listSizer->AddGrowableCol(0);
302 listSizer->AddGrowableRow(0);
304 list = new wxbListCtrl(listPanel, this, ListCtrl, wxDefaultPosition, wxSize(200,50));
305 //treelistSizer->Add(list, 1, wxEXPAND, 10);
307 list->SetImageList(imagelist, wxIMAGE_LIST_SMALL);
310 info.SetMask(wxLIST_MASK_TEXT | wxLIST_MASK_FORMAT);
312 info.SetAlign(wxLIST_FORMAT_CENTER);
313 list->InsertColumn(0, info);
315 info.SetText("Filename");
316 info.SetAlign(wxLIST_FORMAT_LEFT);
317 list->InsertColumn(1, info);
319 info.SetText("Size");
320 info.SetAlign(wxLIST_FORMAT_RIGHT);
321 list->InsertColumn(2, info);
323 info.SetText("Date");
324 info.SetAlign(wxLIST_FORMAT_LEFT);
325 list->InsertColumn(3, info);
327 info.SetText("Perm.");
328 info.SetAlign(wxLIST_FORMAT_LEFT);
329 list->InsertColumn(4, info);
331 info.SetText("User");
332 info.SetAlign(wxLIST_FORMAT_RIGHT);
333 list->InsertColumn(5, info);
335 info.SetText("Group");
336 info.SetAlign(wxLIST_FORMAT_RIGHT);
337 list->InsertColumn(6, info);
339 listSizer->Add(list, 1, wxEXPAND, 0);
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);
349 listSizer->Add(listCtrlSizer, 1, wxALIGN_CENTER_HORIZONTAL, 0);
351 listPanel->SetSizer(listSizer);
353 treelistPanel->SplitVertically(treePanel, listPanel, 210);
355 treelistPanel->SetMinimumPaneSize(210);
357 treelistPanel->Show(false);
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));
367 configPanel = new wxbConfigPanel(this, config, "Please configure parameters concerning files to restore :", RestoreStart, RestoreCancel, -1);
369 configPanel->Show(true);
370 configPanel->Enable(false);
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, ""));
384 restorePanel = new wxbConfigPanel(this, config, "Please configure parameters concerning files restoration :", ConfigOk, ConfigCancel, ConfigApply);
386 restorePanel->Show(false);
388 centerSizer = new wxBoxSizer(wxHORIZONTAL);
389 //centerSizer->Add(treelistPanel, 1, wxEXPAND | wxADJUST_MINSIZE);
391 mainSizer->Add(centerSizer, 1, wxEXPAND, 10);
393 gauge = new wxGauge(this, -1, 1, wxDefaultPosition, wxSize(200,20));
395 mainSizer->Add(gauge, 1, wxEXPAND, 5);
397 gauge->Enable(false);
400 mainSizer->SetSizeHints(this);
404 for (int i = 0; i < 7; i++) {
405 list->SetColumnWidth(i, 70);
408 SetCursor(*wxSTANDARD_CURSOR);
410 markWhenListingDone = false;
416 * wxbRestorePanel destructor
418 wxbRestorePanel::~wxbRestorePanel() {
422 /*----------------------------------------------------------------------------
423 wxbPanel overloadings
424 ----------------------------------------------------------------------------*/
426 wxString wxbRestorePanel::GetTitle() {
430 void wxbRestorePanel::EnablePanel(bool enable) {
432 if (status == disabled) {
433 SetStatus(activable);
441 /*----------------------------------------------------------------------------
442 Commands called by events handler
443 ----------------------------------------------------------------------------*/
445 /* The main button has been clicked */
446 void wxbRestorePanel::CmdStart() {
448 if (status == activable) {
449 wxbMainFrame::GetInstance()->SetStatusText("Getting parameters list.");
450 wxbDataTokenizer* dt = WaitForEnd(".clients\n", true, false);
453 configPanel->ClearRowChoices("Client");
454 restorePanel->ClearRowChoices("Client");
456 if (dt->GetCount() == 0) {
457 wxbMainFrame::GetInstance()->SetStatusText("Error : no clients returned by the director.");
461 for (i = 0; i < dt->GetCount(); i++) {
464 configPanel->AddRowChoice("Client", str);
465 restorePanel->AddRowChoice("Client", str);
475 dt = WaitForEnd(".filesets\n", true, false);
477 configPanel->ClearRowChoices("Fileset");
478 restorePanel->ClearRowChoices("Fileset");
480 if (dt->GetCount() == 0) {
481 wxbMainFrame::GetInstance()->SetStatusText("Error : no filesets returned by the director.");
485 for (i = 0; i < dt->GetCount(); i++) {
488 configPanel->AddRowChoice("Fileset", str);
489 restorePanel->AddRowChoice("Fileset", str);
499 dt = WaitForEnd(".storage\n", true, false);
501 configPanel->ClearRowChoices("Storage");
502 restorePanel->ClearRowChoices("Storage");
504 if (dt->GetCount() == 0) {
505 wxbMainFrame::GetInstance()->SetStatusText("Error : no storage returned by the director.");
509 for (i = 0; i < dt->GetCount(); i++) {
512 configPanel->AddRowChoice("Storage", str);
513 restorePanel->AddRowChoice("Storage", str);
523 dt = WaitForEnd(".jobs\n", true, false);
525 configPanel->ClearRowChoices("Job Name");
527 if (dt->GetCount() == 0) {
528 wxbMainFrame::GetInstance()->SetStatusText("Error : no jobs returned by the director.");
532 for (i = 0; i < dt->GetCount(); i++) {
535 configPanel->AddRowChoice("Job Name", str);
538 configPanel->SetRowString("Job Name", "RestoreFiles");
547 dt = WaitForEnd(".pools\n", true, false);
549 configPanel->ClearRowChoices("Pool");
551 if (dt->GetCount() == 0) {
552 wxbMainFrame::GetInstance()->SetStatusText("Error : no jobs returned by the director.");
556 for (i = 0; i < dt->GetCount(); i++) {
559 configPanel->AddRowChoice("Pool", str);
573 wxbMainFrame::GetInstance()->SetStatusText("Please configure your restore parameters.");
575 else if (status == entered) {
576 /* if (clientChoice->GetStringSelection().Length() < 1) {
577 wxbMainFrame::GetInstance()->SetStatusText("Please select a client.");
580 if (jobChoice->GetStringSelection().Length() < 1) {
581 wxbMainFrame::GetInstance()->SetStatusText("Please select a restore date.");
584 wxbMainFrame::GetInstance()->SetStatusText("Building restore tree...");
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");
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.");
603 wxbTableParser* tableparser = new wxbTableParser();
604 wxbDataTokenizer* dt = new wxbDataTokenizer(true);
606 wxbMainFrame::GetInstance()->Send(wxString() << configPanel->GetRowString("Before") << "\n");
608 while (!tableparser->hasFinished() && !dt->hasFinished()) {
609 wxTheApp->Yield(true);
615 if (dt->hasFinished() && !tableparser->hasFinished()) {
617 if (dt->GetCount() > 1) {
618 str = (*dt)[dt->GetCount()-2];
621 wxbMainFrame::GetInstance()->SetStatusText(wxString("Error while starting restore: ") << str);
631 for (i = 0; i < tableparser->GetCount(); i++) {
632 str = (*tableparser)[i][2];
633 str.Replace(",", "");
634 if (str.ToLong(&l)) {
640 gauge->SetRange(tot);
642 /*wxbMainFrame::GetInstance()->Print(
643 wxString("[") << tot << "]", CS_DEBUG);*/
645 wxDateTime base = wxDateTime::Now();
649 unsigned int lastindex = 0;
653 while (!dt->hasFinished()) {
654 newdate = wxDateTime::Now();
655 if (newdate.Subtract(base).GetMilliseconds() > 10 ) {
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)) {
668 var = (willdo-done)/3;
676 if (gauge->GetValue() <= done) {
677 gauge->SetValue(done);
681 else if (gauge->GetValue() >= willdo) {
682 gauge->SetValue(willdo);
687 gauge->SetValue(gauge->GetValue()+var);
689 /*wxbMainFrame::GetInstance()->Print(
690 wxString("[") << gauge->GetValue() << "/" << done
691 << "-" << willdo << "]", CS_DEBUG);*/
693 wxTheApp->Yield(true);
697 gauge->SetValue(tot);
698 wxTheApp->Yield(true);
709 WaitForEnd("unmark *\n");
710 wxTreeItemId root = tree->AddRoot(configPanel->GetRowString("Client"), -1, -1, new wxbTreeItemData("/", configPanel->GetRowString("Client"), 0));
711 currentTreeItem = root;
713 tree->SelectItem(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.");
718 else if (status == choosing) {
722 wxbDataTokenizer* dt;
726 dt = new wxbDataTokenizer(true);
727 WaitForPrompt("done\n");
729 SetStatus(configuring);
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);
737 if ((j = (*dt)[i].Find(" file selected to be restored.")) > -1) {
738 (*dt)[i].Mid(0, j).ToLong(&totfilemessages);
743 wxbMainFrame::GetInstance()->SetStatusText(
744 wxString("Please configure your restore (")
745 << totfilemessages << " files selected to be restored)...");
747 UpdateSecondConfig(dt);
752 restorePanel->EnableApply(false);
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.");
761 else if (status == configuring) {
762 cancel->Enable(false);
766 wxbMainFrame::GetInstance()->SetStatusText("Restoring, please wait...");
768 wxbDataTokenizer* dt;
770 SetStatus(restoring);
774 gauge->SetRange(totfilemessages);
776 wxDateTime currenttime;
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
785 currenttime -= wxTimeSpan::Seconds(30); //Adding a 30" tolerance
789 wxDateTime scheduledtime;
790 wxStringTokenizer stkz(restorePanel->GetRowString("When"), " ", wxTOKEN_STRTOK);
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
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.");
804 wxString cmd = "list jobid=";
806 wxString jobname = restorePanel->GetRowString("Job Name");
810 wxbTableParser* tableparser;
813 tableparser = CreateAndWaitForParser("list jobs\n");
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";
825 cancel->Enable(true);
834 while (sw2.Time() < 2000) {
835 wxTheApp->Yield(true);
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.");
842 cancel->Enable(true);
847 long filemessages = 0;
850 tableparser = CreateAndWaitForParser(cmd);
851 if ((*tableparser)[0][7] != "C") {
856 dt = WaitForEnd("messages\n", true);
858 for (unsigned int i = 0; i < dt->GetCount(); i++) {
859 wxStringTokenizer tkz((*dt)[i], " ", wxTOKEN_STRTOK);
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
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
877 //wxbMainFrame::GetInstance()->Print(wxString("(") << filemessages << ")", CS_DEBUG);
878 gauge->SetValue(filemessages);
888 wxbMainFrame::GetInstance()->SetStatusText(wxString("Restoring, please wait (") << filemessages << " of " << totfilemessages << " files done)...");
891 while (sw2.Time() < 10000) {
892 wxTheApp->Yield(true);
897 WaitForEnd("messages\n");
899 gauge->SetValue(totfilemessages);
901 if ((*tableparser)[0][7] == "T") {
902 wxbMainFrame::GetInstance()->Print("Restore done successfully.\n", CS_DEBUG);
903 wxbMainFrame::GetInstance()->SetStatusText("Restore done successfully.");
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.");
914 /* The cancel button has been clicked */
915 void wxbRestorePanel::CmdCancel() {
918 if (status == restoring) {
920 wxbMainFrame::GetInstance()->Send(wxString("cancel job=") << jobid << "\n");
922 cancel->Enable(true);
927 while ((IsWorking()) && (cancelled != 2)) {
928 wxTheApp->Yield(true);
930 if (sw.Time() > 30000) { /* 30 seconds timeout */
931 if (status == choosing) {
932 wxbMainFrame::GetInstance()->Send("quit\n");
934 else if (status == configuring) {
935 wxbMainFrame::GetInstance()->Send("no\n");
937 else if (status == restoring) {
948 wxbMainFrame::GetInstance()->Send("quit\n");
951 wxbMainFrame::GetInstance()->Send("no\n");
960 /* Apply configuration changes */
962 /* 1: Level (not appropriate)
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)")
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):")
976 void wxbRestorePanel::CmdConfigApply() {
977 if (cfgUpdated == 0) return;
979 wxbMainFrame::GetInstance()->SetStatusText("Applying restore configuration changes...");
983 wxbDataTokenizer* dt = NULL;
987 while (cfgUpdated > 0) {
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");
999 cfgUpdated = cfgUpdated & (~(1 << ConfigWhere));
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");
1007 cfgUpdated = cfgUpdated & (~(1 << ConfigReplace));
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");
1015 cfgUpdated = cfgUpdated & (~(1 << ConfigWhen));
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");
1023 cfgUpdated = cfgUpdated & (~(1 << ConfigPriority));
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.");
1035 dt = new wxbDataTokenizer(true);
1036 WaitForPrompt(wxString() << client << "\n");
1038 cfgUpdated = cfgUpdated & (~(1 << ConfigClient));
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.");
1050 dt = new wxbDataTokenizer(true);
1051 WaitForPrompt(wxString() << fileset << "\n");
1053 cfgUpdated = cfgUpdated & (~(1 << ConfigFileset));
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.");
1065 dt = new wxbDataTokenizer(true);
1066 WaitForPrompt(wxString() << fileset << "\n");
1068 cfgUpdated = cfgUpdated & (~(1 << ConfigFileset));
1076 for (i = 0; i < dt->GetCount(); i++) {
1077 if ((*dt)[i].Find("Run Restore job") == 0) {
1082 if (i == dt->GetCount()) {
1084 dt = WaitForEnd(def + "\n", true);
1088 UpdateSecondConfig(dt); /* TODO: Check result */
1093 wxbMainFrame::GetInstance()->SetStatusText("Restore configuration changes were applied.");
1099 /* Cancel restore */
1100 void wxbRestorePanel::CmdConfigCancel() {
1102 wxbMainFrame::GetInstance()->Print("Restore cancelled.\n", CS_DEBUG);
1103 wxbMainFrame::GetInstance()->SetStatusText("Restore cancelled.");
1104 SetStatus(finished);
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");
1115 for (int i = tableparser->GetCount()-1; i > -1; i--) {
1116 wxString str = (*tableparser)[i][3];
1117 wxDateTime datetime;
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"));
1125 jobChoice->Append("Invalid");
1131 configPanel->SetRowSelection("Before", 0);
1135 /* List files and directories for a specified tree item */
1136 void wxbRestorePanel::CmdList(wxTreeItemId item) {
1137 if (status == choosing) {
1138 list->DeleteAllItems();
1143 UpdateTreeItem(item, true, false);
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);
1152 list->SetColumnWidth(0, 18);
1154 list->SetColumnWidth(1, wxLIST_AUTOSIZE);
1155 if (list->GetColumnWidth(1) < firstwidth) {
1156 list->SetColumnWidth(1, firstwidth-25);
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];
1172 itemdata = new wxbTreeItemData*[listsize];
1173 itemdatasize = listsize;
1176 if (listitems != NULL) {
1177 for (int i = 0; i < listsize; i++) {
1178 itemdata[i] = (wxbTreeItemData*)list->GetItemData(listitems[i]);
1181 else if (treeitem.IsOk()) {
1182 itemdata[0] = (wxbTreeItemData*)tree->GetItemData(treeitem);
1189 if (itemdata[0] == NULL) { //Should never happen
1194 wxString dir = itemdata[0]->GetPath();
1198 if (dir.GetChar(dir.Length()-1) == '/') {
1202 int i = dir.Find('/', TRUE);
1207 else { /* first dir below root */
1208 file = dir.Mid(i+1);
1209 dir = dir.Mid(0, i+1);
1218 bool marked = false;
1219 bool unmarked = false;
1221 for (int i = 0; i < itemdatasize; i++) {
1222 switch(itemdata[i]->GetMarked()) {
1236 if (marked && unmarked)
1252 WaitForEnd(wxString("cd \"") << dir << "\"\n");
1253 WaitForEnd(wxString((state==1) ? "mark" : "unmark") << " \"" << file << "\"\n");
1255 /* TODO: Check commands results */
1257 /*if ((dir == "/") && (file == "*")) {
1258 itemdata->SetMarked((itemdata->GetMarked() == 1) ? 0 : 1);
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);*/
1268 for (int i = 0; i < listsize; i++) {
1269 SetListItemState(listitems[i], state);
1271 /*UpdateTree(treeitem, (tree->GetSelection() == treeitem));
1272 treeitem = tree->GetItemParent(treeitem);*/
1275 /*while (treeitem.IsOk()) {
1276 WaitForList(treeitem, false);
1277 treeitem = tree->GetItemParent(treeitem);
1284 /*----------------------------------------------------------------------------
1286 ----------------------------------------------------------------------------*/
1288 /* Parse a table in tableParser */
1289 wxbTableParser* wxbRestorePanel::CreateAndWaitForParser(wxString cmd) {
1290 wxbTableParser* tableParser = new wxbTableParser();
1292 wxbMainFrame::GetInstance()->Send(cmd);
1294 //time_t base = wxDateTime::Now().GetTicks();
1295 while (!tableParser->hasFinished()) {
1296 //innerThread->Yield();
1297 wxTheApp->Yield(true);
1299 //if (base+15 < wxDateTime::Now().GetTicks()) break;
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();
1310 wxbMainFrame::GetInstance()->Send(cmd);
1312 //time_t base = wxDateTime::Now().GetTicks();
1313 while (!promptParser->hasFinished()) {
1314 //innerThread->Yield();
1315 wxTheApp->Yield(true);
1317 //if (base+15 < wxDateTime::Now().GetTicks()) break;
1321 return promptParser;
1324 delete promptParser;
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);
1333 wxbMainFrame::GetInstance()->Send(cmd);
1335 //wxbMainFrame::GetInstance()->Print("(<WFE)", CS_DEBUG);
1337 //time_t base = wxDateTime::Now().GetTicks();
1338 while (!datatokenizer->hasFinished()) {
1339 //innerThread->Yield();
1340 wxTheApp->Yield(true);
1342 //if (base+15 < wxDateTime::Now().GetTicks()) break;
1345 //wxbMainFrame::GetInstance()->Print("(>WFE)", CS_DEBUG);
1348 return datatokenizer;
1351 delete datatokenizer;
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;
1361 dt = WaitForEnd(wxString("cd \"") <<
1362 static_cast<wxbTreeItemData*>(tree->GetItemData(item))
1363 ->GetPath() << "\"\n", false);
1365 /* TODO: check command result */
1372 list->DeleteAllItems();
1373 dt = WaitForEnd("dir\n", true);
1377 for (unsigned int i = 0; i < dt->GetCount(); i++) {
1380 if (str.Find("cwd is:") == 0) { // Sometimes cd command result "infiltrate" into listings.
1386 wxString* file = ParseList(str);
1391 wxTreeItemId treeid;
1393 if (file[8].GetChar(file[8].Length()-1) == '/') {
1397 treeid = tree->GetFirstChild(item, cookie);
1399 bool updated = false;
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]);
1410 if ((recurse) && (tree->IsExpanded(treeid))) {
1411 UpdateTreeItem(treeid, false, true);
1416 treeid = tree->GetNextChild(item, cookie);
1420 int img = wxbTreeItemData::GetMarkedStatus(file[6]);
1421 treeid = tree->AppendItem(item, file[8], img, img, new wxbTreeItemData(file[7], file[8], file[6]));
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
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
1453 if (line.Length() < 63)
1456 wxString* ret = new wxString[9];
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();
1467 if (ret[6] == " ") ret[6] = "";
1469 if (ret[7].GetChar(ret[7].Length()-1) == '/') {
1471 ret[8].RemoveLast();
1472 ret[8] = ret[7].Mid(ret[8].Find('/', true)+1);
1475 ret[8] = ret[7].Mid(ret[7].Find('/', true)+1);
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);
1485 wxTreeItemId treeitem;
1487 itemdata->SetMarked(newstate);
1488 list->SetItemImage(listitem, newstate, 0); /* TODO: Find what these ints are for */
1489 list->SetItemImage(listitem, newstate, 1);
1491 if ((treeitem = itemdata->GetId()).IsOk()) {
1492 SetTreeItemState(treeitem, newstate);
1495 UpdateTreeItemState(tree->GetSelection());
1499 /* Sets a tree item state, and update its children, parents and list (if necessary) */
1500 void wxbRestorePanel::SetTreeItemState(wxTreeItemId item, int newstate) {
1502 wxTreeItemId currentChild = tree->GetFirstChild(item, cookie);
1504 wxbTreeItemData* itemdata;
1506 while (currentChild.IsOk()) {
1507 itemdata = (wxbTreeItemData*)tree->GetItemData(currentChild);
1508 int state = itemdata->GetMarked();
1510 if (state != newstate) {
1511 itemdata->SetMarked(newstate);
1512 tree->SetItemImage(currentChild, newstate, wxTreeItemIcon_Normal);
1513 tree->SetItemImage(currentChild, newstate, wxTreeItemIcon_Selected);
1516 currentChild = tree->GetNextChild(item, cookie);
1519 itemdata = (wxbTreeItemData*)tree->GetItemData(item);
1520 itemdata->SetMarked(newstate);
1521 tree->SetItemImage(item, newstate, wxTreeItemIcon_Normal);
1522 tree->SetItemImage(item, newstate, wxTreeItemIcon_Selected);
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);
1532 UpdateTreeItemState(tree->GetItemParent(item));
1535 /* Update a tree item state, and its parents' state */
1536 void wxbRestorePanel::UpdateTreeItemState(wxTreeItemId item) {
1544 wxTreeItemId currentChild = tree->GetFirstChild(item, cookie);
1546 bool onechildmarked = false;
1547 bool onechildunmarked = false;
1549 while (currentChild.IsOk()) {
1550 state = ((wxbTreeItemData*)tree->GetItemData(currentChild))->GetMarked();
1553 onechildunmarked = true;
1556 onechildmarked = true;
1559 onechildmarked = true;
1560 onechildunmarked = true;
1564 if (onechildmarked && onechildunmarked) {
1568 currentChild = tree->GetNextChild(item, cookie);
1571 if (tree->GetSelection() == item) {
1572 for (long i = 0; i < list->GetItemCount(); i++) {
1573 state = ((wxbTreeItemData*)list->GetItemData(i))->GetMarked();
1577 onechildunmarked = true;
1580 onechildmarked = true;
1583 onechildmarked = true;
1584 onechildunmarked = true;
1588 if (onechildmarked && onechildunmarked) {
1596 if (onechildmarked && onechildunmarked) {
1599 else if (onechildmarked) {
1602 else if (onechildunmarked) {
1605 else { // no child, don't change anything
1606 UpdateTreeItemState(tree->GetItemParent(item));
1610 wxbTreeItemData* itemdata = (wxbTreeItemData*)tree->GetItemData(item);
1612 itemdata->SetMarked(state);
1613 tree->SetItemImage(item, state, wxTreeItemIcon_Normal);
1614 tree->SetItemImage(item, state, wxTreeItemIcon_Selected);
1616 UpdateTreeItemState(tree->GetItemParent(item));
1619 /* Refresh the whole tree. */
1620 void wxbRestorePanel::RefreshTree() {
1621 /* Save current selection */
1622 wxArrayString current;
1624 wxTreeItemId item = currentTreeItem;
1626 while ((item.IsOk()) && (item != tree->GetRootItem())) {
1627 current.Add(tree->GetItemText(item));
1628 item = tree->GetItemParent(item);
1631 /* Update the tree */
1632 UpdateTreeItem(tree->GetRootItem(), false, true);
1634 /* Reselect the former selected item */
1635 item = tree->GetRootItem();
1637 if (current.Count() == 0) {
1638 tree->SelectItem(item);
1644 for (int i = current.Count()-1; i >= 0; i--) {
1646 wxTreeItemId currentChild = tree->GetFirstChild(item, cookie);
1650 while (currentChild.IsOk()) {
1651 if (tree->GetItemText(currentChild) == current[i]) {
1652 item = currentChild;
1657 currentChild = tree->GetNextChild(item, cookie);
1663 UpdateTreeItem(item, true, false); /* Update the list */
1665 tree->SelectItem(item);
1668 void wxbRestorePanel::RefreshList() {
1669 if (currentTreeItem.IsOk()) {
1670 UpdateTreeItem(currentTreeItem, true, false); /* Update the list */
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);
1683 * where=/tmp/bacula-restores
1686 * fileset=Full Set */
1692 bool dolistjobs = false;
1694 for (i = 0; i < dt->GetCount(); 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));
1701 else if (name == "client") {
1703 if ((str != configPanel->GetRowString("Client")) || (configPanel->GetRowString("Before") == "")) {
1704 configPanel->SetRowString("Client", str);
1708 else if (name == "storage") {
1709 configPanel->SetRowString("Storage", str.Mid(j+1));
1711 else if (name == "fileset") {
1712 configPanel->SetRowString("Fileset", str.Mid(j+1));
1720 //wxTheApp->Yield(false);
1723 configPanel->Enable(true);
1727 * Update second config.
1730 * JobName: RestoreFiles
1731 * Bootstrap: /var/lib/bacula/restore.bsr
1732 * Where: /tmp/bacula-restores
1737 * When: 2004-04-18 01:18:56
1739 * OK to run? (yes/mod/no):
1742 bool wxbRestorePanel::UpdateSecondConfig(wxbDataTokenizer* dt) {
1744 for (i = 0; i < dt->GetCount(); i++) {
1745 if ((*dt)[i].Find("Run Restore job") == 0)
1749 if ((i + 10) > dt->GetCount()) {
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());
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);
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());
1782 restorePanel->Layout();
1787 /*----------------------------------------------------------------------------
1789 ----------------------------------------------------------------------------*/
1791 /* Set current status by enabling/disabling components */
1792 void wxbRestorePanel::SetStatus(status_enum newstatus) {
1793 switch (newstatus) {
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();
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);
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();
1826 tree->DeleteAllItems();
1827 list->DeleteAllItems();
1828 configPanel->ClearRowChoices("Client");
1829 configPanel->ClearRowChoices("Before");
1830 wxbMainFrame::GetInstance()->EnablePanels();
1831 newstatus = activable;
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);
1844 wxbMainFrame::GetInstance()->DisablePanels(this);
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);
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();
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();
1883 restorePanel->EnableApply(false);
1886 start->SetLabel("Restoring...");
1887 gauge->Enable(true);
1889 start->Enable(false);
1890 configPanel->Enable(false);
1891 tree->Enable(false);
1892 list->Enable(false);
1899 /*----------------------------------------------------------------------------
1901 ----------------------------------------------------------------------------*/
1903 void wxbRestorePanel::SetWorking(bool working) {
1904 this->working = working;
1906 SetCursor(*wxHOURGLASS_CURSOR);
1907 // SetEvtHandlerEnabled(false); //EVTQUEUE
1909 // else if (!processing) { /* Empty event queue if we aren't already doing this */ //EVTQUEUE
1911 // processing = true; //EVTQUEUE
1912 SetCursor(*wxSTANDARD_CURSOR);
1913 // SetEvtHandlerEnabled(true); //EVTQUEUE
1914 /* wxNode *node = pendingEvents->First(); //EVTQUEUE
1916 wxEvent *event = (wxEvent *)node->Data();
1919 wxEvtHandler::ProcessEvent(*event);
1922 node = pendingEvents->First();
1924 processing = false;*/
1928 bool wxbRestorePanel::IsWorking() {
1929 return this->working;
1932 void wxbRestorePanel::EnableConfig(bool enable) {
1933 restorePanel->Enable(enable);
1936 /*----------------------------------------------------------------------------
1938 ----------------------------------------------------------------------------*/
1943 bool wxbRestorePanel::ProcessEvent(wxEvent& event) {
1944 if (IsWorking() || processing) {
1945 wxEvent *eventCopy = event.Clone();
1947 pendingEvents->Append(eventCopy);
1951 return wxEvtHandler::ProcessEvent(event);
1956 void wxbRestorePanel::OnCancel(wxCommandEvent& event) {
1957 cancel->Enable(false);
1958 SetCursor(*wxHOURGLASS_CURSOR);
1960 SetCursor(*wxSTANDARD_CURSOR);
1963 void wxbRestorePanel::OnStart(wxCommandEvent& event) {
1965 AddPendingEvent(event);
1973 void wxbRestorePanel::OnTreeChanging(wxTreeEvent& event) {
1975 AddPendingEvent(event);
1980 void wxbRestorePanel::OnTreeExpanding(wxTreeEvent& event) {
1982 AddPendingEvent(event);
1987 //CmdList(event.GetItem());
1988 if (tree->GetSelection() != event.GetItem()) {
1989 tree->SelectItem(event.GetItem());
1994 void wxbRestorePanel::OnTreeChanged(wxTreeEvent& event) {
1996 AddPendingEvent(event);
1999 if (currentTreeItem == event.GetItem()) {
2002 treeadd->Enable(false);
2003 treeremove->Enable(false);
2004 treerefresh->Enable(false);
2005 markWhenListingDone = false;
2007 currentTreeItem = event.GetItem();
2008 CmdList(event.GetItem());
2009 if (markWhenListingDone) {
2010 CmdMark(event.GetItem(), NULL, 0);
2014 if (event.GetItem().IsOk()) {
2015 int status = ((wxbTreeItemData*)tree->GetItemData(event.GetItem()))->GetMarked();
2016 treeadd->Enable(status != 1);
2017 treeremove->Enable(status != 0);
2019 treerefresh->Enable(true);
2022 void wxbRestorePanel::OnTreeMarked(wxbTreeMarkedEvent& event) {
2023 csprint("Tree marked", CS_DEBUG);
2025 if (tree->GetSelection() == event.GetItem()) {
2026 markWhenListingDone = !markWhenListingDone;
2028 AddPendingEvent(event);
2032 CmdMark(event.GetItem(), NULL, 0);
2036 if (event.GetItem().IsOk()) {
2037 int status = ((wxbTreeItemData*)tree->GetItemData(event.GetItem()))->GetMarked();
2038 treeadd->Enable(status != 1);
2039 treeremove->Enable(status != 0);
2043 void wxbRestorePanel::OnTreeAdd(wxCommandEvent& event) {
2045 AddPendingEvent(event);
2049 if (currentTreeItem.IsOk()) {
2051 CmdMark(currentTreeItem, NULL, 0, 1);
2054 treeremove->Enable(1);
2059 void wxbRestorePanel::OnTreeRemove(wxCommandEvent& event) {
2061 AddPendingEvent(event);
2065 if (currentTreeItem.IsOk()) {
2067 CmdMark(currentTreeItem, NULL, 0, 0);
2070 treeremove->Enable(0);
2075 void wxbRestorePanel::OnTreeRefresh(wxCommandEvent& event) {
2077 AddPendingEvent(event);
2086 void wxbRestorePanel::OnListMarked(wxbListMarkedEvent& event) {
2088 AddPendingEvent(event);
2093 if (list->GetSelectedItemCount() == 0) {
2099 long* items = new long[list->GetSelectedItemCount()];
2103 long item = list->GetNextItem(-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
2104 while (item != -1) {
2107 item = list->GetNextItem(item, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
2110 CmdMark(wxTreeItemId(), items, num);
2114 wxListEvent listevt;
2116 OnListChanged(listevt);
2123 void wxbRestorePanel::OnListActivated(wxListEvent& event) {
2125 AddPendingEvent(event);
2130 long item = event.GetIndex();
2131 // long item = list->GetNextItem(-1, wxLIST_NEXT_ALL, wxLIST_STATE_FOCUSED);
2133 wxbTreeItemData* itemdata = (wxbTreeItemData*)list->GetItemData(item);
2134 wxString name = itemdata->GetName();
2141 if (name.GetChar(name.Length()-1) == '/') {
2142 wxTreeItemId currentChild = tree->GetFirstChild(currentTreeItem, cookie);
2144 while (currentChild.IsOk()) {
2145 wxString name2 = tree->GetItemText(currentChild);
2146 if (name2 == name) {
2147 //tree->UnselectAll();
2149 tree->Expand(currentTreeItem);
2150 tree->SelectItem(currentChild);
2154 currentChild = tree->GetNextChild(currentTreeItem, cookie);
2161 void wxbRestorePanel::OnListChanged(wxListEvent& event) {
2163 AddPendingEvent(event);
2167 listadd->Enable(false);
2168 listremove->Enable(false);
2170 bool marked = false;
2171 bool unmarked = false;
2173 long item = list->GetNextItem(-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
2174 while (item != -1) {
2175 switch (((wxbTreeItemData*)list->GetItemData(item))->GetMarked()) {
2188 // Should never happen
2190 if (marked && unmarked) break;
2191 item = list->GetNextItem(item, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
2194 listadd->Enable(unmarked);
2195 listremove->Enable(marked);
2198 void wxbRestorePanel::OnListAdd(wxCommandEvent& event) {
2200 AddPendingEvent(event);
2206 long* items = new long[list->GetSelectedItemCount()];
2210 long item = list->GetNextItem(-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
2211 while (item != -1) {
2214 item = list->GetNextItem(item, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
2217 CmdMark(wxTreeItemId(), items, num, 1);
2224 listadd->Enable(false);
2225 listremove->Enable(true);
2228 void wxbRestorePanel::OnListRemove(wxCommandEvent& event) {
2230 AddPendingEvent(event);
2236 long* items = new long[list->GetSelectedItemCount()];
2240 long item = list->GetNextItem(-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
2241 while (item != -1) {
2244 item = list->GetNextItem(item, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
2247 CmdMark(wxTreeItemId(), items, num, 0);
2254 listadd->Enable(true);
2255 listremove->Enable(false);
2258 void wxbRestorePanel::OnListRefresh(wxCommandEvent& event) {
2260 AddPendingEvent(event);
2269 void wxbRestorePanel::OnConfigUpdated(wxCommandEvent& event) {
2270 if (status == entered) {
2271 if (event.GetId() == ConfigJobName) {
2276 UpdateFirstConfig();
2279 else if (event.GetId() == ConfigClient) {
2284 configPanel->Enable(false);
2286 configPanel->Enable(true);
2289 cfgUpdated = cfgUpdated | (1 << event.GetId());
2291 else if (status == configuring) {
2292 restorePanel->EnableApply(true);
2293 cfgUpdated = cfgUpdated | (1 << event.GetId());
2297 void wxbRestorePanel::OnConfigOk(wxCommandEvent& WXUNUSED(event)) {
2298 if (status != configuring) return;
2307 void wxbRestorePanel::OnConfigApply(wxCommandEvent& WXUNUSED(event)) {
2308 if (status != configuring) return;
2314 if (cfgUpdated == 0) {
2315 restorePanel->EnableApply(false);
2320 void wxbRestorePanel::OnConfigCancel(wxCommandEvent& WXUNUSED(event)) {
2321 if (status != configuring) return;