X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=bacula%2Fsrc%2Fqt-console%2Frestore%2Frestore.cpp;h=8b3dad760a83bd4fb0f682cf954c94ec85c78e68;hb=2a7fda9473a7ac2669f59e9ff0dec1cba8b12ef1;hp=0a7c416788898dee04db7781e996e48c8bd938f3;hpb=9d2232ffd3bca2a23c842bb4d776b6f806304bca;p=bacula%2Fbacula diff --git a/bacula/src/qt-console/restore/restore.cpp b/bacula/src/qt-console/restore/restore.cpp index 0a7c416788..8b3dad760a 100644 --- a/bacula/src/qt-console/restore/restore.cpp +++ b/bacula/src/qt-console/restore/restore.cpp @@ -1,34 +1,32 @@ /* Bacula® - The Network Backup Solution - Copyright (C) 2007-2007 Free Software Foundation Europe e.V. + Copyright (C) 2007-2010 Free Software Foundation Europe e.V. The main author of Bacula is Kern Sibbald, with contributions from many others, a complete list can be found in the file AUTHORS. This program is Free Software; you can redistribute it and/or - modify it under the terms of version two of the GNU General Public - License as published by the Free Software Foundation plus additions - that are listed in the file LICENSE. + modify it under the terms of version three of the GNU Affero General Public + License as published by the Free Software Foundation and included + in the file LICENSE. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Affero General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - Bacula® is a registered trademark of John Walker. + Bacula® is a registered trademark of Kern Sibbald. The licensor of Bacula is the Free Software Foundation Europe (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich, Switzerland, email:ftf@fsfeurope.org. */ /* - * Version $Id$ - * * Restore Class * * Kern Sibbald, February MMVII @@ -38,35 +36,70 @@ #include "bat.h" #include "restore.h" -restoreDialog::restoreDialog(Console *console) +static const int dbglvl = 100; + +restorePage::restorePage(int conn) { + Dmsg1(dbglvl, "Construcing restorePage Instance connection %i\n", conn); + m_conn = conn; QStringList titles; - m_console = console; - - m_console->setEnabled(false); + setupUi(this); + m_name = tr("Restore Select"); + pgInitialize(); + QTreeWidgetItem* thisitem = mainWin->getFromHash(this); + thisitem->setIcon(0,QIcon(QString::fromUtf8(":images/restore.png"))); + + m_console->notify(m_conn, false); /* this should already be off */ + connect(fileWidget, SIGNAL(itemDoubleClicked(QTreeWidgetItem*, int)), this, SLOT(fileDoubleClicked(QTreeWidgetItem *, int))); + connect(directoryWidget, SIGNAL( + currentItemChanged(QTreeWidgetItem *, QTreeWidgetItem *)), + this, SLOT(directoryItemChanged(QTreeWidgetItem *, QTreeWidgetItem *))); connect(upButton, SIGNAL(pressed()), this, SLOT(upButtonPushed())); connect(markButton, SIGNAL(pressed()), this, SLOT(markButtonPushed())); connect(unmarkButton, SIGNAL(pressed()), this, SLOT(unmarkButtonPushed())); - setFont(m_console->get_font()); - m_console->displayToPrompt(); + connect(okButton, SIGNAL(pressed()), this, SLOT(okButtonPushed())); + connect(cancelButton, SIGNAL(pressed()), this, SLOT(cancelButtonPushed())); + + fileWidget->setContextMenuPolicy(Qt::ActionsContextMenu); + fileWidget->addAction(actionMark); + fileWidget->addAction(actionUnMark); + connect(actionMark, SIGNAL(triggered()), this, SLOT(markButtonPushed())); + connect(actionUnMark, SIGNAL(triggered()), this, SLOT(unmarkButtonPushed())); + setFont(m_console->get_font()); + m_console->displayToPrompt(m_conn); - titles << "Mark" << "File" << "Mode" << "User" << "Group" << "Size" << "Date"; + titles << tr("Mark") << tr("File") << tr("Mode") << tr("User") + << tr("Group") << tr("Size") << tr("Date"); fileWidget->setHeaderLabels(titles); get_cwd(); + + readSettings(); + /* wait was entered from pre-restore + * will exit, but will reenter in fillDirectory */ + mainWin->waitExit(); fillDirectory(); + dockPage(); + setCurrent(); this->show(); + if (mainWin->m_miscDebug) Pmsg0(000, "Leave restorePage\n"); +} + +restorePage::~restorePage() +{ + writeSettings(); } /* * Fill the fileWidget box with the contents of the current directory */ -void restoreDialog::fillDirectory() +void restorePage::fillDirectory() { + mainWin->waitEnter(); char modes[20], user[20], group[20], size[20], date[30]; char marked[10]; int pnl, fnl; @@ -74,15 +107,19 @@ void restoreDialog::fillDirectory() POOLMEM *path = get_pool_memory(PM_FNAME); fileWidget->clear(); - m_console->write_dir("dir"); - QList items; + m_console->write_dir(m_conn, "dir", false); + QList treeItemList; QStringList item; - while (m_console->read() > 0) { - char *p = m_console->msg(); + m_rx.setPattern("has no children\\.$"); + bool first = true; + while (m_console->read(m_conn) > 0) { + char *p = m_console->msg(m_conn); char *l; strip_trailing_junk(p); - if (*p == '$' || !*p) { - continue; + if (*p == '$' || !*p) { continue; } + if (first) { + if (m_rx.indexIn(QString(p)) != -1) { continue; } + first = false; } l = p; skip_nonspaces(&p); /* permissions */ @@ -123,50 +160,186 @@ void restoreDialog::fillDirectory() split_path_and_filename(p, &path, &pnl, &file, &fnl); item.clear(); item << "" << file << modes << user << group << size << date; + if (item[1].endsWith("/")) { + addDirectory(item[1]); + } QTreeWidgetItem *ti = new QTreeWidgetItem((QTreeWidget *)0, item); ti->setTextAlignment(5, Qt::AlignRight); /* right align size */ - items.append(ti); + if (strcmp(marked, "*") == 0) { + ti->setIcon(0, QIcon(QString::fromUtf8(":images/check.png"))); + ti->setData(0, Qt::UserRole, true); + } else { + ti->setIcon(0, QIcon(QString::fromUtf8(":images/unchecked.png"))); + ti->setData(0, Qt::UserRole, false); + } + treeItemList.append(ti); } fileWidget->clear(); - fileWidget->insertTopLevelItems(0, items); + fileWidget->insertTopLevelItems(0, treeItemList); + for (int i=0; i<7; i++) { + fileWidget->resizeColumnToContents(i); + } free_pool_memory(file); free_pool_memory(path); + mainWin->waitExit(); +} + +/* + * Function called from fill directory when a directory is found to see if this + * directory exists in the directory pane and then add it to the directory pane + */ +void restorePage::addDirectory(QString &newdirr) +{ + QString newdir = newdirr; + QString fullpath = m_cwd + newdirr; + bool ok = true; + bool windrive = false; + + if (mainWin->m_miscDebug) { + QString msg = QString(tr("In addDirectory cwd \"%1\" newdir \"%2\" fullpath \"%3\"\n")) + .arg(m_cwd) + .arg(newdir) + .arg(fullpath); + Pmsg0(dbglvl, msg.toUtf8().data()); + } + + if (isWin32Path(newdir)) { + /* this is a windows drive */ + if (mainWin->m_miscDebug) { + Pmsg0(dbglvl, "Found windows drive\n"); + } + windrive = true; + } + + if (windrive) { + if (fullpath.left(1) == "/") { + fullpath.replace(0, 1, ""); /* strip leading / */ + } + /* If drive and not already in add it */ + if (fullpath.length() == 3 && !m_dirPaths.contains(fullpath)) { + QTreeWidgetItem *item = new QTreeWidgetItem(directoryWidget); + item->setIcon(0,QIcon(QString::fromUtf8(":images/folder.png"))); + item->setText(0, fullpath.toUtf8().data()); + if (mainWin->m_miscDebug) { + Pmsg1(dbglvl, "Pre Inserting %s\n",fullpath.toUtf8().data()); + } + m_dirPaths.insert(fullpath, item); + m_dirTreeItems.insert(item, fullpath); + directoryWidget->setCurrentItem(NULL); + } + } else { + // Unix add / first if not already there + if (m_dirPaths.empty()) { + QTreeWidgetItem *item = new QTreeWidgetItem(directoryWidget); + item->setIcon(0,QIcon(QString::fromUtf8(":images/folder.png"))); + + QString text("/"); + item->setText(0, text.toUtf8().data()); + if (mainWin->m_miscDebug) { + Pmsg1(dbglvl, "Pre Inserting %s\n",text.toUtf8().data()); + } + m_dirPaths.insert(text, item); + m_dirTreeItems.insert(item, text); + } + } + + /* Does it already exist ?? */ + if (!m_dirPaths.contains(fullpath)) { + QTreeWidgetItem *item = NULL; + if (windrive) { + /* this is the base widget */ + item = new QTreeWidgetItem(directoryWidget); + item->setText(0, fullpath.toUtf8().data()); + item->setIcon(0,QIcon(QString::fromUtf8(":images/folder.png"))); + } else { + QTreeWidgetItem *parent = m_dirPaths.value(m_cwd); + if (parent) { + /* new directories to add */ + item = new QTreeWidgetItem(parent); + item->setText(0, newdir.toUtf8().data()); + item->setIcon(0,QIcon(QString::fromUtf8(":images/folder.png"))); + directoryWidget->expandItem(parent); + } else { + ok = false; + if (mainWin->m_miscDebug) { + QString msg = QString(tr("In else of if parent cwd \"%1\" newdir \"%2\"\n")) + .arg(m_cwd) + .arg(newdir); + Pmsg0(dbglvl, msg.toUtf8().data()); + } + } + } + /* insert into both forward and reverse hash */ + if (ok) { + if (mainWin->m_miscDebug) { + Pmsg1(dbglvl, "Inserting %s\n",fullpath.toUtf8().data()); + } + m_dirPaths.insert(fullpath, item); + m_dirTreeItems.insert(item, fullpath); + } + } +} + +/* + * Executed when the tree item in the directory pane is changed. This will + * allow us to populate the file pane and make this the cwd. + */ +void restorePage::directoryItemChanged(QTreeWidgetItem *currentitem, + QTreeWidgetItem * /*previousitem*/) +{ + QString fullpath = m_dirTreeItems.value(currentitem); + statusLine->setText(""); + if (fullpath != "") { + cwd(fullpath.toUtf8().data()); + fillDirectory(); + } } -void restoreDialog::accept() +void restorePage::okButtonPushed() { this->hide(); - m_console->write("done"); - delete this; - m_console->setEnabled(true); + m_console->write(m_conn, "done"); + m_console->notify(m_conn, true); + setConsoleCurrent(); + closeStackPage(); mainWin->resetFocus(); } -void restoreDialog::reject() +void restorePage::cancelButtonPushed() { this->hide(); - m_console->write("quit"); - mainWin->set_status("Canceled"); - delete this; - m_console->setEnabled(true); + m_console->write(m_conn, "quit"); + m_console->displayToPrompt(m_conn); + mainWin->set_status(tr("Canceled")); + closeStackPage(); + m_console->notify(m_conn, true); mainWin->resetFocus(); } -void restoreDialog::fileDoubleClicked(QTreeWidgetItem *item, int column) +void restorePage::fileDoubleClicked(QTreeWidgetItem *item, int column) { char cmd[1000]; + statusLine->setText(""); if (column == 0) { /* mark/unmark */ - if (item->text(0) == "*") { - bsnprintf(cmd, sizeof(cmd), "unmark \"%s\"\n", item->text(1).toUtf8().data()); - item->setText(0, " "); + mainWin->waitEnter(); + if (item->data(0, Qt::UserRole).toBool()) { + bsnprintf(cmd, sizeof(cmd), "unmark \"%s\"", item->text(1).toUtf8().data()); + item->setIcon(0, QIcon(QString::fromUtf8(":images/unchecked.png"))); + item->setData(0, Qt::UserRole, false); } else { - bsnprintf(cmd, sizeof(cmd), "mark \"%s\"\n", item->text(1).toUtf8().data()); - item->setText(0, "*"); + bsnprintf(cmd, sizeof(cmd), "mark \"%s\"", item->text(1).toUtf8().data()); + item->setIcon(0, QIcon(QString::fromUtf8(":images/check.png"))); + item->setData(0, Qt::UserRole, true); } - m_console->write(cmd); - m_console->displayToPrompt(); + m_console->write_dir(m_conn, cmd, false); + if (m_console->read(m_conn) > 0) { + strip_trailing_junk(m_console->msg(m_conn)); + statusLine->setText(m_console->msg(m_conn)); + } + m_console->displayToPrompt(m_conn); + mainWin->waitExit(); return; } /* @@ -174,87 +347,162 @@ void restoreDialog::fileDoubleClicked(QTreeWidgetItem *item, int column) * the directory -- or nothing if it is not a directory. */ if (item->text(1).endsWith("/")) { - cwd(item->text(1).toUtf8().data()); - fillDirectory(); + QString fullpath = m_cwd + item->text(1); + QTreeWidgetItem *item = m_dirPaths.value(fullpath); + if (item) { + directoryWidget->setCurrentItem(item); + } else { + QString msg = QString("DoubleClick else of item column %1 fullpath %2\n") + .arg(column,10) + .arg(fullpath); + Pmsg0(dbglvl, msg.toUtf8().data()); + } } } -void restoreDialog::upButtonPushed() +/* + * If up button pushed, making the parent tree widget current will call fill + * directory. + */ +void restorePage::upButtonPushed() { cwd(".."); - fillDirectory(); + QTreeWidgetItem *item = m_dirPaths.value(m_cwd); + if (item) { + directoryWidget->setCurrentItem(item); + } + statusLine->setText(""); } -void restoreDialog::markButtonPushed() +/* + * Mark selected items + */ +void restorePage::markButtonPushed() { - QList items = fileWidget->selectedItems(); + mainWin->waitEnter(); + QList treeItemList = fileWidget->selectedItems(); QTreeWidgetItem *item; char cmd[1000]; - foreach (item, items) { - Dmsg1(000, "item=%s\n", item->text(1).toUtf8().data()); - if (item->text(0) == " ") { - bsnprintf(cmd, sizeof(cmd), "mark \"%s\"", item->text(1).toUtf8().data()); - item->setText(0, "*"); - m_console->write(cmd); - Dmsg1(000, "cmd=%s\n", cmd); - m_console->displayToPrompt(); + int count = 0; + statusLine->setText(""); + foreach (item, treeItemList) { + count++; + bsnprintf(cmd, sizeof(cmd), "mark \"%s\"", item->text(1).toUtf8().data()); + item->setIcon(0, QIcon(QString::fromUtf8(":images/check.png"))); + m_console->write_dir(m_conn, cmd, false); + if (m_console->read(m_conn) > 0) { + strip_trailing_junk(m_console->msg(m_conn)); + statusLine->setText(m_console->msg(m_conn)); } + Dmsg1(dbglvl, "cmd=%s\n", cmd); + m_console->discardToPrompt(m_conn); } + if (count == 0) { + mainWin->set_status("Nothing selected, nothing done"); + statusLine->setText("Nothing selected, nothing done"); + } + mainWin->waitExit(); } -void restoreDialog::unmarkButtonPushed() +/* + * Unmark selected items + */ +void restorePage::unmarkButtonPushed() { - QList items = fileWidget->selectedItems(); + mainWin->waitEnter(); + QList treeItemList = fileWidget->selectedItems(); QTreeWidgetItem *item; char cmd[1000]; - foreach (item, items) { - if (item->text(0) == "*") { - bsnprintf(cmd, sizeof(cmd), "unmark \"%s\"", item->text(1).toUtf8().data()); - item->setText(0, " "); - m_console->write(cmd); - Dmsg1(000, "cmd=%s\n", cmd); - m_console->displayToPrompt(); + int count = 0; + statusLine->setText(""); + foreach (item, treeItemList) { + count++; + bsnprintf(cmd, sizeof(cmd), "unmark \"%s\"", item->text(1).toUtf8().data()); + item->setIcon(0, QIcon(QString::fromUtf8(":images/unchecked.png"))); + m_console->write_dir(m_conn, cmd, false); + if (m_console->read(m_conn) > 0) { + strip_trailing_junk(m_console->msg(m_conn)); + statusLine->setText(m_console->msg(m_conn)); } + Dmsg1(dbglvl, "cmd=%s\n", cmd); + m_console->discardToPrompt(m_conn); + } + if (count == 0) { + mainWin->set_status(tr("Nothing selected, nothing done")); + statusLine->setText(tr("Nothing selected, nothing done")); } + mainWin->waitExit(); } /* * Change current working directory */ -bool restoreDialog::cwd(const char *dir) +bool restorePage::cwd(const char *dir) { int stat; char cd_cmd[MAXSTRING]; - bsnprintf(cd_cmd, sizeof(cd_cmd), "cd \"%s\"\n", dir); - Dmsg2(100, "dir=%s cmd=%s\n", dir, cd_cmd); - m_console->write_dir(cd_cmd); - if ((stat = m_console->read()) > 0) { - m_cwd = m_console->msg(); - Dmsg2(100, "cwd=%s msg=%s\n", m_cwd.toUtf8().data(), m_console->msg()); + mainWin->waitEnter(); + statusLine->setText(""); + bsnprintf(cd_cmd, sizeof(cd_cmd), "cd \"%s\"", dir); + Dmsg2(dbglvl, "dir=%s cmd=%s\n", dir, cd_cmd); + m_console->write_dir(m_conn, cd_cmd, false); + lineEdit->clear(); + if ((stat = m_console->read(m_conn)) > 0) { + m_cwd = m_console->msg(m_conn); + lineEdit->insert(m_cwd); + Dmsg2(dbglvl, "cwd=%s msg=%s\n", m_cwd.toUtf8().data(), m_console->msg(m_conn)); } else { - Dmsg1(000, "stat=%d\n", stat); + Dmsg1(dbglvl, "stat=%d\n", stat); + QMessageBox::critical(this, "Error", tr("cd command failed"), QMessageBox::Ok); } - m_console->discardToPrompt(); - lineEdit->clear(); - lineEdit->insert(m_cwd); + m_console->discardToPrompt(m_conn); + mainWin->waitExit(); return true; /* ***FIXME*** return real status */ } /* * Return cwd when in tree restore mode */ -char *restoreDialog::get_cwd() +char *restorePage::get_cwd() { int stat; - m_console->write_dir(".pwd"); - Dmsg0(100, "send: .pwd\n"); - if ((stat = m_console->read()) > 0) { - m_cwd = m_console->msg(); - Dmsg2(100, "cwd=%s msg=%s\n", m_cwd.toUtf8().data(), m_console->msg()); + mainWin->waitEnter(); + m_console->write_dir(m_conn, ".pwd", false); + Dmsg0(dbglvl, "send: .pwd\n"); + if ((stat = m_console->read(m_conn)) > 0) { + m_cwd = m_console->msg(m_conn); + Dmsg2(dbglvl, "cwd=%s msg=%s\n", m_cwd.toUtf8().data(), m_console->msg(m_conn)); } else { - Dmsg1(000, "stat=%d\n", stat); + Dmsg1(dbglvl, "Something went wrong read stat=%d\n", stat); + QMessageBox::critical(this, "Error", tr(".pwd command failed"), QMessageBox::Ok); } - m_console->displayToPrompt(); + m_console->discardToPrompt(m_conn); + mainWin->waitExit(); return m_cwd.toUtf8().data(); } + +/* + * Save user settings associated with this page + */ +void restorePage::writeSettings() +{ + QSettings settings(m_console->m_dir->name(), "bat"); + settings.beginGroup("RestorePage"); + settings.setValue(m_splitText, splitter->saveState()); + settings.endGroup(); +} + +/* + * Read and restore user settings associated with this page + */ +void restorePage::readSettings() +{ + m_splitText = "splitterSizes_2"; + QSettings settings(m_console->m_dir->name(), "bat"); + settings.beginGroup("RestorePage"); + if (settings.contains(m_splitText)) { + splitter->restoreState(settings.value(m_splitText).toByteArray()); + } + settings.endGroup(); +}