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 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.
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);
220 // Unix add / first if not already there
221 if (m_dirPaths.empty()) {
222 QTreeWidgetItem *item = new QTreeWidgetItem(directoryWidget);
223 item->setIcon(0,QIcon(QString::fromUtf8(":images/folder.png")));
226 item->setText(0, text.toUtf8().data());
227 if (mainWin->m_miscDebug) {
228 Pmsg1(000, "Pre Inserting %s\n",text.toUtf8().data());
230 m_dirPaths.insert(text, item);
231 m_dirTreeItems.insert(item, text);
235 /* Does it already exist ?? */
236 if (!m_dirPaths.contains(fullpath)) {
237 QTreeWidgetItem *item = NULL;
239 /* this is the base widget */
240 item = new QTreeWidgetItem(directoryWidget);
241 item->setText(0, fullpath.toUtf8().data());
242 item->setIcon(0,QIcon(QString::fromUtf8(":images/folder.png")));
244 QTreeWidgetItem *parent = m_dirPaths.value(m_cwd);
246 /* new directories to add */
247 item = new QTreeWidgetItem(parent);
248 item->setText(0, newdir.toUtf8().data());
249 item->setIcon(0,QIcon(QString::fromUtf8(":images/folder.png")));
250 directoryWidget->expandItem(parent);
253 if (mainWin->m_miscDebug) {
254 QString msg = QString(tr("In else of if parent cwd \"%1\" newdir \"%2\"\n"))
257 Pmsg0(000, msg.toUtf8().data());
261 /* insert into both forward and reverse hash */
263 if (mainWin->m_miscDebug) {
264 Pmsg1(000, "Inserting %s\n",fullpath.toUtf8().data());
266 m_dirPaths.insert(fullpath, item);
267 m_dirTreeItems.insert(item, fullpath);
273 * Executed when the tree item in the directory pane is changed. This will
274 * allow us to populate the file pane and make this the cwd.
276 void restorePage::directoryItemChanged(QTreeWidgetItem *currentitem,
277 QTreeWidgetItem * /*previousitem*/)
279 QString fullpath = m_dirTreeItems.value(currentitem);
280 statusLine->setText("");
282 cwd(fullpath.toUtf8().data());
287 void restorePage::okButtonPushed()
289 // printf("In restorePage::okButtonPushed\n");
291 m_console->write("done");
292 m_console->notify(true);
295 mainWin->resetFocus();
299 void restorePage::cancelButtonPushed()
302 m_console->write("quit");
303 m_console->displayToPrompt();
304 mainWin->set_status(tr("Canceled"));
306 m_console->notify(true);
307 mainWin->resetFocus();
310 void restorePage::fileDoubleClicked(QTreeWidgetItem *item, int column)
313 statusLine->setText("");
314 if (column == 0) { /* mark/unmark */
315 if (item->data(0, Qt::UserRole).toBool()) {
316 bsnprintf(cmd, sizeof(cmd), "unmark \"%s\"", item->text(1).toUtf8().data());
317 item->setIcon(0, QIcon(QString::fromUtf8(":images/unchecked.png")));
318 item->setData(0, Qt::UserRole, false);
320 bsnprintf(cmd, sizeof(cmd), "mark \"%s\"", item->text(1).toUtf8().data());
321 item->setIcon(0, QIcon(QString::fromUtf8(":images/check.png")));
322 item->setData(0, Qt::UserRole, true);
324 m_console->write_dir(cmd);
325 if (m_console->read() > 0) {
326 strip_trailing_junk(m_console->msg());
327 statusLine->setText(m_console->msg());
329 m_console->displayToPrompt();
333 * Double clicking other than column 0 means to decend into
334 * the directory -- or nothing if it is not a directory.
336 if (item->text(1).endsWith("/")) {
337 QString fullpath = m_cwd + item->text(1);
338 QTreeWidgetItem *item = m_dirPaths.value(fullpath);
340 directoryWidget->setCurrentItem(item);
342 QString msg = QString("DoubleClick else of item column %1 fullpath %2\n")
345 Pmsg0(000, msg.toUtf8().data());
351 * If up button pushed, making the parent tree widget current will call fill
354 void restorePage::upButtonPushed()
357 QTreeWidgetItem *item = m_dirPaths.value(m_cwd);
359 directoryWidget->setCurrentItem(item);
361 statusLine->setText("");
365 * Mark selected items
367 void restorePage::markButtonPushed()
369 QList<QTreeWidgetItem *> treeItemList = fileWidget->selectedItems();
370 QTreeWidgetItem *item;
373 statusLine->setText("");
374 foreach (item, treeItemList) {
376 bsnprintf(cmd, sizeof(cmd), "mark \"%s\"", item->text(1).toUtf8().data());
377 item->setIcon(0, QIcon(QString::fromUtf8(":images/check.png")));
378 m_console->write_dir(cmd);
379 if (m_console->read() > 0) {
380 strip_trailing_junk(m_console->msg());
381 statusLine->setText(m_console->msg());
383 Dmsg1(100, "cmd=%s\n", cmd);
384 m_console->discardToPrompt();
387 mainWin->set_status("Nothing selected, nothing done");
388 statusLine->setText("Nothing selected, nothing done");
394 * Unmark selected items
396 void restorePage::unmarkButtonPushed()
398 QList<QTreeWidgetItem *> treeItemList = fileWidget->selectedItems();
399 QTreeWidgetItem *item;
402 statusLine->setText("");
403 foreach (item, treeItemList) {
405 bsnprintf(cmd, sizeof(cmd), "unmark \"%s\"", item->text(1).toUtf8().data());
406 item->setIcon(0, QIcon(QString::fromUtf8(":images/unchecked.png")));
407 m_console->write_dir(cmd);
408 if (m_console->read() > 0) {
409 strip_trailing_junk(m_console->msg());
410 statusLine->setText(m_console->msg());
412 Dmsg1(100, "cmd=%s\n", cmd);
413 m_console->discardToPrompt();
416 mainWin->set_status(tr("Nothing selected, nothing done"));
417 statusLine->setText(tr("Nothing selected, nothing done"));
423 * Change current working directory
425 bool restorePage::cwd(const char *dir)
428 char cd_cmd[MAXSTRING];
430 statusLine->setText("");
431 bsnprintf(cd_cmd, sizeof(cd_cmd), "cd \"%s\"", dir);
432 Dmsg2(100, "dir=%s cmd=%s\n", dir, cd_cmd);
433 m_console->write_dir(cd_cmd);
435 if ((stat = m_console->read()) > 0) {
436 m_cwd = m_console->msg();
437 lineEdit->insert(m_cwd);
438 Dmsg2(100, "cwd=%s msg=%s\n", m_cwd.toUtf8().data(), m_console->msg());
440 Dmsg1(000, "stat=%d\n", stat);
441 QMessageBox::critical(this, "Error", tr("cd command failed"), QMessageBox::Ok);
443 m_console->discardToPrompt();
444 return true; /* ***FIXME*** return real status */
448 * Return cwd when in tree restore mode
450 char *restorePage::get_cwd()
453 m_console->write_dir(".pwd");
454 Dmsg0(100, "send: .pwd\n");
455 if ((stat = m_console->read()) > 0) {
456 m_cwd = m_console->msg();
457 Dmsg2(100, "cwd=%s msg=%s\n", m_cwd.toUtf8().data(), m_console->msg());
459 Dmsg1(000, "Something went wrong read stat=%d\n", stat);
460 QMessageBox::critical(this, "Error", tr(".pwd command failed"), QMessageBox::Ok);
462 m_console->discardToPrompt();
463 return m_cwd.toUtf8().data();
467 * Save user settings associated with this page
469 void restorePage::writeSettings()
471 QSettings settings(m_console->m_dir->name(), "bat");
472 settings.beginGroup("RestorePage");
473 settings.setValue("splitterSizes", splitter->saveState());
478 * Read and restore user settings associated with this page
480 void restorePage::readSettings()
482 QSettings settings(m_console->m_dir->name(), "bat");
483 settings.beginGroup("RestorePage");
484 splitter->restoreState(settings.value("splitterSizes").toByteArray());