]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/qt-console/restore/brestore.cpp
bat: Try to implement drag&drop for file selection
[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    m_pathid = 0;
67
68    if (ClientList->currentIndex() < 1) {
69       JobList->setEnabled(false);
70       return;
71    }
72
73    JobList->addItem("Job list for " + m_client);
74
75    QString jobQuery =
76       "SELECT Job.Jobid AS JobId, Job.StartTime AS StartTime,"
77       " Job.Level AS Level,"
78       " Job.Name AS Name"
79       " FROM Job JOIN Client USING (ClientId)"
80       " WHERE"
81       " Job.JobStatus IN ('T','W') AND Job.Type='B' AND"
82       " Client.Name='" + m_client + "' ORDER BY StartTime DESC" ;
83
84    QString job;
85    QStringList results;
86    if (m_console->sql_cmd(jobQuery, results)) {
87       QStringList fieldlist;
88
89       /* Iterate through the record returned from the query */
90       foreach (QString resultline, results) {
91          fieldlist = resultline.split("\t");
92          job = fieldlist[1] + " " + fieldlist[3] + "(" + fieldlist[2] + ") " + fieldlist[0];
93          JobList->addItem(job, QVariant(fieldlist[0]));
94       }
95    }
96 }
97
98
99 void bRestore::setJob()
100 {
101    if (JobList->currentIndex() < 1) {
102       FileList->clearContents();
103       FileList->setRowCount(0);
104       FileRevisions->clearContents();
105       FileRevisions->setRowCount(0);
106       return ;
107    }
108    QStringList results;
109    QVariant tmp = JobList->itemData(JobList->currentIndex(), Qt::UserRole);
110
111    m_jobids = tmp.toString();
112    QString cmd = ".bvfs_get_jobids jobid=" + m_jobids;
113    if (MergeChk->checkState() == Qt::Checked) {
114       cmd.append(" all");
115    }
116
117    m_console->dir_cmd(cmd, results);
118
119    if (results.size() < 1) {
120       FileList->clearContents();
121       FileList->setRowCount(0);
122       FileRevisions->clearContents();
123       FileRevisions->setRowCount(0);
124       return;
125    }
126
127    m_jobids = results.at(0);
128    cmd = ".bvfs_update jobid=" + m_jobids;
129    m_console->dir_cmd(cmd, results);
130
131    Pmsg1(0, "jobids=%s\n", m_jobids.toLocal8Bit().constData());
132
133    displayFiles(m_pathid, QString(""));
134    Pmsg0(000, "update done\n");
135 }
136
137 extern int decode_stat(char *buf, struct stat *statp, int32_t *LinkFI);
138
139 void bRestore::displayFiles(int64_t pathid, QString path)
140 {
141    QString arg;
142    QStringList results;
143    QStringList fieldlist;
144    struct stat statp;
145    int32_t LinkFI;
146    int nb;
147    int row=0;
148    Freeze frz_lst(*FileList); /* disable updating*/
149    Freeze frz_rev(*FileRevisions); /* disable updating*/
150    FileList->clearContents();
151    FileRevisions->clearContents();
152    FileRevisions->setRowCount(0);
153
154    if (pathid > 0) {
155       arg = " pathid=" + QString().setNum(pathid);
156
157       if (path == "..") {
158          path = LocationEntry->text();
159          if (path != "/") {
160             LocationEntry->setText(path.remove(QRegExp("[^/]+/$")));
161          }
162       } else if (path != ".") {
163          LocationEntry->setText(LocationEntry->text() + path);
164       }
165    } else {
166       LocationEntry->setText(path);
167       arg = " path=\"" + path + "\"";
168    }
169
170    QString q = ".bvfs_lsdir jobid=" + m_jobids + arg;
171    if (m_console->dir_cmd(q, results)) {
172       nb = results.size();
173       FileList->setRowCount(nb);
174       foreach (QString resultline, results) {
175          //PathId, FilenameId, fileid, jobid, lstat, path
176          Pmsg1(0, "dir=%s\n", resultline.toLocal8Bit().constData());
177          fieldlist = resultline.split("\t");
178          TableItemFormatter item(*FileList, row++);
179          item.setTextFld(0, resultline); // keep info
180          item.setFileType(1, QString("folder")); // folder or file
181          item.setTextFld(2, fieldlist.at(5)); // path
182          decode_stat(fieldlist.at(4).toLocal8Bit().data(), 
183                      &statp, &LinkFI);
184          item.setDateFld(4, statp.st_mtime); // date
185          if (fieldlist.at(5) == ".") {
186             m_pathid = fieldlist.at(0).toLongLong(); // keep current pathid
187          }
188       }
189    }
190
191    results.clear();
192    q = ".bvfs_lsfiles jobid=" + m_jobids + arg;
193    if (m_console->dir_cmd(q, results)) {
194       FileList->setRowCount(results.size() + nb);
195       foreach (QString resultline, results) {
196          //PathId, FilenameId, fileid, jobid, lstat, name
197          Pmsg1(0, "file=%s\n", resultline.toLocal8Bit().constData());
198          fieldlist = resultline.split("\t");
199          TableItemFormatter item(*FileList, row++);
200          item.setTextFld(0, resultline); // keep info
201          item.setTextFld(2, fieldlist.at(5)); // path
202          decode_stat(fieldlist.at(4).toLocal8Bit().data(), 
203                      &statp, &LinkFI);
204          item.setBytesFld(3, QString().setNum(statp.st_size));
205          item.setDateFld(4, statp.st_mtime);
206       }
207    }
208    FileList->verticalHeader()->hide();
209    FileList->resizeColumnsToContents();
210    FileList->resizeRowsToContents();
211    FileList->setEditTriggers(QAbstractItemView::NoEditTriggers);
212 }
213
214 void bRestore::PgSeltreeWidgetClicked()
215 {
216    if(!m_populated) {
217       setupPage();
218    }
219    if (!isOnceDocked()) {
220       dockPage();
221    }
222 }
223
224 void bRestore::displayFileVersion(QString pathid, QString fnid, QString client)
225 {
226    int row=0;
227    struct stat statp;
228    int32_t LinkFI;
229    Freeze frz_rev(*FileRevisions); /* disable updating*/
230    FileRevisions->clearContents();
231    
232    QString q = ".bvfs_versions jobid=" + m_jobids +
233       " pathid=" + pathid + 
234       " fnid=" + fnid + 
235       " client=" + client;
236
237    if (VersionsChk->checkState() == Qt::Checked) {
238       q.append(" versions");
239    }
240
241    QStringList results;
242    QStringList fieldlist;
243
244    if (m_console->dir_cmd(q, results)) {
245       FileRevisions->setRowCount(results.size());
246       foreach (QString resultline, results) {
247          int col=0;
248          // 0        1          2        3      4    5      6        7
249          //PathId, FilenameId, fileid, jobid, lstat, Md5, VolName, Inchanger
250          Pmsg1(0, "dir=%s\n", resultline.toLocal8Bit().constData());
251          fieldlist = resultline.split("\t");
252          TableItemFormatter item(*FileRevisions, row++);
253          item.setTextFld(col++, resultline); // keep info
254          item.setInChanger(col++, fieldlist.at(7));    // inchanger
255          item.setTextFld(col++, fieldlist.at(6)); // Volume
256          item.setNumericFld(col++, fieldlist.at(3)); // JobId
257          decode_stat(fieldlist.at(4).toLocal8Bit().data(), 
258                      &statp, &LinkFI);
259          item.setBytesFld(col++, QString().setNum(statp.st_size)); // size
260          item.setDateFld(col++, statp.st_mtime); // date
261          item.setTextFld(col++, fieldlist.at(5)); // chksum
262       }
263    }
264    FileRevisions->verticalHeader()->hide();
265    FileRevisions->resizeColumnsToContents();
266    FileRevisions->resizeRowsToContents();
267    FileRevisions->setEditTriggers(QAbstractItemView::NoEditTriggers);
268 }
269
270 void bRestore::showInfoForFile(QTableWidgetItem *widget)
271 {
272    m_current = widget;
273    QTableWidgetItem *first = FileList->item(widget->row(), 0);
274    QStringList lst = first->text().split("\t");
275    if (lst.at(1) == "0") {      // no filenameid, should be a path
276       displayFiles(lst.at(0).toLongLong(), lst.at(5));
277    } else {
278       displayFileVersion(lst.at(0), lst.at(1), m_client);
279    }
280 }
281
282 void bRestore::applyLocation()
283 {
284    displayFiles(0, LocationEntry->text());
285 }
286
287 void bRestore::clearVersions(QTableWidgetItem *item)
288 {
289    if (item != m_current) {
290       FileRevisions->clearContents();
291       FileRevisions->setRowCount(0);
292    }
293    m_current = item ;
294 }
295
296 void bRestore::setupPage()
297 {
298    Pmsg0(000, "Setup page\n");
299    ClientList->addItem("Client list");
300    ClientList->addItems(m_console->client_list);
301    connect(ClientList, SIGNAL(currentIndexChanged(int)), this, SLOT(setClient()));
302    connect(JobList, SIGNAL(currentIndexChanged(int)), this, SLOT(setJob()));
303    connect(FileList, SIGNAL(itemClicked(QTableWidgetItem*)), 
304            this, SLOT(clearVersions(QTableWidgetItem *)));
305    connect(FileList, SIGNAL(itemDoubleClicked(QTableWidgetItem*)), 
306            this, SLOT(showInfoForFile(QTableWidgetItem *)));
307    connect(LocationBp, SIGNAL(pressed()), this, SLOT(applyLocation()));
308    connect(MergeChk, SIGNAL(clicked()), this, SLOT(setJob()));
309
310    FileList->setColumnHidden(0, true);
311    FileRevisions->setColumnHidden(0, true);
312    RestoreList->setColumnHidden(0, true);
313    m_populated = true;
314 }
315
316 bRestore::~bRestore()
317 {
318 }
319
320 void bRestoreTable::mousePressEvent(QMouseEvent *event)
321 {
322    QTableWidget::mousePressEvent(event);
323
324    if (event->button() == Qt::LeftButton) {
325       dragStartPosition = event->pos();
326    }
327 }
328
329 void bRestoreTable::mouseMoveEvent(QMouseEvent *event)
330 {
331    if (!(event->buttons() & Qt::LeftButton)) {
332       QTableWidget::mouseMoveEvent(event);
333       return;
334    }
335    if ((event->pos() - dragStartPosition).manhattanLength()
336        < QApplication::startDragDistance())
337    {
338       QTableWidget::mouseMoveEvent(event);
339       return;
340    }  
341    
342    QDrag *drag = new QDrag(this);
343    QMimeData *mimeData = new QMimeData;
344    
345    mimeData->setText(QString("test"));
346    qDebug() << "1 ========" << mimeData->formats() << "========";
347    drag->setMimeData(mimeData);
348    drag->exec(Qt::CopyAction | Qt::MoveAction);
349 }
350
351 void bRestoreTable::dragEnterEvent(QDragEnterEvent *event)
352 {
353    Pmsg0(0, "dragEnterEvent\n");
354    qDebug() << "2 ========" << event->mimeData()->formats() << "========";
355
356    if (event->mimeData()->hasText()) {
357       qDebug() << event->mimeData()->text();
358       event->acceptProposedAction();
359    } else {
360       event->ignore();
361    }
362 }
363
364 // void bRestoreTable::dragMoveEvent(QDragMoveEvent *event)
365 // {
366 //    Pmsg0(0, "dragMoveEvent\n");
367 //    if (event->mimeData()->hasText()) {
368 //       event->acceptProposedAction();
369 //    } else {
370 //       event->ignore();
371 //    }
372 // }
373 // 
374 void bRestoreTable::dropEvent(QDropEvent *event)
375 {
376    Pmsg0(0, "dropEvent\n");
377    qDebug() << "3 ========" << event->mimeData()->formats() << "========";
378    if (event->mimeData()->hasText()) {
379       qDebug() << event->mimeData()->text();
380       event->acceptProposedAction();
381    } else {
382       event->ignore();
383    }
384 }
385