]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/qt-console/storage/content.cpp
Tweak bat so drives are visable in content menu.
[bacula/bacula] / bacula / src / qt-console / storage / content.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 #include "bat.h"
30 #include <QAbstractEventDispatcher>
31 #include <QMenu>
32 #include "content.h"
33 #include "label/label.h"
34 #include "mediainfo/mediainfo.h"
35 #include "mount/mount.h"
36 #include "util/fmtwidgetitem.h"
37 #include "status/storstat.h"
38
39 // 
40 // TODO: List tray
41 //       List drives in autochanger
42 //       use user selection to add slot= argument
43 // 
44
45 Content::Content(QString storage, QTreeWidgetItem *parentWidget) : Pages()
46 {
47    setupUi(this);
48    pgInitialize(storage, parentWidget);
49    QTreeWidgetItem* thisitem = mainWin->getFromHash(this);
50    thisitem->setIcon(0,QIcon(QString::fromUtf8(":images/package-x-generic.png")));
51
52    m_populated = false;
53    m_firstpopulation = true;
54    m_checkcurwidget = true;
55    m_currentStorage = storage;
56
57    connect(pbUpdate, SIGNAL(clicked()), this,
58            SLOT(consoleUpdateSlots()));
59
60    connect(pbLabel, SIGNAL(clicked()), this,
61            SLOT(consoleLabelStorage()));
62
63    connect(pbMount, SIGNAL(clicked()), this,
64            SLOT(consoleMountStorage()));
65
66    connect(pbUnmount, SIGNAL(clicked()), this,
67            SLOT(consoleUnMountStorage()));
68
69    connect(pbStatus, SIGNAL(clicked()), this,
70            SLOT(statusStorageWindow()));
71
72    connect(pbRelease, SIGNAL(clicked()), this,
73            SLOT(consoleRelease()));
74
75    connect(tableContent, SIGNAL(itemDoubleClicked(QTableWidgetItem*)), this,
76            SLOT(showMediaInfo(QTableWidgetItem *)));
77
78    dockPage();
79    setCurrent();
80 }
81
82
83 /*
84  * Subroutine to call class to show the log in the database from that job
85  */
86 void Content::showMediaInfo(QTableWidgetItem * item)
87 {
88    QTreeWidgetItem* pageSelectorTreeWidgetItem = mainWin->getFromHash(this);
89    int row = item->row();
90    QString vol = tableContent->item(row, 1)->text();
91    if (vol != "") {
92       new MediaInfo(pageSelectorTreeWidgetItem, vol);
93    }
94 }
95
96 void table_get_selection(QTableWidget *table, QString &sel)
97 {
98    QTableWidgetItem *item;
99    int current;
100
101    /* The QT selection returns each cell, so you
102     * have x times the same row number...
103     * We take only one instance
104     */
105    int s = table->rowCount();
106    bool *tab = (bool *)malloc(s * sizeof(bool));
107    memset(tab, 0, s); 
108
109    foreach (item, table->selectedItems()) {
110       current = item->row();
111       tab[current]=true;
112    }
113
114    sel += "=";
115
116    for(int i=0; i<s; i++) {
117       if (tab[i]) {
118          sel += table->item(i, 0)->text();
119          sel += ",";
120       }
121    }
122    sel.chop(1);                 // remove trailing , or useless =
123    free(tab);
124 }
125
126 /* Label Media populating current storage by default */
127 void Content::consoleLabelStorage()
128 {
129    QString sel;
130    table_get_selection(tableContent, sel);
131    if (sel == "") {
132       new labelPage(m_currentStorage);
133    } else {
134       QString cmd = "label barcodes slots";
135       cmd += sel;
136       cmd += " storage=" + m_currentStorage;
137       consoleCommand(cmd);
138    }
139 }
140
141 /* Mount currently selected storage */
142 void Content::consoleMountStorage()
143 {
144    setConsoleCurrent();
145    /* if this storage is an autochanger, lets ask for the slot */
146    new mountDialog(m_console, m_currentStorage);
147 }
148
149 /* Unmount Currently selected storage */
150 void Content::consoleUnMountStorage()
151 {
152    QString cmd("umount storage=");
153    cmd += m_currentStorage;
154    consoleCommand(cmd);
155 }
156
157 void Content::statusStorageWindow()
158 {
159    /* if one exists, then just set it current */
160    bool found = false;
161    foreach(Pages *page, mainWin->m_pagehash) {
162       if (mainWin->currentConsole() == page->console()) {
163          if (page->name() == tr("Storage Status %1").arg(m_currentStorage)) {
164             found = true;
165             page->setCurrent();
166          }
167       }
168    }
169    if (!found) {
170       QTreeWidgetItem *parentItem = mainWin->getFromHash(this);
171       new StorStat(m_currentStorage, parentItem);
172    }
173 }
174
175 /*
176  * The main meat of the class!!  The function that querries the director and 
177  * creates the widgets with appropriate values.
178  */
179 void Content::populateContent()
180 {
181    char buf[200];
182    time_t tim;
183    struct tm tm;
184
185    QStringList results_all;
186    QString cmd("status slots drive=0 storage=\"" + m_currentStorage + "\"");
187    m_console->dir_cmd(cmd, results_all);
188
189    Freeze frz(*tableContent); /* disable updating*/
190    Freeze frz2(*tableTray);
191    Freeze frz3(*tableDrive);
192
193    tableContent->clearContents();
194    tableTray->clearContents();
195    tableTray->clearContents();
196
197    // take only valid records, TODO: Add D to get drive status
198    QStringList results = results_all.filter(QRegExp("^[IS]\\|[0-9]+\\|"));
199    tableContent->setRowCount(results.size());
200
201    QStringList io_results = results_all.filter(QRegExp("^I\\|[0-9]+\\|"));
202    tableTray->setRowCount(io_results.size());
203
204    QString resultline;
205    QStringList fieldlist;
206    int row = 0, row_io=0;
207
208    foreach (resultline, results) {
209       fieldlist = resultline.split("|");
210       if (fieldlist.size() < 10) {
211          Pmsg1(0, "Discarding %s\n", resultline.data());
212          continue; /* some fields missing, ignore row */
213       }
214
215       int index=0;
216       QStringListIterator fld(fieldlist);
217       TableItemFormatter slotitem(*tableContent, row);
218
219       /* Slot type */
220       if (fld.next() == "I") {
221          TableItemFormatter ioitem(*tableTray, row_io++);
222          ioitem.setNumericFld(0, fieldlist[1]);
223          ioitem.setTextFld(1, fieldlist[3]);
224       }
225
226       /* Slot */
227       slotitem.setNumericFld(index++, fld.next()); 
228
229       /* Real Slot */
230       if (fld.next() != "") {
231
232          /* Volume */
233          slotitem.setTextFld(index++, fld.next());
234          
235          /* Bytes */
236          slotitem.setBytesFld(index++, fld.next());
237          
238          /* Status */
239          slotitem.setVolStatusFld(index++, fld.next());
240          
241          /* MediaType */
242          slotitem.setTextFld(index++, fld.next());
243          
244          /* Pool */
245          slotitem.setTextFld(index++, fld.next());
246          
247          tim = fld.next().toInt();
248          if (tim > 0) {
249             /* LastW */
250             localtime_r(&tim, &tm);
251             strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", &tm);
252             slotitem.setTextFld(index++, QString(buf));
253             
254             /* Expire */
255             tim = fld.next().toInt();
256             localtime_r(&tim, &tm);
257             strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", &tm);
258             slotitem.setTextFld(index++, QString(buf));
259          }
260       }
261       row++;
262    }
263
264    tableContent->verticalHeader()->hide();
265    tableContent->sortByColumn(0, Qt::AscendingOrder);
266    tableContent->setSortingEnabled(true);
267    tableContent->resizeColumnsToContents();
268    tableContent->resizeRowsToContents();
269
270    tableContent->setEditTriggers(QAbstractItemView::NoEditTriggers);
271    m_populated = true;
272
273    tableTray->verticalHeader()->hide();
274    tableTray->setEditTriggers(QAbstractItemView::NoEditTriggers);
275
276    tableDrive->verticalHeader()->hide();
277    QStringList drives = results_all.filter(QRegExp("^D\\|[0-9]+\\|"));
278    tableDrive->setRowCount(drives.size());
279
280    row = 0;
281    foreach (resultline, drives) {
282       fieldlist = resultline.split("|");
283       if (fieldlist.size() < 4) {
284          Pmsg1(0, "Discarding %s\n", resultline.data());
285          continue; /* some fields missing, ignore row */
286       }
287
288       int index=0;
289       QStringListIterator fld(fieldlist);
290       TableItemFormatter slotitem(*tableDrive, row);
291
292       /* Drive type */
293       fld.next();
294
295       /* Number */
296       slotitem.setNumericFld(index++, fld.next()); 
297
298       /* Slot */
299       fld.next();
300       
301       /* Volume */
302       slotitem.setTextFld(index++, fld.next());
303          
304       row++;
305    }
306
307    tableDrive->resizeRowsToContents();
308    tableDrive->setEditTriggers(QAbstractItemView::NoEditTriggers);
309 }
310
311 /*
312  * Virtual function which is called when this page is visible on the stack
313  */
314 void Content::currentStackItem()
315 {
316    if(!m_populated) {
317       populateContent();
318    }
319 }
320
321 void Content::treeItemChanged(QTreeWidgetItem *, QTreeWidgetItem *)
322 {
323
324 }
325
326 /* Update Slots */
327 void Content::consoleUpdateSlots()
328 {
329    QString sel = "";
330    table_get_selection(tableContent, sel);
331    
332    QString cmd("update slots");
333    if (sel != "") {
334       cmd += sel;
335    }
336    cmd += " drive=0 storage=" + m_currentStorage;
337
338    Pmsg1(0, "cmd=%s\n", cmd.toUtf8().data());
339
340    consoleCommand(cmd);
341    populateContent();
342 }
343
344 /* Release a tape in the drive */
345 void Content::consoleRelease()
346 {
347    QString cmd("release storage=");
348    cmd += m_currentStorage;
349    consoleCommand(cmd);
350 }