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 ?)
35 5: Client (yes : "The defined Client resources are:\n\t1: velours-fd\n\t2: tom-fd\nSelect Client (File daemon) resource (1-2):")
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 // ----------------------------------------------------------------------------
179 BEGIN_EVENT_TABLE(wxbRestorePanel, wxPanel)
180 EVT_BUTTON(RestoreStart, wxbRestorePanel::OnStart)
181 EVT_CHOICE(ClientChoice, wxbRestorePanel::OnClientChoiceChanged)
183 EVT_TREE_SEL_CHANGING(TreeCtrl, wxbRestorePanel::OnTreeChanging)
184 EVT_TREE_SEL_CHANGED(TreeCtrl, wxbRestorePanel::OnTreeChanged)
185 EVT_TREE_ITEM_EXPANDING(TreeCtrl, wxbRestorePanel::OnTreeExpanding)
186 EVT_LIST_ITEM_ACTIVATED(ListCtrl, wxbRestorePanel::OnListActivated)
188 /*EVT_TREE_MARKED_EVENT(wxID_ANY, wxbRestorePanel::OnTreeMarked)
189 EVT_LIST_MARKED_EVENT(wxID_ANY, wxbRestorePanel::OnListMarked)*/
191 EVT_TEXT(ConfigWhere, wxbRestorePanel::OnConfigUpdated)
192 EVT_TEXT(ConfigWhen, wxbRestorePanel::OnConfigUpdated)
193 EVT_TEXT(ConfigPriority, wxbRestorePanel::OnConfigUpdated)
194 EVT_CHOICE(ConfigReplace, wxbRestorePanel::OnConfigUpdated)
195 EVT_CHOICE(ConfigClient, wxbRestorePanel::OnConfigUpdated)
196 EVT_CHOICE(ConfigFileset, wxbRestorePanel::OnConfigUpdated)
198 EVT_BUTTON(ConfigOk, wxbRestorePanel::OnConfigOk)
199 EVT_BUTTON(ConfigApply, wxbRestorePanel::OnConfigApply)
200 EVT_BUTTON(ConfigCancel, wxbRestorePanel::OnConfigCancel)
203 BEGIN_EVENT_TABLE(wxbTreeListPanel, wxPanel)
204 EVT_TREE_MARKED_EVENT(wxID_ANY, wxbTreeListPanel::OnTreeMarked)
205 EVT_LIST_MARKED_EVENT(wxID_ANY, wxbTreeListPanel::OnListMarked)
209 * wxbRestorePanel constructor
211 wxbRestorePanel::wxbRestorePanel(wxWindow* parent): wxbPanel(parent) {
212 imagelist = new wxImageList(16, 16, TRUE, 3);
213 imagelist->Add(wxIcon(unmarked_xpm));
214 imagelist->Add(wxIcon(marked_xpm));
215 imagelist->Add(wxIcon(partmarked_xpm));
217 wxFlexGridSizer* mainSizer = new wxFlexGridSizer(3, 1, 10, 10);
218 mainSizer->AddGrowableCol(0);
219 mainSizer->AddGrowableRow(1);
221 wxBoxSizer *firstSizer = new wxBoxSizer(wxHORIZONTAL);
223 start = new wxButton(this, RestoreStart, "Enter restore mode", wxDefaultPosition, wxSize(150, 30));
224 firstSizer->Add(start, 1, wxALIGN_CENTER_HORIZONTAL | wxALIGN_CENTER_VERTICAL, 10);
228 clientChoice = new wxChoice(this, ClientChoice, wxDefaultPosition, wxSize(150, 30), 0, elist);
229 firstSizer->Add(clientChoice, 1, wxALIGN_CENTER_HORIZONTAL | wxALIGN_CENTER_VERTICAL, 10);
231 jobChoice = new wxChoice(this, -1, wxDefaultPosition, wxSize(150, 30), 0, elist);
232 firstSizer->Add(jobChoice, 1, wxALIGN_CENTER_HORIZONTAL | wxALIGN_CENTER_VERTICAL, 10);
234 mainSizer->Add(firstSizer, 1, wxALIGN_CENTER_HORIZONTAL | wxALIGN_CENTER_VERTICAL, 10);
236 treelistPanel = new wxbTreeListPanel(this);
238 wxFlexGridSizer* treelistSizer = new wxFlexGridSizer(1, 2, 10, 10);
240 tree = new wxbTreeCtrl(treelistPanel, TreeCtrl, wxDefaultPosition, wxSize(200,50));
241 treelistSizer->Add(tree, 1, wxALIGN_CENTER_HORIZONTAL | wxALIGN_CENTER_VERTICAL | wxEXPAND, 10);
243 tree->SetImageList(imagelist);
245 list = new wxbListCtrl(treelistPanel, ListCtrl, wxDefaultPosition, wxDefaultSize);
246 treelistSizer->Add(list, 1, wxALIGN_CENTER_HORIZONTAL | wxALIGN_CENTER_VERTICAL | wxEXPAND, 10);
248 list->SetImageList(imagelist, wxIMAGE_LIST_SMALL);
251 info.SetMask(wxLIST_MASK_TEXT | wxLIST_MASK_FORMAT);
253 info.SetAlign(wxLIST_FORMAT_CENTER);
254 list->InsertColumn(0, info);
256 info.SetText("Filename");
257 info.SetAlign(wxLIST_FORMAT_LEFT);
258 list->InsertColumn(1, info);
260 info.SetText("Size");
261 info.SetAlign(wxLIST_FORMAT_RIGHT);
262 list->InsertColumn(2, info);
264 info.SetText("Date");
265 info.SetAlign(wxLIST_FORMAT_LEFT);
266 list->InsertColumn(3, info);
268 info.SetText("Perm.");
269 info.SetAlign(wxLIST_FORMAT_LEFT);
270 list->InsertColumn(4, info);
272 info.SetText("User");
273 info.SetAlign(wxLIST_FORMAT_RIGHT);
274 list->InsertColumn(5, info);
276 info.SetText("Group");
277 info.SetAlign(wxLIST_FORMAT_RIGHT);
278 list->InsertColumn(6, info);
280 treelistSizer->AddGrowableCol(1);
281 treelistSizer->AddGrowableRow(0);
283 treelistPanel->SetSizer(treelistSizer);
284 treelistSizer->SetSizeHints(treelistPanel);
286 restorePanel = new wxPanel(this, -1);
288 wxBoxSizer* restoreSizer = new wxBoxSizer(wxVERTICAL);
290 wxFlexGridSizer* cfgSizer = new wxFlexGridSizer(9, 2, 8, 5);
292 cfgJobname = new wxStaticText(restorePanel, -1, " ", wxDefaultPosition, wxDefaultSize, wxALIGN_LEFT);
293 cfgBootstrap = new wxStaticText(restorePanel, -1, " ", wxDefaultPosition, wxDefaultSize, wxALIGN_LEFT);
294 cfgWhere = new wxTextCtrl(restorePanel, ConfigWhere, "", wxDefaultPosition, wxDefaultSize);
295 wxString erlist[] = {"always", "if newer", "if older", "never"};
296 cfgReplace = new wxChoice(restorePanel, ConfigReplace, wxDefaultPosition, wxDefaultSize, 4, erlist);
297 cfgFileset = new wxChoice(restorePanel, ConfigFileset, wxDefaultPosition, wxDefaultSize, 0, elist);
298 cfgClient = new wxChoice(restorePanel, ConfigClient, wxDefaultPosition, wxDefaultSize, 0, elist);
299 cfgStorage = new wxStaticText(restorePanel, -1, " ", wxDefaultPosition, wxDefaultSize, wxALIGN_LEFT);
300 cfgWhen = new wxTextCtrl(restorePanel, ConfigWhen, "0000-00-00 00:00:00", wxDefaultPosition, wxDefaultSize);
301 cfgPriority = new wxTextCtrl(restorePanel, ConfigPriority, "", wxDefaultPosition, wxDefaultSize);
303 cfgSizer->Add(new wxStaticText(restorePanel, -1, "Job Name: ", wxDefaultPosition, wxDefaultSize, wxALIGN_RIGHT), 1, wxEXPAND | wxALIGN_CENTER_HORIZONTAL);
304 cfgSizer->Add(cfgJobname, 1, wxEXPAND | wxADJUST_MINSIZE);
305 cfgSizer->Add(new wxStaticText(restorePanel, -1, "Bootstrap: ", wxDefaultPosition, wxDefaultSize, wxALIGN_RIGHT), 1, wxEXPAND | wxALIGN_CENTER_HORIZONTAL);
306 cfgSizer->Add(cfgBootstrap, 1, wxEXPAND | wxADJUST_MINSIZE);
307 cfgSizer->Add(new wxStaticText(restorePanel, -1, "Where: ", wxDefaultPosition, wxDefaultSize, wxALIGN_RIGHT), 1, wxEXPAND | wxALIGN_CENTER_HORIZONTAL);
308 cfgSizer->Add(cfgWhere, 1, wxEXPAND | wxADJUST_MINSIZE);
309 cfgSizer->Add(new wxStaticText(restorePanel, -1, "Replace: ", wxDefaultPosition, wxDefaultSize, wxALIGN_RIGHT), 1, wxEXPAND | wxALIGN_CENTER_HORIZONTAL);
310 cfgSizer->Add(cfgReplace, 1, wxEXPAND);
311 cfgSizer->Add(new wxStaticText(restorePanel, -1, "Fileset: ", wxDefaultPosition, wxDefaultSize, wxALIGN_RIGHT), 1, wxEXPAND | wxALIGN_CENTER_HORIZONTAL);
312 cfgSizer->Add(cfgFileset, 1, wxEXPAND);
313 cfgSizer->Add(new wxStaticText(restorePanel, -1, "Client: ", wxDefaultPosition, wxDefaultSize, wxALIGN_RIGHT), 1, wxEXPAND | wxALIGN_CENTER_HORIZONTAL);
314 cfgSizer->Add(cfgClient, 1, wxEXPAND);
315 cfgSizer->Add(new wxStaticText(restorePanel, -1, "Storage: ", wxDefaultPosition, wxDefaultSize, wxALIGN_RIGHT), 1, wxEXPAND | wxALIGN_CENTER_HORIZONTAL);
316 cfgSizer->Add(cfgStorage, 1, wxEXPAND | wxADJUST_MINSIZE);
317 cfgSizer->Add(new wxStaticText(restorePanel, -1, "When: ", wxDefaultPosition, wxDefaultSize, wxALIGN_RIGHT), 1, wxEXPAND | wxALIGN_CENTER_HORIZONTAL);
318 cfgSizer->Add(cfgWhen, 1, wxEXPAND | wxADJUST_MINSIZE);
319 cfgSizer->Add(new wxStaticText(restorePanel, -1, "Priority: ", wxDefaultPosition, wxDefaultSize, wxALIGN_RIGHT), 1, wxEXPAND | wxALIGN_CENTER_HORIZONTAL);
320 cfgSizer->Add(cfgPriority, 1, wxEXPAND | wxADJUST_MINSIZE);
322 //cfgSizer->SetMinSize(400, 400);
324 restoreSizer->Add(cfgSizer, 1, wxALIGN_CENTER_HORIZONTAL | wxALIGN_CENTER_VERTICAL | wxALL, 5);
326 wxBoxSizer* restoreBottomSizer = new wxBoxSizer(wxHORIZONTAL);
328 cfgOk = new wxButton(restorePanel, ConfigOk, "OK", wxDefaultPosition, wxSize(70, 25));
329 restoreBottomSizer->Add(cfgOk, 1, wxALIGN_CENTER_VERTICAL | wxRIGHT, 10);
331 cfgApply = new wxButton(restorePanel, ConfigApply, "Apply", wxDefaultPosition, wxSize(70, 25));
332 restoreBottomSizer->Add(cfgApply, 1, wxALIGN_CENTER_VERTICAL | wxLEFT | wxRIGHT, 10);
334 cfgCancel = new wxButton(restorePanel, ConfigCancel, "Cancel", wxDefaultPosition, wxSize(70, 25));
335 restoreBottomSizer->Add(cfgCancel, 1, wxALIGN_CENTER_VERTICAL | wxLEFT, 10);
337 restoreSizer->Add(restoreBottomSizer, 0, wxALIGN_CENTER_HORIZONTAL | wxALIGN_CENTER_VERTICAL | wxALL, 5);
339 restorePanel->SetSizer(restoreSizer);
340 restoreSizer->SetSizeHints(restorePanel);
342 restorePanel->Show(false);
344 centerSizer = new wxBoxSizer(wxHORIZONTAL);
345 centerSizer->Add(treelistPanel, 1, wxEXPAND | wxADJUST_MINSIZE);
347 mainSizer->Add(centerSizer, 1, wxEXPAND, 10);
349 gauge = new wxGauge(this, -1, 1, wxDefaultPosition, wxSize(200,20));
351 mainSizer->Add(gauge, 1, wxEXPAND, 5);
353 gauge->Enable(false);
356 mainSizer->SetSizeHints(this);
360 jobChoice->Enable(false);
362 for (int i = 0; i < 7; i++) {
363 list->SetColumnWidth(i, 70);
367 SetCursor(*wxSTANDARD_CURSOR);
371 * wxbRestorePanel destructor
373 wxbRestorePanel::~wxbRestorePanel() {
377 /*----------------------------------------------------------------------------
378 wxbPanel overloadings
379 ----------------------------------------------------------------------------*/
381 wxString wxbRestorePanel::GetTitle() {
385 void wxbRestorePanel::EnablePanel(bool enable) {
387 if (status == disabled) {
388 SetStatus(activable);
396 /*----------------------------------------------------------------------------
397 Commands called by events handler
398 ----------------------------------------------------------------------------*/
400 /* The main button has been clicked */
401 void wxbRestorePanel::CmdStart() {
402 if (status == activable) {
403 wxbDataTokenizer* dt = WaitForEnd(".clients\n", true, false);
406 clientChoice->Clear();
408 for (unsigned int i = 0; i < dt->GetCount(); i++) {
411 clientChoice->Append(str);
412 cfgClient->Append(str);
417 dt = WaitForEnd(".filesets\n", true, false);
420 for (unsigned int i = 0; i < dt->GetCount(); i++) {
423 cfgFileset->Append(str);
430 else if (status == entered) {
431 if (jobChoice->GetStringSelection().Length() < 1) {
432 wxbMainFrame::GetInstance()->SetStatusText("Please select a client.");
435 WaitForPrompt("restore\n");
436 WaitForPrompt("6\n");
437 wxbPromptParser *pp = WaitForPrompt(wxString() << jobChoice->GetStringSelection() << "\n", true);
438 int client = pp->getChoices()->Index(clientChoice->GetStringSelection());
439 if (client == wxNOT_FOUND) {
440 wxbMainFrame::GetInstance()->SetStatusText("Failed to find the selected client.");
445 wxbDataTokenizer* dt = new wxbDataTokenizer(true);
446 wxbTableParser* tableparser = CreateAndWaitForParser(wxString() << client << "\n");
452 for (i = 0; i < tableparser->size(); i++) {
453 str = (*tableparser)[i][2];
454 str.Replace(",", "");
455 if (str.ToLong(&l)) {
461 gauge->SetRange(tot);
463 /*wxbMainFrame::GetInstance()->Print(
464 wxString("[") << tot << "]", CS_DEBUG);*/
466 wxDateTime base = wxDateTime::Now();
470 unsigned int lastindex = 0;
474 while (!dt->hasFinished()) {
475 newdate = wxDateTime::Now();
476 if ( ( (1000*(newdate.GetTicks()-base.GetTicks())) +
477 (newdate.GetMillisecond()-base.GetMillisecond()) ) > 10 ) {
479 for (; lastindex < dt->GetCount(); lastindex++) {
480 if (((*dt)[lastindex].Find("Building directory tree for JobId ") == 0) &&
481 ((i = (*dt)[lastindex].Find(" ...")) > 0)) {
482 str = (*dt)[lastindex].Mid(34, i-34);
483 for (unsigned int i = 0; i < tableparser->size(); i++) {
484 if (str == (*tableparser)[i][0]) {
485 str = (*tableparser)[i][2];
486 str.Replace(",", "");
487 if (str.ToLong(&l)) {
490 var = (willdo-done)/3;
498 if (gauge->GetValue() <= done) {
499 gauge->SetValue(done);
503 else if (gauge->GetValue() >= willdo) {
504 gauge->SetValue(willdo);
509 gauge->SetValue(gauge->GetValue()+var);
511 /*wxbMainFrame::GetInstance()->Print(
512 wxString("[") << gauge->GetValue() << "/" << done
513 << "-" << willdo << "]", CS_DEBUG);*/
515 wxTheApp->Yield(true);
522 WaitForEnd("unmark *\n");
524 wxTreeItemId root = tree->AddRoot(clientChoice->GetStringSelection(), -1, -1, new wxbTreeItemData("/", clientChoice->GetStringSelection(), 0));
526 UpdateTreeItem(root, true);
527 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.");
530 else if (status == choosing) {
531 SetStatus(configuring);
533 wxbMainFrame::GetInstance()->SetStatusText("Please configure your restore...");
538 wxbDataTokenizer* dt;
542 dt = new wxbDataTokenizer(true);
543 WaitForPrompt("done\n");
545 for (unsigned int i = 0; i < dt->GetCount(); i++) {
546 if ((j = (*dt)[i].Find(" files selected to be restored.")) > -1) {
547 (*dt)[i].Mid(0, j).ToLong(&totfilemessages);
551 if ((j = (*dt)[i].Find(" file selected to be restored.")) > -1) {
552 (*dt)[i].Mid(0, j).ToLong(&totfilemessages);
563 if (totfilemessages == 0) {
564 wxbMainFrame::GetInstance()->Print("Restore failed : no file selected.\n", CS_DEBUG);
565 wxbMainFrame::GetInstance()->SetStatusText("Restore failed : no file selected.");
570 else if (status == configuring) {
572 cfgOk->Enable(false);
573 cfgApply->Enable(false);
574 cfgCancel->Enable(false);
576 wxbMainFrame::GetInstance()->SetStatusText("Restoring, please wait...");
578 wxbDataTokenizer* dt;
580 SetStatus(restoring);
584 gauge->SetRange(totfilemessages);
586 wxString cmd = "list jobid=";
588 wxbTableParser* tableparser = CreateAndWaitForParser("list jobs\n");
589 /* TODO (#1#): Check more carefully which job we just have run. */
590 cmd << (*tableparser)[tableparser->size()-1][0] << "\n";
597 tableparser = CreateAndWaitForParser(cmd);
598 if ((*tableparser)[0][7] != "C") {
603 dt = WaitForEnd("messages\n", true);
605 for (unsigned int i = 0; i < dt->GetCount(); i++) {
606 wxStringTokenizer tkz((*dt)[i], " ", wxTOKEN_STRTOK);
610 // Date Time name: perm ? user grp size date time
611 //04-Apr-2004 17:19 Tom-fd: -rwx------ 1 nicolas None 514967 2004-03-20 20:03:42 filename
613 if (datetime.ParseDate(tkz.GetNextToken()) != NULL) { // Date
614 if (datetime.ParseTime(tkz.GetNextToken()) != NULL) { // Time
615 if (tkz.GetNextToken().Last() == ':') { // name:
616 tkz.GetNextToken(); // perm
617 tkz.GetNextToken(); // ?
618 tkz.GetNextToken(); // user
619 tkz.GetNextToken(); // grp
620 tkz.GetNextToken(); // size
621 if (datetime.ParseDate(tkz.GetNextToken()) != NULL) { //date
622 if (datetime.ParseTime(tkz.GetNextToken()) != NULL) { //time
624 //wxbMainFrame::GetInstance()->Print(wxString("(") << filemessages << ")", CS_DEBUG);
625 gauge->SetValue(filemessages);
635 wxbMainFrame::GetInstance()->SetStatusText(wxString("Restoring, please wait (") << filemessages << " of " << totfilemessages << " files done)...");
637 time_t start = wxDateTime::Now().GetTicks();
638 while (((wxDateTime::Now().GetTicks())-start) < 3) {
643 WaitForEnd("messages\n");
645 gauge->SetValue(totfilemessages);
647 if ((*tableparser)[0][7] == "T") {
648 wxbMainFrame::GetInstance()->Print("Restore done successfully.\n", CS_DEBUG);
649 wxbMainFrame::GetInstance()->SetStatusText("Restore done successfully.");
652 wxbMainFrame::GetInstance()->Print("Restore failed, please look at messages.\n", CS_DEBUG);
653 wxbMainFrame::GetInstance()->SetStatusText("Restore failed, please look at messages in console.");
660 /* Apply configuration changes */
662 /* 1: Level (not appropriate)
663 * 2: Storage (automatic ?)
667 * 6: When (yes : "Please enter desired start time as YYYY-MM-DD HH:MM:SS (return for now):")
668 * 7: Priority (yes : "Enter new Priority: (positive integer)")
670 * 9: Where (yes : "Please enter path prefix for restore (/ for none):")
671 * 10: Replace (yes : "Replace:\n 1: always\n 2: ifnewer\n 3: ifolder\n 4: never\n
672 * Select replace option (1-4):")
676 void wxbRestorePanel::CmdConfigApply() {
677 if (cfgUpdated == 0) return;
681 wxbDataTokenizer* dt = NULL;
683 while (cfgUpdated > 0) {
684 wxString def; //String to send if can't use our data
685 if ((cfgUpdated >> ConfigWhere) & 1) {
686 WaitForPrompt("mod\n"); /* TODO: check results */
687 WaitForPrompt("9\n");
688 dt = new wxbDataTokenizer(true);
689 WaitForPrompt(cfgWhere->GetValue() + "\n");
691 cfgUpdated = cfgUpdated & (~(1 << ConfigWhere));
693 else if ((cfgUpdated >> ConfigReplace) & 1) {
694 WaitForPrompt("mod\n"); /* TODO: check results */
695 WaitForPrompt("10\n");
696 dt = new wxbDataTokenizer(true);
697 WaitForPrompt(wxString() << (cfgReplace->GetSelection()+1) << "\n");
699 cfgUpdated = cfgUpdated & (~(1 << ConfigReplace));
701 else if ((cfgUpdated >> ConfigWhen) & 1) {
702 WaitForPrompt("mod\n"); /* TODO: check results */
703 WaitForPrompt("6\n");
704 dt = new wxbDataTokenizer(true);
705 WaitForPrompt(cfgWhen->GetValue() + "\n");
707 cfgUpdated = cfgUpdated & (~(1 << ConfigWhen));
709 else if ((cfgUpdated >> ConfigPriority) & 1) {
710 WaitForPrompt("mod\n"); /* TODO: check results */
711 WaitForPrompt("7\n");
712 dt = new wxbDataTokenizer(true);
713 WaitForPrompt(cfgPriority->GetValue() + "\n");
715 cfgUpdated = cfgUpdated & (~(1 << ConfigPriority));
717 else if ((cfgUpdated >> ConfigClient) & 1) {
718 WaitForPrompt("mod\n"); /* TODO: check results */
719 wxbPromptParser *pp = WaitForPrompt("5\n", true);
720 int client = pp->getChoices()->Index(cfgClient->GetStringSelection());
721 if (client == wxNOT_FOUND) {
722 wxbMainFrame::GetInstance()->SetStatusText("Failed to find the selected client.");
726 dt = new wxbDataTokenizer(true);
727 WaitForPrompt(wxString() << client << "\n");
729 cfgUpdated = cfgUpdated & (~(1 << ConfigClient));
731 else if ((cfgUpdated >> ConfigFileset) & 1) {
732 WaitForPrompt("mod\n"); /* TODO: check results */
733 wxbPromptParser *pp = WaitForPrompt("4\n", true);
734 int fileset = pp->getChoices()->Index(cfgFileset->GetStringSelection());
735 if (fileset == wxNOT_FOUND) {
736 wxbMainFrame::GetInstance()->SetStatusText("Failed to find the selected fileset.");
740 dt = new wxbDataTokenizer(true);
741 WaitForPrompt(wxString() << fileset << "\n");
743 cfgUpdated = cfgUpdated & (~(1 << ConfigFileset));
751 for (i = 0; i < dt->GetCount(); i++) {
752 if ((*dt)[i].Find("Run Restore job") == 0) {
757 if (i == dt->GetCount()) {
759 dt = WaitForEnd(def + "\n", true);
762 UpdateConfig(dt); /* TODO: Check result */
770 void wxbRestorePanel::CmdConfigCancel() {
772 wxbMainFrame::GetInstance()->Print("Restore cancelled.\n", CS_DEBUG);
773 wxbMainFrame::GetInstance()->SetStatusText("Restore cancelled.");
777 /* List jobs for a specified client */
778 void wxbRestorePanel::CmdListJobs() {
779 if (status == entered) {
781 WaitForPrompt("query\n");
782 WaitForPrompt("6\n");
783 wxbTableParser* tableparser = CreateAndWaitForParser(clientChoice->GetString(clientChoice->GetSelection()) + "\n");
785 for (int i = tableparser->size()-1; i > -1; i--) {
786 wxString str = (*tableparser)[i][3];
789 if ( ( (chr = datetime.ParseDate(str.GetData()) ) != NULL ) && ( datetime.ParseTime(++chr) != NULL ) ) {
790 datetime = datetime.GetTicks() + 1;
791 //wxbMainFrame::GetInstance()->Print(wxString("-") << datetime.Format("%Y-%m-%d %H:%M:%S"), CS_DEBUG);
792 jobChoice->Append(datetime.Format("%Y-%m-%d %H:%M:%S"));
795 jobChoice->Append("Invalid");
801 jobChoice->SetSelection(0);
805 /* List files and directories for a specified tree item */
806 void wxbRestorePanel::CmdList(wxTreeItemId item) {
807 if (status == choosing) {
808 list->DeleteAllItems();
813 UpdateTreeItem(item, (tree->GetSelection() == item));
815 if (list->GetItemCount() > 1) {
816 int firstwidth = list->GetSize().GetWidth();
817 for (int i = 2; i < 7; i++) {
818 list->SetColumnWidth(i, wxLIST_AUTOSIZE);
819 firstwidth -= list->GetColumnWidth(i);
822 list->SetColumnWidth(0, 18);
824 list->SetColumnWidth(1, wxLIST_AUTOSIZE);
825 if (list->GetColumnWidth(1) < firstwidth) {
826 list->SetColumnWidth(1, firstwidth-20);
832 /* Mark a treeitem (directory) or a listitem (file or directory) */
833 void wxbRestorePanel::CmdMark(wxTreeItemId treeitem, long listitem) {
834 if (status == choosing) {
835 wxbTreeItemData* itemdata = NULL;
836 if (listitem != -1) {
837 itemdata = (wxbTreeItemData*)list->GetItemData(listitem);
839 else if (treeitem.IsOk()) {
840 itemdata = (wxbTreeItemData*)tree->GetItemData(treeitem);
846 if (itemdata == NULL) //Should never happen
849 wxString dir = itemdata->GetPath();
853 if (dir.GetChar(dir.Length()-1) == '/') {
857 int i = dir.Find('/', TRUE);
862 else { /* first dir below root */
864 dir = dir.Mid(0, i+1);
872 WaitForEnd(wxString("cd \"") << dir << "\"\n");
873 WaitForEnd(wxString((itemdata->GetMarked() == 1) ? "unmark" : "mark") << " \"" << file << "\"\n");
875 /* TODO: Check commands results */
877 /*if ((dir == "/") && (file == "*")) {
878 itemdata->SetMarked((itemdata->GetMarked() == 1) ? 0 : 1);
881 if (listitem == -1) { /* tree item state changed */
882 SetTreeItemState(treeitem, (itemdata->GetMarked() == 1) ? 0 : 1);
883 /*treeitem = tree->GetSelection();
884 UpdateTree(treeitem, true);
885 treeitem = tree->GetItemParent(treeitem);*/
888 SetListItemState(listitem, (itemdata->GetMarked() == 1) ? 0 : 1);
889 /*UpdateTree(treeitem, (tree->GetSelection() == treeitem));
890 treeitem = tree->GetItemParent(treeitem);*/
893 /*while (treeitem.IsOk()) {
894 WaitForList(treeitem, false);
895 treeitem = tree->GetItemParent(treeitem);
900 /*----------------------------------------------------------------------------
902 ----------------------------------------------------------------------------*/
904 /* Parse a table in tableParser */
905 wxbTableParser* wxbRestorePanel::CreateAndWaitForParser(wxString cmd) {
906 wxbTableParser* tableParser = new wxbTableParser();
908 wxbMainFrame::GetInstance()->Send(cmd);
910 //time_t base = wxDateTime::Now().GetTicks();
911 while (!tableParser->hasFinished()) {
912 //innerThread->Yield();
914 //if (base+15 < wxDateTime::Now().GetTicks()) break;
919 /* Run a command, and waits until prompt result is fully received,
920 * if keepresults is true, returns a valid pointer to a wxbPromptParser
921 * containing the data. */
922 wxbPromptParser* wxbRestorePanel::WaitForPrompt(wxString cmd, bool keepresults) {
923 wxbPromptParser* promptParser = new wxbPromptParser();
925 wxbMainFrame::GetInstance()->Send(cmd);
927 //time_t base = wxDateTime::Now().GetTicks();
928 while (!promptParser->hasFinished()) {
929 //innerThread->Yield();
931 //if (base+15 < wxDateTime::Now().GetTicks()) break;
943 /* Run a command, and waits until result is fully received. */
944 wxbDataTokenizer* wxbRestorePanel::WaitForEnd(wxString cmd, bool keepresults, bool linebyline) {
945 wxbDataTokenizer* datatokenizer = new wxbDataTokenizer(linebyline);
947 wxbMainFrame::GetInstance()->Send(cmd);
949 //wxbMainFrame::GetInstance()->Print("(<WFE)", CS_DEBUG);
951 //time_t base = wxDateTime::Now().GetTicks();
952 while (!datatokenizer->hasFinished()) {
953 //innerThread->Yield();
955 //if (base+15 < wxDateTime::Now().GetTicks()) break;
958 //wxbMainFrame::GetInstance()->Print("(>WFE)", CS_DEBUG);
961 return datatokenizer;
964 delete datatokenizer;
969 /* Run a dir command, and waits until result is fully received. */
970 void wxbRestorePanel::UpdateTreeItem(wxTreeItemId item, bool updatelist) {
971 // this->updatelist = updatelist;
972 currentTreeItem = item;
974 wxbDataTokenizer* dt;
976 dt = WaitForEnd(wxString("cd \"") <<
977 static_cast<wxbTreeItemData*>(tree->GetItemData(currentTreeItem))
978 ->GetPath() << "\"\n", false);
980 /* TODO: check command result */
987 list->DeleteAllItems();
988 dt = WaitForEnd("dir\n", true);
992 for (unsigned int i = 0; i < dt->GetCount(); i++) {
995 if (str.Find("cwd is:") == 0) { // Sometimes cd command result "infiltrate" into listings.
1001 wxString* file = ParseList(str);
1006 wxTreeItemId treeid;
1008 if (file[8].GetChar(file[8].Length()-1) == '/') {
1012 treeid = tree->GetFirstChild(currentTreeItem, cookie);
1014 bool updated = false;
1016 while (treeid.IsOk()) {
1017 itemStr = tree->GetItemText(treeid);
1018 if (file[8] == itemStr) {
1019 int stat = wxbTreeItemData::GetMarkedStatus(file[6]);
1020 if (static_cast<wxbTreeItemData*>(tree->GetItemData(treeid))->GetMarked() != stat) {
1021 tree->SetItemImage(treeid, stat, wxTreeItemIcon_Normal);
1022 tree->SetItemImage(treeid, stat, wxTreeItemIcon_Selected);
1023 static_cast<wxbTreeItemData*>(tree->GetItemData(treeid))->SetMarked(file[6]);
1028 treeid = tree->GetNextChild(currentTreeItem, cookie);
1032 int img = wxbTreeItemData::GetMarkedStatus(file[6]);
1033 treeid = tree->AppendItem(currentTreeItem, file[8], img, img, new wxbTreeItemData(file[7], file[8], file[6]));
1038 long ind = list->InsertItem(list->GetItemCount(), wxbTreeItemData::GetMarkedStatus(file[6]));
1039 wxbTreeItemData* data = new wxbTreeItemData(file[7], file[8], file[6], ind);
1040 data->SetId(treeid);
1041 list->SetItemData(ind, (long)data);
1042 list->SetItem(ind, 1, file[8]); // filename
1043 list->SetItem(ind, 2, file[4]); //Size
1044 list->SetItem(ind, 3, file[5]); //date
1045 list->SetItem(ind, 4, file[0]); //perm
1046 list->SetItem(ind, 5, file[2]); //user
1047 list->SetItem(ind, 6, file[3]); //grp
1056 SetStatus(choosing);
1059 /* Parse dir command results. */
1060 wxString* wxbRestorePanel::ParseList(wxString line) {
1061 //drwx------ 11 1003 42949672 0 2001-07-30 16:45:14 *filename
1062 //+ 10 ++ 4++ 10 ++ 8 ++ 8 + + 19 + *+ ->
1063 //0 10 14 24 32 42 62
1065 if (line.Length() < 63)
1068 wxString* ret = new wxString[9];
1070 ret[0] = line.Mid(0, 10).Trim();
1071 ret[1] = line.Mid(10, 4).Trim();
1072 ret[2] = line.Mid(14, 10).Trim();
1073 ret[3] = line.Mid(24, 8).Trim();
1074 ret[4] = line.Mid(32, 8).Trim();
1075 ret[5] = line.Mid(42, 19).Trim();
1076 ret[6] = line.Mid(62, 1);
1077 ret[7] = line.Mid(63).Trim();
1079 if (ret[6] == " ") ret[6] = "";
1081 if (ret[7].GetChar(ret[7].Length()-1) == '/') {
1083 ret[8].RemoveLast();
1084 ret[8] = ret[7].Mid(ret[8].Find('/', true)+1);
1087 ret[8] = ret[7].Mid(ret[7].Find('/', true)+1);
1093 /* Sets a list item state, and update its parents and children if it is a directory */
1094 void wxbRestorePanel::SetListItemState(long listitem, int newstate) {
1095 wxbTreeItemData* itemdata = (wxbTreeItemData*)list->GetItemData(listitem);
1097 wxTreeItemId treeitem;
1099 itemdata->SetMarked(newstate);
1100 list->SetItemImage(listitem, newstate, 0); /* TODO: Find what these ints are for */
1101 list->SetItemImage(listitem, newstate, 1);
1103 if ((treeitem = itemdata->GetId()).IsOk()) {
1104 SetTreeItemState(treeitem, newstate);
1107 UpdateTreeItemState(tree->GetSelection());
1111 /* Sets a tree item state, and update its children, parents and list (if necessary) */
1112 void wxbRestorePanel::SetTreeItemState(wxTreeItemId item, int newstate) {
1114 wxTreeItemId currentChild = tree->GetFirstChild(item, cookie);
1116 wxbTreeItemData* itemdata;
1118 while (currentChild.IsOk()) {
1119 itemdata = (wxbTreeItemData*)tree->GetItemData(currentChild);
1120 int state = itemdata->GetMarked();
1122 if (state != newstate) {
1123 itemdata->SetMarked(newstate);
1124 tree->SetItemImage(currentChild, newstate, wxTreeItemIcon_Normal);
1125 tree->SetItemImage(currentChild, newstate, wxTreeItemIcon_Selected);
1128 currentChild = tree->GetNextChild(item, cookie);
1131 itemdata = (wxbTreeItemData*)tree->GetItemData(item);
1132 itemdata->SetMarked(newstate);
1133 tree->SetItemImage(item, newstate, wxTreeItemIcon_Normal);
1134 tree->SetItemImage(item, newstate, wxTreeItemIcon_Selected);
1137 if (tree->GetSelection() == item) {
1138 for (long i = 0; i < list->GetItemCount(); i++) {
1139 list->SetItemImage(i, newstate, 0); /* TODO: Find what these ints are for */
1140 list->SetItemImage(i, newstate, 1);
1144 UpdateTreeItemState(tree->GetItemParent(item));
1147 /* Update a tree item state, and its parents' state */
1148 void wxbRestorePanel::UpdateTreeItemState(wxTreeItemId item) {
1156 wxTreeItemId currentChild = tree->GetFirstChild(item, cookie);
1158 bool onechildmarked = false;
1159 bool onechildunmarked = false;
1161 while (currentChild.IsOk()) {
1162 state = ((wxbTreeItemData*)tree->GetItemData(currentChild))->GetMarked();
1165 onechildunmarked = true;
1168 onechildmarked = true;
1171 onechildmarked = true;
1172 onechildunmarked = true;
1176 if (onechildmarked && onechildunmarked) {
1180 currentChild = tree->GetNextChild(item, cookie);
1183 if (tree->GetSelection() == item) {
1184 for (long i = 0; i < list->GetItemCount(); i++) {
1185 state = ((wxbTreeItemData*)list->GetItemData(i))->GetMarked();
1189 onechildunmarked = true;
1192 onechildmarked = true;
1195 onechildmarked = true;
1196 onechildunmarked = true;
1200 if (onechildmarked && onechildunmarked) {
1208 if (onechildmarked && onechildunmarked) {
1211 else if (onechildmarked) {
1214 else if (onechildunmarked) {
1217 else { // no child, don't change anything
1218 UpdateTreeItemState(tree->GetItemParent(item));
1222 wxbTreeItemData* itemdata = (wxbTreeItemData*)tree->GetItemData(item);
1224 itemdata->SetMarked(state);
1225 tree->SetItemImage(item, state, wxTreeItemIcon_Normal);
1226 tree->SetItemImage(item, state, wxTreeItemIcon_Selected);
1228 UpdateTreeItemState(tree->GetItemParent(item));
1232 * Refresh a tree item, and all its childs,
1233 * by asking the director for new lists
1235 void wxbRestorePanel::RefreshTree(wxTreeItemId item) {
1236 /* UpdateTreeItem(item, updatelist);*/
1238 /* Update all child which are not collapsed */
1240 wxTreeItemId currentChild = tree->GetFirstChild(item, cookie);
1242 while (currentChild.IsOk()) {
1243 if (tree->IsExpanded(currentChild))
1244 UpdateTree(currentChild, false);
1246 currentChild = tree->GetNextChild(item, cookie);
1254 * JobName: RestoreFiles
1255 * Bootstrap: /var/lib/bacula/restore.bsr
1256 * Where: /tmp/bacula-restores
1261 * When: 2004-04-18 01:18:56
1263 * OK to run? (yes/mod/no):
1266 bool wxbRestorePanel::UpdateConfig(wxbDataTokenizer* dt) {
1268 for (i = 0; i < dt->GetCount(); i++) {
1269 if ((*dt)[i].Find("Run Restore job") == 0)
1273 if ((i + 10) > dt->GetCount()) {
1279 if ((k = (*dt)[++i].Find("JobName:")) != 0) return false;
1280 cfgJobname->SetLabel((*dt)[i].Mid(10).Trim(false).RemoveLast());
1281 if ((k = (*dt)[++i].Find("Bootstrap:")) != 0) return false;
1282 cfgBootstrap->SetLabel((*dt)[i].Mid(10).Trim(false).RemoveLast());
1283 if ((k = (*dt)[++i].Find("Where:")) != 0) return false;
1284 cfgWhere->SetValue((*dt)[i].Mid(10).Trim(false).RemoveLast());
1286 if ((k = (*dt)[++i].Find("Replace:")) != 0) return false;
1287 wxString str = (*dt)[i].Mid(10).Trim(false).RemoveLast();
1288 if (str == "always") cfgReplace->SetSelection(0);
1289 else if (str == "ifnewer") cfgReplace->SetSelection(1);
1290 else if (str == "ifolder") cfgReplace->SetSelection(2);
1291 else if (str == "never") cfgReplace->SetSelection(3);
1292 else cfgReplace->SetSelection(0);
1294 if ((k = (*dt)[++i].Find("FileSet:")) != 0) return false;
1295 str = (*dt)[i].Mid(10).Trim(false).RemoveLast();
1296 for (k = 0; k < cfgFileset->GetCount(); k++) {
1297 if (str == cfgFileset->GetString(k)) {
1298 cfgFileset->SetSelection(k);
1302 if (k == cfgFileset->GetCount()) { // Should never happen
1303 cfgFileset->Append(str);
1304 cfgFileset->SetSelection(k+1);
1307 if ((k = (*dt)[++i].Find("Client:")) != 0) return false;
1308 str = (*dt)[i].Mid(10).Trim(false).RemoveLast();
1309 for (k = 0; k < cfgClient->GetCount(); k++) {
1310 if (str == cfgClient->GetString(k)) {
1311 cfgClient->SetSelection(k);
1315 if (k == cfgClient->GetCount()) { // Should never happen
1316 cfgClient->Append(str);
1317 cfgClient->SetSelection(k+1);
1320 if ((k = (*dt)[++i].Find("Storage:")) != 0) return false;
1321 cfgStorage->SetLabel((*dt)[i].Mid(10).Trim(false).RemoveLast());
1322 if ((k = (*dt)[++i].Find("When:")) != 0) return false;
1323 cfgWhen->SetValue((*dt)[i].Mid(10).Trim(false).RemoveLast());
1324 if ((k = (*dt)[++i].Find("Priority:")) != 0) return false;
1325 cfgPriority->SetValue((*dt)[i].Mid(10).Trim(false).RemoveLast());
1328 restorePanel->Layout();
1333 /*----------------------------------------------------------------------------
1335 ----------------------------------------------------------------------------*/
1337 /* Set current status by enabling/disabling components */
1338 void wxbRestorePanel::SetStatus(status_enum newstatus) {
1339 switch (newstatus) {
1341 centerSizer->Remove(restorePanel);
1342 centerSizer->Remove(treelistPanel);
1343 restorePanel->Show(false);
1344 centerSizer->Add(treelistPanel, 1, wxEXPAND);
1345 treelistPanel->Show(true);
1347 start->SetLabel("Enter restore mode");
1348 start->Enable(false);
1349 clientChoice->Enable(false);
1350 jobChoice->Enable(false);
1351 tree->Enable(false);
1352 list->Enable(false);
1353 gauge->Enable(false);
1356 centerSizer->Remove(restorePanel);
1357 restorePanel->Show(false);
1358 centerSizer->Add(treelistPanel, 1, wxEXPAND);
1359 treelistPanel->Show(true);
1360 centerSizer->Layout();
1362 tree->DeleteAllItems();
1363 list->DeleteAllItems();
1364 clientChoice->Clear();
1366 wxbMainFrame::GetInstance()->EnablePanels();
1367 newstatus = activable;
1369 start->SetLabel("Enter restore mode");
1370 start->Enable(true);
1371 clientChoice->Enable(false);
1372 jobChoice->Enable(false);
1373 tree->Enable(false);
1374 list->Enable(false);
1375 gauge->Enable(false);
1378 wxbMainFrame::GetInstance()->DisablePanels(this);
1380 start->SetLabel("Choose files to restore");
1381 clientChoice->Enable(true);
1382 jobChoice->Enable(true);
1383 tree->Enable(false);
1384 list->Enable(false);
1390 start->SetLabel("Restore");
1391 clientChoice->Enable(false);
1392 jobChoice->Enable(false);
1396 SetCursor(*wxSTANDARD_CURSOR);
1399 start->Enable(false);
1400 clientChoice->Enable(false);
1401 jobChoice->Enable(false);
1402 tree->Enable(false);
1403 list->Enable(false);
1404 centerSizer->Remove(treelistPanel);
1405 treelistPanel->Show(false);
1406 centerSizer->Add(restorePanel, 1, wxEXPAND);
1407 restorePanel->Show(true);
1408 restorePanel->Layout();
1409 centerSizer->Layout();
1411 cfgApply->Enable(false);
1412 cfgOk->Enable(true);
1415 start->SetLabel("Restoring...");
1416 gauge->Enable(true);
1418 start->Enable(false);
1419 clientChoice->Enable(false);
1420 jobChoice->Enable(false);
1421 tree->Enable(false);
1422 list->Enable(false);
1423 SetCursor(*wxHOURGLASS_CURSOR);
1430 /*----------------------------------------------------------------------------
1432 ----------------------------------------------------------------------------*/
1434 void wxbRestorePanel::EnableConfig(bool enable) {
1435 cfgWhere->Enable(enable);
1436 cfgReplace->Enable(enable);
1437 cfgWhen->Enable(enable);
1438 cfgPriority->Enable(enable);
1439 cfgClient->Enable(enable);
1440 cfgFileset->Enable(enable);
1443 /*----------------------------------------------------------------------------
1445 ----------------------------------------------------------------------------*/
1447 void wxbRestorePanel::OnClientChoiceChanged(wxCommandEvent& event) {
1451 SetCursor(*wxHOURGLASS_CURSOR);
1453 clientChoice->Enable(false);
1454 jobChoice->Enable(false);
1456 clientChoice->Enable(true);
1457 jobChoice->Enable(true);
1458 jobChoice->Refresh();
1460 SetCursor(*wxSTANDARD_CURSOR);
1463 void wxbRestorePanel::OnStart(wxEvent& WXUNUSED(event)) {
1467 SetCursor(*wxHOURGLASS_CURSOR);
1471 SetCursor(*wxSTANDARD_CURSOR);
1474 void wxbRestorePanel::OnTreeChanging(wxTreeEvent& event) {
1480 void wxbRestorePanel::OnTreeExpanding(wxTreeEvent& event) {
1486 //CmdList(event.GetItem());
1487 if (tree->GetSelection() != event.GetItem()) {
1488 tree->SelectItem(event.GetItem());
1493 void wxbRestorePanel::OnTreeChanged(wxTreeEvent& event) {
1497 SetCursor(*wxHOURGLASS_CURSOR);
1499 CmdList(event.GetItem());
1501 SetCursor(*wxSTANDARD_CURSOR);
1504 void wxbRestorePanel::OnTreeMarked(wxbTreeMarkedEvent& event) {
1509 SetCursor(*wxHOURGLASS_CURSOR);
1511 CmdMark(event.GetItem(), -1);
1515 SetCursor(*wxSTANDARD_CURSOR);
1518 void wxbRestorePanel::OnListMarked(wxbListMarkedEvent& event) {
1523 SetCursor(*wxHOURGLASS_CURSOR);
1525 //long item = event.GetId();
1526 long item = list->GetNextItem(-1, wxLIST_NEXT_ALL, wxLIST_STATE_FOCUSED);
1527 CmdMark(wxTreeItemId(), item);
1531 SetCursor(*wxSTANDARD_CURSOR);
1534 void wxbRestorePanel::OnListActivated(wxListEvent& event) {
1539 SetCursor(*wxHOURGLASS_CURSOR);
1541 long item = list->GetNextItem(-1, wxLIST_NEXT_ALL, wxLIST_STATE_FOCUSED);
1543 wxbTreeItemData* itemdata = (wxbTreeItemData*)list->GetItemData(item);
1544 wxString name = itemdata->GetName();
1551 if (name.GetChar(name.Length()-1) == '/') {
1552 wxTreeItemId currentChild = tree->GetFirstChild(currentTreeItem, cookie);
1554 while (currentChild.IsOk()) {
1555 wxString name2 = tree->GetItemText(currentChild);
1556 if (name2 == name) {
1557 //tree->UnselectAll();
1559 SetCursor(*wxSTANDARD_CURSOR);
1560 tree->Expand(currentTreeItem);
1561 tree->SelectItem(currentChild);
1565 currentChild = tree->GetNextChild(currentTreeItem, cookie);
1570 SetCursor(*wxSTANDARD_CURSOR);
1573 void wxbRestorePanel::OnConfigUpdated(wxCommandEvent& event) {
1574 if (status != configuring) return;
1575 cfgApply->Enable(true);
1576 cfgOk->Enable(false);
1577 cfgUpdated = cfgUpdated | (1 << event.GetId());
1580 void wxbRestorePanel::OnConfigOk(wxEvent& WXUNUSED(event)) {
1581 if (status != configuring) return;
1585 SetCursor(*wxHOURGLASS_CURSOR);
1589 SetCursor(*wxSTANDARD_CURSOR);
1592 void wxbRestorePanel::OnConfigApply(wxEvent& WXUNUSED(event)) {
1593 if (status != configuring) return;
1597 SetCursor(*wxHOURGLASS_CURSOR);
1600 if (cfgUpdated == 0) {
1601 cfgApply->Enable(false);
1602 cfgOk->Enable(true);
1605 SetCursor(*wxSTANDARD_CURSOR);
1608 void wxbRestorePanel::OnConfigCancel(wxEvent& WXUNUSED(event)) {
1609 if (status != configuring) return;
1613 SetCursor(*wxHOURGLASS_CURSOR);
1617 SetCursor(*wxSTANDARD_CURSOR);
1620 /* TODO : correct that bad implementation of tree marked event forwarding */
1622 wxbTreeListPanel::wxbTreeListPanel(wxbRestorePanel* parent): wxPanel(parent, -1) {
1623 this->parent = parent;
1626 void wxbTreeListPanel::OnTreeMarked(wxbTreeMarkedEvent& event) {
1627 parent->OnTreeMarked(event);
1630 void wxbTreeListPanel::OnListMarked(wxbListMarkedEvent& event) {
1631 parent->OnListMarked(event);