2 Bacula® - The Network Backup Solution
4 Copyright (C) 2007-2009 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 three of the GNU Affero 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 Affero 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 Kern Sibbald.
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.
31 * bRestore Class (Eric's brestore)
33 * Kern Sibbald, January MMVII
39 #include "util/fmtwidgetitem.h"
43 m_name = tr("bRestore");
47 QTreeWidgetItem* thisitem = mainWin->getFromHash(this);
48 thisitem->setIcon(0, QIcon(QString::fromUtf8(":images/browse.png")));
51 RestoreList->setAcceptDrops(true);
54 void bRestore::setClient()
56 Pmsg0(000, "Repopulating client table\n");
57 // Select the same client, don't touch
58 if (m_client == ClientList->currentText()) {
61 m_client = ClientList->currentText();
62 FileList->clearContents();
63 FileRevisions->clearContents();
65 JobList->setEnabled(true);
66 LocationEntry->clear();
70 if (ClientList->currentIndex() < 1) {
71 JobList->setEnabled(false);
75 JobList->addItem("Job list for " + m_client);
78 "SELECT Job.Jobid AS JobId, Job.StartTime AS StartTime,"
79 " Job.Level AS Level,"
81 " FROM Job JOIN Client USING (ClientId)"
83 " Job.JobStatus IN ('T','W') AND Job.Type='B' AND"
84 " Client.Name='" + m_client + "' ORDER BY StartTime DESC" ;
88 if (m_console->sql_cmd(jobQuery, results)) {
89 QStringList fieldlist;
91 /* Iterate through the record returned from the query */
92 foreach (QString resultline, results) {
93 fieldlist = resultline.split("\t");
94 job = fieldlist[1] + " " + fieldlist[3] + "(" + fieldlist[2] + ") " + fieldlist[0];
95 JobList->addItem(job, QVariant(fieldlist[0]));
101 void bRestore::setJob()
103 if (JobList->currentIndex() < 1) {
104 FileList->clearContents();
105 FileList->setRowCount(0);
106 FileRevisions->clearContents();
107 FileRevisions->setRowCount(0);
111 QVariant tmp = JobList->itemData(JobList->currentIndex(), Qt::UserRole);
113 m_jobids = tmp.toString();
114 QString cmd = ".bvfs_get_jobids jobid=" + m_jobids;
115 if (MergeChk->checkState() == Qt::Checked) {
119 m_console->dir_cmd(cmd, results);
121 if (results.size() < 1) {
122 FileList->clearContents();
123 FileList->setRowCount(0);
124 FileRevisions->clearContents();
125 FileRevisions->setRowCount(0);
129 m_jobids = results.at(0);
130 cmd = ".bvfs_update jobid=" + m_jobids;
131 m_console->dir_cmd(cmd, results);
133 Pmsg1(0, "jobids=%s\n", m_jobids.toLocal8Bit().constData());
135 displayFiles(m_pathid, QString(""));
136 Pmsg0(000, "update done\n");
139 extern int decode_stat(char *buf, struct stat *statp, int32_t *LinkFI);
141 void bRestore::displayFiles(int64_t pathid, QString path)
145 QStringList fieldlist;
150 Freeze frz_lst(*FileList); /* disable updating*/
151 Freeze frz_rev(*FileRevisions); /* disable updating*/
152 FileList->clearContents();
153 FileRevisions->clearContents();
154 FileRevisions->setRowCount(0);
157 arg = " pathid=" + QString().setNum(pathid);
163 m_path.remove(QRegExp("[^/]+/$"));
166 } else if (path == "/" && m_path == "") {
169 } else if (path != "/" && path != ".") {
174 arg = " path=\"" + m_path + "\"";
176 LocationEntry->setText(m_path);
178 QString q = ".bvfs_lsdir jobid=" + m_jobids + arg;
179 if (m_console->dir_cmd(q, results)) {
181 FileList->setRowCount(nb);
182 foreach (QString resultline, results) {
184 //PathId, FilenameId, fileid, jobid, lstat, path
185 fieldlist = resultline.split("\t");
186 TableItemFormatter item(*FileList, row++);
187 item.setFileType(col++, QString("folder")); // folder or file
188 item.setTextFld(col++, fieldlist.at(5)); // path
189 decode_stat(fieldlist.at(4).toLocal8Bit().data(),
191 item.setDateFld(col++, statp.st_mtime); // date
192 fieldlist.replace(3, m_jobids); // use current jobids selection
193 item.widget(1)->setData(Qt::UserRole, fieldlist.join("\t")); // keep info
198 q = ".bvfs_lsfiles jobid=" + m_jobids + arg;
199 if (m_console->dir_cmd(q, results)) {
200 FileList->setRowCount(results.size() + nb);
201 foreach (QString resultline, results) {
202 int col=1; // skip icon
203 //PathId, FilenameId, fileid, jobid, lstat, name
204 fieldlist = resultline.split("\t");
205 TableItemFormatter item(*FileList, row++);
206 item.setTextFld(col++, fieldlist.at(5)); // name
207 decode_stat(fieldlist.at(4).toLocal8Bit().data(),
209 item.setBytesFld(col++, QString().setNum(statp.st_size));
210 item.setDateFld(col++, statp.st_mtime);
211 item.widget(1)->setData(Qt::UserRole, fieldlist.join("\t")); // keep info
214 FileList->verticalHeader()->hide();
215 FileList->resizeColumnsToContents();
216 FileList->resizeRowsToContents();
217 FileList->setEditTriggers(QAbstractItemView::NoEditTriggers);
220 void bRestore::PgSeltreeWidgetClicked()
225 if (!isOnceDocked()) {
230 void bRestore::displayFileVersion(QString pathid, QString fnid,
231 QString client, QString filename)
236 Freeze frz_rev(*FileRevisions); /* disable updating*/
237 FileRevisions->clearContents();
239 QString q = ".bvfs_versions jobid=" + m_jobids +
240 " pathid=" + pathid +
244 if (VersionsChk->checkState() == Qt::Checked) {
245 q.append(" versions");
249 QStringList fieldlist;
251 if (m_console->dir_cmd(q, results)) {
252 FileRevisions->setRowCount(results.size());
253 foreach (QString resultline, results) {
256 //PathId, FilenameId, fileid, jobid, lstat, Md5, VolName, Inchanger
257 fieldlist = resultline.split("\t");
258 TableItemFormatter item(*FileRevisions, row++);
259 item.setInChanger(col++, fieldlist.at(7)); // inchanger
260 item.setTextFld(col++, fieldlist.at(6)); // Volume
261 item.setNumericFld(col++, fieldlist.at(3)); // JobId
262 decode_stat(fieldlist.at(4).toLocal8Bit().data(),
264 item.setBytesFld(col++, QString().setNum(statp.st_size)); // size
265 item.setDateFld(col++, statp.st_mtime); // date
266 item.setTextFld(col++, fieldlist.at(5)); // chksum
268 // Adjust the fieldlist for drag&drop
269 fieldlist.removeLast(); // inchanger
270 fieldlist.removeLast(); // volname
271 fieldlist.removeLast(); // md5
272 fieldlist << m_path + filename;
273 item.widget(1)->setData(Qt::UserRole, fieldlist.join("\t")); // keep info
276 FileRevisions->verticalHeader()->hide();
277 FileRevisions->resizeColumnsToContents();
278 FileRevisions->resizeRowsToContents();
279 FileRevisions->setEditTriggers(QAbstractItemView::NoEditTriggers);
282 void bRestore::showInfoForFile(QTableWidgetItem *widget)
285 QTableWidgetItem *first = FileList->item(widget->row(), 1);
286 QStringList lst = first->data(Qt::UserRole).toString().split("\t");
287 if (lst.at(1) == "0") { // no filenameid, should be a path
288 displayFiles(lst.at(0).toLongLong(), lst.at(5));
290 displayFileVersion(lst.at(0), lst.at(1), m_client, lst.at(5));
294 void bRestore::applyLocation()
296 displayFiles(0, LocationEntry->text());
299 void bRestore::clearVersions(QTableWidgetItem *item)
301 if (item != m_current) {
302 FileRevisions->clearContents();
303 FileRevisions->setRowCount(0);
308 void bRestore::clearRestoreList()
310 RestoreList->clearContents();
311 RestoreList->setRowCount(0);
314 void bRestore::runRestore()
316 bRunRestore *r = new bRunRestore(this);
320 void bRestore::setupPage()
322 ClientList->addItem("Client list");
323 ClientList->addItems(m_console->client_list);
324 connect(ClientList, SIGNAL(currentIndexChanged(int)), this, SLOT(setClient()));
325 connect(JobList, SIGNAL(currentIndexChanged(int)), this, SLOT(setJob()));
326 connect(FileList, SIGNAL(itemClicked(QTableWidgetItem*)),
327 this, SLOT(clearVersions(QTableWidgetItem *)));
328 connect(FileList, SIGNAL(itemDoubleClicked(QTableWidgetItem*)),
329 this, SLOT(showInfoForFile(QTableWidgetItem *)));
330 connect(LocationBp, SIGNAL(pressed()), this, SLOT(applyLocation()));
331 connect(MergeChk, SIGNAL(clicked()), this, SLOT(setJob()));
332 connect(ClearBp, SIGNAL(clicked()), this, SLOT(clearRestoreList()));
333 connect(RestoreBp, SIGNAL(clicked()), this, SLOT(runRestore()));
337 bRestore::~bRestore()
341 void bRestoreTable::mousePressEvent(QMouseEvent *event)
343 QTableWidget::mousePressEvent(event);
345 if (event->button() == Qt::LeftButton) {
346 dragStartPosition = event->pos();
350 // This event permits to send set custom data on drag&drop
351 // Don't forget to call original class if we are not interested
352 void bRestoreTable::mouseMoveEvent(QMouseEvent *event)
356 // Look just for drag&drop
357 if (!(event->buttons() & Qt::LeftButton)) {
358 QTableWidget::mouseMoveEvent(event);
361 if ((event->pos() - dragStartPosition).manhattanLength()
362 < QApplication::startDragDistance())
364 QTableWidget::mouseMoveEvent(event);
368 QList<QTableWidgetItem *> lst = selectedItems();
369 qDebug() << this << " selectedItems: " << lst;
374 QDrag *drag = new QDrag(this);
375 QMimeData *mimeData = new QMimeData;
376 for (int i=0; i < lst.size(); i++) {
377 if (lastrow != lst[i]->row()) {
378 lastrow = lst[i]->row();
379 QTableWidgetItem *it = item(lastrow, 1);
380 mimeData->setText(it->data(Qt::UserRole).toString());
381 break; // at this time, we do it one by one
384 drag->setMimeData(mimeData);
388 // This event is called when the drag item enters in the destination area
389 void bRestoreTable::dragEnterEvent(QDragEnterEvent *event)
391 if (event->source() == this) {
395 if (event->mimeData()->hasText()) {
396 event->acceptProposedAction();
402 // It should not be essential to redefine this event, but it
403 // doesn't work if not defined
404 void bRestoreTable::dragMoveEvent(QDragMoveEvent *event)
406 if (event->mimeData()->hasText()) {
407 event->acceptProposedAction();
413 void bRestoreTable::dropEvent(QDropEvent *event)
418 if (event->mimeData()->hasText()) {
419 TableItemFormatter item(*this, rowCount());
420 setRowCount(rowCount() + 1);
421 QStringList fields = event->mimeData()->text().split("\t");
422 if (fields.size() != 6) {
426 if (fields.at(1) == "0") {
427 item.setFileType(0, "folder");
429 item.setTextFld(col++, fields.at(5)); // filename
430 decode_stat(fields.at(4).toLocal8Bit().data(),
432 item.setBytesFld(col++, QString().setNum(statp.st_size)); // size
433 item.setDateFld(col++, statp.st_mtime); // date
434 item.setNumericFld(col++, fields.at(3)); // jobid
435 item.setNumericFld(col++, fields.at(2)); // fileid
436 item.widget(1)->setData(Qt::UserRole, event->mimeData()->text());
437 event->acceptProposedAction();
443 void bRunRestore::UFRcb()
445 if (UseFileRelocationChk->checkState() == Qt::Checked) {
446 WhereEntry->setEnabled(false);
447 UseRegexpChk->setEnabled(true);
448 if (UseRegexpChk->checkState() == Qt::Checked) {
449 AddSuffixEntry->setEnabled(false);
450 AddPrefixEntry->setEnabled(false);
451 StripPrefixEntry->setEnabled(false);
452 WhereRegexpEntry->setEnabled(true);
454 AddSuffixEntry->setEnabled(true);
455 AddPrefixEntry->setEnabled(true);
456 StripPrefixEntry->setEnabled(true);
457 WhereRegexpEntry->setEnabled(false);
460 WhereEntry->setEnabled(true);
461 AddSuffixEntry->setEnabled(false);
462 AddPrefixEntry->setEnabled(false);
463 StripPrefixEntry->setEnabled(false);
464 UseRegexpChk->setEnabled(false);
465 WhereRegexpEntry->setEnabled(false);
469 void bRunRestore::useRegexp()
471 if (UseRegexpChk->checkState() == Qt::Checked) {
472 AddSuffixEntry->setEnabled(false);
473 AddPrefixEntry->setEnabled(false);
474 StripPrefixEntry->setEnabled(false);
475 WhereRegexpEntry->setEnabled(true);
477 AddSuffixEntry->setEnabled(true);
478 AddPrefixEntry->setEnabled(true);
479 StripPrefixEntry->setEnabled(true);
480 WhereRegexpEntry->setEnabled(false);
484 bRunRestore::bRunRestore(bRestore *parent)
487 ClientCb->addItems(parent->console()->client_list);
488 int i = ClientCb->findText(parent->m_client);
490 ClientCb->setCurrentIndex(i);
492 StorageCb->addItem(QString(""));
493 RestoreCb->addItems(parent->console()->restore_list);
494 WhenEditor->setDateTime(QDateTime::currentDateTime());
495 StorageCb->addItems(parent->console()->storage_list);
496 connect(UseFileRelocationChk, SIGNAL(clicked()), this, SLOT(UFRcb()));
497 connect(UseRegexpChk, SIGNAL(clicked()), this, SLOT(useRegexp()));
498 struct job_defaults jd;
499 jd.job_name = parent->console()->restore_list[0];
500 parent->console()->get_job_defaults(jd);
501 WhereEntry->setText(jd.where);