2 Bacula(R) - The Network Backup Solution
4 Copyright (C) 2000-2017 Kern Sibbald
6 The original author of Bacula is Kern Sibbald, with contributions
7 from many others, a complete list can be found in the file AUTHORS.
9 You may use this file and others of this release according to the
10 license defined in the LICENSE file, which includes the Affero General
11 Public License, v3.0 ("AGPLv3") and some additional permissions and
12 terms pursuant to its AGPLv3 Section 7.
14 This notice must be preserved when any source code is
15 conveyed and/or propagated.
17 Bacula(R) is a registered trademark of Kern Sibbald.
21 #include <QAbstractEventDispatcher>
24 #include "mediaview.h"
25 #include "mediaedit/mediaedit.h"
26 #include "mediainfo/mediainfo.h"
27 #include "joblist/joblist.h"
28 #include "relabel/relabel.h"
30 #include "util/fmtwidgetitem.h"
32 MediaView::MediaView() : Pages()
37 QTreeWidgetItem* thisitem = mainWin->getFromHash(this);
38 thisitem->setIcon(0,QIcon(QString::fromUtf8(":images/cartridge.png")));
39 connect(m_pbApply, SIGNAL(pressed()), this, SLOT(applyPushed()));
40 connect(m_pbEdit, SIGNAL(pressed()), this, SLOT(editPushed()));
41 connect(m_pbPurge, SIGNAL(pressed()), this, SLOT(purgePushed()));
42 connect(m_pbDelete, SIGNAL(pressed()), this, SLOT(deletePushed()));
43 connect(m_pbPrune, SIGNAL(pressed()), this, SLOT(prunePushed()));
44 connect(m_tableMedia, SIGNAL(itemDoubleClicked(QTableWidgetItem*)),
45 this, SLOT(showInfoForMedia(QTableWidgetItem *)));
47 /* mp_treeWidget, Storage Tree Tree Widget inherited from ui_medialist.h */
49 m_checkcurwidget = true;
53 void MediaView::showInfoForMedia(QTableWidgetItem * item)
55 QTreeWidgetItem* pageSelectorTreeWidgetItem = mainWin->getFromHash(this);
56 int row = item->row();
57 QString vol = m_tableMedia->item(row, 0)->text();
58 new MediaInfo(pageSelectorTreeWidgetItem, vol);
59 // connect(j, SIGNAL(destroyed()), this, SLOT(populateTree()));
62 MediaView::~MediaView()
66 void MediaView::applyPushed()
71 void MediaView::editPushed()
77 for(int i=0; i<sel.count(); i++) {
79 new MediaEdit(mainWin->getFromHash(this), cmd);
83 void MediaView::purgePushed()
85 if (QMessageBox::warning(this, "Bat",
86 tr("Are you sure you want to purge ?? !!!.\n"
87 "The Purge command will delete associated Catalog database records from Jobs and"
88 " Volumes without considering the retention period. Purge works only on the"
89 " Catalog database and does not affect data written to Volumes. This command can"
90 " be dangerous because you can delete catalog records associated with current"
91 " backups of files, and we recommend that you do not use it unless you know what"
93 "Press OK to proceed with the purge operation?"),
94 QMessageBox::Ok | QMessageBox::Cancel)
95 == QMessageBox::Cancel) { return; }
100 for(int i=0; i<lst.count(); i++) {
101 cmd = "purge volume=" + lst.at(i);
107 bool MediaView::getSelection(QStringList &list)
109 QTableWidgetItem *it;
110 QList<QTableWidgetItem*> items = m_tableMedia->selectedItems();
112 int nrows; /* number of rows */
114 int nb = items.count();
118 nrows = m_tableMedia->rowCount();
119 tab = (bool *) malloc (nrows * sizeof(bool));
120 memset(tab, 0, sizeof(bool)*nrows);
121 for (int i = 0; i < nb; ++i) {
122 row = items[i]->row();
125 it = m_tableMedia->item(row, 0);
126 list.append(it->text());
130 return list.count() > 0;
133 void MediaView::prunePushed()
139 for(int i=0; i<sel.count(); i++) {
140 cmd = "prune volume=" + sel.at(i);
146 void MediaView::deletePushed()
148 if (QMessageBox::warning(this, "Bat",
149 tr("Are you sure you want to delete?? !!!.\n"
150 "This delete command is used to delete a Volume record and all associated catalog"
151 " records that were created. This command operates only on the Catalog"
152 " database and has no effect on the actual data written to a Volume. This"
153 " command can be dangerous and we strongly recommend that you do not use"
154 " it unless you know what you are doing. All Jobs and all associated"
155 " records (File and JobMedia) will be deleted from the catalog."
156 "Press OK to proceed with delete operation.?"),
157 QMessageBox::Ok | QMessageBox::Cancel)
158 == QMessageBox::Cancel) { return; }
163 for(int i=0; i<lst.count(); i++) {
164 cmd = "delete volume=" + lst.at(i);
170 void MediaView::populateForm()
173 m_cbPool->addItem("");
174 m_cbPool->addItems(m_console->pool_list);
177 m_cbStatus->addItem("");
178 m_cbStatus->addItems(m_console->volstatus_list);
180 m_cbMediaType->clear();
181 m_cbMediaType->addItem("");
182 m_cbMediaType->addItems(m_console->mediatype_list);
184 m_cbLocation->clear();
185 m_cbLocation->addItem("");
186 m_cbLocation->addItems(m_console->location_list);
190 * If chkExpired button is checked, we can remove all non Expired
193 void MediaView::filterExipired(QStringList &list)
195 utime_t t, now = time(NULL);
196 QString resultline, stat, LastWritten;
197 QStringList fieldlist;
199 /* We should now in advance how many rows we will have */
200 if (m_chkExpired->isChecked()) {
201 for (int i=list.size() -1; i >= 0; i--) {
202 fieldlist = list.at(i).split("\t");
203 ASSERT(fieldlist.size() != 9);
204 LastWritten = fieldlist.at(7);
205 if (LastWritten == "") {
209 stat = fieldlist.at(8);
210 t = str_to_utime(LastWritten.toLatin1().data());
211 t = t + stat.toULongLong();
221 * The main meat of the class!! The function that querries the director and
222 * creates the widgets with appropriate values.
224 void MediaView::populateTable()
228 QString stat, resultline, query;
230 QHash<QString, float> hash_size;
231 QStringList fieldlist, results;
238 Freeze frz(*m_tableMedia); /* disable updating*/
241 if (m_cbPool->currentText() != "") {
242 cmd = " Pool.Name = '" + m_cbPool->currentText() + "'";
246 if (m_cbStatus->currentText() != "") {
247 cmd = " Media.VolStatus = '" + m_cbStatus->currentText() + "'";
251 if (m_cbStatus->currentText() != "") {
252 cmd = " Media.VolStatus = '" + m_cbStatus->currentText() + "'";
256 if (m_cbMediaType->currentText() != "") {
257 cmd = " Media.MediaType = '" + m_cbMediaType->currentText() + "'";
261 if (m_cbLocation->currentText() != "") {
262 cmd = " Location.Location = '" + m_cbLocation->currentText() + "'";
266 if (m_textName->text() != "") {
267 cmd = " Media.VolumeName like '%" + m_textName->text() + "%'";
271 if (where.size() > 0) {
272 cmd = " WHERE " + where.join(" AND ");
278 "SELECT AVG(VolBytes) AS size, COUNT(1) as nb, "
279 "MediaType FROM Media "
280 "WHERE VolStatus IN ('Full', 'Used') "
281 "GROUP BY MediaType";
283 if (mainWin->m_sqlDebug) {
284 Pmsg1(000, "MediaView query cmd : %s\n",query.toUtf8().data());
286 if (m_console->sql_cmd(query, results)) {
287 foreach (resultline, results) {
288 fieldlist = resultline.split("\t");
289 if (fieldlist.size() != 3) {
290 Pmsg1(000, "Unexpected line %s", resultline.toUtf8().data());
293 if (fieldlist.at(1).toInt() >= 1) {
295 hash_size[fieldlist.at(2)]
296 = fieldlist.at(0).toFloat();
301 m_tableMedia->clearContents();
303 "SELECT VolumeName, InChanger, "
304 "Slot, MediaType, VolStatus, VolBytes, Pool.Name, "
305 "LastWritten, Media.VolRetention "
306 "FROM Media JOIN Pool USING (PoolId) "
307 "LEFT JOIN Location ON (Media.LocationId=Location.LocationId) "
309 " ORDER BY VolumeName LIMIT " + m_sbLimit->cleanText();
311 m_tableMedia->sortByColumn(0, Qt::AscendingOrder);
312 m_tableMedia->setSortingEnabled(false); /* Don't sort during insert */
314 if (mainWin->m_sqlDebug) {
315 Pmsg1(000, "MediaView query cmd : %s\n",query.toUtf8().data());
317 if (m_console->sql_cmd(query, results)) {
319 filterExipired(results);
320 m_tableMedia->setRowCount(results.size());
321 foreach (resultline, results) { // should have only one result
323 QString Slot, VolBytes, MediaType, LastWritten, VolStatus;
324 fieldlist = resultline.split("\t");
325 if (fieldlist.size() != 9) {
326 Pmsg1(000, "Unexpected line %s", resultline.toUtf8().data());
329 QStringListIterator fld(fieldlist);
330 TableItemFormatter mediaitem(*m_tableMedia, row);
333 mediaitem.setTextFld(index++, fld.next());
336 mediaitem.setInChanger(index++, fld.next());
338 Slot = fld.next(); // Slot
339 mediaitem.setNumericFld(index++, Slot);
341 MediaType = fld.next();
342 VolStatus = fld.next();
345 VolBytes = fld.next();
346 mediaitem.setBytesFld(index++, VolBytes);
350 if (hash_size.contains(MediaType) &&
351 hash_size[MediaType] != 0) {
352 usage = VolBytes.toLongLong() * 100 / hash_size[MediaType];
354 mediaitem.setPercent(index++, usage);
357 mediaitem.setVolStatusFld(index++, VolStatus);
360 mediaitem.setTextFld(index++, fld.next());
363 mediaitem.setTextFld(index++, MediaType);
365 LastWritten = fld.next();
367 if (LastWritten != "") {
368 stat = fld.next(); // VolUseDuration
369 t = str_to_utime(LastWritten.toLatin1().data());
370 t = t + stat.toULongLong();
372 localtime_r(&ttime, &tm);
373 strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", &tm);
377 mediaitem.setTextFld(index++, LastWritten);
380 mediaitem.setTextFld(index++, buf);
384 m_tableMedia->resizeColumnsToContents();
385 m_tableMedia->resizeRowsToContents();
386 m_tableMedia->verticalHeader()->hide();
387 m_tableMedia->setSortingEnabled(true);
390 m_tableMedia->setEditTriggers(QAbstractItemView::NoEditTriggers);
394 * When the treeWidgetItem in the page selector tree is singleclicked, Make sure
395 * The tree has been populated.
397 void MediaView::PgSeltreeWidgetClicked()
403 if (!isOnceDocked()) {
409 * Virtual function which is called when this page is visible on the stack
411 void MediaView::currentStackItem()
420 // * Called from the signal of the context sensitive menu to relabel!
422 // void MediaView::relabelVolume()
424 // setConsoleCurrent();
425 // new relabelDialog(m_console, m_currentVolumeName);
429 // * Called from the signal of the context sensitive menu to purge!
431 // void MediaView::allVolumesFromPool()
433 // QString cmd = "update volume AllFromPool=" + m_currentVolumeName;
434 // consoleCommand(cmd);
438 // void MediaView::allVolumes()
440 // QString cmd = "update volume allfrompools";
441 // consoleCommand(cmd);
446 // * Called from the signal of the context sensitive menu to purge!
448 // void MediaView::volumeFromPool()
450 // QTreeWidgetItem *currentItem = mp_treeWidget->currentItem();
451 // QTreeWidgetItem *parent = currentItem->parent();
452 // QString pool = parent->text(0);
454 // cmd = "update volume=" + m_currentVolumeName + " frompool=" + pool;
455 // consoleCommand(cmd);