]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/qt-console/restore/restore.cpp
Update description of PAGES and changes to TODO. Also removed spacers
[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()
42 {
43    QStringList titles;
44
45    setupUi(this);
46    m_name = "Restore Select";
47    pgInitialize();
48    m_console->notify(false);          /* this should already be off */
49    m_closeable = true;
50
51    connect(fileWidget, SIGNAL(itemDoubleClicked(QTreeWidgetItem*, int)), 
52            this, SLOT(fileDoubleClicked(QTreeWidgetItem *, int)));
53    connect(directoryWidget, SIGNAL(
54            currentItemChanged(QTreeWidgetItem *, QTreeWidgetItem *)),
55            this, SLOT(directoryItemChanged(QTreeWidgetItem *, QTreeWidgetItem *)));
56    connect(upButton, SIGNAL(pressed()), this, SLOT(upButtonPushed()));
57    connect(markButton, SIGNAL(pressed()), this, SLOT(markButtonPushed()));
58    connect(unmarkButton, SIGNAL(pressed()), this, SLOT(unmarkButtonPushed()));
59    connect(okButton, SIGNAL(pressed()), this, SLOT(okButtonPushed()));
60    connect(cancelButton, SIGNAL(pressed()), this, SLOT(cancelButtonPushed()));
61    setFont(m_console->get_font());
62    m_console->displayToPrompt();
63
64    titles << "Mark" << "File" << "Mode" << "User" << "Group" << "Size" << "Date";
65    fileWidget->setHeaderLabels(titles);
66
67    get_cwd();
68
69    fillDirectory();
70    dockPage();
71    setCurrent();
72    this->show();
73 }
74
75 /*
76  * Fill the fileWidget box with the contents of the current directory
77  */
78 void restorePage::fillDirectory()
79 {
80    char modes[20], user[20], group[20], size[20], date[30];
81    char marked[10];
82    int pnl, fnl;
83    POOLMEM *file = get_pool_memory(PM_FNAME);
84    POOLMEM *path = get_pool_memory(PM_FNAME);
85
86    fileWidget->clear();
87    m_console->write_dir("dir");
88    QList<QTreeWidgetItem *> treeItemList;
89    QStringList item;
90    while (m_console->read() > 0) {
91       char *p = m_console->msg();
92       char *l;
93       strip_trailing_junk(p);
94       if (*p == '$' || !*p) {
95          continue;
96       }
97       l = p;
98       skip_nonspaces(&p);             /* permissions */
99       *p++ = 0;
100       bstrncpy(modes, l, sizeof(modes));
101       skip_spaces(&p);
102       skip_nonspaces(&p);             /* link count */
103       *p++ = 0;
104       skip_spaces(&p);
105       l = p;
106       skip_nonspaces(&p);             /* user */
107       *p++ = 0;
108       skip_spaces(&p);
109       bstrncpy(user, l, sizeof(user));
110       l = p;
111       skip_nonspaces(&p);             /* group */
112       *p++ = 0;
113       bstrncpy(group, l, sizeof(group));
114       skip_spaces(&p);
115       l = p;
116       skip_nonspaces(&p);             /* size */
117       *p++ = 0;
118       bstrncpy(size, l, sizeof(size));
119       skip_spaces(&p);
120       l = p;
121       skip_nonspaces(&p);             /* date/time */
122       skip_spaces(&p);
123       skip_nonspaces(&p);
124       *p++ = 0;
125       bstrncpy(date, l, sizeof(date));
126       skip_spaces(&p);
127       if (*p == '*') {
128          bstrncpy(marked, "*", sizeof(marked));
129          p++;
130       } else {
131          bstrncpy(marked, " ", sizeof(marked));
132       }
133       split_path_and_filename(p, &path, &pnl, &file, &fnl);
134       item.clear();
135       item << marked << file << modes << user << group << size << date;
136       if (item[1].endsWith("/")) {
137          addDirectory(item[1]);
138        }
139       QTreeWidgetItem *ti = new QTreeWidgetItem((QTreeWidget *)0, item);
140       ti->setTextAlignment(5, Qt::AlignRight); /* right align size */
141       treeItemList.append(ti);
142    }
143    fileWidget->clear();
144    fileWidget->insertTopLevelItems(0, treeItemList);
145    for (int i=0; i<7; i++) {
146       fileWidget->resizeColumnToContents(i);
147    }
148
149    free_pool_memory(file);
150    free_pool_memory(path);
151 }
152
153 /*
154  * Function called from fill directory when a directory is found to see if this
155  * directory exists in the directory pane and then add it to the directory pane
156  */
157 void restorePage::addDirectory(QString &newdirr)
158 {
159    QString newdir = newdirr;
160    QString fullpath = m_cwd + newdirr;
161    QRegExp regex("^/[a-z]:/$");
162    bool ok=true;
163
164    //printf("In addDirectory cwd \"%s\" newdir \"%s\"\n", m_cwd.toUtf8().data(),
165         //newdir.toUtf8().data());
166
167    /* add unix '/' directory first */
168    if (m_dirPaths.empty() && (regex.indexIn(fullpath,0) == -1)) {
169       QTreeWidgetItem *item = new QTreeWidgetItem(directoryWidget);
170       QString text("/");
171       item->setText(0, text.toUtf8().data());
172       //printf("Pre Inserting %s\n",text.toUtf8().data());
173       m_dirPaths.insert(text, item);
174       m_dirTreeItems.insert(item, text);
175    }
176
177    if (regex.indexIn(fullpath,0) == 0) {
178       /* this is a windows drive */
179       //printf("Need to do windows c:/\n");
180       fullpath.replace(0,1,"");
181    }
182  
183    /* is it already existent ?? */
184    if (!m_dirPaths.contains(fullpath)) {
185       QTreeWidgetItem *item = NULL;
186       if (m_dirPaths.empty()) {
187          /* this is the base widget */
188          item = new QTreeWidgetItem(directoryWidget);
189          item->setText(0, fullpath.toUtf8().data());
190       } else {
191          QTreeWidgetItem *parent = m_dirPaths.value(m_cwd);
192          if (parent) {
193             /* new directories to add */
194             item = new QTreeWidgetItem(parent);
195             item->setText(0, newdir.toUtf8().data());
196             directoryWidget->expandItem(parent);
197          } else {
198             ok=false;
199             //printf("In else of if parent cwd \"%s\" newdir \"%s\"\n", 
200                //m_cwd.toUtf8().data() ,newdir.toUtf8().data());
201          }
202       }
203       /* insert into both forward and reverse hash */
204       if (ok) {
205          //printf("Inserting %s\n",fullpath.toUtf8().data());
206          m_dirPaths.insert(fullpath, item);
207          m_dirTreeItems.insert(item, fullpath);
208       }
209    }
210 }
211
212 /*
213  * Executed when the tree item in the directory pane is changed.  This will
214  * allow us to populate the file pane and make this the cwd.
215  */
216 void restorePage::directoryItemChanged(QTreeWidgetItem *currentitem,
217                                          QTreeWidgetItem * /*previousitem*/)
218 {
219    QString fullpath = m_dirTreeItems.value(currentitem);
220    if (fullpath != ""){
221       cwd(fullpath.toUtf8().data());
222       fillDirectory();
223    }
224 }
225
226 void restorePage::okButtonPushed()
227 {
228    this->hide();
229    m_console->write("done");
230    m_console->notify(true);
231    closeStackPage();
232    mainWin->resetFocus();
233 }
234
235
236 void restorePage::cancelButtonPushed()
237 {
238    this->hide();
239    m_console->write("quit");
240    mainWin->set_status("Canceled");
241    closeStackPage();
242    m_console->notify(true);
243    mainWin->resetFocus();
244 }
245
246 void restorePage::fileDoubleClicked(QTreeWidgetItem *item, int column)
247 {
248    char cmd[1000];
249    if (column == 0) {                 /* mark/unmark */
250       if (item->text(0) == "*") {
251          bsnprintf(cmd, sizeof(cmd), "unmark \"%s\"", item->text(1).toUtf8().data());
252          item->setText(0, " ");
253       } else {
254          bsnprintf(cmd, sizeof(cmd), "mark \"%s\"", item->text(1).toUtf8().data());
255          item->setText(0, "*");
256       }
257       m_console->write_dir(cmd);
258       if (m_console->read() > 0) {
259          strip_trailing_junk(m_console->msg());
260          statusLine->setText(m_console->msg());
261       }
262       m_console->displayToPrompt();
263       return;
264    }    
265    /* 
266     * Double clicking other than column 0 means to decend into
267     *  the directory -- or nothing if it is not a directory.
268     */
269    if (item->text(1).endsWith("/")) {
270       QString fullpath = m_cwd + item->text(1);
271       /* check for fullpath = "/c:/" */
272       QRegExp regex("^/[a-z]:/");
273       if (regex.indexIn(fullpath,0) == 0)  /* remove leading '/' */
274          fullpath.replace(0,1,"");
275       QTreeWidgetItem *item = m_dirPaths.value(fullpath);
276       if (item) {
277          directoryWidget->setCurrentItem(item);
278       } else {
279          /* FIXME ***** Create an error log */
280          //printf("DoubleClick else of item column %i fullpath %s\n", column, fullpath.toUtf8().data());
281       }
282    }
283 }
284
285 /*
286  * If up button pushed, making the parent tree widget current will call fill
287  * directory.
288  */
289 void restorePage::upButtonPushed()
290 {
291    cwd("..");
292    QTreeWidgetItem *item = m_dirPaths.value(m_cwd);
293    if (item) {
294       directoryWidget->setCurrentItem(item);
295    }
296 }
297
298 /*
299  * Mark selected items
300  */
301 void restorePage::markButtonPushed()
302 {
303    QList<QTreeWidgetItem *> treeItemList = fileWidget->selectedItems();
304    QTreeWidgetItem *item;
305    char cmd[1000];
306    foreach (item, treeItemList) {
307       bsnprintf(cmd, sizeof(cmd), "mark \"%s\"", item->text(1).toUtf8().data());
308       item->setText(0, "*");
309       m_console->write_dir(cmd);
310       if (m_console->read() > 0) {
311          strip_trailing_junk(m_console->msg());
312          statusLine->setText(m_console->msg());
313       }
314       Dmsg1(100, "cmd=%s\n", cmd);
315       m_console->discardToPrompt();
316    }
317 }
318
319 /*
320  * Unmark selected items
321  */
322 void restorePage::unmarkButtonPushed()
323 {
324    QList<QTreeWidgetItem *> treeItemList = fileWidget->selectedItems();
325    QTreeWidgetItem *item;
326    char cmd[1000];
327    foreach (item, treeItemList) {
328       bsnprintf(cmd, sizeof(cmd), "unmark \"%s\"", item->text(1).toUtf8().data());
329       item->setText(0, " ");
330       m_console->write_dir(cmd);
331       if (m_console->read() > 0) {
332          strip_trailing_junk(m_console->msg());
333          statusLine->setText(m_console->msg());
334       }
335       Dmsg1(100, "cmd=%s\n", cmd);
336       m_console->discardToPrompt();
337    }
338 }
339
340 /*
341  * Change current working directory 
342  */
343 bool restorePage::cwd(const char *dir)
344 {
345    int stat;
346    char cd_cmd[MAXSTRING];
347
348    bsnprintf(cd_cmd, sizeof(cd_cmd), "cd \"%s\"", dir);
349    Dmsg2(100, "dir=%s cmd=%s\n", dir, cd_cmd);
350    m_console->write_dir(cd_cmd);
351    lineEdit->clear();
352    if ((stat = m_console->read()) > 0) {
353       m_cwd = m_console->msg();
354       lineEdit->insert(m_cwd);
355       Dmsg2(100, "cwd=%s msg=%s\n", m_cwd.toUtf8().data(), m_console->msg());
356    } else {
357       Dmsg1(000, "stat=%d\n", stat);
358       QMessageBox::critical(this, "Error", "cd command failed", QMessageBox::Ok);
359    }
360    m_console->discardToPrompt();
361    return true;  /* ***FIXME*** return real status */
362 }
363
364 /*
365  * Return cwd when in tree restore mode 
366  */
367 char *restorePage::get_cwd()
368 {
369    int stat;
370    m_console->write_dir(".pwd");
371    Dmsg0(100, "send: .pwd\n");
372    if ((stat = m_console->read()) > 0) {
373       m_cwd = m_console->msg();
374       Dmsg2(100, "cwd=%s msg=%s\n", m_cwd.toUtf8().data(), m_console->msg());
375    } else {
376       Dmsg1(000, "stat=%d\n", stat);
377       QMessageBox::critical(this, "Error", ".pwd command failed", QMessageBox::Ok);
378       Dmsg1(000, "stat=%d\n", stat);
379    }
380    m_console->discardToPrompt(); 
381    return m_cwd.toUtf8().data();
382 }