]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/qt-console/medialist/mediaview.cpp
Fix some missed copyright changes
[bacula/bacula] / bacula / src / qt-console / medialist / mediaview.cpp
1 /*
2    Bacula® - The Network Backup Solution
3
4    Copyright (C) 2007-2010 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 #include "bat.h"
30 #include <QAbstractEventDispatcher>
31 #include <QMenu>
32 #include <math.h>
33 #include "mediaview.h"
34 #include "mediaedit/mediaedit.h"
35 #include "mediainfo/mediainfo.h"
36 #include "joblist/joblist.h"
37 #include "relabel/relabel.h"
38 #include "run/run.h"
39 #include "util/fmtwidgetitem.h"
40
41 MediaView::MediaView()
42 {
43    setupUi(this);
44    m_name = tr("Media");
45    pgInitialize();
46    QTreeWidgetItem* thisitem = mainWin->getFromHash(this);
47    thisitem->setIcon(0,QIcon(QString::fromUtf8(":images/cartridge.png")));
48    connect(m_pbApply, SIGNAL(pressed()), this, SLOT(applyPushed()));
49    connect(m_pbEdit, SIGNAL(pressed()), this, SLOT(editPushed()));
50    connect(m_pbPurge, SIGNAL(pressed()), this, SLOT(purgePushed()));
51    connect(m_pbDelete, SIGNAL(pressed()), this, SLOT(deletePushed()));
52    connect(m_pbPrune, SIGNAL(pressed()), this, SLOT(prunePushed()));
53    connect(m_tableMedia, SIGNAL(itemDoubleClicked(QTableWidgetItem*)), 
54            this, SLOT(showInfoForMedia(QTableWidgetItem *)));
55
56    /* mp_treeWidget, Storage Tree Tree Widget inherited from ui_medialist.h */
57    m_populated = false;
58    m_checkcurwidget = true;
59    m_closeable = false;
60 }
61
62 void MediaView::showInfoForMedia(QTableWidgetItem * item)
63 {
64    QTreeWidgetItem* pageSelectorTreeWidgetItem = mainWin->getFromHash(this);
65    int row = item->row();
66    QString vol = m_tableMedia->item(row, 0)->text();
67    new MediaInfo(pageSelectorTreeWidgetItem, vol);
68 //   connect(j, SIGNAL(destroyed()), this, SLOT(populateTree()));
69 }
70
71 MediaView::~MediaView()
72 {
73 }
74
75 void MediaView::applyPushed()
76 {
77    populateTable();
78 }
79
80 void MediaView::editPushed()
81 {
82    QStringList sel;
83    QString cmd;
84    getSelection(sel);
85    
86    for(int i=0; i<sel.count(); i++) {
87       cmd = sel.at(i);
88       new MediaEdit(mainWin->getFromHash(this), cmd);
89    }
90 }
91
92 void MediaView::purgePushed()
93 {
94    if (QMessageBox::warning(this, "Bat",
95       tr("Are you sure you want to purge ??  !!!.\n"
96 "The Purge command will delete associated Catalog database records from Jobs and"
97 " Volumes without considering the retention period. Purge  works only on the"
98 " Catalog database and does not affect data written to Volumes. This command can"
99 " be dangerous because you can delete catalog records associated with current"
100 " backups of files, and we recommend that you do not use it unless you know what"
101 " you are doing.\n"
102       "Press OK to proceed with the purge operation?"),
103       QMessageBox::Ok | QMessageBox::Cancel)
104       == QMessageBox::Cancel) { return; }
105
106    QStringList lst;
107    QString cmd;
108    getSelection(lst);
109    for(int i=0; i<lst.count(); i++) {
110       cmd = "purge volume=" + lst.at(i);
111       consoleCommand(cmd);
112    }
113    populateTable();
114 }
115
116 bool MediaView::getSelection(QStringList &list)
117 {
118    QList<QTableWidgetItem*> items = m_tableMedia->selectedItems();
119    QTableWidgetItem *it;
120    int row;
121    int *tab;
122    int nb = items.count();
123    if (!nb) {
124       return false;
125    }
126    tab = (int *) malloc (nb * sizeof(int));
127    memset(tab, 0, sizeof(int)*nb);
128    for (int i = 0; i < nb; ++i) {
129       row = items[i]->row();
130       if (!tab[row]) {
131          tab[row]=1;
132          it = m_tableMedia->item(row, 0);
133          list.append(it->text());
134       }
135    }
136    free(tab);
137    return list.count() > 0;
138 }
139
140 void MediaView::prunePushed()
141 {
142    QStringList sel;
143    QString cmd;
144    getSelection(sel);
145
146    for(int i=0; i<sel.count(); i++) {
147       cmd = "prune volume=" + sel.at(i);
148       consoleCommand(cmd);
149    }
150 }
151
152
153 void MediaView::deletePushed()
154 {
155    if (QMessageBox::warning(this, "Bat",
156       tr("Are you sure you want to delete??  !!!.\n"
157 "This delete command is used to delete a Volume record and all associated catalog"
158 " records that were created. This command operates only on the Catalog"
159 " database and has no effect on the actual data written to a Volume. This"
160 " command can be dangerous and we strongly recommend that you do not use"
161 " it unless you know what you are doing.  All Jobs and all associated"
162 " records (File and JobMedia) will be deleted from the catalog."
163       "Press OK to proceed with delete operation.?"),
164       QMessageBox::Ok | QMessageBox::Cancel)
165       == QMessageBox::Cancel) { return; }
166
167    QStringList lst;
168    QString cmd;
169    getSelection(lst);
170    for(int i=0; i<lst.count(); i++) {
171       cmd = "delete volume=" + lst.at(i);
172       consoleCommand(cmd);
173    }
174    populateTable();
175 }
176
177 void MediaView::populateForm()
178 {
179    m_cbPool->clear();
180    m_cbPool->addItem("");
181    m_cbPool->addItems(m_console->pool_list);
182
183    m_cbStatus->clear();
184    m_cbStatus->addItem("");
185    m_cbStatus->addItems(m_console->volstatus_list);
186
187    m_cbMediaType->clear();
188    m_cbMediaType->addItem("");
189    m_cbMediaType->addItems(m_console->mediatype_list);
190
191    m_cbLocation->clear();
192    m_cbLocation->addItem("");
193    m_cbLocation->addItems(m_console->location_list);
194 }
195
196 /* 
197  * If chkExpired button is checked, we can remove all non Expired
198  * entries
199  */
200 void MediaView::filterExipired(QStringList &list)
201 {
202    utime_t t, now = time(NULL);
203    QString resultline, stat, LastWritten;
204    QStringList fieldlist;
205
206    /* We should now in advance how many rows we will have */
207    if (m_chkExpired->isChecked()) {
208       for (int i=list.size() -1; i >= 0; i--) {
209          fieldlist = list.at(i).split("\t");
210          ASSERT(fieldlist.size() != 9);
211          LastWritten = fieldlist.at(7);
212          if (LastWritten == "") {
213             list.removeAt(i);
214
215          } else {
216             stat = fieldlist.at(8);
217             t = str_to_utime(LastWritten.toAscii().data());
218             t = t + stat.toULongLong();
219             if (t > now) {
220                list.removeAt(i);
221             }
222          }
223       }
224    }
225 }
226
227 /*
228  * The main meat of the class!!  The function that querries the director and 
229  * creates the widgets with appropriate values.
230  */
231 void MediaView::populateTable()
232 {
233    utime_t t;
234    time_t ttime;
235    QString stat, resultline, query;
236    QString str_usage;
237    QHash<QString, float> hash_size;
238    QStringList fieldlist, results;
239    char buf[256];
240    float usage;
241    struct tm tm;
242
243    m_populated = true;
244
245    Freeze frz(*m_tableMedia); /* disable updating*/
246    QStringList where;
247    QString cmd;
248    if (m_cbPool->currentText() != "") {
249       cmd = " Pool.Name = '" + m_cbPool->currentText() + "'";
250       where.append(cmd);
251    } 
252
253    if (m_cbStatus->currentText() != "") {
254       cmd = " Media.VolStatus = '" + m_cbStatus->currentText() + "'";
255       where.append(cmd);
256    }
257
258    if (m_cbStatus->currentText() != "") {
259       cmd = " Media.VolStatus = '" + m_cbStatus->currentText() + "'";
260       where.append(cmd);
261    }
262
263    if (m_cbMediaType->currentText() != "") {
264       cmd = " Media.MediaType = '" + m_cbMediaType->currentText() + "'";
265       where.append(cmd);
266    }
267
268    if (m_cbLocation->currentText() != "") {
269       cmd = " Location.Location = '" + m_cbLocation->currentText() + "'";
270       where.append(cmd);
271    }
272
273    if (m_textName->text() != "") {
274       cmd = " Media.VolumeName like '%" + m_textName->text() + "%'";
275       where.append(cmd);
276    }
277
278    if (where.size() > 0) {
279       cmd = " WHERE " + where.join(" AND ");
280    } else {
281       cmd = "";
282    }
283
284    query =
285       "SELECT AVG(VolBytes) AS size, COUNT(1) as nb, "
286       "MediaType  FROM Media "
287       "WHERE VolStatus IN ('Full', 'Used') "
288       "GROUP BY MediaType";
289
290    if (mainWin->m_sqlDebug) {
291       Pmsg1(000, "MediaView query cmd : %s\n",query.toUtf8().data());
292    }
293    if (m_console->sql_cmd(query, results)) {
294       foreach (resultline, results) {
295          fieldlist = resultline.split("\t");
296          if (fieldlist.at(1).toInt() >= 1) { 
297             //           MediaType
298             hash_size[fieldlist.at(2)] 
299                = fieldlist.at(0).toFloat(); 
300          }
301       }
302    }      
303    
304    m_tableMedia->clearContents();
305    query = 
306       "SELECT VolumeName, InChanger, "
307       "Slot, MediaType, VolStatus, VolBytes, Pool.Name,  "
308       "LastWritten, Media.VolRetention "
309       "FROM Media JOIN Pool USING (PoolId) "
310       "LEFT JOIN Location ON (Media.LocationId=Location.LocationId) "
311       + cmd + 
312       " ORDER BY VolumeName LIMIT " + m_sbLimit->cleanText();
313
314    m_tableMedia->sortByColumn(0, Qt::AscendingOrder);
315    m_tableMedia->setSortingEnabled(false); /* Don't sort during insert */
316    results.clear();
317    if (mainWin->m_sqlDebug) {
318       Pmsg1(000, "MediaView query cmd : %s\n",query.toUtf8().data());
319    }
320    if (m_console->sql_cmd(query, results)) {
321       int row=0;
322       filterExipired(results);
323       m_tableMedia->setRowCount(results.size());
324
325       foreach (resultline, results) { // should have only one result
326          int index = 0;
327          QString VolBytes, MediaType, LastWritten, VolStatus;
328          fieldlist = resultline.split("\t");
329          if (fieldlist.size() != 10) {
330             continue;
331          }
332          QStringListIterator fld(fieldlist);
333          TableItemFormatter mediaitem(*m_tableMedia, row);
334
335          /* VolumeName */
336          mediaitem.setTextFld(index++, fld.next()); 
337          
338          /* Online */
339          mediaitem.setInChanger(index++, fld.next());
340          fld.next();            // Slot
341
342          MediaType = fld.next();
343          VolStatus = fld.next();
344
345          /* Volume bytes */
346          VolBytes = fld.next();
347          mediaitem.setBytesFld(index++, VolBytes);
348
349          /* Usage */
350          usage = 0;
351          if (hash_size.contains(MediaType) &&
352              hash_size[MediaType] != 0) {
353             usage = VolBytes.toLongLong() * 100 / hash_size[MediaType];
354          }
355          mediaitem.setPercent(index++, usage);
356
357          /* Volstatus */
358          mediaitem.setVolStatusFld(index++, VolStatus);
359
360          /* Pool */
361          mediaitem.setTextFld(index++, fld.next());
362
363          /* MediaType */
364          mediaitem.setTextFld(index++, MediaType);
365
366          LastWritten = fld.next();
367          buf[0] = 0;
368          if (LastWritten != "") {
369             stat = fld.next();  // VolUseDuration
370             t = str_to_utime(LastWritten.toAscii().data());
371             t = t + stat.toULongLong();
372             ttime = t;
373             localtime_r(&ttime, &tm);         
374             strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", &tm);
375          }
376          
377          /* LastWritten */
378          mediaitem.setTextFld(index++, LastWritten);
379
380          /* When expired */
381          mediaitem.setTextFld(index++, buf);
382          row++;
383       }
384    }
385    m_tableMedia->resizeColumnsToContents();
386    m_tableMedia->resizeRowsToContents();
387    m_tableMedia->verticalHeader()->hide();
388    m_tableMedia->setSortingEnabled(true);
389
390    /* make read only */
391    m_tableMedia->setEditTriggers(QAbstractItemView::NoEditTriggers);
392 }
393
394 /*
395  * When the treeWidgetItem in the page selector tree is singleclicked, Make sure
396  * The tree has been populated.
397  */
398 void MediaView::PgSeltreeWidgetClicked()
399 {
400    if (!m_populated) {
401       populateForm();
402       populateTable();
403    }
404    if (!isOnceDocked()) {
405       dockPage();
406    }
407 }
408
409 /*
410  * Virtual function which is called when this page is visible on the stack
411  */
412 void MediaView::currentStackItem()
413 {
414    if(!m_populated) {
415       populateForm();
416       populateTable();
417    }
418 }
419
420 // /*
421 //  * Called from the signal of the context sensitive menu to relabel!
422 //  */
423 // void MediaView::relabelVolume()
424 // {
425 //    setConsoleCurrent();
426 //    new relabelDialog(m_console, m_currentVolumeName);
427 // }
428 // 
429 // /*
430 //  * Called from the signal of the context sensitive menu to purge!
431 //  */
432 // void MediaView::allVolumesFromPool()
433 // {
434 //    QString cmd = "update volume AllFromPool=" + m_currentVolumeName;
435 //    consoleCommand(cmd);
436 //    populateTable();
437 // }
438 // 
439 // void MediaView::allVolumes()
440 // {
441 //    QString cmd = "update volume allfrompools";
442 //    consoleCommand(cmd);
443 //    populateTable();
444 // }
445 // 
446 //  /*
447 //   * Called from the signal of the context sensitive menu to purge!
448 //   */
449 //  void MediaView::volumeFromPool()
450 //  {
451 //     QTreeWidgetItem *currentItem = mp_treeWidget->currentItem();
452 //     QTreeWidgetItem *parent = currentItem->parent();
453 //     QString pool = parent->text(0);
454 //     QString cmd;
455 //     cmd = "update volume=" + m_currentVolumeName + " frompool=" + pool;
456 //     consoleCommand(cmd);
457 //     populateTable();
458 //  }
459 //