]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/qt-console/restore/restore.cpp
ebl Generated 193 translations (186 finished and 7 unfinished)
[bacula/bacula] / bacula / src / qt-console / restore / restore.cpp
1 /*
2    Bacula® - The Network Backup Solution
3
4    Copyright (C) 2007-2008 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 and included
11    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 = tr("Restore Select");
47    pgInitialize();
48    QTreeWidgetItem* thisitem = mainWin->getFromHash(this);
49    thisitem->setIcon(0,QIcon(QString::fromUtf8(":images/restore.png")));
50
51    m_console->notify(false);          /* this should already be off */
52    m_closeable = true;
53
54    connect(fileWidget, SIGNAL(itemDoubleClicked(QTreeWidgetItem*, int)), 
55            this, SLOT(fileDoubleClicked(QTreeWidgetItem *, int)));
56    connect(directoryWidget, SIGNAL(
57            currentItemChanged(QTreeWidgetItem *, QTreeWidgetItem *)),
58            this, SLOT(directoryItemChanged(QTreeWidgetItem *, QTreeWidgetItem *)));
59    connect(upButton, SIGNAL(pressed()), this, SLOT(upButtonPushed()));
60    connect(markButton, SIGNAL(pressed()), this, SLOT(markButtonPushed()));
61    connect(unmarkButton, SIGNAL(pressed()), this, SLOT(unmarkButtonPushed()));
62    connect(okButton, SIGNAL(pressed()), this, SLOT(okButtonPushed()));
63    connect(cancelButton, SIGNAL(pressed()), this, SLOT(cancelButtonPushed()));
64
65    fileWidget->setContextMenuPolicy(Qt::ActionsContextMenu);
66    fileWidget->addAction(actionMark);
67    fileWidget->addAction(actionUnMark);
68    connect(actionMark, SIGNAL(triggered()), this, SLOT(markButtonPushed()));
69    connect(actionUnMark, SIGNAL(triggered()), this, SLOT(unmarkButtonPushed()));
70
71    setFont(m_console->get_font());
72    m_console->displayToPrompt();
73
74    titles << tr("Mark") << tr("File") << tr("Mode") << tr("User") 
75           << tr("Group") << tr("Size") << tr("Date");
76    fileWidget->setHeaderLabels(titles);
77
78    get_cwd();
79
80    readSettings();
81    fillDirectory();
82    dockPage();
83    setCurrent();
84    this->show();
85 }
86
87 restorePage::~restorePage()
88 {
89    writeSettings();
90 }
91
92 /*
93  * Fill the fileWidget box with the contents of the current directory
94  */
95 void restorePage::fillDirectory()
96 {
97    char modes[20], user[20], group[20], size[20], date[30];
98    char marked[10];
99    int pnl, fnl;
100    POOLMEM *file = get_pool_memory(PM_FNAME);
101    POOLMEM *path = get_pool_memory(PM_FNAME);
102
103    fileWidget->clear();
104    m_console->write_dir("dir");
105    QList<QTreeWidgetItem *> treeItemList;
106    QStringList item;
107    while (m_console->read() > 0) {
108       char *p = m_console->msg();
109       char *l;
110       strip_trailing_junk(p);
111       if (*p == '$' || !*p) {
112          continue;
113       }
114       l = p;
115       skip_nonspaces(&p);             /* permissions */
116       *p++ = 0;
117       bstrncpy(modes, l, sizeof(modes));
118       skip_spaces(&p);
119       skip_nonspaces(&p);             /* link count */
120       *p++ = 0;
121       skip_spaces(&p);
122       l = p;
123       skip_nonspaces(&p);             /* user */
124       *p++ = 0;
125       skip_spaces(&p);
126       bstrncpy(user, l, sizeof(user));
127       l = p;
128       skip_nonspaces(&p);             /* group */
129       *p++ = 0;
130       bstrncpy(group, l, sizeof(group));
131       skip_spaces(&p);
132       l = p;
133       skip_nonspaces(&p);             /* size */
134       *p++ = 0;
135       bstrncpy(size, l, sizeof(size));
136       skip_spaces(&p);
137       l = p;
138       skip_nonspaces(&p);             /* date/time */
139       skip_spaces(&p);
140       skip_nonspaces(&p);
141       *p++ = 0;
142       bstrncpy(date, l, sizeof(date));
143       skip_spaces(&p);
144       if (*p == '*') {
145          bstrncpy(marked, "*", sizeof(marked));
146          p++;
147       } else {
148          bstrncpy(marked, " ", sizeof(marked));
149       }
150       split_path_and_filename(p, &path, &pnl, &file, &fnl);
151       item.clear();
152       item << "" << file << modes << user << group << size << date;
153       if (item[1].endsWith("/")) {
154          addDirectory(item[1]);
155       }
156       QTreeWidgetItem *ti = new QTreeWidgetItem((QTreeWidget *)0, item);
157       ti->setTextAlignment(5, Qt::AlignRight); /* right align size */
158       if (strcmp(marked, "*") == 0) {
159          ti->setIcon(0, QIcon(QString::fromUtf8(":images/check.png")));
160          ti->setData(0, Qt::UserRole, true);
161       } else {
162          ti->setIcon(0, QIcon(QString::fromUtf8(":images/unchecked.png")));
163          ti->setData(0, Qt::UserRole, false);
164       }
165       treeItemList.append(ti);
166    }
167    fileWidget->clear();
168    fileWidget->insertTopLevelItems(0, treeItemList);
169    for (int i=0; i<7; i++) {
170       fileWidget->resizeColumnToContents(i);
171    }
172
173    free_pool_memory(file);
174    free_pool_memory(path);
175 }
176
177 /*
178  * Function called from fill directory when a directory is found to see if this
179  * directory exists in the directory pane and then add it to the directory pane
180  */
181 void restorePage::addDirectory(QString &newdirr)
182 {
183    QString newdir = newdirr;
184    QString fullpath = m_cwd + newdirr;
185    bool ok = true;
186    bool windrive = false;
187
188    if (mainWin->m_miscDebug) {
189       QString msg = QString(tr("In addDirectory cwd \"%1\" newdir \"%2\"\n"))
190                     .arg(m_cwd)
191                     .arg(newdir);
192       Pmsg0(000, msg.toUtf8().data());
193    }
194
195    /* add unix '/' directory first */
196    if (m_dirPaths.empty() && !isWin32Path(fullpath)) {
197       QTreeWidgetItem *item = new QTreeWidgetItem(directoryWidget);
198       item->setIcon(0,QIcon(QString::fromUtf8(":images/folder.png")));
199       
200       QString text("/");
201       item->setText(0, text.toUtf8().data());
202       if (mainWin->m_miscDebug) {
203          Pmsg1(000, "Pre Inserting %s\n",text.toUtf8().data());
204       }
205       m_dirPaths.insert(text, item);
206       m_dirTreeItems.insert(item, text);
207    }
208
209    if (isWin32Path(fullpath)) {
210       /* this is a windows drive */
211       if (mainWin->m_miscDebug) {
212          Pmsg0(000, "Need to do windows \"letter\":/\n");
213       }
214       windrive = true;
215    }
216  
217    /* is it already existent ?? */
218    if (!m_dirPaths.contains(fullpath)) {
219       QTreeWidgetItem *item = NULL;
220       if (windrive) {
221          /* this is the base widget */
222          item = new QTreeWidgetItem(directoryWidget);
223          item->setText(0, fullpath.toUtf8().data());
224          item->setIcon(0,QIcon(QString::fromUtf8(":images/folder.png")));
225       } else {
226          QTreeWidgetItem *parent = m_dirPaths.value(m_cwd);
227          if (parent) {
228             /* new directories to add */
229             item = new QTreeWidgetItem(parent);
230             item->setText(0, newdir.toUtf8().data());
231             item->setIcon(0,QIcon(QString::fromUtf8(":images/folder.png")));
232             directoryWidget->expandItem(parent);
233          } else {
234             ok = false;
235             if (mainWin->m_miscDebug) {
236                QString msg = QString(tr("In else of if parent cwd \"%1\" newdir \"%2\"\n"))
237                     .arg(m_cwd)
238                     .arg(newdir);
239                Pmsg0(000, msg.toUtf8().data());
240             }
241          }
242       }
243       /* insert into both forward and reverse hash */
244       if (ok) {
245          if (mainWin->m_miscDebug) {
246             Pmsg1(000, "Inserting %s\n",fullpath.toUtf8().data());
247          }
248          m_dirPaths.insert(fullpath, item);
249          m_dirTreeItems.insert(item, fullpath);
250       }
251    }
252 }
253
254 /*
255  * Executed when the tree item in the directory pane is changed.  This will
256  * allow us to populate the file pane and make this the cwd.
257  */
258 void restorePage::directoryItemChanged(QTreeWidgetItem *currentitem,
259                                          QTreeWidgetItem * /*previousitem*/)
260 {
261    QString fullpath = m_dirTreeItems.value(currentitem);
262    statusLine->setText("");
263    if (fullpath != ""){
264       cwd(fullpath.toUtf8().data());
265       fillDirectory();
266    }
267 }
268
269 void restorePage::okButtonPushed()
270 {
271 // printf("In restorePage::okButtonPushed\n");
272    this->hide();
273    m_console->write("done");
274    m_console->notify(true);
275    setConsoleCurrent();
276    closeStackPage();
277    mainWin->resetFocus();
278 }
279
280
281 void restorePage::cancelButtonPushed()
282 {
283    this->hide();
284    m_console->write("quit");
285    m_console->displayToPrompt();
286    mainWin->set_status(tr("Canceled"));
287    closeStackPage();
288    m_console->notify(true);
289    mainWin->resetFocus();
290 }
291
292 void restorePage::fileDoubleClicked(QTreeWidgetItem *item, int column)
293 {
294    char cmd[1000];
295    statusLine->setText("");
296    if (column == 0) {                 /* mark/unmark */
297       if (item->data(0, Qt::UserRole).toBool()) {
298          bsnprintf(cmd, sizeof(cmd), "unmark \"%s\"", item->text(1).toUtf8().data());
299          item->setIcon(0, QIcon(QString::fromUtf8(":images/unchecked.png")));
300          item->setData(0, Qt::UserRole, false);
301       } else {
302          bsnprintf(cmd, sizeof(cmd), "mark \"%s\"", item->text(1).toUtf8().data());
303          item->setIcon(0, QIcon(QString::fromUtf8(":images/check.png")));
304          item->setData(0, Qt::UserRole, true);
305       }
306       m_console->write_dir(cmd);
307       if (m_console->read() > 0) {
308          strip_trailing_junk(m_console->msg());
309          statusLine->setText(m_console->msg());
310       }
311       m_console->displayToPrompt();
312       return;
313    }    
314    /* 
315     * Double clicking other than column 0 means to decend into
316     *  the directory -- or nothing if it is not a directory.
317     */
318    if (item->text(1).endsWith("/")) {
319       QString fullpath = m_cwd + item->text(1);
320       QTreeWidgetItem *item = m_dirPaths.value(fullpath);
321       if (item) {
322          directoryWidget->setCurrentItem(item);
323       } else {
324          QString msg = QString("DoubleClick else of item column %1 fullpath %2\n")
325               .arg(column,10)
326               .arg(fullpath);
327          Pmsg0(000, msg.toUtf8().data());
328       }
329    }
330 }
331
332 /*
333  * If up button pushed, making the parent tree widget current will call fill
334  * directory.
335  */
336 void restorePage::upButtonPushed()
337 {
338    cwd("..");
339    QTreeWidgetItem *item = m_dirPaths.value(m_cwd);
340    if (item) {
341       directoryWidget->setCurrentItem(item);
342    }
343    statusLine->setText("");
344 }
345
346 /*
347  * Mark selected items
348  */
349 void restorePage::markButtonPushed()
350 {
351    QList<QTreeWidgetItem *> treeItemList = fileWidget->selectedItems();
352    QTreeWidgetItem *item;
353    char cmd[1000];
354    int count = 0;
355    statusLine->setText("");
356    foreach (item, treeItemList) {
357       count++;
358       bsnprintf(cmd, sizeof(cmd), "mark \"%s\"", item->text(1).toUtf8().data());
359       item->setIcon(0, QIcon(QString::fromUtf8(":images/check.png")));
360       m_console->write_dir(cmd);
361       if (m_console->read() > 0) {
362          strip_trailing_junk(m_console->msg());
363          statusLine->setText(m_console->msg());
364       }
365       Dmsg1(100, "cmd=%s\n", cmd);
366       m_console->discardToPrompt();
367    }
368    if (count == 0) {
369       mainWin->set_status("Nothing selected, nothing done");
370       statusLine->setText("Nothing selected, nothing done");
371    }
372       
373 }
374
375 /*
376  * Unmark selected items
377  */
378 void restorePage::unmarkButtonPushed()
379 {
380    QList<QTreeWidgetItem *> treeItemList = fileWidget->selectedItems();
381    QTreeWidgetItem *item;
382    char cmd[1000];
383    int count = 0;
384    statusLine->setText("");
385    foreach (item, treeItemList) {
386       count++;
387       bsnprintf(cmd, sizeof(cmd), "unmark \"%s\"", item->text(1).toUtf8().data());
388       item->setIcon(0, QIcon(QString::fromUtf8(":images/unchecked.png")));
389       m_console->write_dir(cmd);
390       if (m_console->read() > 0) {
391          strip_trailing_junk(m_console->msg());
392          statusLine->setText(m_console->msg());
393       }
394       Dmsg1(100, "cmd=%s\n", cmd);
395       m_console->discardToPrompt();
396    }
397    if (count == 0) {
398       mainWin->set_status("Nothing selected, nothing done");
399       statusLine->setText("Nothing selected, nothing done");
400    }
401
402 }
403
404 /*
405  * Change current working directory 
406  */
407 bool restorePage::cwd(const char *dir)
408 {
409    int stat;
410    char cd_cmd[MAXSTRING];
411
412    statusLine->setText("");
413    bsnprintf(cd_cmd, sizeof(cd_cmd), "cd \"%s\"", dir);
414    Dmsg2(100, "dir=%s cmd=%s\n", dir, cd_cmd);
415    m_console->write_dir(cd_cmd);
416    lineEdit->clear();
417    if ((stat = m_console->read()) > 0) {
418       m_cwd = m_console->msg();
419       lineEdit->insert(m_cwd);
420       Dmsg2(100, "cwd=%s msg=%s\n", m_cwd.toUtf8().data(), m_console->msg());
421    } else {
422       Dmsg1(000, "stat=%d\n", stat);
423       QMessageBox::critical(this, "Error", "cd command failed", QMessageBox::Ok);
424    }
425    m_console->discardToPrompt();
426    return true;  /* ***FIXME*** return real status */
427 }
428
429 /*
430  * Return cwd when in tree restore mode 
431  */
432 char *restorePage::get_cwd()
433 {
434    int stat;
435    m_console->write_dir(".pwd");
436    Dmsg0(100, "send: .pwd\n");
437    if ((stat = m_console->read()) > 0) {
438       m_cwd = m_console->msg();
439       Dmsg2(100, "cwd=%s msg=%s\n", m_cwd.toUtf8().data(), m_console->msg());
440    } else {
441       Dmsg1(000, "Something went wrong read stat=%d\n", stat);
442       QMessageBox::critical(this, "Error", ".pwd command failed", QMessageBox::Ok);
443    }
444    m_console->discardToPrompt(); 
445    return m_cwd.toUtf8().data();
446 }
447
448 /*
449  * Save user settings associated with this page
450  */
451 void restorePage::writeSettings()
452 {
453    QSettings settings(m_console->m_dir->name(), "bat");
454    settings.beginGroup("RestorePage");
455    settings.setValue("splitterSizes", splitter->saveState());
456    settings.endGroup();
457 }
458
459 /*
460  * Read and restore user settings associated with this page
461  */
462 void restorePage::readSettings()
463 {
464    QSettings settings(m_console->m_dir->name(), "bat");
465    settings.beginGroup("RestorePage");
466    splitter->restoreState(settings.value("splitterSizes").toByteArray());
467    settings.endGroup();
468 }