2 Bacula® - The Network Backup Solution
4 Copyright (C) 2007-2007 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 John Walker.
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()
46 m_name = "Restore Select";
48 QTreeWidgetItem* thisitem = mainWin->getFromHash(this);
49 thisitem->setIcon(0,QIcon(QString::fromUtf8(":images/restore.png")));
51 m_console->notify(false); /* this should already be off */
54 connect(fileWidget, SIGNAL(itemDoubleClicked(QTreeWidgetItem*, int)),
55 this, SLOT(fileDoubleClicked(QTreeWidgetItem *, int)));
56 connect(directoryWidget, SIGNAL(
57 currentItemChanged(QTreeWidgetItem *, QTreeWidgetItem *)),
58 this, SLOT(directoryItemChanged(QTreeWidgetItem *, QTreeWidgetItem *)));
59 connect(upButton, SIGNAL(pressed()), this, SLOT(upButtonPushed()));
60 connect(markButton, SIGNAL(pressed()), this, SLOT(markButtonPushed()));
61 connect(unmarkButton, SIGNAL(pressed()), this, SLOT(unmarkButtonPushed()));
62 connect(okButton, SIGNAL(pressed()), this, SLOT(okButtonPushed()));
63 connect(cancelButton, SIGNAL(pressed()), this, SLOT(cancelButtonPushed()));
65 fileWidget->setContextMenuPolicy(Qt::ActionsContextMenu);
66 fileWidget->addAction(actionMark);
67 fileWidget->addAction(actionUnMark);
68 connect(actionMark, SIGNAL(triggered()), this, SLOT(markButtonPushed()));
69 connect(actionUnMark, SIGNAL(triggered()), this, SLOT(unmarkButtonPushed()));
71 setFont(m_console->get_font());
72 m_console->displayToPrompt();
74 titles << "Mark" << "File" << "Mode" << "User" << "Group" << "Size" << "Date";
75 fileWidget->setHeaderLabels(titles);
86 restorePage::~restorePage()
92 * Fill the fileWidget box with the contents of the current directory
94 void restorePage::fillDirectory()
96 char modes[20], user[20], group[20], size[20], date[30];
99 POOLMEM *file = get_pool_memory(PM_FNAME);
100 POOLMEM *path = get_pool_memory(PM_FNAME);
103 m_console->write_dir("dir");
104 QList<QTreeWidgetItem *> treeItemList;
106 while (m_console->read() > 0) {
107 char *p = m_console->msg();
109 strip_trailing_junk(p);
110 if (*p == '$' || !*p) {
114 skip_nonspaces(&p); /* permissions */
116 bstrncpy(modes, l, sizeof(modes));
118 skip_nonspaces(&p); /* link count */
122 skip_nonspaces(&p); /* user */
125 bstrncpy(user, l, sizeof(user));
127 skip_nonspaces(&p); /* group */
129 bstrncpy(group, l, sizeof(group));
132 skip_nonspaces(&p); /* size */
134 bstrncpy(size, l, sizeof(size));
137 skip_nonspaces(&p); /* date/time */
141 bstrncpy(date, l, sizeof(date));
144 bstrncpy(marked, "*", sizeof(marked));
147 bstrncpy(marked, " ", sizeof(marked));
149 split_path_and_filename(p, &path, &pnl, &file, &fnl);
151 item << "" << file << modes << user << group << size << date;
152 if (item[1].endsWith("/")) {
153 addDirectory(item[1]);
155 QTreeWidgetItem *ti = new QTreeWidgetItem((QTreeWidget *)0, item);
156 ti->setTextAlignment(5, Qt::AlignRight); /* right align size */
157 if (strcmp(marked, "*") == 0) {
158 ti->setIcon(0, QIcon(QString::fromUtf8(":images/check.png")));
159 ti->setData(0, Qt::UserRole, true);
161 ti->setIcon(0, QIcon(QString::fromUtf8(":images/unchecked.png")));
162 ti->setData(0, Qt::UserRole, false);
164 treeItemList.append(ti);
167 fileWidget->insertTopLevelItems(0, treeItemList);
168 for (int i=0; i<7; i++) {
169 fileWidget->resizeColumnToContents(i);
172 free_pool_memory(file);
173 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;
184 QRegExp regex("^/[a-z]:/$");
186 bool windrive = false;
188 if (mainWin->m_miscDebug) {
189 QString msg = QString("In addDirectory cwd \"%1\" newdir \"%2\"\n")
192 Pmsg0(000, msg.toUtf8().data());
195 /* add unix '/' directory first */
196 if (m_dirPaths.empty() && (regex.indexIn(fullpath,0) == -1)) {
197 QTreeWidgetItem *item = new QTreeWidgetItem(directoryWidget);
198 item->setIcon(0,QIcon(QString::fromUtf8(":images/folder.png")));
201 item->setText(0, text.toUtf8().data());
202 if (mainWin->m_miscDebug) {
203 Pmsg1(000, "Pre Inserting %s\n",text.toUtf8().data());
205 m_dirPaths.insert(text, item);
206 m_dirTreeItems.insert(item, text);
209 if (regex.indexIn(fullpath,0) == 0) {
210 /* this is a windows drive */
211 if (mainWin->m_miscDebug) {
212 Pmsg0(000, "Need to do windows \"letter\":/\n");
214 fullpath.replace(0,1,"");
218 /* is it already existent ?? */
219 if (!m_dirPaths.contains(fullpath)) {
220 QTreeWidgetItem *item = NULL;
222 /* this is the base widget */
223 item = new QTreeWidgetItem(directoryWidget);
224 item->setText(0, fullpath.toUtf8().data());
225 item->setIcon(0,QIcon(QString::fromUtf8(":images/folder.png")));
227 QTreeWidgetItem *parent = m_dirPaths.value(m_cwd);
229 /* new directories to add */
230 item = new QTreeWidgetItem(parent);
231 item->setText(0, newdir.toUtf8().data());
232 item->setIcon(0,QIcon(QString::fromUtf8(":images/folder.png")));
233 directoryWidget->expandItem(parent);
236 if (mainWin->m_miscDebug) {
237 QString msg = QString("In else of if parent cwd \"%1\" newdir \"%2\"\n")
240 Pmsg0(000, msg.toUtf8().data());
244 /* insert into both forward and reverse hash */
246 if (mainWin->m_miscDebug) {
247 Pmsg1(000, "Inserting %s\n",fullpath.toUtf8().data());
249 m_dirPaths.insert(fullpath, item);
250 m_dirTreeItems.insert(item, fullpath);
256 * Executed when the tree item in the directory pane is changed. This will
257 * allow us to populate the file pane and make this the cwd.
259 void restorePage::directoryItemChanged(QTreeWidgetItem *currentitem,
260 QTreeWidgetItem * /*previousitem*/)
262 QString fullpath = m_dirTreeItems.value(currentitem);
264 cwd(fullpath.toUtf8().data());
269 void restorePage::okButtonPushed()
271 printf("In restorePage::okButtonPushed\n");
273 m_console->write("done");
274 m_console->notify(true);
277 mainWin->resetFocus();
281 void restorePage::cancelButtonPushed()
284 m_console->write("quit");
285 m_console->displayToPrompt();
286 mainWin->set_status("Canceled");
288 m_console->notify(true);
289 mainWin->resetFocus();
292 void restorePage::fileDoubleClicked(QTreeWidgetItem *item, int column)
295 if (column == 0) { /* mark/unmark */
296 if (item->data(0, Qt::UserRole).toBool()) {
297 bsnprintf(cmd, sizeof(cmd), "unmark \"%s\"", item->text(1).toUtf8().data());
298 item->setIcon(0, QIcon(QString::fromUtf8(":images/unchecked.png")));
299 item->setData(0, Qt::UserRole, false);
301 bsnprintf(cmd, sizeof(cmd), "mark \"%s\"", item->text(1).toUtf8().data());
302 item->setIcon(0, QIcon(QString::fromUtf8(":images/check.png")));
303 item->setData(0, Qt::UserRole, true);
305 m_console->write_dir(cmd);
306 if (m_console->read() > 0) {
307 strip_trailing_junk(m_console->msg());
308 statusLine->setText(m_console->msg());
310 m_console->displayToPrompt();
314 * Double clicking other than column 0 means to decend into
315 * the directory -- or nothing if it is not a directory.
317 if (item->text(1).endsWith("/")) {
318 QString fullpath = m_cwd + item->text(1);
319 /* check for fullpath = "/c:/" */
320 QRegExp regex("^/[a-z]:/");
321 if (regex.indexIn(fullpath,0) == 0) /* remove leading '/' */
322 fullpath.replace(0,1,"");
323 QTreeWidgetItem *item = m_dirPaths.value(fullpath);
325 directoryWidget->setCurrentItem(item);
327 QString msg = QString("DoubleClick else of item column %1 fullpath %2\n")
330 Pmsg0(000, msg.toUtf8().data());
336 * If up button pushed, making the parent tree widget current will call fill
339 void restorePage::upButtonPushed()
342 QTreeWidgetItem *item = m_dirPaths.value(m_cwd);
344 directoryWidget->setCurrentItem(item);
349 * Mark selected items
351 void restorePage::markButtonPushed()
353 QList<QTreeWidgetItem *> treeItemList = fileWidget->selectedItems();
354 QTreeWidgetItem *item;
356 foreach (item, treeItemList) {
357 bsnprintf(cmd, sizeof(cmd), "mark \"%s\"", item->text(1).toUtf8().data());
358 item->setIcon(0, QIcon(QString::fromUtf8(":images/check.png")));
359 m_console->write_dir(cmd);
360 if (m_console->read() > 0) {
361 strip_trailing_junk(m_console->msg());
362 statusLine->setText(m_console->msg());
364 Dmsg1(100, "cmd=%s\n", cmd);
365 m_console->discardToPrompt();
370 * Unmark selected items
372 void restorePage::unmarkButtonPushed()
374 QList<QTreeWidgetItem *> treeItemList = fileWidget->selectedItems();
375 QTreeWidgetItem *item;
377 foreach (item, treeItemList) {
378 bsnprintf(cmd, sizeof(cmd), "unmark \"%s\"", item->text(1).toUtf8().data());
379 item->setIcon(0, QIcon(QString::fromUtf8(":images/unchecked.png")));
380 m_console->write_dir(cmd);
381 if (m_console->read() > 0) {
382 strip_trailing_junk(m_console->msg());
383 statusLine->setText(m_console->msg());
385 Dmsg1(100, "cmd=%s\n", cmd);
386 m_console->discardToPrompt();
391 * Change current working directory
393 bool restorePage::cwd(const char *dir)
396 char cd_cmd[MAXSTRING];
398 bsnprintf(cd_cmd, sizeof(cd_cmd), "cd \"%s\"", dir);
399 Dmsg2(100, "dir=%s cmd=%s\n", dir, cd_cmd);
400 m_console->write_dir(cd_cmd);
402 if ((stat = m_console->read()) > 0) {
403 m_cwd = m_console->msg();
404 lineEdit->insert(m_cwd);
405 Dmsg2(100, "cwd=%s msg=%s\n", m_cwd.toUtf8().data(), m_console->msg());
407 Dmsg1(000, "stat=%d\n", stat);
408 QMessageBox::critical(this, "Error", "cd command failed", QMessageBox::Ok);
410 m_console->discardToPrompt();
411 return true; /* ***FIXME*** return real status */
415 * Return cwd when in tree restore mode
417 char *restorePage::get_cwd()
420 m_console->write_dir(".pwd");
421 Dmsg0(100, "send: .pwd\n");
422 if ((stat = m_console->read()) > 0) {
423 m_cwd = m_console->msg();
424 Dmsg2(100, "cwd=%s msg=%s\n", m_cwd.toUtf8().data(), m_console->msg());
426 Dmsg1(000, "Something went wrong read stat=%d\n", stat);
427 QMessageBox::critical(this, "Error", ".pwd command failed", QMessageBox::Ok);
429 m_console->discardToPrompt();
430 return m_cwd.toUtf8().data();
434 * Save user settings associated with this page
436 void restorePage::writeSettings()
438 QSettings settings(m_console->m_dir->name(), "bat");
439 settings.beginGroup("RestorePage");
440 settings.setValue("splitterSizes", splitter->saveState());
445 * Read and restore user settings associated with this page
447 void restorePage::readSettings()
449 QSettings settings(m_console->m_dir->name(), "bat");
450 settings.beginGroup("RestorePage");
451 splitter->restoreState(settings.value("splitterSizes").toByteArray());