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