From 99a9e149537f718eda5adbc4bbbc7289fb04dc4b Mon Sep 17 00:00:00 2001 From: Eric Bollengier Date: Fri, 1 Oct 2010 15:13:34 +0200 Subject: [PATCH] bat: get a simple working brestore file browser using bvfs API --- bacula/src/qt-console/bat.pro.in | 2 +- bacula/src/qt-console/restore/brestore.cpp | 185 +++++++++++++++++++-- bacula/src/qt-console/restore/brestore.ui | 68 +++++++- bacula/src/qt-console/restore/restore.h | 12 +- 4 files changed, 243 insertions(+), 24 deletions(-) diff --git a/bacula/src/qt-console/bat.pro.in b/bacula/src/qt-console/bat.pro.in index b22b3f15b2..94b9b962e8 100644 --- a/bacula/src/qt-console/bat.pro.in +++ b/bacula/src/qt-console/bat.pro.in @@ -20,7 +20,7 @@ TEMPLATE = app TARGET = bat DEPENDPATH += . INCLUDEPATH += .. . ./console ./restore ./select -LIBS += -L../lib -lbaccfg -lbac @OPENSSL_LIBS@ +LIBS += -L../lib -lbaccfg -lbac -L../findlib -lbacfind @OPENSSL_LIBS@ LIBTOOL_LINK = @QMAKE_LIBTOOL@ --silent --tag=CXX --mode=link LIBTOOL_INSTALL = @QMAKE_LIBTOOL@ --silent --mode=install QMAKE_LINK = $${LIBTOOL_LINK} $(CXX) diff --git a/bacula/src/qt-console/restore/brestore.cpp b/bacula/src/qt-console/restore/brestore.cpp index 240dc90344..6f51d05332 100644 --- a/bacula/src/qt-console/restore/brestore.cpp +++ b/bacula/src/qt-console/restore/brestore.cpp @@ -27,7 +27,6 @@ */ /* - * Version $Id$ * * bRestore Class (Eric's brestore) * @@ -37,6 +36,7 @@ #include "bat.h" #include "restore.h" +#include "util/fmtwidgetitem.h" bRestore::bRestore() { @@ -46,8 +46,8 @@ bRestore::bRestore() pgInitialize(); QTreeWidgetItem* thisitem = mainWin->getFromHash(this); thisitem->setIcon(0, QIcon(QString::fromUtf8(":images/browse.png"))); - dockPage(); m_populated = false; + m_current = NULL; } void bRestore::setClient() @@ -65,6 +65,7 @@ void bRestore::setClient() LocationEntry->clear(); if (ClientList->currentIndex() < 1) { + JobList->setEnabled(false); return; } @@ -82,13 +83,12 @@ void bRestore::setClient() QString job; QStringList results; if (m_console->sql_cmd(jobQuery, results)) { - QString field; QStringList fieldlist; /* Iterate through the record returned from the query */ foreach (QString resultline, results) { fieldlist = resultline.split("\t"); - job = fieldlist[1] + " " + fieldlist[3] + "(" + fieldlist[2] + ")"; + job = fieldlist[1] + " " + fieldlist[3] + "(" + fieldlist[2] + ") " + fieldlist[0]; JobList->addItem(job, QVariant(fieldlist[0])); } } @@ -98,34 +98,109 @@ void bRestore::setClient() void bRestore::setJob() { if (JobList->currentIndex() < 1) { + FileList->clearContents(); + FileList->setRowCount(0); + FileRevisions->clearContents(); + FileRevisions->setRowCount(0); return ; } QStringList results; QVariant tmp = JobList->itemData(JobList->currentIndex(), Qt::UserRole); - m_jobids = tmp.toString(); - QString cmd = ".bvfs_update jobid=" + m_jobids; + + m_jobids = tmp.toString(); + QString cmd = ".bvfs_get_jobids jobid=" + m_jobids; m_console->dir_cmd(cmd, results); - displayFiles("/"); - Pmsg0(000, "update done\n"); -} -void bRestore::displayFiles(uint64_t pathid) -{ + if (results.size() < 1) { + FileList->clearContents(); + FileList->setRowCount(0); + FileRevisions->clearContents(); + FileRevisions->setRowCount(0); + return; + } + m_jobids = results.at(0); + cmd = ".bvfs_update jobid=" + m_jobids; + m_console->dir_cmd(cmd, results); + + Pmsg1(0, "jobids=%s\n", m_jobids.toLocal8Bit().constData()); + + displayFiles(0, "/"); + Pmsg0(000, "update done\n"); } -void bRestore::displayFiles(QString path) +extern int decode_stat(char *buf, struct stat *statp, int32_t *LinkFI); + +void bRestore::displayFiles(int64_t pathid, QString path) { - QString q = ".bvfs_lsdir jobid=" + m_jobids + " path=" + path; + QString arg; QStringList results; + QStringList fieldlist; + struct stat statp; + int32_t LinkFI; + int nb; + int row=0; + Freeze frz_lst(*FileList); /* disable updating*/ + Freeze frz_rev(*FileRevisions); /* disable updating*/ + FileList->clearContents(); + FileRevisions->clearContents(); + FileRevisions->setRowCount(0); + + if (pathid > 0) { + arg = " pathid=" + QString().setNum(pathid); + + if (path == "..") { + path = LocationEntry->text(); + if (path != "/") { + LocationEntry->setText(path.remove(QRegExp("[^/]+/$"))); + } + } else if (path != ".") { + LocationEntry->setText(LocationEntry->text() + path); + } + } else { + LocationEntry->setText(path); + arg = " path=\"" + path + "\""; + } + + QString q = ".bvfs_lsdir jobid=" + m_jobids + arg; if (m_console->dir_cmd(q, results)) { - QString field; - QStringList fieldlist; + nb = results.size(); + FileList->setRowCount(nb); + foreach (QString resultline, results) { + //PathId, FilenameId, fileid, jobid, lstat, path + Pmsg1(0, "dir=%s\n", resultline.toLocal8Bit().constData()); + fieldlist = resultline.split("\t"); + TableItemFormatter item(*FileList, row++); + item.setTextFld(0, resultline); // keep info + item.setFileType(1, QString("folder")); // folder or file + item.setTextFld(2, fieldlist.at(5)); // path + decode_stat(fieldlist.at(4).toLocal8Bit().data(), + &statp, &LinkFI); + item.setDateFld(4, statp.st_mtime); // date + } + } + results.clear(); + q = ".bvfs_lsfiles jobid=" + m_jobids + arg; + if (m_console->dir_cmd(q, results)) { + FileList->setRowCount(results.size() + nb); foreach (QString resultline, results) { + //PathId, FilenameId, fileid, jobid, lstat, name + Pmsg1(0, "file=%s\n", resultline.toLocal8Bit().constData()); fieldlist = resultline.split("\t"); + TableItemFormatter item(*FileList, row++); + item.setTextFld(0, resultline); // keep info + item.setTextFld(2, fieldlist.at(5)); // path + decode_stat(fieldlist.at(4).toLocal8Bit().data(), + &statp, &LinkFI); + item.setBytesFld(3, QString().setNum(statp.st_size)); + item.setDateFld(4, statp.st_mtime); } } + FileList->verticalHeader()->hide(); + FileList->resizeColumnsToContents(); + FileList->resizeRowsToContents(); + FileList->setEditTriggers(QAbstractItemView::NoEditTriggers); } void bRestore::PgSeltreeWidgetClicked() @@ -138,6 +213,78 @@ void bRestore::PgSeltreeWidgetClicked() } } +void bRestore::displayFileVersion(QString pathid, QString fnid, QString client) +{ + int row=0; + struct stat statp; + int32_t LinkFI; + Freeze frz_rev(*FileRevisions); /* disable updating*/ + FileRevisions->clearContents(); + + QString q = ".bvfs_versions jobid=" + m_jobids + + " pathid=" + pathid + + " fnid=" + fnid + + " client=" + client; + + if (VersionsChk->checkState() == Qt::Checked) { + q.append(" versions"); + } + + QStringList results; + QStringList fieldlist; + + if (m_console->dir_cmd(q, results)) { + FileRevisions->setRowCount(results.size()); + foreach (QString resultline, results) { + int col=0; + // 0 1 2 3 4 5 6 7 + //PathId, FilenameId, fileid, jobid, lstat, Md5, VolName, Inchanger + Pmsg1(0, "dir=%s\n", resultline.toLocal8Bit().constData()); + fieldlist = resultline.split("\t"); + TableItemFormatter item(*FileRevisions, row++); + item.setTextFld(col++, resultline); // keep info + item.setInChanger(col++, fieldlist.at(7)); // inchanger + item.setTextFld(col++, fieldlist.at(6)); // Volume + item.setNumericFld(col++, fieldlist.at(3)); // JobId + decode_stat(fieldlist.at(4).toLocal8Bit().data(), + &statp, &LinkFI); + item.setBytesFld(col++, QString().setNum(statp.st_size)); // size + item.setDateFld(col++, statp.st_mtime); // date + item.setTextFld(col++, fieldlist.at(5)); // chksum + } + } + FileRevisions->verticalHeader()->hide(); + FileRevisions->resizeColumnsToContents(); + FileRevisions->resizeRowsToContents(); + FileRevisions->setEditTriggers(QAbstractItemView::NoEditTriggers); +} + +void bRestore::showInfoForFile(QTableWidgetItem *widget) +{ + m_current = widget; + QTableWidgetItem *first = FileList->item(widget->row(), 0); + QStringList lst = first->text().split("\t"); + if (lst.at(1) == "0") { // no filenameid, should be a path + displayFiles(lst.at(0).toLongLong(), lst.at(5)); + } else { + displayFileVersion(lst.at(0), lst.at(1), m_client); + } +} + +void bRestore::applyLocation() +{ + displayFiles(0, LocationEntry->text()); +} + +void bRestore::clearVersions(QTableWidgetItem *item) +{ + if (item != m_current) { + FileRevisions->clearContents(); + FileRevisions->setRowCount(0); + } + m_current = item ; +} + void bRestore::setupPage() { Pmsg0(000, "Setup page\n"); @@ -145,6 +292,14 @@ void bRestore::setupPage() ClientList->addItems(m_console->client_list); connect(ClientList, SIGNAL(currentIndexChanged(int)), this, SLOT(setClient())); connect(JobList, SIGNAL(currentIndexChanged(int)), this, SLOT(setJob())); + connect(FileList, SIGNAL(itemClicked(QTableWidgetItem*)), + this, SLOT(clearVersions(QTableWidgetItem *))); + connect(FileList, SIGNAL(itemDoubleClicked(QTableWidgetItem*)), + this, SLOT(showInfoForFile(QTableWidgetItem *))); + connect(LocationBp, SIGNAL(pressed()), this, SLOT(applyLocation())); + FileList->setColumnHidden(0, true); + FileRevisions->setColumnHidden(0, true); + RestoreList->setColumnHidden(0, true); m_populated = true; } diff --git a/bacula/src/qt-console/restore/brestore.ui b/bacula/src/qt-console/restore/brestore.ui index c67b0202ab..31f83836f1 100644 --- a/bacula/src/qt-console/restore/brestore.ui +++ b/bacula/src/qt-console/restore/brestore.ui @@ -54,6 +54,29 @@ 5 + + true + + + true + + + QAbstractItemView::SelectRows + + + false + + + false + + + false + + + + Data + + Type @@ -103,6 +126,26 @@ 0 + + true + + + true + + + QAbstractItemView::SingleSelection + + + QAbstractItemView::SelectRows + + + false + + + + Data + + InChanger @@ -205,6 +248,11 @@ p, li { white-space: pre-wrap; } true + + + Data + + Type @@ -217,22 +265,27 @@ p, li { white-space: pre-wrap; } - JobId + Size - FileIndex + Date - Nb Files + JobId - Size + FileIndex + + + + + Nb Files @@ -294,6 +347,13 @@ p, li { white-space: pre-wrap; } + + + + View all Versions + + + diff --git a/bacula/src/qt-console/restore/restore.h b/bacula/src/qt-console/restore/restore.h index 2a8fa5b49f..f5e87c8957 100644 --- a/bacula/src/qt-console/restore/restore.h +++ b/bacula/src/qt-console/restore/restore.h @@ -126,14 +126,18 @@ public: public slots: void setClient(); void setJob(); - - + void showInfoForFile(QTableWidgetItem *); + void applyLocation(); + void clearVersions(QTableWidgetItem *); + private: QString m_client; + QString m_jobids; + QTableWidgetItem *m_current; void setupPage(); bool m_populated; - void displayFiles(QString path); - void displayFiles(uint64_t pathid); + void displayFiles(int64_t pathid, QString path); + void displayFileVersion(QString pathid, QString fnid, QString client); }; #endif /* _RESTORE_H_ */ -- 2.39.5