]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/qt-console/restore/restore.cpp
Move radio buttons to more intuitive location
[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    setConsoleCurrent();
232    closeStackPage();
233    mainWin->resetFocus();
234 }
235
236
237 void restorePage::cancelButtonPushed()
238 {
239    this->hide();
240    m_console->write("quit");
241    m_console->displayToPrompt();
242    mainWin->set_status("Canceled");
243    closeStackPage();
244    m_console->notify(true);
245    mainWin->resetFocus();
246 }
247
248 void restorePage::fileDoubleClicked(QTreeWidgetItem *item, int column)
249 {
250    char cmd[1000];
251    if (column == 0) {                 /* mark/unmark */
252       if (item->text(0) == "*") {
253          bsnprintf(cmd, sizeof(cmd), "unmark \"%s\"", item->text(1).toUtf8().data());
254          item->setText(0, " ");
255       } else {
256          bsnprintf(cmd, sizeof(cmd), "mark \"%s\"", item->text(1).toUtf8().data());
257          item->setText(0, "*");
258       }
259       m_console->write_dir(cmd);
260       if (m_console->read() > 0) {
261          strip_trailing_junk(m_console->msg());
262          statusLine->setText(m_console->msg());
263       }
264       m_console->displayToPrompt();
265       return;
266    }    
267    /* 
268     * Double clicking other than column 0 means to decend into
269     *  the directory -- or nothing if it is not a directory.
270     */
271    if (item->text(1).endsWith("/")) {
272       QString fullpath = m_cwd + item->text(1);
273       /* check for fullpath = "/c:/" */
274       QRegExp regex("^/[a-z]:/");
275       if (regex.indexIn(fullpath,0) == 0)  /* remove leading '/' */
276          fullpath.replace(0,1,"");
277       QTreeWidgetItem *item = m_dirPaths.value(fullpath);
278       if (item) {
279          directoryWidget->setCurrentItem(item);
280       } else {
281          /* FIXME ***** Create an error log */
282          //printf("DoubleClick else of item column %i fullpath %s\n", column, fullpath.toUtf8().data());
283       }
284    }
285 }
286
287 /*
288  * If up button pushed, making the parent tree widget current will call fill
289  * directory.
290  */
291 void restorePage::upButtonPushed()
292 {
293    cwd("..");
294    QTreeWidgetItem *item = m_dirPaths.value(m_cwd);
295    if (item) {
296       directoryWidget->setCurrentItem(item);
297    }
298 }
299
300 /*
301  * Mark selected items
302  */
303 void restorePage::markButtonPushed()
304 {
305    QList<QTreeWidgetItem *> treeItemList = fileWidget->selectedItems();
306    QTreeWidgetItem *item;
307    char cmd[1000];
308    foreach (item, treeItemList) {
309       bsnprintf(cmd, sizeof(cmd), "mark \"%s\"", item->text(1).toUtf8().data());
310       item->setText(0, "*");
311       m_console->write_dir(cmd);
312       if (m_console->read() > 0) {
313          strip_trailing_junk(m_console->msg());
314          statusLine->setText(m_console->msg());
315       }
316       Dmsg1(100, "cmd=%s\n", cmd);
317       m_console->discardToPrompt();
318    }
319 }
320
321 /*
322  * Unmark selected items
323  */
324 void restorePage::unmarkButtonPushed()
325 {
326    QList<QTreeWidgetItem *> treeItemList = fileWidget->selectedItems();
327    QTreeWidgetItem *item;
328    char cmd[1000];
329    foreach (item, treeItemList) {
330       bsnprintf(cmd, sizeof(cmd), "unmark \"%s\"", item->text(1).toUtf8().data());
331       item->setText(0, " ");
332       m_console->write_dir(cmd);
333       if (m_console->read() > 0) {
334          strip_trailing_junk(m_console->msg());
335          statusLine->setText(m_console->msg());
336       }
337       Dmsg1(100, "cmd=%s\n", cmd);
338       m_console->discardToPrompt();
339    }
340 }
341
342 /*
343  * Change current working directory 
344  */
345 bool restorePage::cwd(const char *dir)
346 {
347    int stat;
348    char cd_cmd[MAXSTRING];
349
350    bsnprintf(cd_cmd, sizeof(cd_cmd), "cd \"%s\"", dir);
351    Dmsg2(100, "dir=%s cmd=%s\n", dir, cd_cmd);
352    m_console->write_dir(cd_cmd);
353    lineEdit->clear();
354    if ((stat = m_console->read()) > 0) {
355       m_cwd = m_console->msg();
356       lineEdit->insert(m_cwd);
357       Dmsg2(100, "cwd=%s msg=%s\n", m_cwd.toUtf8().data(), m_console->msg());
358    } else {
359       Dmsg1(000, "stat=%d\n", stat);
360       QMessageBox::critical(this, "Error", "cd command failed", QMessageBox::Ok);
361    }
362    m_console->discardToPrompt();
363    return true;  /* ***FIXME*** return real status */
364 }
365
366 /*
367  * Return cwd when in tree restore mode 
368  */
369 char *restorePage::get_cwd()
370 {
371    int stat;
372    m_console->write_dir(".pwd");
373    Dmsg0(100, "send: .pwd\n");
374    if ((stat = m_console->read()) > 0) {
375       m_cwd = m_console->msg();
376       Dmsg2(100, "cwd=%s msg=%s\n", m_cwd.toUtf8().data(), m_console->msg());
377    } else {
378       Dmsg1(000, "Something went wrong read stat=%d\n", stat);
379       QMessageBox::critical(this, "Error", ".pwd command failed", QMessageBox::Ok);
380    }
381    m_console->discardToPrompt(); 
382    return m_cwd.toUtf8().data();
383 }