2 Bacula® - The Network Backup Solution
4 Copyright (C) 2007-2010 Free Software Foundation Europe e.V.
6 The main author of Bacula is Kern Sibbald, with contributions from many
7 others, a complete list can be found in the file AUTHORS.
9 You may use this file and others of this release according to the
10 license defined in the LICENSE file, which includes the Affero General
11 Public License, v3.0 ("AGPLv3") and some additional permissions and
12 terms pursuant to its AGPLv3 Section 7.
14 Bacula® is a registered trademark of Kern Sibbald.
20 * Kern Sibbald, February MMVII
27 static const int dbglvl = 100;
29 restorePage::restorePage(int conn) : Pages()
31 Dmsg1(dbglvl, "Construcing restorePage Instance connection %i\n", conn);
36 m_name = tr("Restore Select");
38 QTreeWidgetItem* thisitem = mainWin->getFromHash(this);
39 thisitem->setIcon(0,QIcon(QString::fromUtf8(":images/restore.png")));
41 m_console->notify(m_conn, false); /* this should already be off */
43 connect(fileWidget, SIGNAL(itemDoubleClicked(QTreeWidgetItem*, int)),
44 this, SLOT(fileDoubleClicked(QTreeWidgetItem *, int)));
45 connect(directoryWidget, SIGNAL(
46 currentItemChanged(QTreeWidgetItem *, QTreeWidgetItem *)),
47 this, SLOT(directoryItemChanged(QTreeWidgetItem *, QTreeWidgetItem *)));
48 connect(upButton, SIGNAL(pressed()), this, SLOT(upButtonPushed()));
49 connect(markButton, SIGNAL(pressed()), this, SLOT(markButtonPushed()));
50 connect(unmarkButton, SIGNAL(pressed()), this, SLOT(unmarkButtonPushed()));
51 connect(okButton, SIGNAL(pressed()), this, SLOT(okButtonPushed()));
52 connect(cancelButton, SIGNAL(pressed()), this, SLOT(cancelButtonPushed()));
54 fileWidget->setContextMenuPolicy(Qt::ActionsContextMenu);
55 fileWidget->addAction(actionMark);
56 fileWidget->addAction(actionUnMark);
57 connect(actionMark, SIGNAL(triggered()), this, SLOT(markButtonPushed()));
58 connect(actionUnMark, SIGNAL(triggered()), this, SLOT(unmarkButtonPushed()));
60 setFont(m_console->get_font());
61 m_console->displayToPrompt(m_conn);
63 titles << tr("Mark") << tr("File") << tr("Mode") << tr("User")
64 << tr("Group") << tr("Size") << tr("Date");
65 fileWidget->setHeaderLabels(titles);
70 /* wait was entered from pre-restore
71 * will exit, but will reenter in fillDirectory */
77 if (mainWin->m_miscDebug) Pmsg0(000, "Leave restorePage\n");
80 restorePage::~restorePage()
86 * Fill the fileWidget box with the contents of the current directory
88 void restorePage::fillDirectory()
91 char modes[20], user[20], group[20], size[20], date[30];
94 POOLMEM *file = get_pool_memory(PM_FNAME);
95 POOLMEM *path = get_pool_memory(PM_FNAME);
98 m_console->write_dir(m_conn, "dir", false);
99 QList<QTreeWidgetItem *> treeItemList;
101 m_rx.setPattern("has no children\\.$");
103 while (m_console->read(m_conn) > 0) {
104 char *p = m_console->msg(m_conn);
106 strip_trailing_junk(p);
107 if (*p == '$' || !*p) { continue; }
109 if (m_rx.indexIn(QString(p)) != -1) { continue; }
113 skip_nonspaces(&p); /* permissions */
115 bstrncpy(modes, l, sizeof(modes));
117 skip_nonspaces(&p); /* link count */
121 skip_nonspaces(&p); /* user */
124 bstrncpy(user, l, sizeof(user));
126 skip_nonspaces(&p); /* group */
128 bstrncpy(group, l, sizeof(group));
131 skip_nonspaces(&p); /* size */
133 bstrncpy(size, l, sizeof(size));
136 skip_nonspaces(&p); /* date/time */
140 bstrncpy(date, l, sizeof(date));
143 bstrncpy(marked, "*", sizeof(marked));
146 bstrncpy(marked, " ", sizeof(marked));
148 split_path_and_filename(p, &path, &pnl, &file, &fnl);
150 item << "" << file << modes << user << group << size << date;
151 if (item[1].endsWith("/")) {
152 addDirectory(item[1]);
154 QTreeWidgetItem *ti = new QTreeWidgetItem((QTreeWidget *)0, item);
155 ti->setTextAlignment(5, Qt::AlignRight); /* right align size */
156 if (strcmp(marked, "*") == 0) {
157 ti->setIcon(0, QIcon(QString::fromUtf8(":images/check.png")));
158 ti->setData(0, Qt::UserRole, true);
160 ti->setIcon(0, QIcon(QString::fromUtf8(":images/unchecked.png")));
161 ti->setData(0, Qt::UserRole, false);
163 treeItemList.append(ti);
166 fileWidget->insertTopLevelItems(0, treeItemList);
167 for (int i=0; i<7; i++) {
168 fileWidget->resizeColumnToContents(i);
171 free_pool_memory(file);
172 free_pool_memory(path);
177 * Function called from fill directory when a directory is found to see if this
178 * directory exists in the directory pane and then add it to the directory pane
180 void restorePage::addDirectory(QString &newdirr)
182 QString newdir = newdirr;
183 QString fullpath = m_cwd + newdirr;
186 if (mainWin->m_miscDebug) {
187 QString msg = QString(tr("In addDirectory cwd \"%1\" newdir \"%2\" fullpath \"%3\"\n"))
191 Pmsg1(dbglvl, "%s\n", msg.toUtf8().data());
194 if (isWin32Path(fullpath)) {
195 if (mainWin->m_miscDebug) Pmsg0(dbglvl, "Windows drive\n");
196 if (fullpath.left(1) == "/") {
197 fullpath.replace(0, 1, ""); /* strip leading / */
199 /* If drive and not already in add it */
200 if (fullpath.length() == 3 && !m_dirPaths.contains(fullpath)) {
201 QTreeWidgetItem *item = new QTreeWidgetItem(directoryWidget);
202 item->setIcon(0,QIcon(QString::fromUtf8(":images/folder.png")));
203 item->setText(0, fullpath.toUtf8().data());
204 if (mainWin->m_miscDebug) {
205 Pmsg1(dbglvl, "Pre Inserting %s\n",fullpath.toUtf8().data());
207 m_dirPaths.insert(fullpath, item);
208 m_dirTreeItems.insert(item, fullpath);
209 directoryWidget->setCurrentItem(NULL);
212 // Unix add / first if not already there
213 if (m_dirPaths.empty()) {
214 QTreeWidgetItem *item = new QTreeWidgetItem(directoryWidget);
215 item->setIcon(0,QIcon(QString::fromUtf8(":images/folder.png")));
218 item->setText(0, text.toUtf8().data());
219 if (mainWin->m_miscDebug) {
220 Pmsg1(dbglvl, "Pre Inserting %s\n",text.toUtf8().data());
222 m_dirPaths.insert(text, item);
223 m_dirTreeItems.insert(item, text);
227 /* Does it already exist ?? */
228 if (!m_dirPaths.contains(fullpath)) {
229 QTreeWidgetItem *item = NULL;
230 if (isWin32Path(fullpath)) {
231 /* this is the base widget */
232 item = new QTreeWidgetItem(directoryWidget);
233 item->setText(0, fullpath.toUtf8().data());
234 if (mainWin->m_miscDebug) Pmsg1(dbglvl, "Windows: %s\n", fullpath.toUtf8().data());
235 item->setIcon(0,QIcon(QString::fromUtf8(":images/folder.png")));
237 QTreeWidgetItem *parent = m_dirPaths.value(m_cwd);
239 /* new directories to add */
240 item = new QTreeWidgetItem(parent);
241 item->setText(0, newdir.toUtf8().data());
242 item->setIcon(0,QIcon(QString::fromUtf8(":images/folder.png")));
243 directoryWidget->expandItem(parent);
244 if (mainWin->m_miscDebug) {
245 Pmsg1(dbglvl, "%s\n", newdir.toUtf8().data());
249 if (mainWin->m_miscDebug) {
250 QString msg = QString(tr("In else of if parent cwd \"%1\" newdir \"%2\"\n"))
253 Pmsg1(dbglvl, "%s\n", msg.toUtf8().data());
257 /* insert into both forward and reverse hash */
259 if (mainWin->m_miscDebug) {
260 Pmsg1(dbglvl, "Inserting %s\n",fullpath.toUtf8().data());
262 m_dirPaths.insert(fullpath, item);
263 m_dirTreeItems.insert(item, fullpath);
269 * Executed when the tree item in the directory pane is changed. This will
270 * allow us to populate the file pane and make this the cwd.
272 void restorePage::directoryItemChanged(QTreeWidgetItem *currentitem,
273 QTreeWidgetItem * /*previousitem*/)
275 QString fullpath = m_dirTreeItems.value(currentitem);
276 statusLine->setText("");
277 if (fullpath != "") {
278 cwd(fullpath.toUtf8().data());
283 void restorePage::okButtonPushed()
286 m_console->write(m_conn, "done");
287 m_console->notify(m_conn, true);
290 mainWin->resetFocus();
294 void restorePage::cancelButtonPushed()
297 m_console->write(m_conn, "quit");
298 m_console->displayToPrompt(m_conn);
299 mainWin->set_status(tr("Canceled"));
301 m_console->notify(m_conn, true);
302 mainWin->resetFocus();
305 void restorePage::fileDoubleClicked(QTreeWidgetItem *item, int column)
308 statusLine->setText("");
309 if (column == 0) { /* mark/unmark */
310 mainWin->waitEnter();
311 if (item->data(0, Qt::UserRole).toBool()) {
312 bsnprintf(cmd, sizeof(cmd), "unmark \"%s\"", item->text(1).toUtf8().data());
313 item->setIcon(0, QIcon(QString::fromUtf8(":images/unchecked.png")));
314 item->setData(0, Qt::UserRole, false);
316 bsnprintf(cmd, sizeof(cmd), "mark \"%s\"", item->text(1).toUtf8().data());
317 item->setIcon(0, QIcon(QString::fromUtf8(":images/check.png")));
318 item->setData(0, Qt::UserRole, true);
320 m_console->write_dir(m_conn, cmd, false);
321 if (m_console->read(m_conn) > 0) {
322 strip_trailing_junk(m_console->msg(m_conn));
323 statusLine->setText(m_console->msg(m_conn));
325 m_console->displayToPrompt(m_conn);
330 * Double clicking other than column 0 means to decend into
331 * the directory -- or nothing if it is not a directory.
333 if (item->text(1).endsWith("/")) {
334 QString fullpath = m_cwd + item->text(1);
335 QTreeWidgetItem *item = m_dirPaths.value(fullpath);
336 if (mainWin->m_miscDebug) {
337 Pmsg1(dbglvl, "%s\n", fullpath.toUtf8().data());
340 directoryWidget->setCurrentItem(item);
342 QString msg = QString("DoubleClick else of item column %1 fullpath %2\n")
345 if (mainWin->m_miscDebug) Pmsg1(dbglvl, "%s\n", 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 mainWin->waitEnter();
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(m_conn, cmd, false);
380 if (m_console->read(m_conn) > 0) {
381 strip_trailing_junk(m_console->msg(m_conn));
382 statusLine->setText(m_console->msg(m_conn));
384 Dmsg1(dbglvl, "cmd=%s\n", cmd);
385 m_console->discardToPrompt(m_conn);
388 mainWin->set_status("Nothing selected, nothing done");
389 statusLine->setText("Nothing selected, nothing done");
395 * Unmark selected items
397 void restorePage::unmarkButtonPushed()
399 mainWin->waitEnter();
400 QList<QTreeWidgetItem *> treeItemList = fileWidget->selectedItems();
401 QTreeWidgetItem *item;
404 statusLine->setText("");
405 foreach (item, treeItemList) {
407 bsnprintf(cmd, sizeof(cmd), "unmark \"%s\"", item->text(1).toUtf8().data());
408 item->setIcon(0, QIcon(QString::fromUtf8(":images/unchecked.png")));
409 m_console->write_dir(m_conn, cmd, false);
410 if (m_console->read(m_conn) > 0) {
411 strip_trailing_junk(m_console->msg(m_conn));
412 statusLine->setText(m_console->msg(m_conn));
414 Dmsg1(dbglvl, "cmd=%s\n", cmd);
415 m_console->discardToPrompt(m_conn);
418 mainWin->set_status(tr("Nothing selected, nothing done"));
419 statusLine->setText(tr("Nothing selected, nothing done"));
425 * Change current working directory
427 bool restorePage::cwd(const char *dir)
430 char cd_cmd[MAXSTRING];
432 mainWin->waitEnter();
433 statusLine->setText("");
434 bsnprintf(cd_cmd, sizeof(cd_cmd), "cd \"%s\"", dir);
435 Dmsg2(dbglvl, "dir=%s cmd=%s\n", dir, cd_cmd);
436 m_console->write_dir(m_conn, cd_cmd, false);
438 if ((stat = m_console->read(m_conn)) > 0) {
439 m_cwd = m_console->msg(m_conn);
440 lineEdit->insert(m_cwd);
441 Dmsg2(dbglvl, "cwd=%s msg=%s\n", m_cwd.toUtf8().data(), m_console->msg(m_conn));
443 Dmsg1(dbglvl, "stat=%d\n", stat);
444 QMessageBox::critical(this, "Error", tr("cd command failed"), QMessageBox::Ok);
446 m_console->discardToPrompt(m_conn);
448 return true; /* ***FIXME*** return real status */
452 * Return cwd when in tree restore mode
454 char *restorePage::get_cwd()
457 mainWin->waitEnter();
458 m_console->write_dir(m_conn, ".pwd", false);
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);
469 return m_cwd.toUtf8().data();
473 * Save user settings associated with this page
475 void restorePage::writeSettings()
477 QSettings settings(m_console->m_dir->name(), "bat");
478 settings.beginGroup("RestorePage");
479 settings.setValue(m_splitText, splitter->saveState());
484 * Read and restore user settings associated with this page
486 void restorePage::readSettings()
488 m_splitText = "splitterSizes_2";
489 QSettings settings(m_console->m_dir->name(), "bat");
490 settings.beginGroup("RestorePage");
491 if (settings.contains(m_splitText)) {
492 splitter->restoreState(settings.value(m_splitText).toByteArray());