2 Bacula® - The Network Backup Solution
4 Copyright (C) 2007-2009 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 static const int dbglvl = 100;
43 restorePage::restorePage(int conn)
45 Dmsg1(dbglvl, "Construcing restorePage Instance connection %i\n", conn);
50 m_name = tr("Restore Select");
52 QTreeWidgetItem* thisitem = mainWin->getFromHash(this);
53 thisitem->setIcon(0,QIcon(QString::fromUtf8(":images/restore.png")));
55 m_console->notify(m_conn, false); /* this should already be off */
58 connect(fileWidget, SIGNAL(itemDoubleClicked(QTreeWidgetItem*, int)),
59 this, SLOT(fileDoubleClicked(QTreeWidgetItem *, int)));
60 connect(directoryWidget, SIGNAL(
61 currentItemChanged(QTreeWidgetItem *, QTreeWidgetItem *)),
62 this, SLOT(directoryItemChanged(QTreeWidgetItem *, QTreeWidgetItem *)));
63 connect(upButton, SIGNAL(pressed()), this, SLOT(upButtonPushed()));
64 connect(markButton, SIGNAL(pressed()), this, SLOT(markButtonPushed()));
65 connect(unmarkButton, SIGNAL(pressed()), this, SLOT(unmarkButtonPushed()));
66 connect(okButton, SIGNAL(pressed()), this, SLOT(okButtonPushed()));
67 connect(cancelButton, SIGNAL(pressed()), this, SLOT(cancelButtonPushed()));
69 fileWidget->setContextMenuPolicy(Qt::ActionsContextMenu);
70 fileWidget->addAction(actionMark);
71 fileWidget->addAction(actionUnMark);
72 connect(actionMark, SIGNAL(triggered()), this, SLOT(markButtonPushed()));
73 connect(actionUnMark, SIGNAL(triggered()), this, SLOT(unmarkButtonPushed()));
75 setFont(m_console->get_font());
76 m_console->displayToPrompt(m_conn);
78 titles << tr("Mark") << tr("File") << tr("Mode") << tr("User")
79 << tr("Group") << tr("Size") << tr("Date");
80 fileWidget->setHeaderLabels(titles);
85 /* wait was entered from pre-restore
86 * will exit, but will reenter in fillDirectory */
94 restorePage::~restorePage()
100 * Fill the fileWidget box with the contents of the current directory
102 void restorePage::fillDirectory()
104 mainWin->waitEnter();
105 char modes[20], user[20], group[20], size[20], date[30];
108 POOLMEM *file = get_pool_memory(PM_FNAME);
109 POOLMEM *path = get_pool_memory(PM_FNAME);
112 m_console->write_dir(m_conn, "dir", false);
113 QList<QTreeWidgetItem *> treeItemList;
115 while (m_console->read(m_conn) > 0) {
116 char *p = m_console->msg(m_conn);
118 strip_trailing_junk(p);
119 if (*p == '$' || !*p) {
123 skip_nonspaces(&p); /* permissions */
125 bstrncpy(modes, l, sizeof(modes));
127 skip_nonspaces(&p); /* link count */
131 skip_nonspaces(&p); /* user */
134 bstrncpy(user, l, sizeof(user));
136 skip_nonspaces(&p); /* group */
138 bstrncpy(group, l, sizeof(group));
141 skip_nonspaces(&p); /* size */
143 bstrncpy(size, l, sizeof(size));
146 skip_nonspaces(&p); /* date/time */
150 bstrncpy(date, l, sizeof(date));
153 bstrncpy(marked, "*", sizeof(marked));
156 bstrncpy(marked, " ", sizeof(marked));
158 split_path_and_filename(p, &path, &pnl, &file, &fnl);
160 item << "" << file << modes << user << group << size << date;
161 if (item[1].endsWith("/")) {
162 addDirectory(item[1]);
164 QTreeWidgetItem *ti = new QTreeWidgetItem((QTreeWidget *)0, item);
165 ti->setTextAlignment(5, Qt::AlignRight); /* right align size */
166 if (strcmp(marked, "*") == 0) {
167 ti->setIcon(0, QIcon(QString::fromUtf8(":images/check.png")));
168 ti->setData(0, Qt::UserRole, true);
170 ti->setIcon(0, QIcon(QString::fromUtf8(":images/unchecked.png")));
171 ti->setData(0, Qt::UserRole, false);
173 treeItemList.append(ti);
176 fileWidget->insertTopLevelItems(0, treeItemList);
177 for (int i=0; i<7; i++) {
178 fileWidget->resizeColumnToContents(i);
181 free_pool_memory(file);
182 free_pool_memory(path);
187 * Function called from fill directory when a directory is found to see if this
188 * directory exists in the directory pane and then add it to the directory pane
190 void restorePage::addDirectory(QString &newdirr)
192 QString newdir = newdirr;
193 QString fullpath = m_cwd + newdirr;
195 bool windrive = false;
197 if (mainWin->m_miscDebug) {
198 QString msg = QString(tr("In addDirectory cwd \"%1\" newdir \"%2\" fullpath \"%3\"\n"))
202 Pmsg0(dbglvl, msg.toUtf8().data());
205 if (isWin32Path(newdir)) {
206 /* this is a windows drive */
207 if (mainWin->m_miscDebug) {
208 Pmsg0(dbglvl, "Found windows drive\n");
214 if (fullpath.left(1) == "/") {
215 fullpath.replace(0, 1, ""); /* strip leading / */
217 /* If drive and not already in add it */
218 if (fullpath.length() == 3 && !m_dirPaths.contains(fullpath)) {
219 QTreeWidgetItem *item = new QTreeWidgetItem(directoryWidget);
220 item->setIcon(0,QIcon(QString::fromUtf8(":images/folder.png")));
221 item->setText(0, fullpath.toUtf8().data());
222 if (mainWin->m_miscDebug) {
223 Pmsg1(dbglvl, "Pre Inserting %s\n",fullpath.toUtf8().data());
225 m_dirPaths.insert(fullpath, item);
226 m_dirTreeItems.insert(item, fullpath);
227 directoryWidget->setCurrentItem(NULL);
230 // Unix add / first if not already there
231 if (m_dirPaths.empty()) {
232 QTreeWidgetItem *item = new QTreeWidgetItem(directoryWidget);
233 item->setIcon(0,QIcon(QString::fromUtf8(":images/folder.png")));
236 item->setText(0, text.toUtf8().data());
237 if (mainWin->m_miscDebug) {
238 Pmsg1(dbglvl, "Pre Inserting %s\n",text.toUtf8().data());
240 m_dirPaths.insert(text, item);
241 m_dirTreeItems.insert(item, text);
245 /* Does it already exist ?? */
246 if (!m_dirPaths.contains(fullpath)) {
247 QTreeWidgetItem *item = NULL;
249 /* this is the base widget */
250 item = new QTreeWidgetItem(directoryWidget);
251 item->setText(0, fullpath.toUtf8().data());
252 item->setIcon(0,QIcon(QString::fromUtf8(":images/folder.png")));
254 QTreeWidgetItem *parent = m_dirPaths.value(m_cwd);
256 /* new directories to add */
257 item = new QTreeWidgetItem(parent);
258 item->setText(0, newdir.toUtf8().data());
259 item->setIcon(0,QIcon(QString::fromUtf8(":images/folder.png")));
260 directoryWidget->expandItem(parent);
263 if (mainWin->m_miscDebug) {
264 QString msg = QString(tr("In else of if parent cwd \"%1\" newdir \"%2\"\n"))
267 Pmsg0(dbglvl, msg.toUtf8().data());
271 /* insert into both forward and reverse hash */
273 if (mainWin->m_miscDebug) {
274 Pmsg1(dbglvl, "Inserting %s\n",fullpath.toUtf8().data());
276 m_dirPaths.insert(fullpath, item);
277 m_dirTreeItems.insert(item, fullpath);
283 * Executed when the tree item in the directory pane is changed. This will
284 * allow us to populate the file pane and make this the cwd.
286 void restorePage::directoryItemChanged(QTreeWidgetItem *currentitem,
287 QTreeWidgetItem * /*previousitem*/)
289 QString fullpath = m_dirTreeItems.value(currentitem);
290 statusLine->setText("");
292 cwd(fullpath.toUtf8().data());
297 void restorePage::okButtonPushed()
300 m_console->write(m_conn, "done");
301 m_console->notify(m_conn, true);
304 mainWin->resetFocus();
308 void restorePage::cancelButtonPushed()
311 m_console->write(m_conn, "quit");
312 m_console->displayToPrompt(m_conn);
313 mainWin->set_status(tr("Canceled"));
315 m_console->notify(m_conn, true);
316 mainWin->resetFocus();
319 void restorePage::fileDoubleClicked(QTreeWidgetItem *item, int column)
322 statusLine->setText("");
323 if (column == 0) { /* mark/unmark */
324 mainWin->waitEnter();
325 if (item->data(0, Qt::UserRole).toBool()) {
326 bsnprintf(cmd, sizeof(cmd), "unmark \"%s\"", item->text(1).toUtf8().data());
327 item->setIcon(0, QIcon(QString::fromUtf8(":images/unchecked.png")));
328 item->setData(0, Qt::UserRole, false);
330 bsnprintf(cmd, sizeof(cmd), "mark \"%s\"", item->text(1).toUtf8().data());
331 item->setIcon(0, QIcon(QString::fromUtf8(":images/check.png")));
332 item->setData(0, Qt::UserRole, true);
334 m_console->write_dir(m_conn, cmd, false);
335 if (m_console->read(m_conn) > 0) {
336 strip_trailing_junk(m_console->msg(m_conn));
337 statusLine->setText(m_console->msg(m_conn));
339 m_console->displayToPrompt(m_conn);
344 * Double clicking other than column 0 means to decend into
345 * the directory -- or nothing if it is not a directory.
347 if (item->text(1).endsWith("/")) {
348 QString fullpath = m_cwd + item->text(1);
349 QTreeWidgetItem *item = m_dirPaths.value(fullpath);
351 directoryWidget->setCurrentItem(item);
353 QString msg = QString("DoubleClick else of item column %1 fullpath %2\n")
356 Pmsg0(dbglvl, msg.toUtf8().data());
362 * If up button pushed, making the parent tree widget current will call fill
365 void restorePage::upButtonPushed()
368 QTreeWidgetItem *item = m_dirPaths.value(m_cwd);
370 directoryWidget->setCurrentItem(item);
372 statusLine->setText("");
376 * Mark selected items
378 void restorePage::markButtonPushed()
380 mainWin->waitEnter();
381 QList<QTreeWidgetItem *> treeItemList = fileWidget->selectedItems();
382 QTreeWidgetItem *item;
385 statusLine->setText("");
386 foreach (item, treeItemList) {
388 bsnprintf(cmd, sizeof(cmd), "mark \"%s\"", item->text(1).toUtf8().data());
389 item->setIcon(0, QIcon(QString::fromUtf8(":images/check.png")));
390 m_console->write_dir(m_conn, cmd, false);
391 if (m_console->read(m_conn) > 0) {
392 strip_trailing_junk(m_console->msg(m_conn));
393 statusLine->setText(m_console->msg(m_conn));
395 Dmsg1(dbglvl, "cmd=%s\n", cmd);
396 m_console->discardToPrompt(m_conn);
399 mainWin->set_status("Nothing selected, nothing done");
400 statusLine->setText("Nothing selected, nothing done");
406 * Unmark selected items
408 void restorePage::unmarkButtonPushed()
410 mainWin->waitEnter();
411 QList<QTreeWidgetItem *> treeItemList = fileWidget->selectedItems();
412 QTreeWidgetItem *item;
415 statusLine->setText("");
416 foreach (item, treeItemList) {
418 bsnprintf(cmd, sizeof(cmd), "unmark \"%s\"", item->text(1).toUtf8().data());
419 item->setIcon(0, QIcon(QString::fromUtf8(":images/unchecked.png")));
420 m_console->write_dir(m_conn, cmd, false);
421 if (m_console->read(m_conn) > 0) {
422 strip_trailing_junk(m_console->msg(m_conn));
423 statusLine->setText(m_console->msg(m_conn));
425 Dmsg1(dbglvl, "cmd=%s\n", cmd);
426 m_console->discardToPrompt(m_conn);
429 mainWin->set_status(tr("Nothing selected, nothing done"));
430 statusLine->setText(tr("Nothing selected, nothing done"));
436 * Change current working directory
438 bool restorePage::cwd(const char *dir)
441 char cd_cmd[MAXSTRING];
443 mainWin->waitEnter();
444 statusLine->setText("");
445 bsnprintf(cd_cmd, sizeof(cd_cmd), "cd \"%s\"", dir);
446 Dmsg2(dbglvl, "dir=%s cmd=%s\n", dir, cd_cmd);
447 m_console->write_dir(m_conn, cd_cmd, false);
449 if ((stat = m_console->read(m_conn)) > 0) {
450 m_cwd = m_console->msg(m_conn);
451 lineEdit->insert(m_cwd);
452 Dmsg2(dbglvl, "cwd=%s msg=%s\n", m_cwd.toUtf8().data(), m_console->msg(m_conn));
454 Dmsg1(dbglvl, "stat=%d\n", stat);
455 QMessageBox::critical(this, "Error", tr("cd command failed"), QMessageBox::Ok);
457 m_console->discardToPrompt(m_conn);
459 return true; /* ***FIXME*** return real status */
463 * Return cwd when in tree restore mode
465 char *restorePage::get_cwd()
468 mainWin->waitEnter();
469 m_console->write_dir(m_conn, ".pwd", false);
470 Dmsg0(dbglvl, "send: .pwd\n");
471 if ((stat = m_console->read(m_conn)) > 0) {
472 m_cwd = m_console->msg(m_conn);
473 Dmsg2(dbglvl, "cwd=%s msg=%s\n", m_cwd.toUtf8().data(), m_console->msg(m_conn));
475 Dmsg1(dbglvl, "Something went wrong read stat=%d\n", stat);
476 QMessageBox::critical(this, "Error", tr(".pwd command failed"), QMessageBox::Ok);
478 m_console->discardToPrompt(m_conn);
480 return m_cwd.toUtf8().data();
484 * Save user settings associated with this page
486 void restorePage::writeSettings()
488 QSettings settings(m_console->m_dir->name(), "bat");
489 settings.beginGroup("RestorePage");
490 settings.setValue("splitterSizes", splitter->saveState());
495 * Read and restore user settings associated with this page
497 void restorePage::readSettings()
499 QSettings settings(m_console->m_dir->name(), "bat");
500 settings.beginGroup("RestorePage");
501 splitter->restoreState(settings.value("splitterSizes").toByteArray());