2 Bacula(R) - The Network Backup Solution
4 Copyright (C) 2000-2015 Kern Sibbald
5 Copyright (C) 2007-2010 Free Software Foundation Europe e.V.
7 The original author of Bacula is Kern Sibbald, with contributions
8 from many others, a complete list can be found in the file AUTHORS.
10 You may use this file and others of this release according to the
11 license defined in the LICENSE file, which includes the Affero General
12 Public License, v3.0 ("AGPLv3") and some additional permissions and
13 terms pursuant to its AGPLv3 Section 7.
15 This notice must be preserved when any source code is
16 conveyed and/or propagated.
18 Bacula(R) is a registered trademark of Kern Sibbald.
24 * Kern Sibbald, February MMVII
31 static const int dbglvl = 100;
33 restorePage::restorePage(int conn) : Pages()
35 Dmsg1(dbglvl, "Construcing restorePage Instance connection %i\n", conn);
40 m_name = tr("Restore Select");
42 QTreeWidgetItem* thisitem = mainWin->getFromHash(this);
43 thisitem->setIcon(0,QIcon(QString::fromUtf8(":images/restore.png")));
45 m_console->notify(m_conn, false); /* this should already be off */
47 connect(fileWidget, SIGNAL(itemDoubleClicked(QTreeWidgetItem*, int)),
48 this, SLOT(fileDoubleClicked(QTreeWidgetItem *, int)));
49 connect(directoryWidget, SIGNAL(
50 currentItemChanged(QTreeWidgetItem *, QTreeWidgetItem *)),
51 this, SLOT(directoryItemChanged(QTreeWidgetItem *, QTreeWidgetItem *)));
52 connect(upButton, SIGNAL(pressed()), this, SLOT(upButtonPushed()));
53 connect(markButton, SIGNAL(pressed()), this, SLOT(markButtonPushed()));
54 connect(unmarkButton, SIGNAL(pressed()), this, SLOT(unmarkButtonPushed()));
55 connect(okButton, SIGNAL(pressed()), this, SLOT(okButtonPushed()));
56 connect(cancelButton, SIGNAL(pressed()), this, SLOT(cancelButtonPushed()));
58 fileWidget->setContextMenuPolicy(Qt::ActionsContextMenu);
59 fileWidget->addAction(actionMark);
60 fileWidget->addAction(actionUnMark);
61 connect(actionMark, SIGNAL(triggered()), this, SLOT(markButtonPushed()));
62 connect(actionUnMark, SIGNAL(triggered()), this, SLOT(unmarkButtonPushed()));
64 setFont(m_console->get_font());
65 m_console->displayToPrompt(m_conn);
67 titles << tr("Mark") << tr("File") << tr("Mode") << tr("User")
68 << tr("Group") << tr("Size") << tr("Date");
69 fileWidget->setHeaderLabels(titles);
74 /* wait was entered from pre-restore
75 * will exit, but will reenter in fillDirectory */
81 if (mainWin->m_miscDebug) Pmsg0(000, "Leave restorePage\n");
84 restorePage::~restorePage()
90 * Fill the fileWidget box with the contents of the current directory
92 void restorePage::fillDirectory()
95 char modes[20], user[20], group[20], size[20], date[30];
98 POOLMEM *file = get_pool_memory(PM_FNAME);
99 POOLMEM *path = get_pool_memory(PM_FNAME);
102 m_console->write_dir(m_conn, "dir", false);
103 QList<QTreeWidgetItem *> treeItemList;
105 m_rx.setPattern("has no children\\.$");
107 while (m_console->read(m_conn) > 0) {
108 char *p = m_console->msg(m_conn);
110 strip_trailing_junk(p);
111 if (*p == '$' || !*p) { continue; }
113 if (m_rx.indexIn(QString(p)) != -1) { continue; }
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);
181 * Function called from fill directory when a directory is found to see if this
182 * directory exists in the directory pane and then add it to the directory pane
184 void restorePage::addDirectory(QString &newdirr)
186 QString newdir = newdirr;
187 QString fullpath = m_cwd + newdirr;
190 if (mainWin->m_miscDebug) {
191 QString msg = QString(tr("In addDirectory cwd \"%1\" newdir \"%2\" fullpath \"%3\"\n"))
195 Pmsg1(dbglvl, "%s\n", msg.toUtf8().data());
198 if (isWin32Path(fullpath)) {
199 if (mainWin->m_miscDebug) Pmsg0(dbglvl, "Windows drive\n");
200 if (fullpath.left(1) == "/") {
201 fullpath.replace(0, 1, ""); /* strip leading / */
203 /* If drive and not already in add it */
204 if (fullpath.length() == 3 && !m_dirPaths.contains(fullpath)) {
205 QTreeWidgetItem *item = new QTreeWidgetItem(directoryWidget);
206 item->setIcon(0,QIcon(QString::fromUtf8(":images/folder.png")));
207 item->setText(0, fullpath.toUtf8().data());
208 if (mainWin->m_miscDebug) {
209 Pmsg1(dbglvl, "Pre Inserting %s\n",fullpath.toUtf8().data());
211 m_dirPaths.insert(fullpath, item);
212 m_dirTreeItems.insert(item, fullpath);
213 directoryWidget->setCurrentItem(NULL);
216 // Unix add / first if not already there
217 if (m_dirPaths.empty()) {
218 QTreeWidgetItem *item = new QTreeWidgetItem(directoryWidget);
219 item->setIcon(0,QIcon(QString::fromUtf8(":images/folder.png")));
222 item->setText(0, text.toUtf8().data());
223 if (mainWin->m_miscDebug) {
224 Pmsg1(dbglvl, "Pre Inserting %s\n",text.toUtf8().data());
226 m_dirPaths.insert(text, item);
227 m_dirTreeItems.insert(item, text);
231 /* Does it already exist ?? */
232 if (!m_dirPaths.contains(fullpath)) {
233 QTreeWidgetItem *item = NULL;
234 if (isWin32Path(fullpath)) {
235 /* this is the base widget */
236 item = new QTreeWidgetItem(directoryWidget);
237 item->setText(0, fullpath.toUtf8().data());
238 if (mainWin->m_miscDebug) Pmsg1(dbglvl, "Windows: %s\n", fullpath.toUtf8().data());
239 item->setIcon(0,QIcon(QString::fromUtf8(":images/folder.png")));
241 QTreeWidgetItem *parent = m_dirPaths.value(m_cwd);
243 /* new directories to add */
244 item = new QTreeWidgetItem(parent);
245 item->setText(0, newdir.toUtf8().data());
246 item->setIcon(0,QIcon(QString::fromUtf8(":images/folder.png")));
247 directoryWidget->expandItem(parent);
248 if (mainWin->m_miscDebug) {
249 Pmsg1(dbglvl, "%s\n", newdir.toUtf8().data());
253 if (mainWin->m_miscDebug) {
254 QString msg = QString(tr("In else of if parent cwd \"%1\" newdir \"%2\"\n"))
257 Pmsg1(dbglvl, "%s\n", msg.toUtf8().data());
261 /* insert into both forward and reverse hash */
263 if (mainWin->m_miscDebug) {
264 Pmsg1(dbglvl, "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("");
281 if (fullpath != "") {
282 cwd(fullpath.toUtf8().data());
287 void restorePage::okButtonPushed()
290 m_console->write(m_conn, "done");
291 m_console->notify(m_conn, true);
294 mainWin->resetFocus();
298 void restorePage::cancelButtonPushed()
301 m_console->write(m_conn, "quit");
302 m_console->displayToPrompt(m_conn);
303 mainWin->set_status(tr("Canceled"));
305 m_console->notify(m_conn, true);
306 mainWin->resetFocus();
309 void restorePage::fileDoubleClicked(QTreeWidgetItem *item, int column)
312 statusLine->setText("");
313 if (column == 0) { /* mark/unmark */
314 mainWin->waitEnter();
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(m_conn, cmd, false);
325 if (m_console->read(m_conn) > 0) {
326 strip_trailing_junk(m_console->msg(m_conn));
327 statusLine->setText(m_console->msg(m_conn));
329 m_console->displayToPrompt(m_conn);
334 * Double clicking other than column 0 means to decend into
335 * the directory -- or nothing if it is not a directory.
337 if (item->text(1).endsWith("/")) {
338 QString fullpath = m_cwd + item->text(1);
339 QTreeWidgetItem *item = m_dirPaths.value(fullpath);
340 if (mainWin->m_miscDebug) {
341 Pmsg1(dbglvl, "%s\n", fullpath.toUtf8().data());
344 directoryWidget->setCurrentItem(item);
346 QString msg = QString("DoubleClick else of item column %1 fullpath %2\n")
349 if (mainWin->m_miscDebug) Pmsg1(dbglvl, "%s\n", msg.toUtf8().data());
355 * If up button pushed, making the parent tree widget current will call fill
358 void restorePage::upButtonPushed()
361 QTreeWidgetItem *item = m_dirPaths.value(m_cwd);
363 directoryWidget->setCurrentItem(item);
365 statusLine->setText("");
369 * Mark selected items
371 void restorePage::markButtonPushed()
373 mainWin->waitEnter();
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, false);
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 mainWin->waitEnter();
404 QList<QTreeWidgetItem *> treeItemList = fileWidget->selectedItems();
405 QTreeWidgetItem *item;
408 statusLine->setText("");
409 foreach (item, treeItemList) {
411 bsnprintf(cmd, sizeof(cmd), "unmark \"%s\"", item->text(1).toUtf8().data());
412 item->setIcon(0, QIcon(QString::fromUtf8(":images/unchecked.png")));
413 m_console->write_dir(m_conn, cmd, false);
414 if (m_console->read(m_conn) > 0) {
415 strip_trailing_junk(m_console->msg(m_conn));
416 statusLine->setText(m_console->msg(m_conn));
418 Dmsg1(dbglvl, "cmd=%s\n", cmd);
419 m_console->discardToPrompt(m_conn);
422 mainWin->set_status(tr("Nothing selected, nothing done"));
423 statusLine->setText(tr("Nothing selected, nothing done"));
429 * Change current working directory
431 bool restorePage::cwd(const char *dir)
434 char cd_cmd[MAXSTRING];
436 mainWin->waitEnter();
437 statusLine->setText("");
438 bsnprintf(cd_cmd, sizeof(cd_cmd), "cd \"%s\"", dir);
439 Dmsg2(dbglvl, "dir=%s cmd=%s\n", dir, cd_cmd);
440 m_console->write_dir(m_conn, cd_cmd, false);
442 if ((stat = m_console->read(m_conn)) > 0) {
443 m_cwd = m_console->msg(m_conn);
444 lineEdit->insert(m_cwd);
445 Dmsg2(dbglvl, "cwd=%s msg=%s\n", m_cwd.toUtf8().data(), m_console->msg(m_conn));
447 Dmsg1(dbglvl, "stat=%d\n", stat);
448 QMessageBox::critical(this, "Error", tr("cd command failed"), QMessageBox::Ok);
450 m_console->discardToPrompt(m_conn);
452 return true; /* ***FIXME*** return real status */
456 * Return cwd when in tree restore mode
458 char *restorePage::get_cwd()
461 mainWin->waitEnter();
462 m_console->write_dir(m_conn, ".pwd", false);
463 Dmsg0(dbglvl, "send: .pwd\n");
464 if ((stat = m_console->read(m_conn)) > 0) {
465 m_cwd = m_console->msg(m_conn);
466 Dmsg2(dbglvl, "cwd=%s msg=%s\n", m_cwd.toUtf8().data(), m_console->msg(m_conn));
468 Dmsg1(dbglvl, "Something went wrong read stat=%d\n", stat);
469 QMessageBox::critical(this, "Error", tr(".pwd command failed"), QMessageBox::Ok);
471 m_console->discardToPrompt(m_conn);
473 return m_cwd.toUtf8().data();
477 * Save user settings associated with this page
479 void restorePage::writeSettings()
481 QSettings settings(m_console->m_dir->name(), "bat");
482 settings.beginGroup("RestorePage");
483 settings.setValue(m_splitText, splitter->saveState());
488 * Read and restore user settings associated with this page
490 void restorePage::readSettings()
492 m_splitText = "splitterSizes_2";
493 QSettings settings(m_console->m_dir->name(), "bat");
494 settings.beginGroup("RestorePage");
495 if (settings.contains(m_splitText)) {
496 splitter->restoreState(settings.value(m_splitText).toByteArray());