]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/qt-console/restore/brestore.cpp
bat: get a simple working brestore file browser using bvfs API
[bacula/bacula] / bacula / src / qt-console / restore / brestore.cpp
1 /*
2    Bacula® - The Network Backup Solution
3
4    Copyright (C) 2007-2009 Free Software Foundation Europe e.V.
5
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
11    in the file LICENSE.
12
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.
17
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
21    02110-1301, USA.
22
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.
27 */
28  
29 /*
30  *
31  *  bRestore Class  (Eric's brestore)
32  *
33  *   Kern Sibbald, January MMVII
34  *
35  */ 
36
37 #include "bat.h"
38 #include "restore.h"
39 #include "util/fmtwidgetitem.h"
40
41 bRestore::bRestore()
42 {
43    m_name = tr("bRestore");
44    m_client = "";
45    setupUi(this);
46    pgInitialize();
47    QTreeWidgetItem* thisitem = mainWin->getFromHash(this);
48    thisitem->setIcon(0, QIcon(QString::fromUtf8(":images/browse.png")));
49    m_populated = false;
50    m_current = NULL;
51 }
52
53 void bRestore::setClient()
54 {
55    Pmsg0(000, "Repopulating client table\n");
56    // Select the same client, don't touch
57    if (m_client == ClientList->currentText()) {
58       return;
59    }
60    m_client = ClientList->currentText();
61    FileList->clearContents();
62    FileRevisions->clearContents();
63    JobList->clear();
64    JobList->setEnabled(true);
65    LocationEntry->clear();
66
67    if (ClientList->currentIndex() < 1) {
68       JobList->setEnabled(false);
69       return;
70    }
71
72    JobList->addItem("Job list for " + m_client);
73
74    QString jobQuery =
75       "SELECT Job.Jobid AS JobId, Job.StartTime AS StartTime,"
76       " Job.Level AS Level,"
77       " Job.Name AS Name"
78       " FROM Job JOIN Client USING (ClientId)"
79       " WHERE"
80       " Job.JobStatus IN ('T','W') AND Job.Type='B' AND"
81       " Client.Name='" + m_client + "' ORDER BY StartTime DESC" ;
82
83    QString job;
84    QStringList results;
85    if (m_console->sql_cmd(jobQuery, results)) {
86       QStringList fieldlist;
87
88       /* Iterate through the record returned from the query */
89       foreach (QString resultline, results) {
90          fieldlist = resultline.split("\t");
91          job = fieldlist[1] + " " + fieldlist[3] + "(" + fieldlist[2] + ") " + fieldlist[0];
92          JobList->addItem(job, QVariant(fieldlist[0]));
93       }
94    }
95 }
96
97
98 void bRestore::setJob()
99 {
100    if (JobList->currentIndex() < 1) {
101       FileList->clearContents();
102       FileList->setRowCount(0);
103       FileRevisions->clearContents();
104       FileRevisions->setRowCount(0);
105       return ;
106    }
107    QStringList results;
108    QVariant tmp = JobList->itemData(JobList->currentIndex(), Qt::UserRole);
109
110    m_jobids = tmp.toString();
111    QString cmd = ".bvfs_get_jobids jobid=" + m_jobids;
112    m_console->dir_cmd(cmd, results);
113
114    if (results.size() < 1) {
115       FileList->clearContents();
116       FileList->setRowCount(0);
117       FileRevisions->clearContents();
118       FileRevisions->setRowCount(0);
119       return;
120    }
121
122    m_jobids = results.at(0);
123    cmd = ".bvfs_update jobid=" + m_jobids;
124    m_console->dir_cmd(cmd, results);
125
126    Pmsg1(0, "jobids=%s\n", m_jobids.toLocal8Bit().constData());
127
128    displayFiles(0, "/");
129    Pmsg0(000, "update done\n");
130 }
131
132 extern int decode_stat(char *buf, struct stat *statp, int32_t *LinkFI);
133
134 void bRestore::displayFiles(int64_t pathid, QString path)
135 {
136    QString arg;
137    QStringList results;
138    QStringList fieldlist;
139    struct stat statp;
140    int32_t LinkFI;
141    int nb;
142    int row=0;
143    Freeze frz_lst(*FileList); /* disable updating*/
144    Freeze frz_rev(*FileRevisions); /* disable updating*/
145    FileList->clearContents();
146    FileRevisions->clearContents();
147    FileRevisions->setRowCount(0);
148
149    if (pathid > 0) {
150       arg = " pathid=" + QString().setNum(pathid);
151
152       if (path == "..") {
153          path = LocationEntry->text();
154          if (path != "/") {
155             LocationEntry->setText(path.remove(QRegExp("[^/]+/$")));
156          }
157       } else if (path != ".") {
158          LocationEntry->setText(LocationEntry->text() + path);
159       }
160    } else {
161       LocationEntry->setText(path);
162       arg = " path=\"" + path + "\"";
163    }
164
165    QString q = ".bvfs_lsdir jobid=" + m_jobids + arg;
166    if (m_console->dir_cmd(q, results)) {
167       nb = results.size();
168       FileList->setRowCount(nb);
169       foreach (QString resultline, results) {
170          //PathId, FilenameId, fileid, jobid, lstat, path
171          Pmsg1(0, "dir=%s\n", resultline.toLocal8Bit().constData());
172          fieldlist = resultline.split("\t");
173          TableItemFormatter item(*FileList, row++);
174          item.setTextFld(0, resultline); // keep info
175          item.setFileType(1, QString("folder")); // folder or file
176          item.setTextFld(2, fieldlist.at(5)); // path
177          decode_stat(fieldlist.at(4).toLocal8Bit().data(), 
178                      &statp, &LinkFI);
179          item.setDateFld(4, statp.st_mtime); // date
180       }
181    }
182
183    results.clear();
184    q = ".bvfs_lsfiles jobid=" + m_jobids + arg;
185    if (m_console->dir_cmd(q, results)) {
186       FileList->setRowCount(results.size() + nb);
187       foreach (QString resultline, results) {
188          //PathId, FilenameId, fileid, jobid, lstat, name
189          Pmsg1(0, "file=%s\n", resultline.toLocal8Bit().constData());
190          fieldlist = resultline.split("\t");
191          TableItemFormatter item(*FileList, row++);
192          item.setTextFld(0, resultline); // keep info
193          item.setTextFld(2, fieldlist.at(5)); // path
194          decode_stat(fieldlist.at(4).toLocal8Bit().data(), 
195                      &statp, &LinkFI);
196          item.setBytesFld(3, QString().setNum(statp.st_size));
197          item.setDateFld(4, statp.st_mtime);
198       }
199    }
200    FileList->verticalHeader()->hide();
201    FileList->resizeColumnsToContents();
202    FileList->resizeRowsToContents();
203    FileList->setEditTriggers(QAbstractItemView::NoEditTriggers);
204 }
205
206 void bRestore::PgSeltreeWidgetClicked()
207 {
208    if(!m_populated) {
209       setupPage();
210    }
211    if (!isOnceDocked()) {
212       dockPage();
213    }
214 }
215
216 void bRestore::displayFileVersion(QString pathid, QString fnid, QString client)
217 {
218    int row=0;
219    struct stat statp;
220    int32_t LinkFI;
221    Freeze frz_rev(*FileRevisions); /* disable updating*/
222    FileRevisions->clearContents();
223    
224    QString q = ".bvfs_versions jobid=" + m_jobids +
225       " pathid=" + pathid + 
226       " fnid=" + fnid + 
227       " client=" + client;
228
229    if (VersionsChk->checkState() == Qt::Checked) {
230       q.append(" versions");
231    }
232
233    QStringList results;
234    QStringList fieldlist;
235
236    if (m_console->dir_cmd(q, results)) {
237       FileRevisions->setRowCount(results.size());
238       foreach (QString resultline, results) {
239          int col=0;
240          // 0        1          2        3      4    5      6        7
241          //PathId, FilenameId, fileid, jobid, lstat, Md5, VolName, Inchanger
242          Pmsg1(0, "dir=%s\n", resultline.toLocal8Bit().constData());
243          fieldlist = resultline.split("\t");
244          TableItemFormatter item(*FileRevisions, row++);
245          item.setTextFld(col++, resultline); // keep info
246          item.setInChanger(col++, fieldlist.at(7));    // inchanger
247          item.setTextFld(col++, fieldlist.at(6)); // Volume
248          item.setNumericFld(col++, fieldlist.at(3)); // JobId
249          decode_stat(fieldlist.at(4).toLocal8Bit().data(), 
250                      &statp, &LinkFI);
251          item.setBytesFld(col++, QString().setNum(statp.st_size)); // size
252          item.setDateFld(col++, statp.st_mtime); // date
253          item.setTextFld(col++, fieldlist.at(5)); // chksum
254       }
255    }
256    FileRevisions->verticalHeader()->hide();
257    FileRevisions->resizeColumnsToContents();
258    FileRevisions->resizeRowsToContents();
259    FileRevisions->setEditTriggers(QAbstractItemView::NoEditTriggers);
260 }
261
262 void bRestore::showInfoForFile(QTableWidgetItem *widget)
263 {
264    m_current = widget;
265    QTableWidgetItem *first = FileList->item(widget->row(), 0);
266    QStringList lst = first->text().split("\t");
267    if (lst.at(1) == "0") {      // no filenameid, should be a path
268       displayFiles(lst.at(0).toLongLong(), lst.at(5));
269    } else {
270       displayFileVersion(lst.at(0), lst.at(1), m_client);
271    }
272 }
273
274 void bRestore::applyLocation()
275 {
276    displayFiles(0, LocationEntry->text());
277 }
278
279 void bRestore::clearVersions(QTableWidgetItem *item)
280 {
281    if (item != m_current) {
282       FileRevisions->clearContents();
283       FileRevisions->setRowCount(0);
284    }
285    m_current = item ;
286 }
287
288 void bRestore::setupPage()
289 {
290    Pmsg0(000, "Setup page\n");
291    ClientList->addItem("Client list");
292    ClientList->addItems(m_console->client_list);
293    connect(ClientList, SIGNAL(currentIndexChanged(int)), this, SLOT(setClient()));
294    connect(JobList, SIGNAL(currentIndexChanged(int)), this, SLOT(setJob()));
295    connect(FileList, SIGNAL(itemClicked(QTableWidgetItem*)), 
296            this, SLOT(clearVersions(QTableWidgetItem *)));
297    connect(FileList, SIGNAL(itemDoubleClicked(QTableWidgetItem*)), 
298            this, SLOT(showInfoForFile(QTableWidgetItem *)));
299    connect(LocationBp, SIGNAL(pressed()), this, SLOT(applyLocation()));
300    FileList->setColumnHidden(0, true);
301    FileRevisions->setColumnHidden(0, true);
302    RestoreList->setColumnHidden(0, true);
303    m_populated = true;
304 }
305
306 bRestore::~bRestore()
307 {
308 }