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 item.widget(1)->setData(Qt::UserRole, fieldlist.join("\t")); // keep info
197 q = ".bvfs_lsfiles jobid=" + m_jobids + arg;
198 if (m_console->dir_cmd(q, results)) {
199 FileList->setRowCount(results.size() + nb);
200 foreach (QString resultline, results) {
201 int col=1; // skip icon
202 //PathId, FilenameId, fileid, jobid, lstat, name
203 fieldlist = resultline.split("\t");
204 TableItemFormatter item(*FileList, row++);
205 item.setTextFld(col++, fieldlist.at(5)); // name
206 decode_stat(fieldlist.at(4).toLocal8Bit().data(),
208 item.setBytesFld(col++, QString().setNum(statp.st_size));
209 item.setDateFld(col++, statp.st_mtime);
210 item.widget(1)->setData(Qt::UserRole, fieldlist.join("\t")); // keep info
213 FileList->verticalHeader()->hide();
214 FileList->resizeColumnsToContents();
215 FileList->resizeRowsToContents();
216 FileList->setEditTriggers(QAbstractItemView::NoEditTriggers);
219 void bRestore::PgSeltreeWidgetClicked()
224 if (!isOnceDocked()) {
229 void bRestore::displayFileVersion(QString pathid, QString fnid,
230 QString client, QString filename)
235 Freeze frz_rev(*FileRevisions); /* disable updating*/
236 FileRevisions->clearContents();
238 QString q = ".bvfs_versions jobid=" + m_jobids +
239 " pathid=" + pathid +
243 if (VersionsChk->checkState() == Qt::Checked) {
244 q.append(" versions");
248 QStringList fieldlist;
250 if (m_console->dir_cmd(q, results)) {
251 FileRevisions->setRowCount(results.size());
252 foreach (QString resultline, results) {
255 //PathId, FilenameId, fileid, jobid, lstat, Md5, VolName, Inchanger
256 fieldlist = resultline.split("\t");
257 TableItemFormatter item(*FileRevisions, row++);
258 item.setInChanger(col++, fieldlist.at(7)); // inchanger
259 item.setTextFld(col++, fieldlist.at(6)); // Volume
260 item.setNumericFld(col++, fieldlist.at(3)); // JobId
261 decode_stat(fieldlist.at(4).toLocal8Bit().data(),
263 item.setBytesFld(col++, QString().setNum(statp.st_size)); // size
264 item.setDateFld(col++, statp.st_mtime); // date
265 item.setTextFld(col++, fieldlist.at(5)); // chksum
267 // Adjust the fieldlist for drag&drop
268 fieldlist.removeLast(); // inchanger
269 fieldlist.removeLast(); // volname
270 fieldlist.removeLast(); // md5
271 fieldlist << m_path + filename;
272 item.widget(1)->setData(Qt::UserRole, fieldlist.join("\t")); // keep info
275 FileRevisions->verticalHeader()->hide();
276 FileRevisions->resizeColumnsToContents();
277 FileRevisions->resizeRowsToContents();
278 FileRevisions->setEditTriggers(QAbstractItemView::NoEditTriggers);
281 void bRestore::showInfoForFile(QTableWidgetItem *widget)
284 QTableWidgetItem *first = FileList->item(widget->row(), 1);
285 QStringList lst = first->data(Qt::UserRole).toString().split("\t");
286 if (lst.at(1) == "0") { // no filenameid, should be a path
287 displayFiles(lst.at(0).toLongLong(), lst.at(5));
289 displayFileVersion(lst.at(0), lst.at(1), m_client, lst.at(5));
293 void bRestore::applyLocation()
295 displayFiles(0, LocationEntry->text());
298 void bRestore::clearVersions(QTableWidgetItem *item)
300 if (item != m_current) {
301 FileRevisions->clearContents();
302 FileRevisions->setRowCount(0);
307 void bRestore::setupPage()
309 ClientList->addItem("Client list");
310 ClientList->addItems(m_console->client_list);
311 connect(ClientList, SIGNAL(currentIndexChanged(int)), this, SLOT(setClient()));
312 connect(JobList, SIGNAL(currentIndexChanged(int)), this, SLOT(setJob()));
313 connect(FileList, SIGNAL(itemClicked(QTableWidgetItem*)),
314 this, SLOT(clearVersions(QTableWidgetItem *)));
315 connect(FileList, SIGNAL(itemDoubleClicked(QTableWidgetItem*)),
316 this, SLOT(showInfoForFile(QTableWidgetItem *)));
317 connect(LocationBp, SIGNAL(pressed()), this, SLOT(applyLocation()));
318 connect(MergeChk, SIGNAL(clicked()), this, SLOT(setJob()));
323 bRestore::~bRestore()
327 void bRestoreTable::mousePressEvent(QMouseEvent *event)
329 QTableWidget::mousePressEvent(event);
331 if (event->button() == Qt::LeftButton) {
332 dragStartPosition = event->pos();
336 // This event permits to send set custom data on drag&drop
337 // Don't forget to call original class if we are not interested
338 void bRestoreTable::mouseMoveEvent(QMouseEvent *event)
342 // Look just for drag&drop
343 if (!(event->buttons() & Qt::LeftButton)) {
344 QTableWidget::mouseMoveEvent(event);
347 if ((event->pos() - dragStartPosition).manhattanLength()
348 < QApplication::startDragDistance())
350 QTableWidget::mouseMoveEvent(event);
354 QList<QTableWidgetItem *> lst = selectedItems();
355 qDebug() << this << " selectedItems: " << lst;
360 QDrag *drag = new QDrag(this);
361 QMimeData *mimeData = new QMimeData;
362 for (int i=0; i < lst.size(); i++) {
363 if (lastrow != lst[i]->row()) {
364 lastrow = lst[i]->row();
365 QTableWidgetItem *it = item(lastrow, 1);
366 mimeData->setText(it->data(Qt::UserRole).toString());
367 break; // at this time, we do it one by one
370 drag->setMimeData(mimeData);
374 // This event is called when the drag item enters in the destination area
375 void bRestoreTable::dragEnterEvent(QDragEnterEvent *event)
377 if (event->source() == this) {
381 if (event->mimeData()->hasText()) {
382 event->acceptProposedAction();
388 // It should not be essential to redefine this event, but it
389 // doesn't work if not defined
390 void bRestoreTable::dragMoveEvent(QDragMoveEvent *event)
392 if (event->mimeData()->hasText()) {
393 event->acceptProposedAction();
399 void bRestoreTable::dropEvent(QDropEvent *event)
404 if (event->mimeData()->hasText()) {
405 TableItemFormatter item(*this, rowCount());
406 setRowCount(rowCount() + 1);
407 QStringList fields = event->mimeData()->text().split("\t");
408 if (fields.size() != 6) {
412 if (fields.at(1) == "0") {
413 item.setFileType(0, "folder");
415 item.setTextFld(col++, fields.at(5)); // filename
416 decode_stat(fields.at(4).toLocal8Bit().data(),
418 item.setBytesFld(col++, QString().setNum(statp.st_size)); // size
419 item.setDateFld(col++, statp.st_mtime); // date
420 item.setNumericFld(col++, fields.at(3)); // jobid
421 item.setNumericFld(col++, fields.at(2)); // fileid
422 item.widget(1)->setData(Qt::UserRole, event->mimeData()->text());
423 event->acceptProposedAction();