2 Copyright (C) 2004 Kern Sibbald and John Walker
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18 /* Note concerning "done" output (modifiable marked with +)
21 Bootstrap: /var/lib/bacula/restore.bsr
22 +Where: /tmp/bacula-restores
27 +When: 2004-04-18 01:18:56
29 OK to run? (yes/mod/no):mod
31 1: Level (not appropriate)
32 2: Storage (automatic ?)
36 6: When (yes : "Please enter desired start time as YYYY-MM-DD HH:MM:SS (return for now):")
37 7: Priority (yes : "Enter new Priority: (positive integer)")
39 9: Where (yes : "Please enter path prefix for restore (/ for none):")
40 10: Replace (yes : "Replace:\n 1: always\n 2: ifnewer\n 3: ifolder\n 4: never\n
41 Select replace option (1-4):")
43 Select parameter to modify (1-11):
46 #include "wxbrestorepanel.h"
48 #include "wxbmainframe.h"
52 #include <wx/choice.h>
53 #include <wx/datetime.h>
55 #include "unmarked.xpm"
57 #include "partmarked.xpm"
59 /* A macro named Yield is defined under MinGW */
63 * Class which is stored in the tree and in the list to keep informations
66 class wxbTreeItemData : public wxTreeItemData {
68 wxbTreeItemData(wxString path, wxString name, int marked, long listid = -1);
69 wxbTreeItemData(wxString path, wxString name, wxString marked, long listid = -1);
75 void SetMarked(int marked);
76 void SetMarked(wxString marked);
80 static int GetMarkedStatus(wxString file);
82 wxString* path; /* Full path */
83 wxString* name; /* File name */
84 int marked; /* 0 - Not Marked, 1 - Marked, 2 - Some file under is marked */
85 long listid; /* list ID : >-1 if this data is in the list (and/or on the tree) */
88 wxbTreeItemData::wxbTreeItemData(wxString path, wxString name, int marked, long listid): wxTreeItemData() {
89 this->path = new wxString(path);
90 this->name = new wxString(name);
91 this->marked = marked;
92 this->listid = listid;
95 wxbTreeItemData::wxbTreeItemData(wxString path, wxString name, wxString marked, long listid): wxTreeItemData() {
96 this->path = new wxString(path);
97 this->name = new wxString(name);
99 this->listid = listid;
102 wxbTreeItemData::~wxbTreeItemData() {
107 int wxbTreeItemData::GetMarked() {
111 void wxbTreeItemData::SetMarked(wxString marked) {
115 else if (marked == "+") {
123 void wxbTreeItemData::SetMarked(int marked) {
124 this->marked = marked;
127 long wxbTreeItemData::GetListId() {
131 wxString wxbTreeItemData::GetPath() {
135 wxString wxbTreeItemData::GetName() {
139 /*wxbTreeItemData* wxbTreeItemData::GetChild(wxString dirname) {
140 int marked = GetMarkedStatus(dirname);
141 return new wxbTreeItemData(path + (marked ? dirname.Mid(1) : dirname), marked);
144 int wxbTreeItemData::GetMarkedStatus(wxString file) {
145 if (file.Length() == 0)
148 switch (file.GetChar(0)) {
158 // ----------------------------------------------------------------------------
159 // event tables and other macros for wxWindows
160 // ----------------------------------------------------------------------------
177 BEGIN_EVENT_TABLE(wxbRestorePanel, wxPanel)
178 EVT_BUTTON(RestoreStart, wxbRestorePanel::OnStart)
179 EVT_CHOICE(ClientChoice, wxbRestorePanel::OnClientChoiceChanged)
181 EVT_TREE_SEL_CHANGING(TreeCtrl, wxbRestorePanel::OnTreeChanging)
182 EVT_TREE_SEL_CHANGED(TreeCtrl, wxbRestorePanel::OnTreeChanged)
183 EVT_TREE_ITEM_EXPANDING(TreeCtrl, wxbRestorePanel::OnTreeExpanding)
184 EVT_LIST_ITEM_ACTIVATED(ListCtrl, wxbRestorePanel::OnListActivated)
186 /*EVT_TREE_MARKED_EVENT(wxID_ANY, wxbRestorePanel::OnTreeMarked)
187 EVT_LIST_MARKED_EVENT(wxID_ANY, wxbRestorePanel::OnListMarked)*/
189 EVT_TEXT(ConfigWhere, wxbRestorePanel::OnConfigUpdated)
190 EVT_TEXT(ConfigWhen, wxbRestorePanel::OnConfigUpdated)
191 EVT_TEXT(ConfigPriority, wxbRestorePanel::OnConfigUpdated)
192 EVT_CHOICE(ConfigReplace, wxbRestorePanel::OnConfigUpdated)
194 EVT_BUTTON(ConfigOk, wxbRestorePanel::OnConfigOk)
195 EVT_BUTTON(ConfigApply, wxbRestorePanel::OnConfigApply)
196 EVT_BUTTON(ConfigCancel, wxbRestorePanel::OnConfigCancel)
199 BEGIN_EVENT_TABLE(wxbTreeListPanel, wxPanel)
200 EVT_TREE_MARKED_EVENT(wxID_ANY, wxbTreeListPanel::OnTreeMarked)
201 EVT_LIST_MARKED_EVENT(wxID_ANY, wxbTreeListPanel::OnListMarked)
205 * wxbRestorePanel constructor
207 wxbRestorePanel::wxbRestorePanel(wxWindow* parent): wxbPanel(parent) {
208 imagelist = new wxImageList(16, 16, TRUE, 3);
209 imagelist->Add(wxIcon(unmarked_xpm));
210 imagelist->Add(wxIcon(marked_xpm));
211 imagelist->Add(wxIcon(partmarked_xpm));
213 wxFlexGridSizer* mainSizer = new wxFlexGridSizer(3, 1, 10, 10);
214 mainSizer->AddGrowableCol(0);
215 mainSizer->AddGrowableRow(1);
217 wxBoxSizer *firstSizer = new wxBoxSizer(wxHORIZONTAL);
219 start = new wxButton(this, RestoreStart, "Enter restore mode", wxDefaultPosition, wxSize(150, 30));
220 firstSizer->Add(start, 1, wxALIGN_CENTER_HORIZONTAL | wxALIGN_CENTER_VERTICAL, 10);
222 wxString* elist = new wxString[1];
224 clientChoice = new wxChoice(this, ClientChoice, wxDefaultPosition, wxSize(150, 30), 0, elist);
225 firstSizer->Add(clientChoice, 1, wxALIGN_CENTER_HORIZONTAL | wxALIGN_CENTER_VERTICAL, 10);
227 jobChoice = new wxChoice(this, -1, wxDefaultPosition, wxSize(150, 30), 0, elist);
228 firstSizer->Add(jobChoice, 1, wxALIGN_CENTER_HORIZONTAL | wxALIGN_CENTER_VERTICAL, 10);
230 mainSizer->Add(firstSizer, 1, wxALIGN_CENTER_HORIZONTAL | wxALIGN_CENTER_VERTICAL, 10);
232 treelistPanel = new wxbTreeListPanel(this);
234 wxFlexGridSizer* treelistSizer = new wxFlexGridSizer(1, 2, 10, 10);
236 tree = new wxbTreeCtrl(treelistPanel, TreeCtrl, wxDefaultPosition, wxSize(200,50));
237 treelistSizer->Add(tree, 1, wxALIGN_CENTER_HORIZONTAL | wxALIGN_CENTER_VERTICAL | wxEXPAND, 10);
239 tree->SetImageList(imagelist);
241 list = new wxbListCtrl(treelistPanel, ListCtrl, wxDefaultPosition, wxDefaultSize);
242 treelistSizer->Add(list, 1, wxALIGN_CENTER_HORIZONTAL | wxALIGN_CENTER_VERTICAL | wxEXPAND, 10);
244 list->SetImageList(imagelist, wxIMAGE_LIST_SMALL);
247 info.SetMask(wxLIST_MASK_TEXT | wxLIST_MASK_FORMAT);
249 info.SetAlign(wxLIST_FORMAT_CENTER);
250 list->InsertColumn(0, info);
252 info.SetText("Filename");
253 info.SetAlign(wxLIST_FORMAT_LEFT);
254 list->InsertColumn(1, info);
256 info.SetText("Size");
257 info.SetAlign(wxLIST_FORMAT_RIGHT);
258 list->InsertColumn(2, info);
260 info.SetText("Date");
261 info.SetAlign(wxLIST_FORMAT_LEFT);
262 list->InsertColumn(3, info);
264 info.SetText("Perm.");
265 info.SetAlign(wxLIST_FORMAT_LEFT);
266 list->InsertColumn(4, info);
268 info.SetText("User");
269 info.SetAlign(wxLIST_FORMAT_RIGHT);
270 list->InsertColumn(5, info);
272 info.SetText("Group");
273 info.SetAlign(wxLIST_FORMAT_RIGHT);
274 list->InsertColumn(6, info);
276 treelistSizer->AddGrowableCol(1);
277 treelistSizer->AddGrowableRow(0);
279 treelistPanel->SetSizer(treelistSizer);
280 treelistSizer->SetSizeHints(treelistPanel);
282 restorePanel = new wxPanel(this, -1);
284 wxBoxSizer* restoreSizer = new wxBoxSizer(wxVERTICAL);
286 wxGridSizer* cfgSizer = new wxGridSizer(9, 2, 15, 5);
288 cfgJobname = new wxStaticText(restorePanel, -1, " ", wxDefaultPosition, wxDefaultSize, wxALIGN_LEFT);
289 cfgBootstrap = new wxStaticText(restorePanel, -1, " ", wxDefaultPosition, wxDefaultSize, wxALIGN_LEFT);
290 cfgWhere = new wxTextCtrl(restorePanel, ConfigWhere);
291 elist = new wxString[4];
293 elist[1] = "ifnewer";
294 elist[2] = "ifolder";
296 cfgReplace = new wxChoice(restorePanel, ConfigReplace, wxDefaultPosition, wxDefaultSize, 4, elist);
297 cfgFileset = new wxStaticText(restorePanel, -1, " ", wxDefaultPosition, wxDefaultSize, wxALIGN_LEFT);
298 cfgClient = new wxStaticText(restorePanel, -1, " ", wxDefaultPosition, wxDefaultSize, wxALIGN_LEFT);
299 cfgStorage = new wxStaticText(restorePanel, -1, " ", wxDefaultPosition, wxDefaultSize, wxALIGN_LEFT);
300 cfgWhen = new wxTextCtrl(restorePanel, ConfigWhen);
301 cfgPriority = new wxTextCtrl(restorePanel, ConfigPriority);
303 cfgSizer->Add(new wxStaticText(restorePanel, -1, "Job Name", wxDefaultPosition, wxDefaultSize, wxALIGN_RIGHT), 1, wxEXPAND);
304 cfgSizer->Add(cfgJobname, 1, wxEXPAND);
305 cfgSizer->Add(new wxStaticText(restorePanel, -1, "Bootstrap", wxDefaultPosition, wxDefaultSize, wxALIGN_RIGHT), 1, wxEXPAND);
306 cfgSizer->Add(cfgBootstrap, 1, wxEXPAND);
307 cfgSizer->Add(new wxStaticText(restorePanel, -1, "Where", wxDefaultPosition, wxDefaultSize, wxALIGN_RIGHT), 1, wxEXPAND);
308 cfgSizer->Add(cfgWhere, 1, wxEXPAND);
309 cfgSizer->Add(new wxStaticText(restorePanel, -1, "Replace", wxDefaultPosition, wxDefaultSize, wxALIGN_RIGHT), 1, wxEXPAND);
310 cfgSizer->Add(cfgReplace, 1, wxEXPAND);
311 cfgSizer->Add(new wxStaticText(restorePanel, -1, "Fileset", wxDefaultPosition, wxDefaultSize, wxALIGN_RIGHT), 1, wxEXPAND);
312 cfgSizer->Add(cfgFileset, 1, wxEXPAND);
313 cfgSizer->Add(new wxStaticText(restorePanel, -1, "Client", wxDefaultPosition, wxDefaultSize, wxALIGN_RIGHT), 1, wxEXPAND);
314 cfgSizer->Add(cfgClient, 1, wxEXPAND);
315 cfgSizer->Add(new wxStaticText(restorePanel, -1, "Storage", wxDefaultPosition, wxDefaultSize, wxALIGN_RIGHT), 1, wxEXPAND);
316 cfgSizer->Add(cfgStorage, 1, wxEXPAND);
317 cfgSizer->Add(new wxStaticText(restorePanel, -1, "When", wxDefaultPosition, wxDefaultSize, wxALIGN_RIGHT), 1, wxEXPAND);
318 cfgSizer->Add(cfgWhen, 1, wxEXPAND);
319 cfgSizer->Add(new wxStaticText(restorePanel, -1, "Priority", wxDefaultPosition, wxDefaultSize, wxALIGN_RIGHT), 1, wxEXPAND);
320 cfgSizer->Add(cfgPriority, 1, wxEXPAND);
322 restoreSizer->Add(cfgSizer, 1, wxALIGN_CENTER_HORIZONTAL | wxALIGN_CENTER_VERTICAL | wxALL, 5);
324 wxBoxSizer* restoreBottomSizer = new wxBoxSizer(wxHORIZONTAL);
326 cfgOk = new wxButton(restorePanel, ConfigOk, "OK", wxDefaultPosition, wxSize(70, 25));
327 restoreBottomSizer->Add(cfgOk, 1, wxALIGN_CENTER_VERTICAL | wxRIGHT, 10);
329 cfgApply = new wxButton(restorePanel, ConfigApply, "Apply", wxDefaultPosition, wxSize(70, 25));
330 restoreBottomSizer->Add(cfgApply, 1, wxALIGN_CENTER_VERTICAL | wxLEFT | wxRIGHT, 10);
332 cfgCancel = new wxButton(restorePanel, ConfigCancel, "Cancel", wxDefaultPosition, wxSize(70, 25));
333 restoreBottomSizer->Add(cfgCancel, 1, wxALIGN_CENTER_VERTICAL | wxLEFT, 10);
335 restoreSizer->Add(restoreBottomSizer, 0, wxALIGN_CENTER_HORIZONTAL | wxALIGN_CENTER_VERTICAL | wxALL, 5);
337 restorePanel->SetSizer(restoreSizer);
338 restoreSizer->SetSizeHints(restorePanel);
340 restorePanel->Show(false);
342 centerSizer = new wxBoxSizer(wxHORIZONTAL);
343 //centerSizer->Add(treelistSizer, 1, wxEXPAND);
345 mainSizer->Add(centerSizer, 1, wxEXPAND, 10);
347 gauge = new wxGauge(this, -1, 1, wxDefaultPosition, wxSize(200,20));
349 mainSizer->Add(gauge, 1, wxEXPAND, 5);
351 gauge->Enable(false);
354 mainSizer->SetSizeHints(this);
358 jobChoice->Enable(false);
360 for (int i = 0; i < 7; i++) {
361 list->SetColumnWidth(i, 70);
368 * wxbRestorePanel destructor
370 wxbRestorePanel::~wxbRestorePanel() {
374 /*----------------------------------------------------------------------------
375 wxbPanel overloadings
376 ----------------------------------------------------------------------------*/
378 wxString wxbRestorePanel::GetTitle() {
382 void wxbRestorePanel::EnablePanel(bool enable) {
384 if (status == disabled) {
385 SetStatus(activable);
393 /*----------------------------------------------------------------------------
394 Commands called by events handler
395 ----------------------------------------------------------------------------*/
397 /* The main button has been clicked */
398 void wxbRestorePanel::CmdStart() {
399 if (status == activable) {
400 wxbTableParser* tableparser = CreateAndWaitForParser("list clients\n");
402 clientChoice->Clear();
403 for (unsigned int i = 0; i < tableparser->size(); i++) {
405 (*tableparser)[i][0].ToLong(j);
406 clientChoice->Append((*tableparser)[i][1], (void*)j);
413 else if (status == entered) {
414 if (jobChoice->GetStringSelection().Length() < 1) {
415 wxbMainFrame::GetInstance()->SetStatusText("Please select a client.");
418 WaitForEnd("restore\n");
420 WaitForEnd(wxString() << jobChoice->GetStringSelection() << "\n");
421 WaitForEnd(wxString() << *((long*)clientChoice->GetClientData(clientChoice->GetSelection())) << "\n");
422 WaitForEnd("unmark *\n");
424 wxTreeItemId root = tree->AddRoot(clientChoice->GetStringSelection(), -1, -1, new wxbTreeItemData("/", clientChoice->GetStringSelection(), 0));
426 UpdateTreeItem(root, true);
427 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.");
430 else if (status == choosing) {
431 SetStatus(configuring);
432 wxbMainFrame::GetInstance()->SetStatusText("Restoring, please wait...");
435 wxbDataTokenizer* dt;
437 dt = WaitForEnd("estimate\n", true);
441 for (unsigned int i = 0; i < dt->GetCount(); i++) {
442 /* 15847 total files; 1 marked to be restored; 1,034 bytes. */
443 if ((j = (*dt)[i].Find(" marked to be restored;")) > -1) {
444 k = (*dt)[i].Find("; ");
445 (*dt)[i].Mid(k+2, j).ToLong(&totfilemessages);
452 dt = WaitForEnd("done\n", true);
454 for (unsigned int i = 0; i < dt->GetCount(); i++) {
455 if ((j = (*dt)[i].Find(" files selected to be restored.")) > -1) {
456 (*dt)[i].Mid(0, j).ToLong(&totfilemessages);
460 if ((j = (*dt)[i].Find(" file selected to be restored.")) > -1) {
461 (*dt)[i].Mid(0, j).ToLong(&totfilemessages);
470 if (totfilemessages == 0) {
471 wxbMainFrame::GetInstance()->Print("Restore failed : no file selected.\n", CS_DEBUG);
472 wxbMainFrame::GetInstance()->SetStatusText("Restore failed : no file selected.");
477 else if (status == configuring) {
478 wxbDataTokenizer* dt;
480 SetStatus(restoring);
484 gauge->SetRange(totfilemessages);
486 wxString cmd = "list jobid=";
488 wxbTableParser* tableparser = CreateAndWaitForParser("list jobs\n");
489 /* TODO (#1#): Check more carefully which job we just have run. */
490 cmd << (*tableparser)[tableparser->size()-1][0] << "\n";
497 tableparser = CreateAndWaitForParser(cmd);
498 if ((*tableparser)[0][7] != "C") {
503 dt = WaitForEnd("messages\n", true);
505 for (unsigned int i = 0; i < dt->GetCount(); i++) {
506 wxStringTokenizer tkz((*dt)[i], " ", wxTOKEN_STRTOK);
510 // Date Time name: perm ? user grp size date time
511 //04-Apr-2004 17:19 Tom-fd: -rwx------ 1 nicolas None 514967 2004-03-20 20:03:42 filename
513 if (datetime.ParseDate(tkz.GetNextToken()) != NULL) { // Date
514 if (datetime.ParseTime(tkz.GetNextToken()) != NULL) { // Time
515 if (tkz.GetNextToken().Last() == ':') { // name:
516 tkz.GetNextToken(); // perm
517 tkz.GetNextToken(); // ?
518 tkz.GetNextToken(); // user
519 tkz.GetNextToken(); // grp
520 tkz.GetNextToken(); // size
521 if (datetime.ParseDate(tkz.GetNextToken()) != NULL) { //date
522 if (datetime.ParseTime(tkz.GetNextToken()) != NULL) { //time
524 //wxbMainFrame::GetInstance()->Print(wxString("(") << filemessages << ")", CS_DEBUG);
525 gauge->SetValue(filemessages);
535 wxbMainFrame::GetInstance()->SetStatusText(wxString("Restoring, please wait (") << filemessages << " of " << totfilemessages << " files done)...");
537 time_t start = wxDateTime::Now().GetTicks();
538 while (((wxDateTime::Now().GetTicks())-start) < 3) {
543 WaitForEnd("messages\n");
545 gauge->SetValue(totfilemessages);
547 if ((*tableparser)[0][7] == "T") {
548 wxbMainFrame::GetInstance()->Print("Restore done successfully.\n", CS_DEBUG);
549 wxbMainFrame::GetInstance()->SetStatusText("Restore done successfully.");
552 wxbMainFrame::GetInstance()->Print("Restore failed, please look at messages.\n", CS_DEBUG);
553 wxbMainFrame::GetInstance()->SetStatusText("Restore failed, please look at messages in console.");
560 /* Apply configuration changes */
562 /* 1: Level (not appropriate)
563 * 2: Storage (automatic ?)
567 * 6: When (yes : "Please enter desired start time as YYYY-MM-DD HH:MM:SS (return for now):")
568 * 7: Priority (yes : "Enter new Priority: (positive integer)")
570 * 9: Where (yes : "Please enter path prefix for restore (/ for none):")
571 * 10: Replace (yes : "Replace:\n 1: always\n 2: ifnewer\n 3: ifolder\n 4: never\n
572 * Select replace option (1-4):")
576 void wxbRestorePanel::CmdConfigApply() {
577 if (cfgUpdated == 0) return;
579 wxbDataTokenizer* dt = NULL;
580 while (cfgUpdated > 0) {
581 wxString def; //String to send if can't use our data
582 if ((cfgUpdated >> ConfigWhere) & 1) {
583 WaitForEnd("mod\n"); /* TODO: check results */
585 dt = WaitForEnd(cfgWhere->GetValue() + "\n", true);
587 cfgUpdated = cfgUpdated & (~(1 << ConfigWhere));
589 else if ((cfgUpdated >> ConfigReplace) & 1) {
590 WaitForEnd("mod\n"); /* TODO: check results */
592 dt = WaitForEnd(wxString() << (cfgReplace->GetSelection()+1) << "\n", true);
594 cfgUpdated = cfgUpdated & (~(1 << ConfigReplace));
596 else if ((cfgUpdated >> ConfigWhen) & 1) {
597 WaitForEnd("mod\n"); /* TODO: check results */
599 dt = WaitForEnd(cfgWhen->GetValue() + "\n", true);
601 cfgUpdated = cfgUpdated & (~(1 << ConfigWhen));
603 else if ((cfgUpdated >> ConfigPriority) & 1) {
604 WaitForEnd("mod\n"); /* TODO: check results */
606 dt = WaitForEnd(cfgPriority->GetValue() + "\n", true);
608 cfgUpdated = cfgUpdated & (~(1 << ConfigPriority));
616 for (i = 0; i < dt->GetCount(); i++) {
617 if ((*dt)[i].Find("Run Restore job")) {
622 if (i == (dt->GetCount()-1)) {
624 dt = WaitForEnd(def + "\n");
627 UpdateConfig(dt); /* TODO: Check result */
633 void wxbRestorePanel::CmdConfigCancel() {
635 wxbMainFrame::GetInstance()->Print("Restore cancelled.\n", CS_DEBUG);
636 wxbMainFrame::GetInstance()->SetStatusText("Restore cancelled.");
640 /* List jobs for a specified client */
641 void wxbRestorePanel::CmdListJobs() {
642 if (status == entered) {
644 WaitForEnd("query\n");
646 wxbTableParser* tableparser = CreateAndWaitForParser(clientChoice->GetString(clientChoice->GetSelection()) + "\n");
648 for (int i = tableparser->size()-1; i > -1; i--) {
649 wxString str = (*tableparser)[i][3];
652 if ( ( (chr = datetime.ParseDate(str.GetData()) ) != NULL ) && ( datetime.ParseTime(++chr) != NULL ) ) {
653 datetime = datetime.GetTicks() + 1;
654 //wxbMainFrame::GetInstance()->Print(wxString("-") << datetime.Format("%Y-%m-%d %H:%M:%S"), CS_DEBUG);
655 jobChoice->Append(datetime.Format("%Y-%m-%d %H:%M:%S"));
658 jobChoice->Append("Invalid");
664 jobChoice->SetSelection(0);
668 /* List files and directories for a specified tree item */
669 void wxbRestorePanel::CmdList(wxTreeItemId item) {
670 if (status == choosing) {
671 list->DeleteAllItems();
676 UpdateTreeItem(item, (tree->GetSelection() == item));
678 if (list->GetItemCount() > 1) {
679 int firstwidth = list->GetSize().GetWidth();
680 for (int i = 2; i < 7; i++) {
681 list->SetColumnWidth(i, wxLIST_AUTOSIZE);
682 firstwidth -= list->GetColumnWidth(i);
685 list->SetColumnWidth(0, 18);
687 list->SetColumnWidth(1, wxLIST_AUTOSIZE);
688 if (list->GetColumnWidth(1) < firstwidth) {
689 list->SetColumnWidth(1, firstwidth-20);
695 /* Mark a treeitem (directory) or a listitem (file or directory) */
696 void wxbRestorePanel::CmdMark(wxTreeItemId treeitem, long listitem) {
697 if (status == choosing) {
698 wxbTreeItemData* itemdata = NULL;
699 if (listitem != -1) {
700 itemdata = (wxbTreeItemData*)list->GetItemData(listitem);
702 else if (treeitem.IsOk()) {
703 itemdata = (wxbTreeItemData*)tree->GetItemData(treeitem);
709 if (itemdata == NULL) //Should never happen
712 wxString dir = itemdata->GetPath();
716 if (dir.GetChar(dir.Length()-1) == '/') {
720 int i = dir.Find('/', TRUE);
725 else { /* first dir below root */
727 dir = dir.Mid(0, i+1);
735 WaitForEnd(wxString("cd ") << dir << "\n");
736 WaitForEnd(wxString((itemdata->GetMarked() == 1) ? "unmark " : "mark ") << file << "\n");
738 /* TODO: Check commands results */
740 /*if ((dir == "/") && (file == "*")) {
741 itemdata->SetMarked((itemdata->GetMarked() == 1) ? 0 : 1);
744 if (listitem == -1) { /* tree item state changed */
745 SetTreeItemState(treeitem, (itemdata->GetMarked() == 1) ? 0 : 1);
746 /*treeitem = tree->GetSelection();
747 UpdateTree(treeitem, true);
748 treeitem = tree->GetItemParent(treeitem);*/
751 SetListItemState(listitem, (itemdata->GetMarked() == 1) ? 0 : 1);
752 /*UpdateTree(treeitem, (tree->GetSelection() == treeitem));
753 treeitem = tree->GetItemParent(treeitem);*/
756 /*while (treeitem.IsOk()) {
757 WaitForList(treeitem, false);
758 treeitem = tree->GetItemParent(treeitem);
763 /*----------------------------------------------------------------------------
765 ----------------------------------------------------------------------------*/
767 /* Parse a table in tableParser */
768 wxbTableParser* wxbRestorePanel::CreateAndWaitForParser(wxString cmd) {
769 wxbTableParser* tableParser = new wxbTableParser();
771 wxbMainFrame::GetInstance()->Send(cmd);
773 //time_t base = wxDateTime::Now().GetTicks();
774 while (!tableParser->hasFinished()) {
775 //innerThread->Yield();
777 //if (base+15 < wxDateTime::Now().GetTicks()) break;
782 /* Run a command, and waits until result is fully received. */
783 wxbDataTokenizer* wxbRestorePanel::WaitForEnd(wxString cmd, bool keepresults) {
784 wxbDataTokenizer* datatokenizer = new wxbDataTokenizer();
786 wxbMainFrame::GetInstance()->Send(cmd);
788 //wxbMainFrame::GetInstance()->Print("(<WFE)", CS_DEBUG);
790 //time_t base = wxDateTime::Now().GetTicks();
791 while (!datatokenizer->hasFinished()) {
792 //innerThread->Yield();
794 //if (base+15 < wxDateTime::Now().GetTicks()) break;
797 //wxbMainFrame::GetInstance()->Print("(>WFE)", CS_DEBUG);
800 return datatokenizer;
803 delete datatokenizer;
808 /* Run a dir command, and waits until result is fully received. */
809 void wxbRestorePanel::UpdateTreeItem(wxTreeItemId item, bool updatelist) {
810 // this->updatelist = updatelist;
811 currentTreeItem = item;
813 wxbDataTokenizer* dt;
815 dt = WaitForEnd(wxString("cd \"") <<
816 static_cast<wxbTreeItemData*>(tree->GetItemData(currentTreeItem))
817 ->GetPath() << "\"\n", false);
819 /* TODO: check command result */
826 list->DeleteAllItems();
827 dt = WaitForEnd("dir\n", true);
831 for (unsigned int i = 0; i < dt->GetCount(); i++) {
834 if (str.Find("cwd is:") == 0) { // Sometimes cd command result "infiltrate" into listings.
840 wxString* file = ParseList(str);
847 if (file[8].GetChar(file[8].Length()-1) == '/') {
851 treeid = tree->GetFirstChild(currentTreeItem, cookie);
853 bool updated = false;
855 while (treeid.IsOk()) {
856 itemStr = tree->GetItemText(treeid);
857 if (file[8] == itemStr) {
858 int stat = wxbTreeItemData::GetMarkedStatus(file[6]);
859 if (static_cast<wxbTreeItemData*>(tree->GetItemData(treeid))->GetMarked() != stat) {
860 tree->SetItemImage(treeid, stat, wxTreeItemIcon_Normal);
861 tree->SetItemImage(treeid, stat, wxTreeItemIcon_Selected);
862 static_cast<wxbTreeItemData*>(tree->GetItemData(treeid))->SetMarked(file[6]);
867 treeid = tree->GetNextChild(currentTreeItem, cookie);
871 int img = wxbTreeItemData::GetMarkedStatus(file[6]);
872 treeid = tree->AppendItem(currentTreeItem, file[8], img, img, new wxbTreeItemData(file[7], file[8], file[6]));
877 long ind = list->InsertItem(list->GetItemCount(), wxbTreeItemData::GetMarkedStatus(file[6]));
878 wxbTreeItemData* data = new wxbTreeItemData(file[7], file[8], file[6], ind);
880 list->SetItemData(ind, (long)data);
881 list->SetItem(ind, 1, file[8]); // filename
882 list->SetItem(ind, 2, file[4]); //Size
883 list->SetItem(ind, 3, file[5]); //date
884 list->SetItem(ind, 4, file[0]); //perm
885 list->SetItem(ind, 5, file[2]); //user
886 list->SetItem(ind, 6, file[3]); //grp
898 /* Parse dir command results. */
899 wxString* wxbRestorePanel::ParseList(wxString line) {
900 //drwx------ 11 1003 42949672 0 2001-07-30 16:45:14 *filename
901 //+ 10 ++ 4++ 10 ++ 8 ++ 8 + + 19 + *+ ->
902 //0 10 14 24 32 42 62
904 if (line.Length() < 63)
907 wxString* ret = new wxString[9];
909 ret[0] = line.Mid(0, 10).Trim();
910 ret[1] = line.Mid(10, 4).Trim();
911 ret[2] = line.Mid(14, 10).Trim();
912 ret[3] = line.Mid(24, 8).Trim();
913 ret[4] = line.Mid(32, 8).Trim();
914 ret[5] = line.Mid(42, 19).Trim();
915 ret[6] = line.Mid(62, 1);
916 ret[7] = line.Mid(63).Trim();
918 if (ret[6] == " ") ret[6] = "";
920 if (ret[7].GetChar(ret[7].Length()-1) == '/') {
923 ret[8] = ret[7].Mid(ret[8].Find('/', true)+1);
926 ret[8] = ret[7].Mid(ret[7].Find('/', true)+1);
932 /* Sets a list item state, and update its parents and children if it is a directory */
933 void wxbRestorePanel::SetListItemState(long listitem, int newstate) {
934 wxbTreeItemData* itemdata = (wxbTreeItemData*)list->GetItemData(listitem);
936 wxTreeItemId treeitem;
938 itemdata->SetMarked(newstate);
939 list->SetItemImage(listitem, newstate, 0); /* TODO: Find what these ints are for */
940 list->SetItemImage(listitem, newstate, 1);
942 if ((treeitem = itemdata->GetId()).IsOk()) {
943 SetTreeItemState(treeitem, newstate);
946 UpdateTreeItemState(tree->GetSelection());
950 /* Sets a tree item state, and update its children, parents and list (if necessary) */
951 void wxbRestorePanel::SetTreeItemState(wxTreeItemId item, int newstate) {
953 wxTreeItemId currentChild = tree->GetFirstChild(item, cookie);
955 wxbTreeItemData* itemdata;
957 while (currentChild.IsOk()) {
958 itemdata = (wxbTreeItemData*)tree->GetItemData(currentChild);
959 int state = itemdata->GetMarked();
961 if (state != newstate) {
962 itemdata->SetMarked(newstate);
963 tree->SetItemImage(currentChild, newstate, wxTreeItemIcon_Normal);
964 tree->SetItemImage(currentChild, newstate, wxTreeItemIcon_Selected);
967 currentChild = tree->GetNextChild(item, cookie);
970 itemdata = (wxbTreeItemData*)tree->GetItemData(item);
971 itemdata->SetMarked(newstate);
972 tree->SetItemImage(item, newstate, wxTreeItemIcon_Normal);
973 tree->SetItemImage(item, newstate, wxTreeItemIcon_Selected);
976 if (tree->GetSelection() == item) {
977 for (long i = 0; i < list->GetItemCount(); i++) {
978 list->SetItemImage(i, newstate, 0); /* TODO: Find what these ints are for */
979 list->SetItemImage(i, newstate, 1);
983 UpdateTreeItemState(tree->GetParent(item));
986 /* Update a tree item state, and its parents' state */
987 void wxbRestorePanel::UpdateTreeItemState(wxTreeItemId item) {
995 wxTreeItemId currentChild = tree->GetFirstChild(item, cookie);
997 bool onechildmarked = false;
998 bool onechildunmarked = false;
1000 while (currentChild.IsOk()) {
1001 state = ((wxbTreeItemData*)tree->GetItemData(currentChild))->GetMarked();
1004 onechildunmarked = true;
1007 onechildmarked = true;
1010 onechildmarked = true;
1011 onechildunmarked = true;
1015 if (onechildmarked && onechildunmarked) {
1019 currentChild = tree->GetNextChild(item, cookie);
1022 if (tree->GetSelection() == item) {
1023 for (long i = 0; i < list->GetItemCount(); i++) {
1024 state = ((wxbTreeItemData*)list->GetItemData(i))->GetMarked();
1028 onechildunmarked = true;
1031 onechildmarked = true;
1034 onechildmarked = true;
1035 onechildunmarked = true;
1039 if (onechildmarked && onechildunmarked) {
1047 if (onechildmarked && onechildunmarked) {
1050 else if (onechildmarked) {
1053 else if (onechildunmarked) {
1056 else { // no child, don't change anything
1057 UpdateTreeItemState(tree->GetParent(item));
1061 wxbTreeItemData* itemdata = (wxbTreeItemData*)tree->GetItemData(item);
1063 itemdata->SetMarked(state);
1064 tree->SetItemImage(item, state, wxTreeItemIcon_Normal);
1065 tree->SetItemImage(item, state, wxTreeItemIcon_Selected);
1067 UpdateTreeItemState(tree->GetParent(item));
1071 * Refresh a tree item, and all its childs,
1072 * by asking the director for new lists
1074 void wxbRestorePanel::RefreshTree(wxTreeItemId item) {
1075 /* UpdateTreeItem(item, updatelist);*/
1077 /* Update all child which are not collapsed */
1079 wxTreeItemId currentChild = tree->GetFirstChild(item, cookie);
1081 while (currentChild.IsOk()) {
1082 if (tree->IsExpanded(currentChild))
1083 UpdateTree(currentChild, false);
1085 currentChild = tree->GetNextChild(item, cookie);
1093 * JobName: RestoreFiles
1094 * Bootstrap: /var/lib/bacula/restore.bsr
1095 * Where: /tmp/bacula-restores
1100 * When: 2004-04-18 01:18:56
1102 * OK to run? (yes/mod/no):
1105 bool wxbRestorePanel::UpdateConfig(wxbDataTokenizer* dt) {
1107 for (i = 0; i < dt->GetCount(); i++) {
1108 if ((*dt)[i].Find("Run Restore job") == 0)
1112 if ((i + 10) > dt->GetCount()) {
1118 if ((k = (*dt)[++i].Find("JobName:")) != 0) return false;
1119 cfgJobname->SetLabel((*dt)[i].Mid(10).Trim(false).RemoveLast());
1120 if ((k = (*dt)[++i].Find("Bootstrap:")) != 0) return false;
1121 cfgBootstrap->SetLabel((*dt)[i].Mid(10).Trim(false).RemoveLast());
1122 if ((k = (*dt)[++i].Find("Where:")) != 0) return false;
1123 cfgWhere->SetValue((*dt)[i].Mid(10).Trim(false).RemoveLast());
1125 if ((k = (*dt)[++i].Find("Replace:")) != 0) return false;
1126 wxString str = (*dt)[i].Mid(10).Trim(false).RemoveLast();
1127 if (str == "always") cfgReplace->SetSelection(0);
1128 else if (str == "ifnewer") cfgReplace->SetSelection(1);
1129 else if (str == "ifolder") cfgReplace->SetSelection(2);
1130 else if (str == "never") cfgReplace->SetSelection(3);
1131 else cfgReplace->SetSelection(0);
1133 if ((k = (*dt)[++i].Find("FileSet:")) != 0) return false;
1134 cfgFileset->SetLabel((*dt)[i].Mid(10).Trim(false).RemoveLast());
1135 if ((k = (*dt)[++i].Find("Client:")) != 0) return false;
1136 cfgClient->SetLabel((*dt)[i].Mid(10).Trim(false).RemoveLast());
1137 if ((k = (*dt)[++i].Find("Storage:")) != 0) return false;
1138 cfgStorage->SetLabel((*dt)[i].Mid(10).Trim(false).RemoveLast());
1139 if ((k = (*dt)[++i].Find("When:")) != 0) return false;
1140 cfgWhen->SetValue((*dt)[i].Mid(10).Trim(false).RemoveLast());
1141 if ((k = (*dt)[++i].Find("Priority:")) != 0) return false;
1142 cfgPriority->SetValue((*dt)[i].Mid(10).Trim(false).RemoveLast());
1145 restorePanel->Layout();
1150 /*----------------------------------------------------------------------------
1152 ----------------------------------------------------------------------------*/
1154 /* Set current status by enabling/disabling components */
1155 void wxbRestorePanel::SetStatus(status_enum newstatus) {
1156 switch (newstatus) {
1158 centerSizer->Remove(restorePanel);
1159 centerSizer->Remove(treelistPanel);
1160 restorePanel->Show(false);
1161 centerSizer->Add(treelistPanel, 1, wxEXPAND);
1162 treelistPanel->Show(true);
1163 centerSizer->Layout();
1164 start->SetLabel("Enter restore mode");
1165 start->Enable(false);
1166 clientChoice->Enable(false);
1167 jobChoice->Enable(false);
1168 tree->Enable(false);
1169 list->Enable(false);
1170 gauge->Enable(false);
1173 centerSizer->Remove(restorePanel);
1174 restorePanel->Show(false);
1175 centerSizer->Add(treelistPanel, 1, wxEXPAND);
1176 treelistPanel->Show(true);
1177 centerSizer->Layout();
1178 tree->DeleteAllItems();
1179 list->DeleteAllItems();
1180 clientChoice->Clear();
1182 wxbMainFrame::GetInstance()->EnablePanels();
1183 newstatus = activable;
1185 start->SetLabel("Enter restore mode");
1186 start->Enable(true);
1187 clientChoice->Enable(false);
1188 jobChoice->Enable(false);
1189 tree->Enable(false);
1190 list->Enable(false);
1191 gauge->Enable(false);
1194 wxbMainFrame::GetInstance()->DisablePanels(this);
1196 start->SetLabel("Choose files to restore");
1197 clientChoice->Enable(true);
1198 jobChoice->Enable(true);
1199 tree->Enable(false);
1200 list->Enable(false);
1206 start->SetLabel("Restore");
1207 clientChoice->Enable(false);
1208 jobChoice->Enable(false);
1214 start->Enable(false);
1215 clientChoice->Enable(false);
1216 jobChoice->Enable(false);
1217 tree->Enable(false);
1218 list->Enable(false);
1219 centerSizer->Remove(treelistPanel);
1220 treelistPanel->Show(false);
1221 centerSizer->Add(restorePanel, 1, wxEXPAND);
1222 restorePanel->Show(true);
1223 restorePanel->Layout();
1224 centerSizer->Layout();
1225 cfgApply->Enable(false);
1226 cfgOk->Enable(true);
1229 start->SetLabel("Restoring...");
1230 gauge->Enable(true);
1232 start->Enable(false);
1233 clientChoice->Enable(false);
1234 jobChoice->Enable(false);
1235 tree->Enable(false);
1236 list->Enable(false);
1243 /*----------------------------------------------------------------------------
1245 ----------------------------------------------------------------------------*/
1247 void wxbRestorePanel::OnClientChoiceChanged(wxCommandEvent& event) {
1252 clientChoice->Enable(false);
1254 clientChoice->Enable(true);
1255 jobChoice->Refresh();
1259 void wxbRestorePanel::OnStart(wxEvent& WXUNUSED(event)) {
1268 void wxbRestorePanel::OnTreeChanging(wxTreeEvent& event) {
1274 void wxbRestorePanel::OnTreeExpanding(wxTreeEvent& event) {
1280 //CmdList(event.GetItem());
1281 if (tree->GetSelection() != event.GetItem()) {
1282 tree->SelectItem(event.GetItem());
1287 void wxbRestorePanel::OnTreeChanged(wxTreeEvent& event) {
1293 CmdList(event.GetItem());
1297 void wxbRestorePanel::OnTreeMarked(wxbTreeMarkedEvent& event) {
1303 CmdMark(event.GetItem(), -1);
1309 void wxbRestorePanel::OnListMarked(wxbListMarkedEvent& event) {
1315 //long item = event.GetId();
1316 long item = list->GetNextItem(-1, wxLIST_NEXT_ALL, wxLIST_STATE_FOCUSED);
1317 CmdMark(wxTreeItemId(), item);
1323 void wxbRestorePanel::OnListActivated(wxListEvent& event) {
1329 long item = list->GetNextItem(-1, wxLIST_NEXT_ALL, wxLIST_STATE_FOCUSED);
1331 wxbTreeItemData* itemdata = (wxbTreeItemData*)list->GetItemData(item);
1332 wxString name = itemdata->GetName();
1339 if (name.GetChar(name.Length()-1) == '/') {
1340 wxTreeItemId currentChild = tree->GetFirstChild(currentTreeItem, cookie);
1342 while (currentChild.IsOk()) {
1343 wxString name2 = tree->GetItemText(currentChild);
1344 if (name2 == name) {
1345 //tree->UnselectAll();
1347 tree->Expand(currentTreeItem);
1348 tree->SelectItem(currentChild);
1352 currentChild = tree->GetNextChild(currentTreeItem, cookie);
1359 void wxbRestorePanel::OnConfigUpdated(wxCommandEvent& event) {
1360 cfgApply->Enable(true);
1361 cfgOk->Enable(false);
1362 cfgUpdated = cfgUpdated | (1 << event.GetId());
1365 void wxbRestorePanel::OnConfigOk(wxEvent& WXUNUSED(event)) {
1374 void wxbRestorePanel::OnConfigApply(wxEvent& WXUNUSED(event)) {
1380 if (cfgUpdated == 0) {
1381 cfgApply->Enable(false);
1382 cfgOk->Enable(true);
1387 void wxbRestorePanel::OnConfigCancel(wxEvent& WXUNUSED(event)) {
1396 /* TODO : correct that bad implementation of tree marked event forwarding */
1398 wxbTreeListPanel::wxbTreeListPanel(wxbRestorePanel* parent): wxPanel(parent, -1) {
1399 this->parent = parent;
1402 void wxbTreeListPanel::OnTreeMarked(wxbTreeMarkedEvent& event) {
1403 parent->OnTreeMarked(event);
1406 void wxbTreeListPanel::OnListMarked(wxbListMarkedEvent& event) {
1407 parent->OnListMarked(event);