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