]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/qt-console/restore/restore.cpp
Addressed issue of long compiles. Simplify with Pages::setCurrent
[bacula/bacula] / bacula / src / qt-console / restore / restore.cpp
1 /*
2    Bacula® - The Network Backup Solution
3
4    Copyright (C) 2007-2007 Free Software Foundation Europe e.V.
5
6    The main author of Bacula is Kern Sibbald, with contributions from
7    many others, a complete list can be found in the file AUTHORS.
8    This program is Free Software; you can redistribute it and/or
9    modify it under the terms of version two of the GNU General Public
10    License as published by the Free Software Foundation plus additions
11    that are listed in the file LICENSE.
12
13    This program is distributed in the hope that it will be useful, but
14    WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16    General Public License for more details.
17
18    You should have received a copy of the GNU General Public License
19    along with this program; if not, write to the Free Software
20    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21    02110-1301, USA.
22
23    Bacula® is a registered trademark of John Walker.
24    The licensor of Bacula is the Free Software Foundation Europe
25    (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
26    Switzerland, email:ftf@fsfeurope.org.
27 */
28  
29 /*
30  *   Version $Id$
31  *
32  *  Restore Class 
33  *
34  *   Kern Sibbald, February MMVII
35  *
36  */ 
37
38 #include "bat.h"
39 #include "restore.h"
40
41 restorePage::restorePage(Console *console)
42 {
43    QStringList titles;
44
45    setupUi(this);
46    QTreeWidgetItem *parent = mainWin->getFromHash(console);
47    if (!parent) {
48       /* Make this a user configurable stdout msg *** FIXME ****/
49       printf("Error retrieving tree widget.");
50       return;
51    }
52    m_name = "Restore";
53    pgInitialize(parent);
54    m_console->notify(false);          /* this should already be off */
55    m_closeable = true;
56
57    connect(fileWidget, SIGNAL(itemDoubleClicked(QTreeWidgetItem*, int)), 
58            this, SLOT(fileDoubleClicked(QTreeWidgetItem *, int)));
59    connect(directoryWidget, SIGNAL(
60            currentItemChanged(QTreeWidgetItem *, QTreeWidgetItem *)),
61            this, SLOT(directoryItemChanged(QTreeWidgetItem *, QTreeWidgetItem *)));
62    connect(upButton, SIGNAL(pressed()), this, SLOT(upButtonPushed()));
63    connect(markButton, SIGNAL(pressed()), this, SLOT(markButtonPushed()));
64    connect(unmarkButton, SIGNAL(pressed()), this, SLOT(unmarkButtonPushed()));
65    connect(okButton, SIGNAL(pressed()), this, SLOT(okButtonPushed()));
66    connect(cancelButton, SIGNAL(pressed()), this, SLOT(cancelButtonPushed()));
67    setFont(m_console->get_font());
68    m_console->displayToPrompt();
69
70    titles << "Mark" << "File" << "Mode" << "User" << "Group" << "Size" << "Date";
71    fileWidget->setHeaderLabels(titles);
72
73    get_cwd();
74
75    //QString root("");
76    //addDirectory(root);
77    fillDirectory();
78    dockPage();
79    setCurrent();
80    this->show();
81 }
82
83 /*
84  * Fill the fileWidget box with the contents of the current directory
85  */
86 void restorePage::fillDirectory()
87 {
88    char modes[20], user[20], group[20], size[20], date[30];
89    char marked[10];
90    int pnl, fnl;
91    POOLMEM *file = get_pool_memory(PM_FNAME);
92    POOLMEM *path = get_pool_memory(PM_FNAME);
93
94    fileWidget->clear();
95    m_console->write_dir("dir");
96    QList<QTreeWidgetItem *> treeItemList;
97    QStringList item;
98    while (m_console->read() > 0) {
99       char *p = m_console->msg();
100       char *l;
101       strip_trailing_junk(p);
102       if (*p == '$' || !*p) {
103          continue;
104       }
105       l = p;
106       skip_nonspaces(&p);             /* permissions */
107       *p++ = 0;
108       bstrncpy(modes, l, sizeof(modes));
109       skip_spaces(&p);
110       skip_nonspaces(&p);             /* link count */
111       *p++ = 0;
112       skip_spaces(&p);
113       l = p;
114       skip_nonspaces(&p);             /* user */
115       *p++ = 0;
116       skip_spaces(&p);
117       bstrncpy(user, l, sizeof(user));
118       l = p;
119       skip_nonspaces(&p);             /* group */
120       *p++ = 0;
121       bstrncpy(group, l, sizeof(group));
122       skip_spaces(&p);
123       l = p;
124       skip_nonspaces(&p);             /* size */
125       *p++ = 0;
126       bstrncpy(size, l, sizeof(size));
127       skip_spaces(&p);
128       l = p;
129       skip_nonspaces(&p);             /* date/time */
130       skip_spaces(&p);
131       skip_nonspaces(&p);
132       *p++ = 0;
133       bstrncpy(date, l, sizeof(date));
134       skip_spaces(&p);
135       if (*p == '*') {
136          bstrncpy(marked, "*", sizeof(marked));
137          p++;
138       } else {
139          bstrncpy(marked, " ", sizeof(marked));
140       }
141       split_path_and_filename(p, &path, &pnl, &file, &fnl);
142       item.clear();
143       item << marked << file << modes << user << group << size << date;
144       if (item[1].endsWith("/")) {
145          addDirectory(item[1]);
146        }
147       QTreeWidgetItem *ti = new QTreeWidgetItem((QTreeWidget *)0, item);
148       ti->setTextAlignment(5, Qt::AlignRight); /* right align size */
149       treeItemList.append(ti);
150    }
151    fileWidget->clear();
152    fileWidget->insertTopLevelItems(0, treeItemList);
153    for (int i=0; i<7; i++) {
154       fileWidget->resizeColumnToContents(i);
155    }
156
157    free_pool_memory(file);
158    free_pool_memory(path);
159 }
160
161 /*
162  * Function called from fill directory when a directory is found to see if this
163  * directory exists in the directory pane and then add it to the directory pane
164  */
165 void restorePage::addDirectory(QString &newdirr)
166 {
167    QString newdir = newdirr;
168    QString fullpath = m_cwd + newdirr;
169    QRegExp regex("^/[a-z]:/$");
170    bool ok=true;
171
172    //printf("In addDirectory cwd \"%s\" newdir \"%s\"\n", m_cwd.toUtf8().data(),
173         //newdir.toUtf8().data());
174
175    /* add unix '/' directory first */
176    if (m_dirPaths.empty() && (regex.indexIn(fullpath,0) == -1)) {
177       QTreeWidgetItem *item = new QTreeWidgetItem(directoryWidget);
178       QString text("/");
179       item->setText(0, text.toUtf8().data());
180       //printf("Pre Inserting %s\n",text.toUtf8().data());
181       m_dirPaths.insert(text, item);
182       m_dirTreeItems.insert(item, text);
183    }
184
185    if (regex.indexIn(fullpath,0) == 0) {
186       /* this is a windows drive */
187       //printf("Need to do windows c:/\n");
188       fullpath.replace(0,1,"");
189    }
190  
191    /* is it already existent ?? */
192    if (!m_dirPaths.contains(fullpath)) {
193       QTreeWidgetItem *item = NULL;
194       if (m_dirPaths.empty()) {
195          /* this is the base widget */
196          item = new QTreeWidgetItem(directoryWidget);
197          item->setText(0, fullpath.toUtf8().data());
198       } else {
199          QTreeWidgetItem *parent = m_dirPaths.value(m_cwd);
200          if (parent) {
201             /* new directories to add */
202             item = new QTreeWidgetItem(parent);
203             item->setText(0, newdir.toUtf8().data());
204             directoryWidget->expandItem(parent);
205          } else {
206             ok=false;
207             //printf("In else of if parent cwd \"%s\" newdir \"%s\"\n", 
208                //m_cwd.toUtf8().data() ,newdir.toUtf8().data());
209          }
210       }
211       /* insert into both forward and reverse hash */
212       if (ok) {
213          //printf("Inserting %s\n",fullpath.toUtf8().data());
214          m_dirPaths.insert(fullpath, item);
215          m_dirTreeItems.insert(item, fullpath);
216       }
217    }
218 }
219
220 /*
221  * Executed when the tree item in the directory pane is changed.  This will
222  * allow us to populate the file pane and make this the cwd.
223  */
224 void restorePage::directoryItemChanged(QTreeWidgetItem *currentitem,
225                                          QTreeWidgetItem * /*previousitem*/)
226 {
227    QString fullpath = m_dirTreeItems.value(currentitem);
228    if (fullpath != ""){
229       cwd(fullpath.toUtf8().data());
230       fillDirectory();
231    }
232 }
233
234 void restorePage::okButtonPushed()
235 {
236    this->hide();
237    m_console->write("done");
238    m_console->notify(true);
239    closeStackPage();
240    mainWin->resetFocus();
241 }
242
243
244 void restorePage::cancelButtonPushed()
245 {
246    this->hide();
247    m_console->write("quit");
248    mainWin->set_status("Canceled");
249    closeStackPage();
250    m_console->notify(true);
251    mainWin->resetFocus();
252 }
253
254 void restorePage::fileDoubleClicked(QTreeWidgetItem *item, int column)
255 {
256    char cmd[1000];
257    if (column == 0) {                 /* mark/unmark */
258       if (item->text(0) == "*") {
259          bsnprintf(cmd, sizeof(cmd), "unmark \"%s\"", item->text(1).toUtf8().data());
260          item->setText(0, " ");
261       } else {
262          bsnprintf(cmd, sizeof(cmd), "mark \"%s\"", item->text(1).toUtf8().data());
263          item->setText(0, "*");
264       }
265       m_console->write_dir(cmd);
266       if (m_console->read() > 0) {
267          strip_trailing_junk(m_console->msg());
268          statusLine->setText(m_console->msg());
269       }
270       m_console->displayToPrompt();
271       return;
272    }    
273    /* 
274     * Double clicking other than column 0 means to decend into
275     *  the directory -- or nothing if it is not a directory.
276     */
277    if (item->text(1).endsWith("/")) {
278       QString fullpath = m_cwd + item->text(1);
279       /* check for fullpath = "/c:/" */
280       QRegExp regex("^/[a-z]:/");
281       if (regex.indexIn(fullpath,0) == 0)  /* remove leading '/' */
282          fullpath.replace(0,1,"");
283       QTreeWidgetItem *item = m_dirPaths.value(fullpath);
284       if (item) {
285          directoryWidget->setCurrentItem(item);
286       } else {
287          /* FIXME ***** Create an error log */
288          //printf("DoubleClick else of item column %i fullpath %s\n", column, fullpath.toUtf8().data());
289       }
290    }
291 }
292
293 /*
294  * If up button pushed, making the parent tree widget current will call fill
295  * directory.
296  */
297 void restorePage::upButtonPushed()
298 {
299    cwd("..");
300    QTreeWidgetItem *item = m_dirPaths.value(m_cwd);
301    if (item) {
302       directoryWidget->setCurrentItem(item);
303    }
304 }
305
306 /*
307  * Mark selected items
308  */
309 void restorePage::markButtonPushed()
310 {
311    QList<QTreeWidgetItem *> treeItemList = fileWidget->selectedItems();
312    QTreeWidgetItem *item;
313    char cmd[1000];
314    foreach (item, treeItemList) {
315       bsnprintf(cmd, sizeof(cmd), "mark \"%s\"", item->text(1).toUtf8().data());
316       item->setText(0, "*");
317       m_console->write_dir(cmd);
318       if (m_console->read() > 0) {
319          strip_trailing_junk(m_console->msg());
320          statusLine->setText(m_console->msg());
321       }
322       Dmsg1(100, "cmd=%s\n", cmd);
323       m_console->discardToPrompt();
324    }
325 }
326
327 /*
328  * Unmark selected items
329  */
330 void restorePage::unmarkButtonPushed()
331 {
332    QList<QTreeWidgetItem *> treeItemList = fileWidget->selectedItems();
333    QTreeWidgetItem *item;
334    char cmd[1000];
335    foreach (item, treeItemList) {
336       bsnprintf(cmd, sizeof(cmd), "unmark \"%s\"", item->text(1).toUtf8().data());
337       item->setText(0, " ");
338       m_console->write_dir(cmd);
339       if (m_console->read() > 0) {
340          strip_trailing_junk(m_console->msg());
341          statusLine->setText(m_console->msg());
342       }
343       Dmsg1(100, "cmd=%s\n", cmd);
344       m_console->discardToPrompt();
345    }
346 }
347
348 /*
349  * Change current working directory 
350  */
351 bool restorePage::cwd(const char *dir)
352 {
353    int stat;
354    char cd_cmd[MAXSTRING];
355
356    bsnprintf(cd_cmd, sizeof(cd_cmd), "cd \"%s\"", dir);
357    Dmsg2(100, "dir=%s cmd=%s\n", dir, cd_cmd);
358    m_console->write_dir(cd_cmd);
359    lineEdit->clear();
360    if ((stat = m_console->read()) > 0) {
361       m_cwd = m_console->msg();
362       lineEdit->insert(m_cwd);
363       Dmsg2(100, "cwd=%s msg=%s\n", m_cwd.toUtf8().data(), m_console->msg());
364    } else {
365       Dmsg1(000, "stat=%d\n", stat);
366       QMessageBox::critical(this, "Error", "cd command failed", QMessageBox::Ok);
367    }
368    m_console->discardToPrompt();
369    return true;  /* ***FIXME*** return real status */
370 }
371
372 /*
373  * Return cwd when in tree restore mode 
374  */
375 char *restorePage::get_cwd()
376 {
377    int stat;
378    m_console->write_dir(".pwd");
379    Dmsg0(100, "send: .pwd\n");
380    if ((stat = m_console->read()) > 0) {
381       m_cwd = m_console->msg();
382       Dmsg2(100, "cwd=%s msg=%s\n", m_cwd.toUtf8().data(), m_console->msg());
383    } else {
384       Dmsg1(000, "stat=%d\n", stat);
385       QMessageBox::critical(this, "Error", ".pwd command failed", QMessageBox::Ok);
386       Dmsg1(000, "stat=%d\n", stat);
387    }
388    m_console->discardToPrompt(); 
389    return m_cwd.toUtf8().data();
390 }