2 Bacula® - The Network Backup Solution
4 Copyright (C) 2007-2008 Free Software Foundation Europe e.V.
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
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.
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
23 Bacula® is a registered trademark of Kern Sibbald.
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.
34 * Kern Sibbald, February MMVII
41 restorePage::restorePage()
46 m_name = tr("Restore Select");
48 QTreeWidgetItem* thisitem = mainWin->getFromHash(this);
49 thisitem->setIcon(0,QIcon(QString::fromUtf8(":images/restore.png")));
51 m_console->notify(false); /* this should already be off */
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()));
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()));
71 setFont(m_console->get_font());
72 m_console->displayToPrompt();
74 titles << tr("Mark") << tr("File") << tr("Mode") << tr("User")
75 << tr("Group") << tr("Size") << tr("Date");
76 fileWidget->setHeaderLabels(titles);
87 restorePage::~restorePage()
93 * Fill the fileWidget box with the contents of the current directory
95 void restorePage::fillDirectory()
97 char modes[20], user[20], group[20], size[20], date[30];
100 POOLMEM *file = get_pool_memory(PM_FNAME);
101 POOLMEM *path = get_pool_memory(PM_FNAME);
104 m_console->write_dir("dir");
105 QList<QTreeWidgetItem *> treeItemList;
107 while (m_console->read() > 0) {
108 char *p = m_console->msg();
110 strip_trailing_junk(p);
111 if (*p == '$' || !*p) {
115 skip_nonspaces(&p); /* permissions */
117 bstrncpy(modes, l, sizeof(modes));
119 skip_nonspaces(&p); /* link count */
123 skip_nonspaces(&p); /* user */
126 bstrncpy(user, l, sizeof(user));
128 skip_nonspaces(&p); /* group */
130 bstrncpy(group, l, sizeof(group));
133 skip_nonspaces(&p); /* size */
135 bstrncpy(size, l, sizeof(size));
138 skip_nonspaces(&p); /* date/time */
142 bstrncpy(date, l, sizeof(date));
145 bstrncpy(marked, "*", sizeof(marked));
148 bstrncpy(marked, " ", sizeof(marked));
150 split_path_and_filename(p, &path, &pnl, &file, &fnl);
152 item << "" << file << modes << user << group << size << date;
153 if (item[1].endsWith("/")) {
154 addDirectory(item[1]);
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);
162 ti->setIcon(0, QIcon(QString::fromUtf8(":images/unchecked.png")));
163 ti->setData(0, Qt::UserRole, false);
165 treeItemList.append(ti);
168 fileWidget->insertTopLevelItems(0, treeItemList);
169 for (int i=0; i<7; i++) {
170 fileWidget->resizeColumnToContents(i);
173 free_pool_memory(file);
174 free_pool_memory(path);
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
181 void restorePage::addDirectory(QString &newdirr)
183 QString newdir = newdirr;
184 QString fullpath = m_cwd + newdirr;
186 bool windrive = false;
188 if (mainWin->m_miscDebug) {
189 QString msg = QString(tr("In addDirectory cwd \"%1\" newdir \"%2\" fullpath \"%3\"\n"))
193 Pmsg0(000, msg.toUtf8().data());
196 if (isWin32Path(newdir)) {
197 /* this is a windows drive */
198 if (mainWin->m_miscDebug) {
199 Pmsg0(000, "Found windows drive\n");
205 if (fullpath.left(1) == "/") {
206 fullpath.replace(0, 1, ""); /* strip leading / */
208 /* If drive and not already in add it */
209 if (fullpath.length() == 3 && !m_dirPaths.contains(fullpath)) {
210 QTreeWidgetItem *item = new QTreeWidgetItem(directoryWidget);
211 item->setIcon(0,QIcon(QString::fromUtf8(":images/folder.png")));
212 item->setText(0, fullpath.toUtf8().data());
213 if (mainWin->m_miscDebug) {
214 Pmsg1(000, "Pre Inserting %s\n",fullpath.toUtf8().data());
216 m_dirPaths.insert(fullpath, item);
217 m_dirTreeItems.insert(item, fullpath);
218 directoryWidget->setCurrentItem(NULL);
221 // Unix add / first if not already there
222 if (m_dirPaths.empty()) {
223 QTreeWidgetItem *item = new QTreeWidgetItem(directoryWidget);
224 item->setIcon(0,QIcon(QString::fromUtf8(":images/folder.png")));
227 item->setText(0, text.toUtf8().data());
228 if (mainWin->m_miscDebug) {
229 Pmsg1(000, "Pre Inserting %s\n",text.toUtf8().data());
231 m_dirPaths.insert(text, item);
232 m_dirTreeItems.insert(item, text);
236 /* Does it already exist ?? */
237 if (!m_dirPaths.contains(fullpath)) {
238 QTreeWidgetItem *item = NULL;
240 /* this is the base widget */
241 item = new QTreeWidgetItem(directoryWidget);
242 item->setText(0, fullpath.toUtf8().data());
243 item->setIcon(0,QIcon(QString::fromUtf8(":images/folder.png")));
245 QTreeWidgetItem *parent = m_dirPaths.value(m_cwd);
247 /* new directories to add */
248 item = new QTreeWidgetItem(parent);
249 item->setText(0, newdir.toUtf8().data());
250 item->setIcon(0,QIcon(QString::fromUtf8(":images/folder.png")));
251 directoryWidget->expandItem(parent);
254 if (mainWin->m_miscDebug) {
255 QString msg = QString(tr("In else of if parent cwd \"%1\" newdir \"%2\"\n"))
258 Pmsg0(000, msg.toUtf8().data());
262 /* insert into both forward and reverse hash */
264 if (mainWin->m_miscDebug) {
265 Pmsg1(000, "Inserting %s\n",fullpath.toUtf8().data());
267 m_dirPaths.insert(fullpath, item);
268 m_dirTreeItems.insert(item, fullpath);
274 * Executed when the tree item in the directory pane is changed. This will
275 * allow us to populate the file pane and make this the cwd.
277 void restorePage::directoryItemChanged(QTreeWidgetItem *currentitem,
278 QTreeWidgetItem * /*previousitem*/)
280 QString fullpath = m_dirTreeItems.value(currentitem);
281 statusLine->setText("");
283 cwd(fullpath.toUtf8().data());
288 void restorePage::okButtonPushed()
290 // printf("In restorePage::okButtonPushed\n");
292 m_console->write("done");
293 m_console->notify(true);
296 mainWin->resetFocus();
300 void restorePage::cancelButtonPushed()
303 m_console->write("quit");
304 m_console->displayToPrompt();
305 mainWin->set_status(tr("Canceled"));
307 m_console->notify(true);
308 mainWin->resetFocus();
311 void restorePage::fileDoubleClicked(QTreeWidgetItem *item, int column)
314 statusLine->setText("");
315 if (column == 0) { /* mark/unmark */
316 if (item->data(0, Qt::UserRole).toBool()) {
317 bsnprintf(cmd, sizeof(cmd), "unmark \"%s\"", item->text(1).toUtf8().data());
318 item->setIcon(0, QIcon(QString::fromUtf8(":images/unchecked.png")));
319 item->setData(0, Qt::UserRole, false);
321 bsnprintf(cmd, sizeof(cmd), "mark \"%s\"", item->text(1).toUtf8().data());
322 item->setIcon(0, QIcon(QString::fromUtf8(":images/check.png")));
323 item->setData(0, Qt::UserRole, true);
325 m_console->write_dir(cmd);
326 if (m_console->read() > 0) {
327 strip_trailing_junk(m_console->msg());
328 statusLine->setText(m_console->msg());
330 m_console->displayToPrompt();
334 * Double clicking other than column 0 means to decend into
335 * the directory -- or nothing if it is not a directory.
337 if (item->text(1).endsWith("/")) {
338 QString fullpath = m_cwd + item->text(1);
339 QTreeWidgetItem *item = m_dirPaths.value(fullpath);
341 directoryWidget->setCurrentItem(item);
343 QString msg = QString("DoubleClick else of item column %1 fullpath %2\n")
346 Pmsg0(000, msg.toUtf8().data());
352 * If up button pushed, making the parent tree widget current will call fill
355 void restorePage::upButtonPushed()
358 QTreeWidgetItem *item = m_dirPaths.value(m_cwd);
360 directoryWidget->setCurrentItem(item);
362 statusLine->setText("");
366 * Mark selected items
368 void restorePage::markButtonPushed()
370 QList<QTreeWidgetItem *> treeItemList = fileWidget->selectedItems();
371 QTreeWidgetItem *item;
374 statusLine->setText("");
375 foreach (item, treeItemList) {
377 bsnprintf(cmd, sizeof(cmd), "mark \"%s\"", item->text(1).toUtf8().data());
378 item->setIcon(0, QIcon(QString::fromUtf8(":images/check.png")));
379 m_console->write_dir(cmd);
380 if (m_console->read() > 0) {
381 strip_trailing_junk(m_console->msg());
382 statusLine->setText(m_console->msg());
384 Dmsg1(100, "cmd=%s\n", cmd);
385 m_console->discardToPrompt();
388 mainWin->set_status("Nothing selected, nothing done");
389 statusLine->setText("Nothing selected, nothing done");
395 * Unmark selected items
397 void restorePage::unmarkButtonPushed()
399 QList<QTreeWidgetItem *> treeItemList = fileWidget->selectedItems();
400 QTreeWidgetItem *item;
403 statusLine->setText("");
404 foreach (item, treeItemList) {
406 bsnprintf(cmd, sizeof(cmd), "unmark \"%s\"", item->text(1).toUtf8().data());
407 item->setIcon(0, QIcon(QString::fromUtf8(":images/unchecked.png")));
408 m_console->write_dir(cmd);
409 if (m_console->read() > 0) {
410 strip_trailing_junk(m_console->msg());
411 statusLine->setText(m_console->msg());
413 Dmsg1(100, "cmd=%s\n", cmd);
414 m_console->discardToPrompt();
417 mainWin->set_status(tr("Nothing selected, nothing done"));
418 statusLine->setText(tr("Nothing selected, nothing done"));
424 * Change current working directory
426 bool restorePage::cwd(const char *dir)
429 char cd_cmd[MAXSTRING];
431 statusLine->setText("");
432 bsnprintf(cd_cmd, sizeof(cd_cmd), "cd \"%s\"", dir);
433 Dmsg2(100, "dir=%s cmd=%s\n", dir, cd_cmd);
434 m_console->write_dir(cd_cmd);
436 if ((stat = m_console->read()) > 0) {
437 m_cwd = m_console->msg();
438 lineEdit->insert(m_cwd);
439 Dmsg2(100, "cwd=%s msg=%s\n", m_cwd.toUtf8().data(), m_console->msg());
441 Dmsg1(000, "stat=%d\n", stat);
442 QMessageBox::critical(this, "Error", tr("cd command failed"), QMessageBox::Ok);
444 m_console->discardToPrompt();
445 return true; /* ***FIXME*** return real status */
449 * Return cwd when in tree restore mode
451 char *restorePage::get_cwd()
454 m_console->write_dir(".pwd");
455 Dmsg0(100, "send: .pwd\n");
456 if ((stat = m_console->read()) > 0) {
457 m_cwd = m_console->msg();
458 Dmsg2(100, "cwd=%s msg=%s\n", m_cwd.toUtf8().data(), m_console->msg());
460 Dmsg1(000, "Something went wrong read stat=%d\n", stat);
461 QMessageBox::critical(this, "Error", tr(".pwd command failed"), QMessageBox::Ok);
463 m_console->discardToPrompt();
464 return m_cwd.toUtf8().data();
468 * Save user settings associated with this page
470 void restorePage::writeSettings()
472 QSettings settings(m_console->m_dir->name(), "bat");
473 settings.beginGroup("RestorePage");
474 settings.setValue("splitterSizes", splitter->saveState());
479 * Read and restore user settings associated with this page
481 void restorePage::readSettings()
483 QSettings settings(m_console->m_dir->name(), "bat");
484 settings.beginGroup("RestorePage");
485 splitter->restoreState(settings.value("splitterSizes").toByteArray());