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 plus additions
11 that are listed in the file LICENSE.
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 m_console->notify(false); /* this should already be off */
51 connect(fileWidget, SIGNAL(itemDoubleClicked(QTreeWidgetItem*, int)),
52 this, SLOT(fileDoubleClicked(QTreeWidgetItem *, int)));
53 connect(directoryWidget, SIGNAL(
54 currentItemChanged(QTreeWidgetItem *, QTreeWidgetItem *)),
55 this, SLOT(directoryItemChanged(QTreeWidgetItem *, QTreeWidgetItem *)));
56 connect(upButton, SIGNAL(pressed()), this, SLOT(upButtonPushed()));
57 connect(markButton, SIGNAL(pressed()), this, SLOT(markButtonPushed()));
58 connect(unmarkButton, SIGNAL(pressed()), this, SLOT(unmarkButtonPushed()));
59 connect(okButton, SIGNAL(pressed()), this, SLOT(okButtonPushed()));
60 connect(cancelButton, SIGNAL(pressed()), this, SLOT(cancelButtonPushed()));
61 setFont(m_console->get_font());
62 m_console->displayToPrompt();
64 titles << "Mark" << "File" << "Mode" << "User" << "Group" << "Size" << "Date";
65 fileWidget->setHeaderLabels(titles);
76 * Fill the fileWidget box with the contents of the current directory
78 void restorePage::fillDirectory()
80 char modes[20], user[20], group[20], size[20], date[30];
83 POOLMEM *file = get_pool_memory(PM_FNAME);
84 POOLMEM *path = get_pool_memory(PM_FNAME);
87 m_console->write_dir("dir");
88 QList<QTreeWidgetItem *> treeItemList;
90 while (m_console->read() > 0) {
91 char *p = m_console->msg();
93 strip_trailing_junk(p);
94 if (*p == '$' || !*p) {
98 skip_nonspaces(&p); /* permissions */
100 bstrncpy(modes, l, sizeof(modes));
102 skip_nonspaces(&p); /* link count */
106 skip_nonspaces(&p); /* user */
109 bstrncpy(user, l, sizeof(user));
111 skip_nonspaces(&p); /* group */
113 bstrncpy(group, l, sizeof(group));
116 skip_nonspaces(&p); /* size */
118 bstrncpy(size, l, sizeof(size));
121 skip_nonspaces(&p); /* date/time */
125 bstrncpy(date, l, sizeof(date));
128 bstrncpy(marked, "*", sizeof(marked));
131 bstrncpy(marked, " ", sizeof(marked));
133 split_path_and_filename(p, &path, &pnl, &file, &fnl);
135 item << "" << file << modes << user << group << size << date;
136 if (item[1].endsWith("/")) {
137 addDirectory(item[1]);
139 QTreeWidgetItem *ti = new QTreeWidgetItem((QTreeWidget *)0, item);
140 ti->setTextAlignment(5, Qt::AlignRight); /* right align size */
141 if (strcmp(marked, "*") == 0) {
142 ti->setIcon(0,QIcon(QString::fromUtf8(":images/check.png")));
144 ti->setIcon(0,QIcon(QString::fromUtf8(":images/unchecked.png")));
146 treeItemList.append(ti);
149 fileWidget->insertTopLevelItems(0, treeItemList);
150 for (int i=0; i<7; i++) {
151 fileWidget->resizeColumnToContents(i);
154 free_pool_memory(file);
155 free_pool_memory(path);
159 * Function called from fill directory when a directory is found to see if this
160 * directory exists in the directory pane and then add it to the directory pane
162 void restorePage::addDirectory(QString &newdirr)
164 QString newdir = newdirr;
165 QString fullpath = m_cwd + newdirr;
166 QRegExp regex("^/[a-z]:/$");
168 bool windrive = false;
170 if (mainWin->m_miscDebug) {
171 QString msg = QString("In addDirectory cwd \"%1\" newdir \"%2\"\n")
174 Pmsg0(000, msg.toUtf8().data());
177 /* add unix '/' directory first */
178 if (m_dirPaths.empty() && (regex.indexIn(fullpath,0) == -1)) {
179 QTreeWidgetItem *item = new QTreeWidgetItem(directoryWidget);
181 item->setText(0, text.toUtf8().data());
182 if (mainWin->m_miscDebug) {
183 Pmsg1(000, "Pre Inserting %s\n",text.toUtf8().data());
185 m_dirPaths.insert(text, item);
186 m_dirTreeItems.insert(item, text);
189 if (regex.indexIn(fullpath,0) == 0) {
190 /* this is a windows drive */
191 if (mainWin->m_miscDebug) {
192 printf("Need to do windows \"letter\":/\n");
194 fullpath.replace(0,1,"");
198 /* is it already existent ?? */
199 if (!m_dirPaths.contains(fullpath)) {
200 QTreeWidgetItem *item = NULL;
202 /* this is the base widget */
203 item = new QTreeWidgetItem(directoryWidget);
204 item->setText(0, fullpath.toUtf8().data());
206 QTreeWidgetItem *parent = m_dirPaths.value(m_cwd);
208 /* new directories to add */
209 item = new QTreeWidgetItem(parent);
210 item->setText(0, newdir.toUtf8().data());
211 directoryWidget->expandItem(parent);
214 if (mainWin->m_miscDebug) {
215 QString msg = QString("In else of if parent cwd \"%1\" newdir \"%2\"\n")
218 Pmsg0(000, msg.toUtf8().data());
222 /* insert into both forward and reverse hash */
224 if (mainWin->m_miscDebug) {
225 Pmsg1(000, "Inserting %s\n",fullpath.toUtf8().data());
227 m_dirPaths.insert(fullpath, item);
228 m_dirTreeItems.insert(item, fullpath);
234 * Executed when the tree item in the directory pane is changed. This will
235 * allow us to populate the file pane and make this the cwd.
237 void restorePage::directoryItemChanged(QTreeWidgetItem *currentitem,
238 QTreeWidgetItem * /*previousitem*/)
240 QString fullpath = m_dirTreeItems.value(currentitem);
242 cwd(fullpath.toUtf8().data());
247 void restorePage::okButtonPushed()
250 m_console->write("done");
251 m_console->notify(true);
254 mainWin->resetFocus();
258 void restorePage::cancelButtonPushed()
261 m_console->write("quit");
262 m_console->displayToPrompt();
263 mainWin->set_status("Canceled");
265 m_console->notify(true);
266 mainWin->resetFocus();
269 void restorePage::fileDoubleClicked(QTreeWidgetItem *item, int column)
272 if (column == 0) { /* mark/unmark */
273 if (item->text(0) == "*") {
274 bsnprintf(cmd, sizeof(cmd), "unmark \"%s\"", item->text(1).toUtf8().data());
275 item->setIcon(0, QIcon(QString::fromUtf8(":images/unchecked.png")));
277 bsnprintf(cmd, sizeof(cmd), "mark \"%s\"", item->text(1).toUtf8().data());
278 item->setIcon(0, QIcon(QString::fromUtf8(":images/check.png")));
280 m_console->write_dir(cmd);
281 if (m_console->read() > 0) {
282 strip_trailing_junk(m_console->msg());
283 statusLine->setText(m_console->msg());
285 m_console->displayToPrompt();
289 * Double clicking other than column 0 means to decend into
290 * the directory -- or nothing if it is not a directory.
292 if (item->text(1).endsWith("/")) {
293 QString fullpath = m_cwd + item->text(1);
294 /* check for fullpath = "/c:/" */
295 QRegExp regex("^/[a-z]:/");
296 if (regex.indexIn(fullpath,0) == 0) /* remove leading '/' */
297 fullpath.replace(0,1,"");
298 QTreeWidgetItem *item = m_dirPaths.value(fullpath);
300 directoryWidget->setCurrentItem(item);
302 QString msg = QString("DoubleClick else of item column %1 fullpath %2\n")
305 Pmsg0(000, msg.toUtf8().data());
311 * If up button pushed, making the parent tree widget current will call fill
314 void restorePage::upButtonPushed()
317 QTreeWidgetItem *item = m_dirPaths.value(m_cwd);
319 directoryWidget->setCurrentItem(item);
324 * Mark selected items
326 void restorePage::markButtonPushed()
328 QList<QTreeWidgetItem *> treeItemList = fileWidget->selectedItems();
329 QTreeWidgetItem *item;
331 foreach (item, treeItemList) {
332 bsnprintf(cmd, sizeof(cmd), "mark \"%s\"", item->text(1).toUtf8().data());
333 item->setIcon(0, QIcon(QString::fromUtf8(":images/check.png")));
334 m_console->write_dir(cmd);
335 if (m_console->read() > 0) {
336 strip_trailing_junk(m_console->msg());
337 statusLine->setText(m_console->msg());
339 Dmsg1(100, "cmd=%s\n", cmd);
340 m_console->discardToPrompt();
345 * Unmark selected items
347 void restorePage::unmarkButtonPushed()
349 QList<QTreeWidgetItem *> treeItemList = fileWidget->selectedItems();
350 QTreeWidgetItem *item;
352 foreach (item, treeItemList) {
353 bsnprintf(cmd, sizeof(cmd), "unmark \"%s\"", item->text(1).toUtf8().data());
354 item->setIcon(0, QIcon(QString::fromUtf8(":images/unchecked.png")));
355 m_console->write_dir(cmd);
356 if (m_console->read() > 0) {
357 strip_trailing_junk(m_console->msg());
358 statusLine->setText(m_console->msg());
360 Dmsg1(100, "cmd=%s\n", cmd);
361 m_console->discardToPrompt();
366 * Change current working directory
368 bool restorePage::cwd(const char *dir)
371 char cd_cmd[MAXSTRING];
373 bsnprintf(cd_cmd, sizeof(cd_cmd), "cd \"%s\"", dir);
374 Dmsg2(100, "dir=%s cmd=%s\n", dir, cd_cmd);
375 m_console->write_dir(cd_cmd);
377 if ((stat = m_console->read()) > 0) {
378 m_cwd = m_console->msg();
379 lineEdit->insert(m_cwd);
380 Dmsg2(100, "cwd=%s msg=%s\n", m_cwd.toUtf8().data(), m_console->msg());
382 Dmsg1(000, "stat=%d\n", stat);
383 QMessageBox::critical(this, "Error", "cd command failed", QMessageBox::Ok);
385 m_console->discardToPrompt();
386 return true; /* ***FIXME*** return real status */
390 * Return cwd when in tree restore mode
392 char *restorePage::get_cwd()
395 m_console->write_dir(".pwd");
396 Dmsg0(100, "send: .pwd\n");
397 if ((stat = m_console->read()) > 0) {
398 m_cwd = m_console->msg();
399 Dmsg2(100, "cwd=%s msg=%s\n", m_cwd.toUtf8().data(), m_console->msg());
401 Dmsg1(000, "Something went wrong read stat=%d\n", stat);
402 QMessageBox::critical(this, "Error", ".pwd command failed", QMessageBox::Ok);
404 m_console->discardToPrompt();
405 return m_cwd.toUtf8().data();