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(int conn)
43 Pmsg1(000, "Construcing restorePage Instance connection %i\n", conn);
48 m_name = tr("Restore Select");
50 QTreeWidgetItem* thisitem = mainWin->getFromHash(this);
51 thisitem->setIcon(0,QIcon(QString::fromUtf8(":images/restore.png")));
53 m_console->notify(m_conn, false); /* this should already be off */
56 connect(fileWidget, SIGNAL(itemDoubleClicked(QTreeWidgetItem*, int)),
57 this, SLOT(fileDoubleClicked(QTreeWidgetItem *, int)));
58 connect(directoryWidget, SIGNAL(
59 currentItemChanged(QTreeWidgetItem *, QTreeWidgetItem *)),
60 this, SLOT(directoryItemChanged(QTreeWidgetItem *, QTreeWidgetItem *)));
61 connect(upButton, SIGNAL(pressed()), this, SLOT(upButtonPushed()));
62 connect(markButton, SIGNAL(pressed()), this, SLOT(markButtonPushed()));
63 connect(unmarkButton, SIGNAL(pressed()), this, SLOT(unmarkButtonPushed()));
64 connect(okButton, SIGNAL(pressed()), this, SLOT(okButtonPushed()));
65 connect(cancelButton, SIGNAL(pressed()), this, SLOT(cancelButtonPushed()));
67 fileWidget->setContextMenuPolicy(Qt::ActionsContextMenu);
68 fileWidget->addAction(actionMark);
69 fileWidget->addAction(actionUnMark);
70 connect(actionMark, SIGNAL(triggered()), this, SLOT(markButtonPushed()));
71 connect(actionUnMark, SIGNAL(triggered()), this, SLOT(unmarkButtonPushed()));
73 setFont(m_console->get_font());
74 m_console->displayToPrompt(m_conn);
76 titles << tr("Mark") << tr("File") << tr("Mode") << tr("User")
77 << tr("Group") << tr("Size") << tr("Date");
78 fileWidget->setHeaderLabels(titles);
89 restorePage::~restorePage()
95 * Fill the fileWidget box with the contents of the current directory
97 void restorePage::fillDirectory()
99 char modes[20], user[20], group[20], size[20], date[30];
102 POOLMEM *file = get_pool_memory(PM_FNAME);
103 POOLMEM *path = get_pool_memory(PM_FNAME);
106 m_console->write_dir(m_conn, "dir");
107 QList<QTreeWidgetItem *> treeItemList;
109 while (m_console->read(m_conn) > 0) {
110 char *p = m_console->msg(m_conn);
112 strip_trailing_junk(p);
113 if (*p == '$' || !*p) {
117 skip_nonspaces(&p); /* permissions */
119 bstrncpy(modes, l, sizeof(modes));
121 skip_nonspaces(&p); /* link count */
125 skip_nonspaces(&p); /* user */
128 bstrncpy(user, l, sizeof(user));
130 skip_nonspaces(&p); /* group */
132 bstrncpy(group, l, sizeof(group));
135 skip_nonspaces(&p); /* size */
137 bstrncpy(size, l, sizeof(size));
140 skip_nonspaces(&p); /* date/time */
144 bstrncpy(date, l, sizeof(date));
147 bstrncpy(marked, "*", sizeof(marked));
150 bstrncpy(marked, " ", sizeof(marked));
152 split_path_and_filename(p, &path, &pnl, &file, &fnl);
154 item << "" << file << modes << user << group << size << date;
155 if (item[1].endsWith("/")) {
156 addDirectory(item[1]);
158 QTreeWidgetItem *ti = new QTreeWidgetItem((QTreeWidget *)0, item);
159 ti->setTextAlignment(5, Qt::AlignRight); /* right align size */
160 if (strcmp(marked, "*") == 0) {
161 ti->setIcon(0, QIcon(QString::fromUtf8(":images/check.png")));
162 ti->setData(0, Qt::UserRole, true);
164 ti->setIcon(0, QIcon(QString::fromUtf8(":images/unchecked.png")));
165 ti->setData(0, Qt::UserRole, false);
167 treeItemList.append(ti);
170 fileWidget->insertTopLevelItems(0, treeItemList);
171 for (int i=0; i<7; i++) {
172 fileWidget->resizeColumnToContents(i);
175 free_pool_memory(file);
176 free_pool_memory(path);
180 * Function called from fill directory when a directory is found to see if this
181 * directory exists in the directory pane and then add it to the directory pane
183 void restorePage::addDirectory(QString &newdirr)
185 QString newdir = newdirr;
186 QString fullpath = m_cwd + newdirr;
188 bool windrive = false;
190 if (mainWin->m_miscDebug) {
191 QString msg = QString(tr("In addDirectory cwd \"%1\" newdir \"%2\" fullpath \"%3\"\n"))
195 Pmsg0(000, msg.toUtf8().data());
198 if (isWin32Path(newdir)) {
199 /* this is a windows drive */
200 if (mainWin->m_miscDebug) {
201 Pmsg0(000, "Found windows drive\n");
207 if (fullpath.left(1) == "/") {
208 fullpath.replace(0, 1, ""); /* strip leading / */
210 /* If drive and not already in add it */
211 if (fullpath.length() == 3 && !m_dirPaths.contains(fullpath)) {
212 QTreeWidgetItem *item = new QTreeWidgetItem(directoryWidget);
213 item->setIcon(0,QIcon(QString::fromUtf8(":images/folder.png")));
214 item->setText(0, fullpath.toUtf8().data());
215 if (mainWin->m_miscDebug) {
216 Pmsg1(000, "Pre Inserting %s\n",fullpath.toUtf8().data());
218 m_dirPaths.insert(fullpath, item);
219 m_dirTreeItems.insert(item, fullpath);
220 directoryWidget->setCurrentItem(NULL);
223 // Unix add / first if not already there
224 if (m_dirPaths.empty()) {
225 QTreeWidgetItem *item = new QTreeWidgetItem(directoryWidget);
226 item->setIcon(0,QIcon(QString::fromUtf8(":images/folder.png")));
229 item->setText(0, text.toUtf8().data());
230 if (mainWin->m_miscDebug) {
231 Pmsg1(000, "Pre Inserting %s\n",text.toUtf8().data());
233 m_dirPaths.insert(text, item);
234 m_dirTreeItems.insert(item, text);
238 /* Does it already exist ?? */
239 if (!m_dirPaths.contains(fullpath)) {
240 QTreeWidgetItem *item = NULL;
242 /* this is the base widget */
243 item = new QTreeWidgetItem(directoryWidget);
244 item->setText(0, fullpath.toUtf8().data());
245 item->setIcon(0,QIcon(QString::fromUtf8(":images/folder.png")));
247 QTreeWidgetItem *parent = m_dirPaths.value(m_cwd);
249 /* new directories to add */
250 item = new QTreeWidgetItem(parent);
251 item->setText(0, newdir.toUtf8().data());
252 item->setIcon(0,QIcon(QString::fromUtf8(":images/folder.png")));
253 directoryWidget->expandItem(parent);
256 if (mainWin->m_miscDebug) {
257 QString msg = QString(tr("In else of if parent cwd \"%1\" newdir \"%2\"\n"))
260 Pmsg0(000, msg.toUtf8().data());
264 /* insert into both forward and reverse hash */
266 if (mainWin->m_miscDebug) {
267 Pmsg1(000, "Inserting %s\n",fullpath.toUtf8().data());
269 m_dirPaths.insert(fullpath, item);
270 m_dirTreeItems.insert(item, fullpath);
276 * Executed when the tree item in the directory pane is changed. This will
277 * allow us to populate the file pane and make this the cwd.
279 void restorePage::directoryItemChanged(QTreeWidgetItem *currentitem,
280 QTreeWidgetItem * /*previousitem*/)
282 QString fullpath = m_dirTreeItems.value(currentitem);
283 statusLine->setText("");
285 cwd(fullpath.toUtf8().data());
290 void restorePage::okButtonPushed()
292 // printf("In restorePage::okButtonPushed\n");
294 m_console->write(m_conn, "done");
295 m_console->notify(m_conn, true);
298 mainWin->resetFocus();
302 void restorePage::cancelButtonPushed()
305 m_console->write(m_conn, "quit");
306 m_console->displayToPrompt(m_conn);
307 mainWin->set_status(tr("Canceled"));
309 m_console->notify(m_conn, true);
310 mainWin->resetFocus();
313 void restorePage::fileDoubleClicked(QTreeWidgetItem *item, int column)
316 statusLine->setText("");
317 if (column == 0) { /* mark/unmark */
318 if (item->data(0, Qt::UserRole).toBool()) {
319 bsnprintf(cmd, sizeof(cmd), "unmark \"%s\"", item->text(1).toUtf8().data());
320 item->setIcon(0, QIcon(QString::fromUtf8(":images/unchecked.png")));
321 item->setData(0, Qt::UserRole, false);
323 bsnprintf(cmd, sizeof(cmd), "mark \"%s\"", item->text(1).toUtf8().data());
324 item->setIcon(0, QIcon(QString::fromUtf8(":images/check.png")));
325 item->setData(0, Qt::UserRole, true);
327 m_console->write_dir(m_conn, cmd);
328 if (m_console->read(m_conn) > 0) {
329 strip_trailing_junk(m_console->msg(m_conn));
330 statusLine->setText(m_console->msg(m_conn));
332 m_console->displayToPrompt(m_conn);
336 * Double clicking other than column 0 means to decend into
337 * the directory -- or nothing if it is not a directory.
339 if (item->text(1).endsWith("/")) {
340 QString fullpath = m_cwd + item->text(1);
341 QTreeWidgetItem *item = m_dirPaths.value(fullpath);
343 directoryWidget->setCurrentItem(item);
345 QString msg = QString("DoubleClick else of item column %1 fullpath %2\n")
348 Pmsg0(000, msg.toUtf8().data());
354 * If up button pushed, making the parent tree widget current will call fill
357 void restorePage::upButtonPushed()
360 QTreeWidgetItem *item = m_dirPaths.value(m_cwd);
362 directoryWidget->setCurrentItem(item);
364 statusLine->setText("");
368 * Mark selected items
370 void restorePage::markButtonPushed()
372 QList<QTreeWidgetItem *> treeItemList = fileWidget->selectedItems();
373 QTreeWidgetItem *item;
376 statusLine->setText("");
377 foreach (item, treeItemList) {
379 bsnprintf(cmd, sizeof(cmd), "mark \"%s\"", item->text(1).toUtf8().data());
380 item->setIcon(0, QIcon(QString::fromUtf8(":images/check.png")));
381 m_console->write_dir(m_conn, cmd);
382 if (m_console->read(m_conn) > 0) {
383 strip_trailing_junk(m_console->msg(m_conn));
384 statusLine->setText(m_console->msg(m_conn));
386 Dmsg1(100, "cmd=%s\n", cmd);
387 m_console->discardToPrompt(m_conn);
390 mainWin->set_status("Nothing selected, nothing done");
391 statusLine->setText("Nothing selected, nothing done");
397 * Unmark selected items
399 void restorePage::unmarkButtonPushed()
401 QList<QTreeWidgetItem *> treeItemList = fileWidget->selectedItems();
402 QTreeWidgetItem *item;
405 statusLine->setText("");
406 foreach (item, treeItemList) {
408 bsnprintf(cmd, sizeof(cmd), "unmark \"%s\"", item->text(1).toUtf8().data());
409 item->setIcon(0, QIcon(QString::fromUtf8(":images/unchecked.png")));
410 m_console->write_dir(m_conn, cmd);
411 if (m_console->read(m_conn) > 0) {
412 strip_trailing_junk(m_console->msg(m_conn));
413 statusLine->setText(m_console->msg(m_conn));
415 Dmsg1(100, "cmd=%s\n", cmd);
416 m_console->discardToPrompt(m_conn);
419 mainWin->set_status(tr("Nothing selected, nothing done"));
420 statusLine->setText(tr("Nothing selected, nothing done"));
426 * Change current working directory
428 bool restorePage::cwd(const char *dir)
431 char cd_cmd[MAXSTRING];
433 statusLine->setText("");
434 bsnprintf(cd_cmd, sizeof(cd_cmd), "cd \"%s\"", dir);
435 Dmsg2(100, "dir=%s cmd=%s\n", dir, cd_cmd);
436 m_console->write_dir(m_conn, cd_cmd);
438 if ((stat = m_console->read(m_conn)) > 0) {
439 m_cwd = m_console->msg(m_conn);
440 lineEdit->insert(m_cwd);
441 Dmsg2(100, "cwd=%s msg=%s\n", m_cwd.toUtf8().data(), m_console->msg(m_conn));
443 Dmsg1(000, "stat=%d\n", stat);
444 QMessageBox::critical(this, "Error", tr("cd command failed"), QMessageBox::Ok);
446 m_console->discardToPrompt(m_conn);
447 return true; /* ***FIXME*** return real status */
451 * Return cwd when in tree restore mode
453 char *restorePage::get_cwd()
456 m_console->write_dir(m_conn, ".pwd");
457 Dmsg0(100, "send: .pwd\n");
458 if ((stat = m_console->read(m_conn)) > 0) {
459 m_cwd = m_console->msg(m_conn);
460 Dmsg2(100, "cwd=%s msg=%s\n", m_cwd.toUtf8().data(), m_console->msg(m_conn));
462 Dmsg1(000, "Something went wrong read stat=%d\n", stat);
463 QMessageBox::critical(this, "Error", tr(".pwd command failed"), QMessageBox::Ok);
465 m_console->discardToPrompt(m_conn);
466 return m_cwd.toUtf8().data();
470 * Save user settings associated with this page
472 void restorePage::writeSettings()
474 QSettings settings(m_console->m_dir->name(), "bat");
475 settings.beginGroup("RestorePage");
476 settings.setValue("splitterSizes", splitter->saveState());
481 * Read and restore user settings associated with this page
483 void restorePage::readSettings()
485 QSettings settings(m_console->m_dir->name(), "bat");
486 settings.beginGroup("RestorePage");
487 splitter->restoreState(settings.value("splitterSizes").toByteArray());