3 * wxbPanel for restoring files
5 * Nicolas Boichat, April-July 2004
10 Copyright (C) 2004 Kern Sibbald and John Walker
12 This program is free software; you can redistribute it and/or
13 modify it under the terms of the GNU General Public License
14 as published by the Free Software Foundation; either version 2
15 of the License, or (at your option) any later version.
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with this program; if not, write to the Free Software
24 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
26 /* Note concerning "done" output (modifiable marked with +)
28 +JobName: RestoreFiles
29 Bootstrap: /var/lib/bacula/restore.bsr
30 +Where: /tmp/bacula-restores
35 +When: 2004-04-18 01:18:56
37 OK to run? (yes/mod/no):mod
39 1: Level (not appropriate)
40 2: Storage (automatic ?)
43 5: Client (yes : "The defined Client resources are:\n\t1: velours-fd\n\t2: tom-fd\nSelect Client (File daemon) resource (1-2):")
44 6: When (yes : "Please enter desired start time as YYYY-MM-DD HH:MM:SS (return for now):")
45 7: Priority (yes : "Enter new Priority: (positive integer)")
47 9: Where (yes : "Please enter path prefix for restore (/ for none):")
48 10: Replace (yes : "Replace:\n 1: always\n 2: ifnewer\n 3: ifolder\n 4: never\n
49 Select replace option (1-4):")
51 Select parameter to modify (1-11):
54 #include "wxbrestorepanel.h"
56 #include "wxbmainframe.h"
60 #include <wx/choice.h>
61 #include <wx/datetime.h>
65 #include "unmarked.xpm"
67 #include "partmarked.xpm"
69 #include <wx/listimpl.cpp>
71 /* A macro named Yield is defined under MinGW */
74 WX_DEFINE_LIST(wxbEventList);
77 * Class which is stored in the tree and in the list to keep informations
80 class wxbTreeItemData : public wxTreeItemData {
82 wxbTreeItemData(wxString path, wxString name, int marked, long listid = -1);
83 wxbTreeItemData(wxString path, wxString name, wxString marked, long listid = -1);
89 void SetMarked(int marked);
90 void SetMarked(wxString marked);
94 static int GetMarkedStatus(wxString file);
96 wxString* path; /* Full path */
97 wxString* name; /* File name */
98 int marked; /* 0 - Not Marked, 1 - Marked, 2 - Some file under is marked */
99 long listid; /* list ID : >-1 if this data is in the list (and/or on the tree) */
102 wxbTreeItemData::wxbTreeItemData(wxString path, wxString name, int marked, long listid): wxTreeItemData() {
103 this->path = new wxString(path);
104 this->name = new wxString(name);
105 this->marked = marked;
106 this->listid = listid;
109 wxbTreeItemData::wxbTreeItemData(wxString path, wxString name, wxString marked, long listid): wxTreeItemData() {
110 this->path = new wxString(path);
111 this->name = new wxString(name);
113 this->listid = listid;
116 wxbTreeItemData::~wxbTreeItemData() {
121 int wxbTreeItemData::GetMarked() {
125 void wxbTreeItemData::SetMarked(wxString marked) {
129 else if (marked == "+") {
137 void wxbTreeItemData::SetMarked(int marked) {
138 this->marked = marked;
141 long wxbTreeItemData::GetListId() {
145 wxString wxbTreeItemData::GetPath() {
149 wxString wxbTreeItemData::GetName() {
153 /*wxbTreeItemData* wxbTreeItemData::GetChild(wxString dirname) {
154 int marked = GetMarkedStatus(dirname);
155 return new wxbTreeItemData(path + (marked ? dirname.Mid(1) : dirname), marked);
158 int wxbTreeItemData::GetMarkedStatus(wxString file) {
159 if (file.Length() == 0)
162 switch (file.GetChar(0)) {
172 // ----------------------------------------------------------------------------
173 // event tables and other macros for wxWindows
174 // ----------------------------------------------------------------------------
202 BEGIN_EVENT_TABLE(wxbRestorePanel, wxPanel)
203 EVT_BUTTON(RestoreStart, wxbRestorePanel::OnStart)
204 EVT_BUTTON(RestoreCancel, wxbRestorePanel::OnCancel)
206 EVT_TREE_SEL_CHANGING(TreeCtrl, wxbRestorePanel::OnTreeChanging)
207 EVT_TREE_SEL_CHANGED(TreeCtrl, wxbRestorePanel::OnTreeChanged)
208 EVT_TREE_ITEM_EXPANDING(TreeCtrl, wxbRestorePanel::OnTreeExpanding)
209 EVT_TREE_MARKED_EVENT(TreeCtrl, wxbRestorePanel::OnTreeMarked)
210 EVT_BUTTON(TreeAdd, wxbRestorePanel::OnTreeAdd)
211 EVT_BUTTON(TreeRemove, wxbRestorePanel::OnTreeRemove)
212 EVT_BUTTON(TreeRefresh, wxbRestorePanel::OnTreeRefresh)
214 EVT_LIST_ITEM_ACTIVATED(ListCtrl, wxbRestorePanel::OnListActivated)
215 EVT_LIST_MARKED_EVENT(ListCtrl, wxbRestorePanel::OnListMarked)
216 EVT_LIST_ITEM_SELECTED(ListCtrl, wxbRestorePanel::OnListChanged)
217 EVT_LIST_ITEM_DESELECTED(ListCtrl, wxbRestorePanel::OnListChanged)
218 EVT_BUTTON(ListAdd, wxbRestorePanel::OnListAdd)
219 EVT_BUTTON(ListRemove, wxbRestorePanel::OnListRemove)
220 EVT_BUTTON(ListRefresh, wxbRestorePanel::OnListRefresh)
222 EVT_TEXT(ConfigWhere, wxbRestorePanel::OnConfigUpdated)
223 EVT_TEXT(ConfigWhen, wxbRestorePanel::OnConfigUpdated)
224 EVT_TEXT(ConfigPriority, wxbRestorePanel::OnConfigUpdated)
225 EVT_CHOICE(ConfigWhen, wxbRestorePanel::OnConfigUpdated)
226 EVT_CHOICE(ConfigReplace, wxbRestorePanel::OnConfigUpdated)
227 EVT_CHOICE(ConfigClient, wxbRestorePanel::OnConfigUpdated)
228 EVT_CHOICE(ConfigFileset, wxbRestorePanel::OnConfigUpdated)
229 EVT_CHOICE(ConfigStorage, wxbRestorePanel::OnConfigUpdated)
230 EVT_CHOICE(ConfigJobName, wxbRestorePanel::OnConfigUpdated)
231 EVT_CHOICE(ConfigPool, wxbRestorePanel::OnConfigUpdated)
233 EVT_BUTTON(ConfigOk, wxbRestorePanel::OnConfigOk)
234 EVT_BUTTON(ConfigApply, wxbRestorePanel::OnConfigApply)
235 EVT_BUTTON(ConfigCancel, wxbRestorePanel::OnConfigCancel)
239 * wxbRestorePanel constructor
241 wxbRestorePanel::wxbRestorePanel(wxWindow* parent): wxbPanel(parent) {
242 //pendingEvents = new wxbEventList(); //EVTQUEUE
243 //processing = false; //EVTQUEUE
246 imagelist = new wxImageList(16, 16, TRUE, 3);
247 imagelist->Add(wxIcon(unmarked_xpm));
248 imagelist->Add(wxIcon(marked_xpm));
249 imagelist->Add(wxIcon(partmarked_xpm));
251 wxFlexGridSizer* mainSizer = new wxFlexGridSizer(3, 1, 10, 10);
252 mainSizer->AddGrowableCol(0);
253 mainSizer->AddGrowableRow(1);
255 wxFlexGridSizer *firstSizer = new wxFlexGridSizer(1, 2, 10, 10);
257 firstSizer->AddGrowableCol(0);
258 firstSizer->AddGrowableRow(0);
260 start = new wxButton(this, RestoreStart, "Enter restore mode", wxDefaultPosition, wxSize(150, 30));
261 firstSizer->Add(start, 0, wxALIGN_CENTER_HORIZONTAL | wxALIGN_CENTER_VERTICAL, 10);
263 cancel = new wxButton(this, RestoreCancel, "Cancel restore", wxDefaultPosition, wxSize(150, 30));
264 firstSizer->Add(cancel, 0, wxALIGN_CENTER_HORIZONTAL | wxALIGN_RIGHT, 10);
268 /* clientChoice = new wxChoice(this, ClientChoice, wxDefaultPosition, wxSize(150, 30), 0, elist);
269 firstSizer->Add(clientChoice, 1, wxALIGN_CENTER_HORIZONTAL | wxALIGN_CENTER_VERTICAL, 10);
271 jobChoice = new wxChoice(this, -1, wxDefaultPosition, wxSize(150, 30), 0, elist);
272 firstSizer->Add(jobChoice, 1, wxALIGN_CENTER_HORIZONTAL | wxALIGN_CENTER_VERTICAL, 10);*/
274 mainSizer->Add(firstSizer, 1, wxEXPAND, 10);
276 treelistPanel = new wxSplitterWindow(this);
278 wxPanel* treePanel = new wxPanel(treelistPanel);
279 wxFlexGridSizer *treeSizer = new wxFlexGridSizer(2, 1, 0, 0);
280 treeSizer->AddGrowableCol(0);
281 treeSizer->AddGrowableRow(0);
283 tree = new wxbTreeCtrl(treePanel, this, TreeCtrl, wxDefaultPosition, wxSize(200,50));
284 tree->SetImageList(imagelist);
286 treeSizer->Add(tree, 1, wxEXPAND, 0);
288 wxBoxSizer *treeCtrlSizer = new wxBoxSizer(wxHORIZONTAL);
289 treeadd = new wxButton(treePanel, TreeAdd, "Add", wxDefaultPosition, wxSize(60, 25));
290 treeCtrlSizer->Add(treeadd, 0, wxLEFT | wxRIGHT, 3);
291 treeremove = new wxButton(treePanel, TreeRemove, "Remove", wxDefaultPosition, wxSize(60, 25));
292 treeCtrlSizer->Add(treeremove, 0, wxLEFT | wxRIGHT, 3);
293 treerefresh = new wxButton(treePanel, TreeRefresh, "Refresh", wxDefaultPosition, wxSize(60, 25));
294 treeCtrlSizer->Add(treerefresh, 0, wxLEFT | wxRIGHT, 3);
296 treeSizer->Add(treeCtrlSizer, 1, wxALIGN_CENTER_HORIZONTAL, 0);
298 treePanel->SetSizer(treeSizer);
300 wxPanel* listPanel = new wxPanel(treelistPanel);
301 wxFlexGridSizer *listSizer = new wxFlexGridSizer(2, 1, 0, 0);
302 listSizer->AddGrowableCol(0);
303 listSizer->AddGrowableRow(0);
305 list = new wxbListCtrl(listPanel, this, ListCtrl, wxDefaultPosition, wxSize(200,50));
306 //treelistSizer->Add(list, 1, wxEXPAND, 10);
308 list->SetImageList(imagelist, wxIMAGE_LIST_SMALL);
311 info.SetMask(wxLIST_MASK_TEXT | wxLIST_MASK_FORMAT);
313 info.SetAlign(wxLIST_FORMAT_CENTER);
314 list->InsertColumn(0, info);
316 info.SetText("Filename");
317 info.SetAlign(wxLIST_FORMAT_LEFT);
318 list->InsertColumn(1, info);
320 info.SetText("Size");
321 info.SetAlign(wxLIST_FORMAT_RIGHT);
322 list->InsertColumn(2, info);
324 info.SetText("Date");
325 info.SetAlign(wxLIST_FORMAT_LEFT);
326 list->InsertColumn(3, info);
328 info.SetText("Perm.");
329 info.SetAlign(wxLIST_FORMAT_LEFT);
330 list->InsertColumn(4, info);
332 info.SetText("User");
333 info.SetAlign(wxLIST_FORMAT_RIGHT);
334 list->InsertColumn(5, info);
336 info.SetText("Group");
337 info.SetAlign(wxLIST_FORMAT_RIGHT);
338 list->InsertColumn(6, info);
340 listSizer->Add(list, 1, wxEXPAND, 0);
342 wxBoxSizer *listCtrlSizer = new wxBoxSizer(wxHORIZONTAL);
343 listadd = new wxButton(listPanel, ListAdd, "Add", wxDefaultPosition, wxSize(60, 25));
344 listCtrlSizer->Add(listadd, 0, wxLEFT | wxRIGHT, 5);
345 listremove = new wxButton(listPanel, ListRemove, "Remove", wxDefaultPosition, wxSize(60, 25));
346 listCtrlSizer->Add(listremove, 0, wxLEFT | wxRIGHT, 5);
347 listrefresh = new wxButton(listPanel, ListRefresh, "Refresh", wxDefaultPosition, wxSize(60, 25));
348 listCtrlSizer->Add(listrefresh, 0, wxLEFT | wxRIGHT, 5);
350 listSizer->Add(listCtrlSizer, 1, wxALIGN_CENTER_HORIZONTAL, 0);
352 listPanel->SetSizer(listSizer);
354 treelistPanel->SplitVertically(treePanel, listPanel, 210);
356 treelistPanel->SetMinimumPaneSize(210);
358 treelistPanel->Show(false);
360 wxbConfig* config = new wxbConfig();
361 config->Add(new wxbConfigParam("Job Name", ConfigJobName, choice, 0, elist));
362 config->Add(new wxbConfigParam("Client", ConfigClient, choice, 0, elist));
363 config->Add(new wxbConfigParam("Fileset", ConfigFileset, choice, 0, elist));
364 config->Add(new wxbConfigParam("Pool", ConfigPool, choice, 0, elist));
365 config->Add(new wxbConfigParam("Storage", ConfigStorage, choice, 0, elist));
366 config->Add(new wxbConfigParam("Before", ConfigWhen, choice, 0, elist));
368 configPanel = new wxbConfigPanel(this, config, "Please configure parameters concerning files to restore :", RestoreStart, RestoreCancel, -1);
370 configPanel->Show(true);
371 configPanel->Enable(false);
373 config = new wxbConfig();
374 config->Add(new wxbConfigParam("Job Name", -1, text, ""));
375 config->Add(new wxbConfigParam("Bootstrap", -1, text, ""));
376 config->Add(new wxbConfigParam("Where", ConfigWhere, modifiableText, ""));
377 wxString erlist[] = {"always", "if newer", "if older", "never"};
378 config->Add(new wxbConfigParam("Replace", ConfigReplace, choice, 4, erlist));
379 config->Add(new wxbConfigParam("Fileset", ConfigFileset, choice, 0, erlist));
380 config->Add(new wxbConfigParam("Client", ConfigClient, choice, 0, erlist));
381 config->Add(new wxbConfigParam("Storage", ConfigStorage, choice, 0, erlist));
382 config->Add(new wxbConfigParam("When", ConfigWhen, modifiableText, ""));
383 config->Add(new wxbConfigParam("Priority", ConfigPriority, modifiableText, ""));
385 restorePanel = new wxbConfigPanel(this, config, "Please configure parameters concerning files restoration :", ConfigOk, ConfigCancel, ConfigApply);
387 restorePanel->Show(false);
389 centerSizer = new wxBoxSizer(wxHORIZONTAL);
390 //centerSizer->Add(treelistPanel, 1, wxEXPAND | wxADJUST_MINSIZE);
392 mainSizer->Add(centerSizer, 1, wxEXPAND, 10);
394 gauge = new wxGauge(this, -1, 1, wxDefaultPosition, wxSize(200,20));
396 mainSizer->Add(gauge, 1, wxEXPAND, 5);
398 gauge->Enable(false);
401 mainSizer->SetSizeHints(this);
405 for (int i = 0; i < 7; i++) {
406 list->SetColumnWidth(i, 70);
409 SetCursor(*wxSTANDARD_CURSOR);
411 markWhenListingDone = false;
417 * wxbRestorePanel destructor
419 wxbRestorePanel::~wxbRestorePanel() {
423 /*----------------------------------------------------------------------------
424 wxbPanel overloadings
425 ----------------------------------------------------------------------------*/
427 wxString wxbRestorePanel::GetTitle() {
431 void wxbRestorePanel::EnablePanel(bool enable) {
433 if (status == disabled) {
434 SetStatus(activable);
442 /*----------------------------------------------------------------------------
443 Commands called by events handler
444 ----------------------------------------------------------------------------*/
446 /* The main button has been clicked */
447 void wxbRestorePanel::CmdStart() {
449 if (status == activable) {
450 wxbMainFrame::GetInstance()->SetStatusText("Getting parameters list.");
451 wxbDataTokenizer* dt = wxbUtils::WaitForEnd(".clients\n", true, false);
454 configPanel->ClearRowChoices("Client");
455 restorePanel->ClearRowChoices("Client");
457 if (dt->GetCount() == 0) {
458 wxbMainFrame::GetInstance()->SetStatusText("Error : no clients returned by the director.");
462 for (i = 0; i < dt->GetCount(); i++) {
465 configPanel->AddRowChoice("Client", str);
466 restorePanel->AddRowChoice("Client", str);
476 dt = wxbUtils::WaitForEnd(".filesets\n", true, false);
478 configPanel->ClearRowChoices("Fileset");
479 restorePanel->ClearRowChoices("Fileset");
481 if (dt->GetCount() == 0) {
482 wxbMainFrame::GetInstance()->SetStatusText("Error : no filesets returned by the director.");
486 for (i = 0; i < dt->GetCount(); i++) {
489 configPanel->AddRowChoice("Fileset", str);
490 restorePanel->AddRowChoice("Fileset", str);
500 dt = wxbUtils::WaitForEnd(".storage\n", true, false);
502 configPanel->ClearRowChoices("Storage");
503 restorePanel->ClearRowChoices("Storage");
505 if (dt->GetCount() == 0) {
506 wxbMainFrame::GetInstance()->SetStatusText("Error : no storage returned by the director.");
510 for (i = 0; i < dt->GetCount(); i++) {
513 configPanel->AddRowChoice("Storage", str);
514 restorePanel->AddRowChoice("Storage", str);
524 dt = wxbUtils::WaitForEnd(".jobs\n", true, false);
526 configPanel->ClearRowChoices("Job Name");
528 if (dt->GetCount() == 0) {
529 wxbMainFrame::GetInstance()->SetStatusText("Error : no jobs returned by the director.");
533 for (i = 0; i < dt->GetCount(); i++) {
536 configPanel->AddRowChoice("Job Name", str);
539 configPanel->SetRowString("Job Name", "RestoreFiles");
548 dt = wxbUtils::WaitForEnd(".pools\n", true, false);
550 configPanel->ClearRowChoices("Pool");
552 if (dt->GetCount() == 0) {
553 wxbMainFrame::GetInstance()->SetStatusText("Error : no jobs returned by the director.");
557 for (i = 0; i < dt->GetCount(); i++) {
560 configPanel->AddRowChoice("Pool", str);
574 wxbMainFrame::GetInstance()->SetStatusText("Please configure your restore parameters.");
576 else if (status == entered) {
577 /* if (clientChoice->GetStringSelection().Length() < 1) {
578 wxbMainFrame::GetInstance()->SetStatusText("Please select a client.");
581 if (jobChoice->GetStringSelection().Length() < 1) {
582 wxbMainFrame::GetInstance()->SetStatusText("Please select a restore date.");
585 wxbMainFrame::GetInstance()->SetStatusText("Building restore tree...");
589 wxbTableParser* tableparser = new wxbTableParser();
590 wxbDataTokenizer* dt = new wxbDataTokenizer(true);
592 wxbMainFrame::GetInstance()->Send(wxString("restore") <<
593 " client=\"" << configPanel->GetRowString("Client") <<
594 "\" fileset=\"" << configPanel->GetRowString("Fileset") <<
595 "\" pool=\"" << configPanel->GetRowString("Pool") <<
596 "\" storage=\"" << configPanel->GetRowString("Storage") <<
597 "\" before=\"" << configPanel->GetRowString("Before") <<
599 //wxbUtils::WaitForPrompt("6\n");
601 /*wxbPromptParser *pp = wxbUtils::WaitForPrompt(wxString() << configPanel->GetRowString("Before") << "\n", true);
602 int client = pp->getChoices()->Index(configPanel->GetRowString("Client"));
603 if (client == wxNOT_FOUND) {
604 wxbMainFrame::GetInstance()->SetStatusText("Failed to find the selected client.");
609 //wxbMainFrame::GetInstance()->Send(wxString() << configPanel->GetRowString("Before") << "\n");
611 while (!tableparser->hasFinished() && !dt->hasFinished()) {
612 wxTheApp->Yield(true);
618 if (dt->hasFinished() && !tableparser->hasFinished()) {
620 if (dt->GetCount() > 1) {
621 str = (*dt)[dt->GetCount()-2];
624 wxbMainFrame::GetInstance()->SetStatusText(wxString("Error while starting restore: ") << str);
634 for (i = 0; i < tableparser->GetCount(); i++) {
635 str = (*tableparser)[i][2];
636 str.Replace(",", "");
637 if (str.ToLong(&l)) {
643 gauge->SetRange(tot);
645 /*wxbMainFrame::GetInstance()->Print(
646 wxString("[") << tot << "]", CS_DEBUG);*/
648 wxDateTime base = wxDateTime::Now();
652 unsigned int lastindex = 0;
659 newdate = wxDateTime::Now();
660 if (newdate.Subtract(base).GetMilliseconds() > 10 ) {
662 for (; lastindex < dt->GetCount(); lastindex++) {
663 if (((i1 = (*dt)[lastindex].Find("Building directory tree for JobId ")) >= 0) &&
664 ((i2 = (*dt)[lastindex].Find(" ...")) > 0)) {
665 str = (*dt)[lastindex].Mid(i1+34, i2-(i1+34));
666 for (i = 0; i < tableparser->GetCount(); i++) {
667 if (str == (*tableparser)[i][0]) {
668 str = (*tableparser)[i][2];
669 str.Replace(",", "");
670 if (str.ToLong(&l)) {
673 var = (willdo-done)/3;
681 if (gauge->GetValue() <= done) {
682 gauge->SetValue(done);
686 else if (gauge->GetValue() >= willdo) {
687 gauge->SetValue(willdo);
692 gauge->SetValue(gauge->GetValue()+var);
694 if (dt->hasFinished()) {
698 /*wxbMainFrame::GetInstance()->Print(
699 wxString("[") << gauge->GetValue() << "/" << done
700 << "-" << willdo << "]", CS_DEBUG);*/
702 wxTheApp->Yield(true);
706 gauge->SetValue(tot);
707 wxTheApp->Yield(true);
718 wxbUtils::WaitForEnd("unmark *\n");
719 wxTreeItemId root = tree->AddRoot(configPanel->GetRowString("Client"), -1, -1, new wxbTreeItemData("/", configPanel->GetRowString("Client"), 0));
720 currentTreeItem = root;
722 tree->SelectItem(root);
724 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.");
727 else if (status == choosing) {
731 wxbDataTokenizer* dt;
735 dt = new wxbDataTokenizer(true);
736 wxbUtils::WaitForPrompt("done\n");
738 SetStatus(configuring);
740 for (i = 0; i < dt->GetCount(); i++) {
741 if ((j = (*dt)[i].Find(" files selected to be restored.")) > -1) {
742 (*dt)[i].Mid(0, j).ToLong(&totfilemessages);
746 if ((j = (*dt)[i].Find(" file selected to be restored.")) > -1) {
747 (*dt)[i].Mid(0, j).ToLong(&totfilemessages);
752 wxbMainFrame::GetInstance()->SetStatusText(
753 wxString("Please configure your restore (")
754 << totfilemessages << " files selected to be restored)...");
756 UpdateSecondConfig(dt);
761 restorePanel->EnableApply(false);
763 if (totfilemessages == 0) {
764 wxbMainFrame::GetInstance()->Print("Restore failed : no file selected.\n", CS_DEBUG);
765 wxbMainFrame::GetInstance()->SetStatusText("Restore failed : no file selected.");
770 else if (status == configuring) {
771 cancel->Enable(false);
775 wxbMainFrame::GetInstance()->SetStatusText("Restoring, please wait...");
777 wxbDataTokenizer* dt;
779 SetStatus(restoring);
780 wxbUtils::WaitForEnd("yes\n");
783 gauge->SetRange(totfilemessages);
785 wxDateTime currenttime;
787 dt = wxbUtils::WaitForEnd("time\n", true);
788 wxStringTokenizer ttkz((*dt)[0], " ", wxTOKEN_STRTOK);
789 if ((currenttime.ParseDate(ttkz.GetNextToken()) == NULL) || // Date
790 (currenttime.ParseTime(ttkz.GetNextToken()) == NULL)) { // Time
791 currenttime.SetYear(1990); // If parsing fails, set currenttime to a dummy date
794 currenttime -= wxTimeSpan::Seconds(30); //Adding a 30" tolerance
798 wxDateTime scheduledtime;
799 wxStringTokenizer stkz(restorePanel->GetRowString("When"), " ", wxTOKEN_STRTOK);
801 if ((scheduledtime.ParseDate(stkz.GetNextToken()) == NULL) || // Date
802 (scheduledtime.ParseTime(stkz.GetNextToken()) == NULL)) { // Time
803 scheduledtime.SetYear(2090); // If parsing fails, set scheduledtime to a dummy date
806 if (scheduledtime.Subtract(currenttime).IsLongerThan(wxTimeSpan::Seconds(150))) {
807 wxbMainFrame::GetInstance()->Print("Restore is scheduled in more than two minutes, wx-console will not wait for its completion.\n", CS_DEBUG);
808 wxbMainFrame::GetInstance()->SetStatusText("Restore is scheduled in more than two minutes, wx-console will not wait for its completion.");
813 wxString cmd = "list jobid=";
815 wxString jobname = restorePanel->GetRowString("Job Name");
819 wxbTableParser* tableparser;
822 tableparser = wxbUtils::CreateAndWaitForParser("list jobs\n");
826 for (i = 0; i < tableparser->GetCount(); i++) {
827 if (jobname == (*tableparser)[i][1]) {
828 wxStringTokenizer jtkz((*tableparser)[i][2], " ", wxTOKEN_STRTOK);
829 if ((jobtime.ParseDate(jtkz.GetNextToken()) != NULL) && // Date
830 (jobtime.ParseTime(jtkz.GetNextToken()) != NULL)) { // Time
831 if (jobtime.IsLaterThan(currenttime)) {
832 jobid = (*tableparser)[i][0];
833 cmd << jobid << "\n";
836 cancel->Enable(true);
843 if (tableparser == NULL) { //The job was found
850 while (sw2.Time() < 2000) {
851 wxTheApp->Yield(true);
854 if (sw.Time() > 60000) {
855 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);
856 wxbMainFrame::GetInstance()->SetStatusText("The restore job has not been created within one minute, wx-console will not wait for its completion anymore.");
858 cancel->Enable(true);
863 long filemessages = 0;
866 tableparser = wxbUtils::CreateAndWaitForParser(cmd);
867 if ((*tableparser)[0][7] != "C") {
872 dt = wxbUtils::WaitForEnd("messages\n", true);
874 for (unsigned int i = 0; i < dt->GetCount(); i++) {
875 wxStringTokenizer tkz((*dt)[i], " ", wxTOKEN_STRTOK);
879 // Date Time name: perm ? user grp size date time
880 //04-Apr-2004 17:19 Tom-fd: -rwx------ 1 nicolas None 514967 2004-03-20 20:03:42 filename
882 if (datetime.ParseDate(tkz.GetNextToken()) != NULL) { // Date
883 if (datetime.ParseTime(tkz.GetNextToken()) != NULL) { // Time
884 if (tkz.GetNextToken().Last() == ':') { // name:
885 tkz.GetNextToken(); // perm
886 tkz.GetNextToken(); // ?
887 tkz.GetNextToken(); // user
888 tkz.GetNextToken(); // grp
889 tkz.GetNextToken(); // size
890 if (datetime.ParseDate(tkz.GetNextToken()) != NULL) { //date
891 if (datetime.ParseTime(tkz.GetNextToken()) != NULL) { //time
893 //wxbMainFrame::GetInstance()->Print(wxString("(") << filemessages << ")", CS_DEBUG);
894 gauge->SetValue(filemessages);
904 wxbMainFrame::GetInstance()->SetStatusText(wxString("Restoring, please wait (") << filemessages << " of " << totfilemessages << " files done)...");
907 while (sw2.Time() < 10000) {
908 wxTheApp->Yield(true);
913 wxbUtils::WaitForEnd("messages\n");
915 gauge->SetValue(totfilemessages);
917 if ((*tableparser)[0][7] == "T") {
918 wxbMainFrame::GetInstance()->Print("Restore done successfully.\n", CS_DEBUG);
919 wxbMainFrame::GetInstance()->SetStatusText("Restore done successfully.");
922 wxbMainFrame::GetInstance()->Print("Restore failed, please look at messages.\n", CS_DEBUG);
923 wxbMainFrame::GetInstance()->SetStatusText("Restore failed, please look at messages in console.");
930 /* The cancel button has been clicked */
931 void wxbRestorePanel::CmdCancel() {
934 if (status == restoring) {
936 wxbMainFrame::GetInstance()->Send(wxString("cancel job=") << jobid << "\n");
938 cancel->Enable(true);
943 while ((IsWorking()) && (cancelled != 2)) {
944 wxTheApp->Yield(true);
946 if (sw.Time() > 30000) { /* 30 seconds timeout */
947 if (status == choosing) {
948 wxbMainFrame::GetInstance()->Send("quit\n");
950 else if (status == configuring) {
951 wxbMainFrame::GetInstance()->Send("no\n");
953 else if (status == restoring) {
964 wxbMainFrame::GetInstance()->Send("quit\n");
967 wxbMainFrame::GetInstance()->Send("no\n");
976 /* Apply configuration changes */
978 /* 1: Level (not appropriate)
983 * 6: When (yes : "Please enter desired start time as YYYY-MM-DD HH:MM:SS (return for now):")
984 * 7: Priority (yes : "Enter new Priority: (positive integer)")
986 * 9: Where (yes : "Please enter path prefix for restore (/ for none):")
987 * 10: Replace (yes : "Replace:\n 1: always\n 2: ifnewer\n 3: ifolder\n 4: never\n
988 * Select replace option (1-4):")
992 void wxbRestorePanel::CmdConfigApply() {
993 if (cfgUpdated == 0) return;
995 wxbMainFrame::GetInstance()->SetStatusText("Applying restore configuration changes...");
999 wxbDataTokenizer* dt = NULL;
1001 bool failed = false;
1003 while (cfgUpdated > 0) {
1008 wxString def; //String to send if can't use our data
1009 if ((cfgUpdated >> ConfigWhere) & 1) {
1010 wxbUtils::WaitForPrompt("mod\n"); /* TODO: check results */
1011 wxbUtils::WaitForPrompt("9\n");
1012 dt = new wxbDataTokenizer(true);
1013 wxbUtils::WaitForPrompt(restorePanel->GetRowString("Where") + "\n");
1015 cfgUpdated = cfgUpdated & (~(1 << ConfigWhere));
1017 else if ((cfgUpdated >> ConfigReplace) & 1) {
1018 wxbUtils::WaitForPrompt("mod\n"); /* TODO: check results */
1019 wxbUtils::WaitForPrompt("10\n");
1020 dt = new wxbDataTokenizer(true);
1021 wxbUtils::WaitForPrompt(wxString() << (restorePanel->GetRowSelection("Replace")+1) << "\n");
1023 cfgUpdated = cfgUpdated & (~(1 << ConfigReplace));
1025 else if ((cfgUpdated >> ConfigWhen) & 1) {
1026 wxbUtils::WaitForPrompt("mod\n"); /* TODO: check results */
1027 wxbUtils::WaitForPrompt("6\n");
1028 dt = new wxbDataTokenizer(true);
1029 wxbUtils::WaitForPrompt(restorePanel->GetRowString("When") + "\n");
1031 cfgUpdated = cfgUpdated & (~(1 << ConfigWhen));
1033 else if ((cfgUpdated >> ConfigPriority) & 1) {
1034 wxbUtils::WaitForPrompt("mod\n"); /* TODO: check results */
1035 wxbUtils::WaitForPrompt("7\n");
1036 dt = new wxbDataTokenizer(true);
1037 wxbUtils::WaitForPrompt(restorePanel->GetRowString("Priority") + "\n");
1039 cfgUpdated = cfgUpdated & (~(1 << ConfigPriority));
1041 else if ((cfgUpdated >> ConfigClient) & 1) {
1042 wxbUtils::WaitForPrompt("mod\n"); /* TODO: check results */
1043 wxbPromptParser *pp = wxbUtils::WaitForPrompt("5\n", true);
1044 int client = pp->getChoices()->Index(restorePanel->GetRowString("Client"));
1045 if (client == wxNOT_FOUND) {
1046 wxbMainFrame::GetInstance()->SetStatusText("Failed to find the selected client.");
1051 dt = new wxbDataTokenizer(true);
1052 wxbUtils::WaitForPrompt(wxString() << client << "\n");
1054 cfgUpdated = cfgUpdated & (~(1 << ConfigClient));
1056 else if ((cfgUpdated >> ConfigFileset) & 1) {
1057 wxbUtils::WaitForPrompt("mod\n"); /* TODO: check results */
1058 wxbPromptParser *pp = wxbUtils::WaitForPrompt("4\n", true);
1059 int fileset = pp->getChoices()->Index(restorePanel->GetRowString("Fileset"));
1060 if (fileset == wxNOT_FOUND) {
1061 wxbMainFrame::GetInstance()->SetStatusText("Failed to find the selected fileset.");
1066 dt = new wxbDataTokenizer(true);
1067 wxbUtils::WaitForPrompt(wxString() << fileset << "\n");
1069 cfgUpdated = cfgUpdated & (~(1 << ConfigFileset));
1071 else if ((cfgUpdated >> ConfigStorage) & 1) {
1072 wxbUtils::WaitForPrompt("mod\n"); /* TODO: check results */
1073 wxbPromptParser *pp = wxbUtils::WaitForPrompt("2\n", true);
1074 int fileset = pp->getChoices()->Index(restorePanel->GetRowString("Storage"));
1075 if (fileset == wxNOT_FOUND) {
1076 wxbMainFrame::GetInstance()->SetStatusText("Failed to find the selected storage.");
1081 dt = new wxbDataTokenizer(true);
1082 wxbUtils::WaitForPrompt(wxString() << fileset << "\n");
1084 cfgUpdated = cfgUpdated & (~(1 << ConfigFileset));
1092 for (i = 0; i < dt->GetCount(); i++) {
1093 if ((*dt)[i].Find("Run Restore job") == 0) {
1098 if (i == dt->GetCount()) {
1100 dt = wxbUtils::WaitForEnd(def + "\n", true);
1104 UpdateSecondConfig(dt); /* TODO: Check result */
1109 wxbMainFrame::GetInstance()->SetStatusText("Restore configuration changes were applied.");
1115 /* Cancel restore */
1116 void wxbRestorePanel::CmdConfigCancel() {
1117 wxbUtils::WaitForEnd("no\n");
1118 wxbMainFrame::GetInstance()->Print("Restore cancelled.\n", CS_DEBUG);
1119 wxbMainFrame::GetInstance()->SetStatusText("Restore cancelled.");
1120 SetStatus(finished);
1123 /* List jobs for a specified client */
1124 void wxbRestorePanel::CmdListJobs() {
1125 if (status == entered) {
1126 configPanel->ClearRowChoices("Before");
1127 wxbUtils::WaitForPrompt("query\n");
1128 wxbUtils::WaitForPrompt("6\n");
1129 wxbTableParser* tableparser = new wxbTableParser();
1130 wxbDataTokenizer* dt = wxbUtils::WaitForEnd(configPanel->GetRowString("Client") + "\n", true);
1132 if (!tableparser->hasFinished()) {
1133 for (unsigned int i = 0; i < dt->Count(); i++) {
1134 if ((*dt)[i].Find("No results to list.") == 0) {
1135 configPanel->AddRowChoice("Before", "No backup found for this client.");
1136 configPanel->SetRowSelection("Before", 0);
1137 configPanel->EnableApply(true); // Enabling the not existing apply button disables the ok button.
1142 else if (((*dt)[i].Find("ERROR") > -1) || ((*dt)[i].Find("Query failed") > -1)) {
1143 configPanel->AddRowChoice("Before", "Cannot get previous backups list, see console.");
1144 configPanel->SetRowSelection("Before", 0);
1145 configPanel->EnableApply(true); // Enabling the not existing apply button disables the ok button.
1153 while (!tableparser->hasFinished()) {
1154 wxTheApp->Yield(true);
1160 for (int i = tableparser->GetCount()-1; i > -1; i--) {
1161 wxString str = (*tableparser)[i][3];
1162 wxDateTime datetime;
1164 if ( ( (chr = datetime.ParseDate(str.GetData()) ) != NULL ) && ( datetime.ParseTime(++chr) != NULL ) ) {
1165 datetime += wxTimeSpan::Seconds(1);
1166 //wxbMainFrame::GetInstance()->Print(wxString("-") << datetime.Format("%Y-%m-%d %H:%M:%S"), CS_DEBUG);
1167 configPanel->AddRowChoice("Before", datetime.Format("%Y-%m-%d %H:%M:%S"));
1170 jobChoice->Append("Invalid");
1176 configPanel->SetRowSelection("Before", 0);
1177 configPanel->EnableApply(false); // Disabling the not existing apply button enables the ok button.
1181 /* List files and directories for a specified tree item */
1182 void wxbRestorePanel::CmdList(wxTreeItemId item) {
1183 if (status == choosing) {
1184 list->DeleteAllItems();
1189 UpdateTreeItem(item, true, false);
1191 if (list->GetItemCount() >= 1) {
1192 int firstwidth = list->GetSize().GetWidth();
1193 for (int i = 2; i < 7; i++) {
1194 list->SetColumnWidth(i, wxLIST_AUTOSIZE);
1195 firstwidth -= list->GetColumnWidth(i);
1198 list->SetColumnWidth(0, 18);
1200 list->SetColumnWidth(1, wxLIST_AUTOSIZE);
1201 if (list->GetColumnWidth(1) < firstwidth) {
1202 list->SetColumnWidth(1, firstwidth-25);
1208 /* Mark a treeitem (directory) or a listitem (file or directory) */
1209 void wxbRestorePanel::CmdMark(wxTreeItemId treeitem, long* listitems, int listsize, int state) {
1210 if (status == choosing) {
1211 wxbTreeItemData** itemdata;
1212 int itemdatasize = 0;
1213 if (listsize == 0) {
1214 itemdata = new wxbTreeItemData*[1];
1218 itemdata = new wxbTreeItemData*[listsize];
1219 itemdatasize = listsize;
1222 if (listitems != NULL) {
1223 for (int i = 0; i < listsize; i++) {
1224 itemdata[i] = (wxbTreeItemData*)list->GetItemData(listitems[i]);
1227 else if (treeitem.IsOk()) {
1228 itemdata[0] = (wxbTreeItemData*)tree->GetItemData(treeitem);
1235 if (itemdata[0] == NULL) { //Should never happen
1240 wxString dir = itemdata[0]->GetPath();
1244 if (dir.GetChar(dir.Length()-1) == '/') {
1248 int i = dir.Find('/', TRUE);
1253 else { /* first dir below root */
1254 file = dir.Mid(i+1);
1255 dir = dir.Mid(0, i+1);
1264 bool marked = false;
1265 bool unmarked = false;
1267 for (int i = 0; i < itemdatasize; i++) {
1268 switch(itemdata[i]->GetMarked()) {
1282 if (marked && unmarked)
1298 wxbUtils::WaitForEnd(wxString("cd \"") << dir << "\"\n");
1299 wxbUtils::WaitForEnd(wxString((state==1) ? "mark" : "unmark") << " \"" << file << "\"\n");
1301 /* TODO: Check commands results */
1303 /*if ((dir == "/") && (file == "*")) {
1304 itemdata->SetMarked((itemdata->GetMarked() == 1) ? 0 : 1);
1307 if (listitems == NULL) { /* tree item state changed */
1308 SetTreeItemState(treeitem, state);
1309 /*treeitem = tree->GetSelection();
1310 UpdateTree(treeitem, true);
1311 treeitem = tree->GetItemParent(treeitem);*/
1314 for (int i = 0; i < listsize; i++) {
1315 SetListItemState(listitems[i], state);
1317 /*UpdateTree(treeitem, (tree->GetSelection() == treeitem));
1318 treeitem = tree->GetItemParent(treeitem);*/
1321 /*while (treeitem.IsOk()) {
1322 WaitForList(treeitem, false);
1323 treeitem = tree->GetItemParent(treeitem);
1330 /*----------------------------------------------------------------------------
1332 ----------------------------------------------------------------------------*/
1334 /* Run a dir command, and waits until result is fully received. */
1335 void wxbRestorePanel::UpdateTreeItem(wxTreeItemId item, bool updatelist, bool recurse) {
1336 // this->updatelist = updatelist;
1337 wxbDataTokenizer* dt;
1339 dt = wxbUtils::WaitForEnd(wxString("cd \"") <<
1340 static_cast<wxbTreeItemData*>(tree->GetItemData(item))
1341 ->GetPath() << "\"\n", false);
1343 /* TODO: check command result */
1350 list->DeleteAllItems();
1351 dt = wxbUtils::WaitForEnd("dir\n", true);
1355 for (unsigned int i = 0; i < dt->GetCount(); i++) {
1358 if (str.Find("cwd is:") == 0) { // Sometimes cd command result "infiltrate" into listings.
1364 wxString* file = ParseList(str);
1369 wxTreeItemId treeid;
1371 if (file[8].GetChar(file[8].Length()-1) == '/') {
1375 treeid = tree->GetFirstChild(item, cookie);
1377 bool updated = false;
1379 while (treeid.IsOk()) {
1380 itemStr = tree->GetItemText(treeid);
1381 if (file[8] == itemStr) {
1382 int stat = wxbTreeItemData::GetMarkedStatus(file[6]);
1383 if (static_cast<wxbTreeItemData*>(tree->GetItemData(treeid))->GetMarked() != stat) {
1384 tree->SetItemImage(treeid, stat, wxTreeItemIcon_Normal);
1385 tree->SetItemImage(treeid, stat, wxTreeItemIcon_Selected);
1386 static_cast<wxbTreeItemData*>(tree->GetItemData(treeid))->SetMarked(file[6]);
1388 if ((recurse) && (tree->IsExpanded(treeid))) {
1389 UpdateTreeItem(treeid, false, true);
1394 treeid = tree->GetNextChild(item, cookie);
1398 int img = wxbTreeItemData::GetMarkedStatus(file[6]);
1399 treeid = tree->AppendItem(item, file[8], img, img, new wxbTreeItemData(file[7], file[8], file[6]));
1404 long ind = list->InsertItem(list->GetItemCount(), wxbTreeItemData::GetMarkedStatus(file[6]));
1405 wxbTreeItemData* data = new wxbTreeItemData(file[7], file[8], file[6], ind);
1406 data->SetId(treeid);
1407 list->SetItemData(ind, (long)data);
1408 list->SetItem(ind, 1, file[8]); // filename
1409 list->SetItem(ind, 2, file[4]); //Size
1410 list->SetItem(ind, 3, file[5]); //date
1411 list->SetItem(ind, 4, file[0]); //perm
1412 list->SetItem(ind, 5, file[2]); //user
1413 list->SetItem(ind, 6, file[3]); //grp
1425 /* Parse dir command results. */
1426 wxString* wxbRestorePanel::ParseList(wxString line) {
1427 /* See ls_output in dird/ua_tree.c */
1429 //drwxrwxrwx 1 root root 0 2004-04-03 14:35:21 f:/tocd/NVSU 1.00.00/
1430 //+ 10 + ++ + 8 + + 8 ++ 8 + + 19 + *+ ->
1431 //0 12 15 24 32 42 62
1433 if (line.Length() < 63)
1436 wxString* ret = new wxString[9];
1438 ret[0] = line.Mid(0, 10).Trim();
1439 ret[1] = line.Mid(12, 2).Trim();
1440 ret[2] = line.Mid(15, 8).Trim();
1441 ret[3] = line.Mid(24, 8).Trim();
1442 ret[4] = line.Mid(32, 8).Trim();
1443 ret[5] = line.Mid(42, 19).Trim();
1444 ret[6] = line.Mid(62, 1);
1445 ret[7] = line.Mid(63).Trim();
1447 if (ret[6] == " ") ret[6] = "";
1449 if (ret[7].GetChar(ret[7].Length()-1) == '/') {
1451 ret[8].RemoveLast();
1452 ret[8] = ret[7].Mid(ret[8].Find('/', true)+1);
1455 ret[8] = ret[7].Mid(ret[7].Find('/', true)+1);
1461 /* Sets a list item state, and update its parents and children if it is a directory */
1462 void wxbRestorePanel::SetListItemState(long listitem, int newstate) {
1463 wxbTreeItemData* itemdata = (wxbTreeItemData*)list->GetItemData(listitem);
1465 wxTreeItemId treeitem;
1467 itemdata->SetMarked(newstate);
1468 list->SetItemImage(listitem, newstate, 0); /* TODO: Find what these ints are for */
1469 list->SetItemImage(listitem, newstate, 1);
1471 if ((treeitem = itemdata->GetId()).IsOk()) {
1472 SetTreeItemState(treeitem, newstate);
1475 UpdateTreeItemState(tree->GetSelection());
1479 /* Sets a tree item state, and update its children, parents and list (if necessary) */
1480 void wxbRestorePanel::SetTreeItemState(wxTreeItemId item, int newstate) {
1482 wxTreeItemId currentChild = tree->GetFirstChild(item, cookie);
1484 wxbTreeItemData* itemdata;
1486 while (currentChild.IsOk()) {
1487 itemdata = (wxbTreeItemData*)tree->GetItemData(currentChild);
1488 int state = itemdata->GetMarked();
1490 if (state != newstate) {
1491 itemdata->SetMarked(newstate);
1492 tree->SetItemImage(currentChild, newstate, wxTreeItemIcon_Normal);
1493 tree->SetItemImage(currentChild, newstate, wxTreeItemIcon_Selected);
1496 currentChild = tree->GetNextChild(item, cookie);
1499 itemdata = (wxbTreeItemData*)tree->GetItemData(item);
1500 itemdata->SetMarked(newstate);
1501 tree->SetItemImage(item, newstate, wxTreeItemIcon_Normal);
1502 tree->SetItemImage(item, newstate, wxTreeItemIcon_Selected);
1505 if (tree->GetSelection() == item) {
1506 for (long i = 0; i < list->GetItemCount(); i++) {
1507 list->SetItemImage(i, newstate, 0); /* TODO: Find what these ints are for */
1508 list->SetItemImage(i, newstate, 1);
1512 UpdateTreeItemState(tree->GetItemParent(item));
1515 /* Update a tree item state, and its parents' state */
1516 void wxbRestorePanel::UpdateTreeItemState(wxTreeItemId item) {
1524 wxTreeItemId currentChild = tree->GetFirstChild(item, cookie);
1526 bool onechildmarked = false;
1527 bool onechildunmarked = false;
1529 while (currentChild.IsOk()) {
1530 state = ((wxbTreeItemData*)tree->GetItemData(currentChild))->GetMarked();
1533 onechildunmarked = true;
1536 onechildmarked = true;
1539 onechildmarked = true;
1540 onechildunmarked = true;
1544 if (onechildmarked && onechildunmarked) {
1548 currentChild = tree->GetNextChild(item, cookie);
1551 if (tree->GetSelection() == item) {
1552 for (long i = 0; i < list->GetItemCount(); i++) {
1553 state = ((wxbTreeItemData*)list->GetItemData(i))->GetMarked();
1557 onechildunmarked = true;
1560 onechildmarked = true;
1563 onechildmarked = true;
1564 onechildunmarked = true;
1568 if (onechildmarked && onechildunmarked) {
1576 if (onechildmarked && onechildunmarked) {
1579 else if (onechildmarked) {
1582 else if (onechildunmarked) {
1585 else { // no child, don't change anything
1586 UpdateTreeItemState(tree->GetItemParent(item));
1590 wxbTreeItemData* itemdata = (wxbTreeItemData*)tree->GetItemData(item);
1592 itemdata->SetMarked(state);
1593 tree->SetItemImage(item, state, wxTreeItemIcon_Normal);
1594 tree->SetItemImage(item, state, wxTreeItemIcon_Selected);
1596 UpdateTreeItemState(tree->GetItemParent(item));
1599 /* Refresh the whole tree. */
1600 void wxbRestorePanel::RefreshTree() {
1601 /* Save current selection */
1602 wxArrayString current;
1604 wxTreeItemId item = currentTreeItem;
1606 while ((item.IsOk()) && (item != tree->GetRootItem())) {
1607 current.Add(tree->GetItemText(item));
1608 item = tree->GetItemParent(item);
1611 /* Update the tree */
1612 UpdateTreeItem(tree->GetRootItem(), false, true);
1614 /* Reselect the former selected item */
1615 item = tree->GetRootItem();
1617 if (current.Count() == 0) {
1618 tree->SelectItem(item);
1624 for (int i = current.Count()-1; i >= 0; i--) {
1626 wxTreeItemId currentChild = tree->GetFirstChild(item, cookie);
1630 while (currentChild.IsOk()) {
1631 if (tree->GetItemText(currentChild) == current[i]) {
1632 item = currentChild;
1637 currentChild = tree->GetNextChild(item, cookie);
1643 UpdateTreeItem(item, true, false); /* Update the list */
1645 tree->SelectItem(item);
1648 void wxbRestorePanel::RefreshList() {
1649 if (currentTreeItem.IsOk()) {
1650 UpdateTreeItem(currentTreeItem, true, false); /* Update the list */
1654 /* Update first config, adapting settings to the job name selected */
1655 void wxbRestorePanel::UpdateFirstConfig() {
1656 configPanel->Enable(false);
1657 wxbDataTokenizer* dt = wxbUtils::WaitForEnd(wxString(".defaults job=") + configPanel->GetRowString("Job Name") + "\n", true, false);
1663 * where=/tmp/bacula-restores
1666 * fileset=Full Set */
1672 bool dolistjobs = false;
1674 for (i = 0; i < dt->GetCount(); i++) {
1676 if ((j = str.Find('=')) > -1) {
1677 name = str.Mid(0, j);
1678 if (name == "pool") {
1679 configPanel->SetRowString("Pool", str.Mid(j+1));
1681 else if (name == "client") {
1683 if ((str != configPanel->GetRowString("Client")) || (configPanel->GetRowString("Before") == "")) {
1684 configPanel->SetRowString("Client", str);
1688 else if (name == "storage") {
1689 configPanel->SetRowString("Storage", str.Mid(j+1));
1691 else if (name == "fileset") {
1692 configPanel->SetRowString("Fileset", str.Mid(j+1));
1700 //wxTheApp->Yield(false);
1703 configPanel->Enable(true);
1707 * Update second config.
1710 * JobName: RestoreFiles
1711 * Bootstrap: /var/lib/bacula/restore.bsr
1712 * Where: /tmp/bacula-restores
1717 * When: 2004-04-18 01:18:56
1719 * OK to run? (yes/mod/no):
1722 bool wxbRestorePanel::UpdateSecondConfig(wxbDataTokenizer* dt) {
1724 for (i = 0; i < dt->GetCount(); i++) {
1725 if ((*dt)[i].Find("Run Restore job") == 0)
1729 if ((i + 10) > dt->GetCount()) {
1735 if ((k = (*dt)[++i].Find("JobName:")) != 0) return false;
1736 restorePanel->SetRowString("Job Name", (*dt)[i].Mid(10).Trim(false).RemoveLast());
1737 if ((k = (*dt)[++i].Find("Bootstrap:")) != 0) return false;
1738 restorePanel->SetRowString("Bootstrap", (*dt)[i].Mid(10).Trim(false).RemoveLast());
1739 if ((k = (*dt)[++i].Find("Where:")) != 0) return false;
1740 restorePanel->SetRowString("Where", (*dt)[i].Mid(10).Trim(false).RemoveLast());
1742 if ((k = (*dt)[++i].Find("Replace:")) != 0) return false;
1743 wxString str = (*dt)[i].Mid(10).Trim(false).RemoveLast();
1744 if (str == "always") restorePanel->SetRowSelection("Replace", 0);
1745 else if (str == "ifnewer") restorePanel->SetRowSelection("Replace", 1);
1746 else if (str == "ifolder") restorePanel->SetRowSelection("Replace", 2);
1747 else if (str == "never") restorePanel->SetRowSelection("Replace", 3);
1748 else restorePanel->SetRowSelection("Replace", 0);
1750 if ((k = (*dt)[++i].Find("FileSet:")) != 0) return false;
1751 restorePanel->SetRowString("Fileset", (*dt)[i].Mid(10).Trim(false).RemoveLast());
1752 if ((k = (*dt)[++i].Find("Client:")) != 0) return false;
1753 restorePanel->SetRowString("Client", (*dt)[i].Mid(10).Trim(false).RemoveLast());
1754 if ((k = (*dt)[++i].Find("Storage:")) != 0) return false;
1755 restorePanel->SetRowString("Storage", (*dt)[i].Mid(10).Trim(false).RemoveLast());
1756 if ((k = (*dt)[++i].Find("When:")) != 0) return false;
1757 restorePanel->SetRowString("When", (*dt)[i].Mid(10).Trim(false).RemoveLast());
1758 if ((k = (*dt)[++i].Find("Priority:")) != 0) return false;
1759 restorePanel->SetRowString("Priority", (*dt)[i].Mid(10).Trim(false).RemoveLast());
1762 restorePanel->Layout();
1767 /*----------------------------------------------------------------------------
1769 ----------------------------------------------------------------------------*/
1771 /* Set current status by enabling/disabling components */
1772 void wxbRestorePanel::SetStatus(status_enum newstatus) {
1773 switch (newstatus) {
1775 centerSizer->Remove(configPanel);
1776 centerSizer->Remove(restorePanel);
1777 centerSizer->Remove(treelistPanel);
1778 treelistPanel->Show(false);
1779 restorePanel->Show(false);
1780 centerSizer->Add(configPanel, 1, wxEXPAND);
1781 configPanel->Show(true);
1782 configPanel->Layout();
1783 centerSizer->Layout();
1785 start->SetLabel("Enter restore mode");
1786 start->Enable(false);
1787 configPanel->Enable(false);
1788 tree->Enable(false);
1789 list->Enable(false);
1790 gauge->Enable(false);
1791 cancel->Enable(false);
1796 centerSizer->Remove(configPanel);
1797 centerSizer->Remove(restorePanel);
1798 centerSizer->Remove(treelistPanel);
1799 treelistPanel->Show(false);
1800 restorePanel->Show(false);
1801 centerSizer->Add(configPanel, 1, wxEXPAND);
1802 configPanel->Show(true);
1803 configPanel->Layout();
1804 centerSizer->Layout();
1806 tree->DeleteAllItems();
1807 list->DeleteAllItems();
1808 configPanel->ClearRowChoices("Client");
1809 configPanel->ClearRowChoices("Before");
1810 wxbMainFrame::GetInstance()->EnablePanels();
1811 newstatus = activable;
1814 start->SetLabel("Enter restore mode");
1815 start->Enable(true);
1816 configPanel->Enable(false);
1817 tree->Enable(false);
1818 list->Enable(false);
1819 gauge->Enable(false);
1820 cancel->Enable(false);
1824 wxbMainFrame::GetInstance()->DisablePanels(this);
1826 start->Enable(false);
1827 //start->SetLabel("Choose files to restore");
1828 configPanel->Enable(true);
1829 tree->Enable(false);
1830 list->Enable(false);
1831 cancel->Enable(true);
1838 start->Enable(true);
1839 start->SetLabel("Restore");
1840 centerSizer->Remove(configPanel);
1841 configPanel->Show(false);
1842 centerSizer->Add(treelistPanel, 1, wxEXPAND);
1843 treelistPanel->Show(true);
1844 treelistPanel->Layout();
1845 centerSizer->Layout();
1852 start->Enable(false);
1853 configPanel->Enable(false);
1854 tree->Enable(false);
1855 list->Enable(false);
1856 centerSizer->Remove(treelistPanel);
1857 treelistPanel->Show(false);
1858 centerSizer->Add(restorePanel, 1, wxEXPAND);
1859 restorePanel->Show(true);
1860 restorePanel->Layout();
1861 centerSizer->Layout();
1863 restorePanel->EnableApply(false);
1866 start->SetLabel("Restoring...");
1867 gauge->Enable(true);
1869 start->Enable(false);
1870 configPanel->Enable(false);
1871 tree->Enable(false);
1872 list->Enable(false);
1879 /*----------------------------------------------------------------------------
1881 ----------------------------------------------------------------------------*/
1883 void wxbRestorePanel::SetWorking(bool working) {
1884 this->working = working;
1886 SetCursor(*wxHOURGLASS_CURSOR);
1887 // SetEvtHandlerEnabled(false); //EVTQUEUE
1889 // else if (!processing) { /* Empty event queue if we aren't already doing this */ //EVTQUEUE
1891 // processing = true; //EVTQUEUE
1892 SetCursor(*wxSTANDARD_CURSOR);
1893 // SetEvtHandlerEnabled(true); //EVTQUEUE
1894 /* wxNode *node = pendingEvents->First(); //EVTQUEUE
1896 wxEvent *event = (wxEvent *)node->Data();
1899 wxEvtHandler::ProcessEvent(*event);
1902 node = pendingEvents->First();
1904 processing = false;*/
1908 bool wxbRestorePanel::IsWorking() {
1909 return this->working;
1912 void wxbRestorePanel::EnableConfig(bool enable) {
1913 restorePanel->Enable(enable);
1916 /*----------------------------------------------------------------------------
1918 ----------------------------------------------------------------------------*/
1923 bool wxbRestorePanel::ProcessEvent(wxEvent& event) {
1924 if (IsWorking() || processing) {
1925 wxEvent *eventCopy = event.Clone();
1927 pendingEvents->Append(eventCopy);
1931 return wxEvtHandler::ProcessEvent(event);
1936 void wxbRestorePanel::OnCancel(wxCommandEvent& event) {
1937 cancel->Enable(false);
1938 SetCursor(*wxHOURGLASS_CURSOR);
1940 SetCursor(*wxSTANDARD_CURSOR);
1943 void wxbRestorePanel::OnStart(wxCommandEvent& event) {
1945 AddPendingEvent(event);
1953 void wxbRestorePanel::OnTreeChanging(wxTreeEvent& event) {
1955 AddPendingEvent(event);
1960 void wxbRestorePanel::OnTreeExpanding(wxTreeEvent& event) {
1962 AddPendingEvent(event);
1967 //CmdList(event.GetItem());
1968 if (tree->GetSelection() != event.GetItem()) {
1969 tree->SelectItem(event.GetItem());
1974 void wxbRestorePanel::OnTreeChanged(wxTreeEvent& event) {
1976 AddPendingEvent(event);
1979 if (currentTreeItem == event.GetItem()) {
1982 treeadd->Enable(false);
1983 treeremove->Enable(false);
1984 treerefresh->Enable(false);
1985 markWhenListingDone = false;
1987 currentTreeItem = event.GetItem();
1988 CmdList(event.GetItem());
1989 if (markWhenListingDone) {
1990 CmdMark(event.GetItem(), NULL, 0);
1994 if (event.GetItem().IsOk()) {
1995 int status = ((wxbTreeItemData*)tree->GetItemData(event.GetItem()))->GetMarked();
1996 treeadd->Enable(status != 1);
1997 treeremove->Enable(status != 0);
1999 treerefresh->Enable(true);
2002 void wxbRestorePanel::OnTreeMarked(wxbTreeMarkedEvent& event) {
2003 csprint("Tree marked", CS_DEBUG);
2005 if (tree->GetSelection() == event.GetItem()) {
2006 markWhenListingDone = !markWhenListingDone;
2008 AddPendingEvent(event);
2012 CmdMark(event.GetItem(), NULL, 0);
2016 if (event.GetItem().IsOk()) {
2017 int status = ((wxbTreeItemData*)tree->GetItemData(event.GetItem()))->GetMarked();
2018 treeadd->Enable(status != 1);
2019 treeremove->Enable(status != 0);
2023 void wxbRestorePanel::OnTreeAdd(wxCommandEvent& event) {
2025 AddPendingEvent(event);
2029 if (currentTreeItem.IsOk()) {
2031 CmdMark(currentTreeItem, NULL, 0, 1);
2034 treeremove->Enable(1);
2039 void wxbRestorePanel::OnTreeRemove(wxCommandEvent& event) {
2041 AddPendingEvent(event);
2045 if (currentTreeItem.IsOk()) {
2047 CmdMark(currentTreeItem, NULL, 0, 0);
2050 treeremove->Enable(0);
2055 void wxbRestorePanel::OnTreeRefresh(wxCommandEvent& event) {
2057 AddPendingEvent(event);
2066 void wxbRestorePanel::OnListMarked(wxbListMarkedEvent& event) {
2068 AddPendingEvent(event);
2073 if (list->GetSelectedItemCount() == 0) {
2079 long* items = new long[list->GetSelectedItemCount()];
2083 long item = list->GetNextItem(-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
2084 while (item != -1) {
2087 item = list->GetNextItem(item, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
2090 CmdMark(wxTreeItemId(), items, num);
2094 wxListEvent listevt;
2096 OnListChanged(listevt);
2103 void wxbRestorePanel::OnListActivated(wxListEvent& event) {
2105 AddPendingEvent(event);
2110 long item = event.GetIndex();
2111 // long item = list->GetNextItem(-1, wxLIST_NEXT_ALL, wxLIST_STATE_FOCUSED);
2113 wxbTreeItemData* itemdata = (wxbTreeItemData*)list->GetItemData(item);
2114 wxString name = itemdata->GetName();
2121 if (name.GetChar(name.Length()-1) == '/') {
2122 wxTreeItemId currentChild = tree->GetFirstChild(currentTreeItem, cookie);
2124 while (currentChild.IsOk()) {
2125 wxString name2 = tree->GetItemText(currentChild);
2126 if (name2 == name) {
2127 //tree->UnselectAll();
2129 tree->Expand(currentTreeItem);
2130 tree->SelectItem(currentChild);
2134 currentChild = tree->GetNextChild(currentTreeItem, cookie);
2141 void wxbRestorePanel::OnListChanged(wxListEvent& event) {
2143 AddPendingEvent(event);
2147 listadd->Enable(false);
2148 listremove->Enable(false);
2150 bool marked = false;
2151 bool unmarked = false;
2153 long item = list->GetNextItem(-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
2154 while (item != -1) {
2155 switch (((wxbTreeItemData*)list->GetItemData(item))->GetMarked()) {
2168 // Should never happen
2170 if (marked && unmarked) break;
2171 item = list->GetNextItem(item, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
2174 listadd->Enable(unmarked);
2175 listremove->Enable(marked);
2178 void wxbRestorePanel::OnListAdd(wxCommandEvent& event) {
2180 AddPendingEvent(event);
2186 long* items = new long[list->GetSelectedItemCount()];
2190 long item = list->GetNextItem(-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
2191 while (item != -1) {
2194 item = list->GetNextItem(item, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
2197 CmdMark(wxTreeItemId(), items, num, 1);
2204 listadd->Enable(false);
2205 listremove->Enable(true);
2208 void wxbRestorePanel::OnListRemove(wxCommandEvent& event) {
2210 AddPendingEvent(event);
2216 long* items = new long[list->GetSelectedItemCount()];
2220 long item = list->GetNextItem(-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
2221 while (item != -1) {
2224 item = list->GetNextItem(item, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
2227 CmdMark(wxTreeItemId(), items, num, 0);
2234 listadd->Enable(true);
2235 listremove->Enable(false);
2238 void wxbRestorePanel::OnListRefresh(wxCommandEvent& event) {
2240 AddPendingEvent(event);
2249 void wxbRestorePanel::OnConfigUpdated(wxCommandEvent& event) {
2250 if (status == entered) {
2251 if (event.GetId() == ConfigJobName) {
2256 UpdateFirstConfig();
2259 else if (event.GetId() == ConfigClient) {
2264 configPanel->Enable(false);
2266 configPanel->Enable(true);
2269 cfgUpdated = cfgUpdated | (1 << event.GetId());
2271 else if (status == configuring) {
2272 restorePanel->EnableApply(true);
2273 cfgUpdated = cfgUpdated | (1 << event.GetId());
2277 void wxbRestorePanel::OnConfigOk(wxCommandEvent& WXUNUSED(event)) {
2278 if (status != configuring) return;
2287 void wxbRestorePanel::OnConfigApply(wxCommandEvent& WXUNUSED(event)) {
2288 if (status != configuring) return;
2294 if (cfgUpdated == 0) {
2295 restorePanel->EnableApply(false);
2300 void wxbRestorePanel::OnConfigCancel(wxCommandEvent& WXUNUSED(event)) {
2301 if (status != configuring) return;