X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=bacula%2Fsrc%2Fqt-console%2Frestore%2Frestore.cpp;h=305c374ab279afcd405a0e674a6ac458e9b86831;hb=873a7e4b2e27e205f1f96a1db2cf33febdfa671c;hp=fececa06c2d24752491a98ea079867925f323193;hpb=4013157a3631e0a510a91f4463c035c1316c04e4;p=bacula%2Fbacula diff --git a/bacula/src/qt-console/restore/restore.cpp b/bacula/src/qt-console/restore/restore.cpp index fececa06c2..305c374ab2 100644 --- a/bacula/src/qt-console/restore/restore.cpp +++ b/bacula/src/qt-console/restore/restore.cpp @@ -1,14 +1,14 @@ /* Bacula® - The Network Backup Solution - Copyright (C) 2007-2007 Free Software Foundation Europe e.V. + Copyright (C) 2007-2008 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. + 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 @@ -27,118 +27,88 @@ */ /* - * Version $Id: restore.cpp 0 2007-02-12 10:39:38Z kerns $ + * Version $Id$ * * Restore Class * - * Kern Sibbald, February MMVI + * Kern Sibbald, February MMVII * */ #include "bat.h" #include "restore.h" - -prerestoreDialog::prerestoreDialog(Console *console) +restorePage::restorePage() { - m_console = console; /* keep compiler quiet */ + QStringList titles; + setupUi(this); - jobCombo->addItems(console->job_list); - filesetCombo->addItems(console->fileset_list); - clientCombo->addItems(console->client_list); - poolCombo->addItems(console->pool_list); - storageCombo->addItems(console->storage_list); - job_name_change(0); - connect(jobCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(job_name_change(int))); + m_name = tr("Restore Select"); + pgInitialize(); + QTreeWidgetItem* thisitem = mainWin->getFromHash(this); + thisitem->setIcon(0,QIcon(QString::fromUtf8(":images/restore.png"))); - this->show(); -} + m_console->notify(false); /* this should already be off */ + m_closeable = true; -void prerestoreDialog::accept() -{ - QString cmd; + 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())); + connect(okButton, SIGNAL(pressed()), this, SLOT(okButtonPushed())); + connect(cancelButton, SIGNAL(pressed()), this, SLOT(cancelButtonPushed())); - this->hide(); - - cmd = QString( - "restore select current fileset=\"%1\" client=\"%2\" pool=\"%3\" " - "storage=\"%4\"\n") - .arg(filesetCombo->currentText()) - .arg(clientCombo->currentText()) - .arg(poolCombo->currentText()) - .arg(storageCombo->currentText()); - - m_console->write(cmd); - m_console->display_text(cmd); - delete this; - new restoreDialog(m_console); -} + 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(); -void prerestoreDialog::reject() -{ - mainWin->set_status("Canceled"); - this->hide(); - delete this; -} + titles << tr("Mark") << tr("File") << tr("Mode") << tr("User") + << tr("Group") << tr("Size") << tr("Date"); + fileWidget->setHeaderLabels(titles); + get_cwd(); -void prerestoreDialog::job_name_change(int index) -{ - job_defaults job_defs; - - (void)index; - job_defs.job_name = jobCombo->currentText(); - if (m_console->get_job_defaults(job_defs)) { - filesetCombo->setCurrentIndex(filesetCombo->findText(job_defs.fileset_name, Qt::MatchExactly)); - clientCombo->setCurrentIndex(clientCombo->findText(job_defs.client_name, Qt::MatchExactly)); - poolCombo->setCurrentIndex(poolCombo->findText(job_defs.pool_name, Qt::MatchExactly)); - storageCombo->setCurrentIndex(storageCombo->findText(job_defs.store_name, Qt::MatchExactly)); - } + readSettings(); + fillDirectory(); + dockPage(); + setCurrent(); + this->show(); } -restoreDialog::restoreDialog(Console *console) +restorePage::~restorePage() { - m_console = console; - setupUi(this); - fillDirectory("/"); - this->show(); + writeSettings(); } /* - * Fill the CList box with files at path + * Fill the fileWidget box with the contents of the current directory */ -void restoreDialog::fillDirectory(const char *path) +void restorePage::fillDirectory() { - char pathbuf[MAXSTRING]; char modes[20], user[20], group[20], size[20], date[30]; - char file[1000]; char marked[10]; - int row = 0; - - m_console->setEnabled(false); - m_fname = path; - - - m_console->displayToPrompt(); - bsnprintf(pathbuf, sizeof(pathbuf), "cd %s", path); - Dmsg1(100, "%s\n", pathbuf); - - m_console->write(pathbuf); - m_console->display_text(pathbuf); - m_console->displayToPrompt(); + int pnl, fnl; + POOLMEM *file = get_pool_memory(PM_FNAME); + POOLMEM *path = get_pool_memory(PM_FNAME); - m_console-> write_dir("dir"); - m_console->display_text("dir"); + fileWidget->clear(); + m_console->write_dir("dir"); + QList treeItemList; + QStringList item; while (m_console->read() > 0) { char *p = m_console->msg(); char *l; strip_trailing_junk(p); - if (*p == '$') { - break; - } - Dmsg1(200, "Got: %s\n", p); - if (!*p) { + if (*p == '$' || !*p) { continue; } l = p; @@ -172,23 +142,345 @@ void restoreDialog::fillDirectory(const char *path) bstrncpy(date, l, sizeof(date)); skip_spaces(&p); if (*p == '*') { - bstrncpy(marked, "x", sizeof(marked)); + bstrncpy(marked, "*", sizeof(marked)); p++; } else { bstrncpy(marked, " ", sizeof(marked)); } -// split_path_and_filename(p, &restore->path, &restore->pnl, -// &restore->file, &restore->fnl); + 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 */ + 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, treeItemList); + for (int i=0; i<7; i++) { + fileWidget->resizeColumnToContents(i); + } + + free_pool_memory(file); + free_pool_memory(path); +} + +/* + * 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(000, msg.toUtf8().data()); + } + + if (isWin32Path(newdir)) { + /* this is a windows drive */ + if (mainWin->m_miscDebug) { + Pmsg0(000, "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(000, "Pre Inserting %s\n",fullpath.toUtf8().data()); + } + m_dirPaths.insert(fullpath, item); + m_dirTreeItems.insert(item, fullpath); + } + } 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(000, "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(000, msg.toUtf8().data()); + } + } + } + /* insert into both forward and reverse hash */ + if (ok) { + if (mainWin->m_miscDebug) { + Pmsg1(000, "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 restorePage::okButtonPushed() +{ +// printf("In restorePage::okButtonPushed\n"); + this->hide(); + m_console->write("done"); + m_console->notify(true); + setConsoleCurrent(); + closeStackPage(); + mainWin->resetFocus(); +} + + +void restorePage::cancelButtonPushed() +{ + this->hide(); + m_console->write("quit"); + m_console->displayToPrompt(); + mainWin->set_status(tr("Canceled")); + closeStackPage(); + m_console->notify(true); + mainWin->resetFocus(); +} + +void restorePage::fileDoubleClicked(QTreeWidgetItem *item, int column) +{ + char cmd[1000]; + statusLine->setText(""); + if (column == 0) { /* mark/unmark */ + 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\"", item->text(1).toUtf8().data()); + item->setIcon(0, QIcon(QString::fromUtf8(":images/check.png"))); + item->setData(0, Qt::UserRole, true); + } + m_console->write_dir(cmd); + if (m_console->read() > 0) { + strip_trailing_junk(m_console->msg()); + statusLine->setText(m_console->msg()); + } + m_console->displayToPrompt(); + return; + } + /* + * Double clicking other than column 0 means to decend into + * the directory -- or nothing if it is not a directory. + */ + if (item->text(1).endsWith("/")) { + 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(000, msg.toUtf8().data()); + } + } +} + +/* + * If up button pushed, making the parent tree widget current will call fill + * directory. + */ +void restorePage::upButtonPushed() +{ + cwd(".."); + QTreeWidgetItem *item = m_dirPaths.value(m_cwd); + if (item) { + directoryWidget->setCurrentItem(item); + } + statusLine->setText(""); +} + +/* + * Mark selected items + */ +void restorePage::markButtonPushed() +{ + QList treeItemList = fileWidget->selectedItems(); + QTreeWidgetItem *item; + char cmd[1000]; + 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(cmd); + if (m_console->read() > 0) { + strip_trailing_junk(m_console->msg()); + statusLine->setText(m_console->msg()); + } + Dmsg1(100, "cmd=%s\n", cmd); + m_console->discardToPrompt(); + } + if (count == 0) { + mainWin->set_status("Nothing selected, nothing done"); + statusLine->setText("Nothing selected, nothing done"); + } + +} -// Dmsg1(000, "restore->fname=%s\n", restore->fname); -// bstrncpy(file, restore->file, sizeof(file)); - printf("modes=%s user=%s group=%s size=%s date=%s file=%s\n", - modes, user, group, size, date, file); +/* + * Unmark selected items + */ +void restorePage::unmarkButtonPushed() +{ + QList treeItemList = fileWidget->selectedItems(); + QTreeWidgetItem *item; + char cmd[1000]; + 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(cmd); + if (m_console->read() > 0) { + strip_trailing_junk(m_console->msg()); + statusLine->setText(m_console->msg()); + } + Dmsg1(100, "cmd=%s\n", cmd); + m_console->discardToPrompt(); + } + if (count == 0) { + mainWin->set_status(tr("Nothing selected, nothing done")); + statusLine->setText(tr("Nothing selected, nothing done")); + } -// append to list +} - row++; +/* + * Change current working directory + */ +bool restorePage::cwd(const char *dir) +{ + int stat; + char cd_cmd[MAXSTRING]; + + statusLine->setText(""); + bsnprintf(cd_cmd, sizeof(cd_cmd), "cd \"%s\"", dir); + Dmsg2(100, "dir=%s cmd=%s\n", dir, cd_cmd); + m_console->write_dir(cd_cmd); + lineEdit->clear(); + if ((stat = m_console->read()) > 0) { + m_cwd = m_console->msg(); + lineEdit->insert(m_cwd); + Dmsg2(100, "cwd=%s msg=%s\n", m_cwd.toUtf8().data(), m_console->msg()); + } else { + Dmsg1(000, "stat=%d\n", stat); + QMessageBox::critical(this, "Error", tr("cd command failed"), QMessageBox::Ok); } + m_console->discardToPrompt(); + return true; /* ***FIXME*** return real status */ +} - m_console->setEnabled(true); +/* + * Return cwd when in tree restore mode + */ +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()); + } else { + Dmsg1(000, "Something went wrong read stat=%d\n", stat); + QMessageBox::critical(this, "Error", tr(".pwd command failed"), QMessageBox::Ok); + } + m_console->discardToPrompt(); + 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("splitterSizes", splitter->saveState()); + settings.endGroup(); +} + +/* + * Read and restore user settings associated with this page + */ +void restorePage::readSettings() +{ + QSettings settings(m_console->m_dir->name(), "bat"); + settings.beginGroup("RestorePage"); + splitter->restoreState(settings.value("splitterSizes").toByteArray()); + settings.endGroup(); }