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 static const int dbglvl = 100;
43 restorePage::restorePage(int conn)
45 Pmsg1(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);
91 restorePage::~restorePage()
97 * Fill the fileWidget box with the contents of the current directory
99 void restorePage::fillDirectory()
101 char modes[20], user[20], group[20], size[20], date[30];
104 POOLMEM *file = get_pool_memory(PM_FNAME);
105 POOLMEM *path = get_pool_memory(PM_FNAME);
108 m_console->write_dir(m_conn, "dir");
109 QList<QTreeWidgetItem *> treeItemList;
111 while (m_console->read(m_conn) > 0) {
112 char *p = m_console->msg(m_conn);
114 strip_trailing_junk(p);
115 if (*p == '$' || !*p) {
119 skip_nonspaces(&p); /* permissions */
121 bstrncpy(modes, l, sizeof(modes));
123 skip_nonspaces(&p); /* link count */
127 skip_nonspaces(&p); /* user */
130 bstrncpy(user, l, sizeof(user));
132 skip_nonspaces(&p); /* group */
134 bstrncpy(group, l, sizeof(group));
137 skip_nonspaces(&p); /* size */
139 bstrncpy(size, l, sizeof(size));
142 skip_nonspaces(&p); /* date/time */
146 bstrncpy(date, l, sizeof(date));
149 bstrncpy(marked, "*", sizeof(marked));
152 bstrncpy(marked, " ", sizeof(marked));
154 split_path_and_filename(p, &path, &pnl, &file, &fnl);
156 item << "" << file << modes << user << group << size << date;
157 if (item[1].endsWith("/")) {
158 addDirectory(item[1]);
160 QTreeWidgetItem *ti = new QTreeWidgetItem((QTreeWidget *)0, item);
161 ti->setTextAlignment(5, Qt::AlignRight); /* right align size */
162 if (strcmp(marked, "*") == 0) {
163 ti->setIcon(0, QIcon(QString::fromUtf8(":images/check.png")));
164 ti->setData(0, Qt::UserRole, true);
166 ti->setIcon(0, QIcon(QString::fromUtf8(":images/unchecked.png")));
167 ti->setData(0, Qt::UserRole, false);
169 treeItemList.append(ti);
172 fileWidget->insertTopLevelItems(0, treeItemList);
173 for (int i=0; i<7; i++) {
174 fileWidget->resizeColumnToContents(i);
177 free_pool_memory(file);
178 free_pool_memory(path);
182 * Function called from fill directory when a directory is found to see if this
183 * directory exists in the directory pane and then add it to the directory pane
185 void restorePage::addDirectory(QString &newdirr)
187 QString newdir = newdirr;
188 QString fullpath = m_cwd + newdirr;
190 bool windrive = false;
192 if (mainWin->m_miscDebug) {
193 QString msg = QString(tr("In addDirectory cwd \"%1\" newdir \"%2\" fullpath \"%3\"\n"))
197 Pmsg0(dbglvl, msg.toUtf8().data());
200 if (isWin32Path(newdir)) {
201 /* this is a windows drive */
202 if (mainWin->m_miscDebug) {
203 Pmsg0(dbglvl, "Found windows drive\n");
209 if (fullpath.left(1) == "/") {
210 fullpath.replace(0, 1, ""); /* strip leading / */
212 /* If drive and not already in add it */
213 if (fullpath.length() == 3 && !m_dirPaths.contains(fullpath)) {
214 QTreeWidgetItem *item = new QTreeWidgetItem(directoryWidget);
215 item->setIcon(0,QIcon(QString::fromUtf8(":images/folder.png")));
216 item->setText(0, fullpath.toUtf8().data());
217 if (mainWin->m_miscDebug) {
218 Pmsg1(dbglvl, "Pre Inserting %s\n",fullpath.toUtf8().data());
220 m_dirPaths.insert(fullpath, item);
221 m_dirTreeItems.insert(item, fullpath);
222 directoryWidget->setCurrentItem(NULL);
225 // Unix add / first if not already there
226 if (m_dirPaths.empty()) {
227 QTreeWidgetItem *item = new QTreeWidgetItem(directoryWidget);
228 item->setIcon(0,QIcon(QString::fromUtf8(":images/folder.png")));
231 item->setText(0, text.toUtf8().data());
232 if (mainWin->m_miscDebug) {
233 Pmsg1(dbglvl, "Pre Inserting %s\n",text.toUtf8().data());
235 m_dirPaths.insert(text, item);
236 m_dirTreeItems.insert(item, text);
240 /* Does it already exist ?? */
241 if (!m_dirPaths.contains(fullpath)) {
242 QTreeWidgetItem *item = NULL;
244 /* this is the base widget */
245 item = new QTreeWidgetItem(directoryWidget);
246 item->setText(0, fullpath.toUtf8().data());
247 item->setIcon(0,QIcon(QString::fromUtf8(":images/folder.png")));
249 QTreeWidgetItem *parent = m_dirPaths.value(m_cwd);
251 /* new directories to add */
252 item = new QTreeWidgetItem(parent);
253 item->setText(0, newdir.toUtf8().data());
254 item->setIcon(0,QIcon(QString::fromUtf8(":images/folder.png")));
255 directoryWidget->expandItem(parent);
258 if (mainWin->m_miscDebug) {
259 QString msg = QString(tr("In else of if parent cwd \"%1\" newdir \"%2\"\n"))
262 Pmsg0(dbglvl, msg.toUtf8().data());
266 /* insert into both forward and reverse hash */
268 if (mainWin->m_miscDebug) {
269 Pmsg1(dbglvl, "Inserting %s\n",fullpath.toUtf8().data());
271 m_dirPaths.insert(fullpath, item);
272 m_dirTreeItems.insert(item, fullpath);
278 * Executed when the tree item in the directory pane is changed. This will
279 * allow us to populate the file pane and make this the cwd.
281 void restorePage::directoryItemChanged(QTreeWidgetItem *currentitem,
282 QTreeWidgetItem * /*previousitem*/)
284 QString fullpath = m_dirTreeItems.value(currentitem);
285 statusLine->setText("");
287 cwd(fullpath.toUtf8().data());
292 void restorePage::okButtonPushed()
294 // printf("In restorePage::okButtonPushed\n");
296 m_console->write(m_conn, "done");
297 m_console->notify(m_conn, true);
300 mainWin->resetFocus();
304 void restorePage::cancelButtonPushed()
307 m_console->write(m_conn, "quit");
308 m_console->displayToPrompt(m_conn);
309 mainWin->set_status(tr("Canceled"));
311 m_console->notify(m_conn, true);
312 mainWin->resetFocus();
315 void restorePage::fileDoubleClicked(QTreeWidgetItem *item, int column)
318 statusLine->setText("");
319 if (column == 0) { /* mark/unmark */
320 if (item->data(0, Qt::UserRole).toBool()) {
321 bsnprintf(cmd, sizeof(cmd), "unmark \"%s\"", item->text(1).toUtf8().data());
322 item->setIcon(0, QIcon(QString::fromUtf8(":images/unchecked.png")));
323 item->setData(0, Qt::UserRole, false);
325 bsnprintf(cmd, sizeof(cmd), "mark \"%s\"", item->text(1).toUtf8().data());
326 item->setIcon(0, QIcon(QString::fromUtf8(":images/check.png")));
327 item->setData(0, Qt::UserRole, true);
329 m_console->write_dir(m_conn, cmd);
330 if (m_console->read(m_conn) > 0) {
331 strip_trailing_junk(m_console->msg(m_conn));
332 statusLine->setText(m_console->msg(m_conn));
334 m_console->displayToPrompt(m_conn);
338 * Double clicking other than column 0 means to decend into
339 * the directory -- or nothing if it is not a directory.
341 if (item->text(1).endsWith("/")) {
342 QString fullpath = m_cwd + item->text(1);
343 QTreeWidgetItem *item = m_dirPaths.value(fullpath);
345 directoryWidget->setCurrentItem(item);
347 QString msg = QString("DoubleClick else of item column %1 fullpath %2\n")
350 Pmsg0(dbglvl, msg.toUtf8().data());
356 * If up button pushed, making the parent tree widget current will call fill
359 void restorePage::upButtonPushed()
362 QTreeWidgetItem *item = m_dirPaths.value(m_cwd);
364 directoryWidget->setCurrentItem(item);
366 statusLine->setText("");
370 * Mark selected items
372 void restorePage::markButtonPushed()
374 QList<QTreeWidgetItem *> treeItemList = fileWidget->selectedItems();
375 QTreeWidgetItem *item;
378 statusLine->setText("");
379 foreach (item, treeItemList) {
381 bsnprintf(cmd, sizeof(cmd), "mark \"%s\"", item->text(1).toUtf8().data());
382 item->setIcon(0, QIcon(QString::fromUtf8(":images/check.png")));
383 m_console->write_dir(m_conn, cmd);
384 if (m_console->read(m_conn) > 0) {
385 strip_trailing_junk(m_console->msg(m_conn));
386 statusLine->setText(m_console->msg(m_conn));
388 Dmsg1(dbglvl, "cmd=%s\n", cmd);
389 m_console->discardToPrompt(m_conn);
392 mainWin->set_status("Nothing selected, nothing done");
393 statusLine->setText("Nothing selected, nothing done");
399 * Unmark selected items
401 void restorePage::unmarkButtonPushed()
403 QList<QTreeWidgetItem *> treeItemList = fileWidget->selectedItems();
404 QTreeWidgetItem *item;
407 statusLine->setText("");
408 foreach (item, treeItemList) {
410 bsnprintf(cmd, sizeof(cmd), "unmark \"%s\"", item->text(1).toUtf8().data());
411 item->setIcon(0, QIcon(QString::fromUtf8(":images/unchecked.png")));
412 m_console->write_dir(m_conn, cmd);
413 if (m_console->read(m_conn) > 0) {
414 strip_trailing_junk(m_console->msg(m_conn));
415 statusLine->setText(m_console->msg(m_conn));
417 Dmsg1(dbglvl, "cmd=%s\n", cmd);
418 m_console->discardToPrompt(m_conn);
421 mainWin->set_status(tr("Nothing selected, nothing done"));
422 statusLine->setText(tr("Nothing selected, nothing done"));
428 * Change current working directory
430 bool restorePage::cwd(const char *dir)
433 char cd_cmd[MAXSTRING];
435 statusLine->setText("");
436 bsnprintf(cd_cmd, sizeof(cd_cmd), "cd \"%s\"", dir);
437 Dmsg2(dbglvl, "dir=%s cmd=%s\n", dir, cd_cmd);
438 m_console->write_dir(m_conn, cd_cmd);
440 if ((stat = m_console->read(m_conn)) > 0) {
441 m_cwd = m_console->msg(m_conn);
442 lineEdit->insert(m_cwd);
443 Dmsg2(dbglvl, "cwd=%s msg=%s\n", m_cwd.toUtf8().data(), m_console->msg(m_conn));
445 Dmsg1(dbglvl, "stat=%d\n", stat);
446 QMessageBox::critical(this, "Error", tr("cd command failed"), QMessageBox::Ok);
448 m_console->discardToPrompt(m_conn);
449 return true; /* ***FIXME*** return real status */
453 * Return cwd when in tree restore mode
455 char *restorePage::get_cwd()
458 m_console->write_dir(m_conn, ".pwd");
459 Dmsg0(dbglvl, "send: .pwd\n");
460 if ((stat = m_console->read(m_conn)) > 0) {
461 m_cwd = m_console->msg(m_conn);
462 Dmsg2(dbglvl, "cwd=%s msg=%s\n", m_cwd.toUtf8().data(), m_console->msg(m_conn));
464 Dmsg1(dbglvl, "Something went wrong read stat=%d\n", stat);
465 QMessageBox::critical(this, "Error", tr(".pwd command failed"), QMessageBox::Ok);
467 m_console->discardToPrompt(m_conn);
468 return m_cwd.toUtf8().data();
472 * Save user settings associated with this page
474 void restorePage::writeSettings()
476 QSettings settings(m_console->m_dir->name(), "bat");
477 settings.beginGroup("RestorePage");
478 settings.setValue("splitterSizes", splitter->saveState());
483 * Read and restore user settings associated with this page
485 void restorePage::readSettings()
487 QSettings settings(m_console->m_dir->name(), "bat");
488 settings.beginGroup("RestorePage");
489 splitter->restoreState(settings.value("splitterSizes").toByteArray());