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