]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/qt-console/status/storstat.cpp
5eb326eeafe04a0ac319d354205bcc5ad0854db8
[bacula/bacula] / bacula / src / qt-console / status / storstat.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  *
21  *   Dirk Bartley, March 2007
22  */
23  
24 #include "bat.h"
25 #include <QAbstractEventDispatcher>
26 #include <QTableWidgetItem>
27 #include "storstat.h"
28 #include "mount/mount.h"
29 #include "label/label.h"
30
31 static bool working = false;     /* prevent timer recursion */
32
33 /*
34 .status storage=<storage-name> <keyword>
35 where <storage-name> is the storage name in the Director, and 
36 <keyword> is one of the following:
37 header
38 running
39 terminated
40
41 waitreservation
42 devices
43 volumes
44 spooling
45 */
46
47 /*
48  * Constructor for the class
49  */
50 StorStat::StorStat(QString &storage, QTreeWidgetItem *parentTreeWidgetItem)
51    : Pages()
52 {
53    m_storage = storage;
54    setupUi(this);
55    pgInitialize(tr("Storage Status %1").arg(m_storage), parentTreeWidgetItem);
56    QTreeWidgetItem* thisitem = mainWin->getFromHash(this);
57    thisitem->setIcon(0,QIcon(QString::fromUtf8(":images/status.png")));
58    m_cursor = new QTextCursor(textEditHeader->document());
59
60    m_timer = new QTimer(this);
61    readSettings();
62
63    createConnections();
64    m_timer->start(1000);
65    setCurrent();
66
67    dockPage();
68 }
69
70 void StorStat::getFont()
71 {
72    QFont font = textEditHeader->font();
73
74    QString dirname;
75    m_console->getDirResName(dirname);
76    QSettings settings(dirname, "bat");
77    settings.beginGroup("Console");
78    font.setFamily(settings.value("consoleFont", "Courier").value<QString>());
79    font.setPointSize(settings.value("consolePointSize", 10).toInt());
80    font.setFixedPitch(settings.value("consoleFixedPitch", true).toBool());
81    settings.endGroup();
82    textEditHeader->setFont(font);
83 }
84
85 /*
86  * Write the m_splitter settings in the destructor
87  */
88 StorStat::~StorStat()
89 {
90    writeSettings();
91 }
92
93 /*
94  * Populate all tables and header widgets
95  */
96 void StorStat::populateAll()
97 {
98    populateTerminated();
99    populateCurrentTab(tabWidget->currentIndex());
100 }
101
102 /*
103  *  Timer is triggered, see if is current and repopulate.
104  */
105 void StorStat::timerTriggered()
106 {
107    double value = timerDisplay->value();
108    value -= 1;
109    if (value <= 0 && !working) {
110       working = true;
111       value = spinBox->value();
112       bool iscurrent = mainWin->tabWidget->currentIndex() == mainWin->tabWidget->indexOf(this);
113       if (((isDocked() && iscurrent) || (!isDocked())) && (checkBox->checkState() == Qt::Checked)) {
114          populateAll();
115       }
116       working = false;
117    }
118    timerDisplay->display(value);
119 }
120
121 /*
122  * Populate header text widget
123  */
124 void StorStat::populateHeader()
125 {
126    QString command = QString(".status storage=\"" + m_storage + "\" header");
127    if (mainWin->m_commandDebug)
128       Pmsg1(000, "sending command : %s\n",command.toUtf8().data());
129    QStringList results;
130    textEditHeader->clear();
131
132    if (m_console->dir_cmd(command, results)) {
133       foreach (QString line, results) {
134          line += "\n";
135          textEditHeader->insertPlainText(line);
136       }
137    }
138 }
139
140 void StorStat::populateWaitReservation()
141 {
142    QString command = QString(".status storage=\"" + m_storage + "\" waitreservation");
143    if (mainWin->m_commandDebug)
144       Pmsg1(000, "sending command : %s\n",command.toUtf8().data());
145    QStringList results;
146    textEditWaitReservation->clear();
147
148    if (m_console->dir_cmd(command, results)) {
149       foreach (QString line, results) {
150          line += "\n";
151          textEditWaitReservation->insertPlainText(line);
152       }
153    }
154 }
155
156 void StorStat::populateDevices()
157 {
158    QString command = QString(".status storage=\"" + m_storage + "\" devices");
159    if (mainWin->m_commandDebug)
160       Pmsg1(000, "sending command : %s\n",command.toUtf8().data());
161    QStringList results;
162    textEditDevices->clear();
163
164    if (m_console->dir_cmd(command, results)) {
165       foreach (QString line, results) {
166          line += "\n";
167          textEditDevices->insertPlainText(line);
168       }
169    }
170 }
171
172 void StorStat::populateVolumes()
173 {
174    QString command = QString(".status storage=\"" + m_storage + "\" volumes");
175    if (mainWin->m_commandDebug)
176       Pmsg1(000, "sending command : %s\n",command.toUtf8().data());
177    QStringList results;
178    textEditVolumes->clear();
179
180    if (m_console->dir_cmd(command, results)) {
181       foreach (QString line, results) {
182          line += "\n";
183          textEditVolumes->insertPlainText(line);
184       }
185    }
186 }
187
188 void StorStat::populateSpooling()
189 {
190    QString command = QString(".status storage=\"" + m_storage + "\" spooling");
191    if (mainWin->m_commandDebug)
192       Pmsg1(000, "sending command : %s\n",command.toUtf8().data());
193    QStringList results;
194    textEditSpooling->clear();
195
196    if (m_console->dir_cmd(command, results)) {
197       foreach (QString line, results) {
198          line += "\n";
199          textEditSpooling->insertPlainText(line);
200       }
201    }
202 }
203
204 void StorStat::populateRunning()
205 {
206    QString command = QString(".status storage=\"" + m_storage + "\" running");
207    if (mainWin->m_commandDebug)
208       Pmsg1(000, "sending command : %s\n",command.toUtf8().data());
209    QStringList results;
210    textEditRunning->clear();
211
212    if (m_console->dir_cmd(command, results)) {
213       foreach (QString line, results) {
214          line += "\n";
215          textEditRunning->insertPlainText(line);
216       }
217    }
218 }
219
220 /*
221  * Populate teminated table
222  */
223 void StorStat::populateTerminated()
224 {
225    QString command = QString(".status storage=\"" + m_storage + "\" terminated");
226    if (mainWin->m_commandDebug)
227       Pmsg1(000, "sending command : %s\n",command.toUtf8().data());
228    QStringList results;
229    QBrush blackBrush(Qt::black);
230
231    terminatedTable->clear();
232    QStringList headerlist = (QStringList()
233       << tr("Job Id") << tr("Job Level") << tr("Job Files")
234       << tr("Job Bytes") << tr("Job Status") << tr("Job Time") 
235       << tr("Job Name"));
236    QStringList flaglist = (QStringList()
237       << "R" << "L" << "R" << "R" << "LC" 
238       << "L" << "L");
239
240    terminatedTable->setColumnCount(headerlist.size());
241    terminatedTable->setHorizontalHeaderLabels(headerlist);
242
243    if (m_console->dir_cmd(command, results)) {
244       int row = 0;
245       QTableWidgetItem* p_tableitem;
246       terminatedTable->setRowCount(results.size());
247       foreach (QString line, results) {
248          /* Iterate through the record returned from the query */
249          QStringList fieldlist = line.split("\t");
250          int column = 0;
251          QString statusCode("");
252          /* Iterate through fields in the record */
253          foreach (QString field, fieldlist) {
254             field = field.trimmed();  /* strip leading & trailing spaces */
255             p_tableitem = new QTableWidgetItem(field, 1);
256             p_tableitem->setForeground(blackBrush);
257             p_tableitem->setFlags(0);
258             if (flaglist[column].contains("R"))
259                p_tableitem->setTextAlignment(Qt::AlignRight);
260             if (flaglist[column].contains("C")) {
261                if (field == "OK")
262                   p_tableitem->setBackground(Qt::green);
263                else
264                   p_tableitem->setBackground(Qt::red);
265             }
266             terminatedTable->setItem(row, column, p_tableitem);
267             column += 1;
268          }
269          row += 1;
270       }
271    }
272    terminatedTable->resizeColumnsToContents();
273    terminatedTable->resizeRowsToContents();
274    terminatedTable->verticalHeader()->hide();
275 }
276
277 /*
278  * When the treeWidgetItem in the page selector tree is singleclicked, Make sure
279  * The tree has been populated.
280  */
281 void StorStat::PgSeltreeWidgetClicked()
282 {
283    if (!m_populated) {
284       populateAll();
285       m_populated=true;
286    }
287 }
288
289 /*
290  *  Virtual function override of pages function which is called when this page
291  *  is visible on the stack
292  */
293 void StorStat::currentStackItem()
294 {
295    populateAll();
296    timerDisplay->display(spinBox->value());
297    if (!m_populated) {
298       m_populated=true;
299    }
300 }
301
302 /*
303  * Function to create connections for context sensitive menu for this and
304  * the page selector
305  */
306 void StorStat::createConnections()
307 {
308    connect(actionRefresh, SIGNAL(triggered()), this, SLOT(populateAll()));
309    connect(tabWidget, SIGNAL(currentChanged(int)), this, SLOT(populateCurrentTab(int)));
310    connect(mountButton, SIGNAL(pressed()), this, SLOT(mountButtonPushed()));
311    connect(umountButton, SIGNAL(pressed()), this, SLOT(umountButtonPushed()));
312    connect(labelButton, SIGNAL(pressed()), this, SLOT(labelButtonPushed()));
313    connect(releaseButton, SIGNAL(pressed()), this, SLOT(releaseButtonPushed()));
314    terminatedTable->setContextMenuPolicy(Qt::ActionsContextMenu);
315    terminatedTable->addAction(actionRefresh);
316    connect(m_timer, SIGNAL(timeout()), this, SLOT(timerTriggered()));
317 }
318
319 /*
320  * Save user settings associated with this page
321  */
322 void StorStat::writeSettings()
323 {
324    QSettings settings(m_console->m_dir->name(), "bat");
325    settings.beginGroup(m_groupText);
326    settings.setValue(m_splitText, splitter->saveState());
327    settings.setValue("refreshInterval", spinBox->value());
328    settings.setValue("refreshCheck", checkBox->checkState());
329    settings.endGroup();
330
331    settings.beginGroup("OpenOnExit");
332    QString toWrite = "StorageStatus_" + m_storage;
333    settings.setValue(toWrite, 1);
334    settings.endGroup();
335 }
336
337 /*
338  * Read and restore user settings associated with this page
339  */
340 void StorStat::readSettings()
341 {
342    m_groupText = "StorStatPage";
343    m_splitText = "splitterSizes_0";
344    QSettings settings(m_console->m_dir->name(), "bat");
345    settings.beginGroup(m_groupText);
346    if (settings.contains(m_splitText)) { splitter->restoreState(settings.value(m_splitText).toByteArray()); }
347    spinBox->setValue(settings.value("refreshInterval", 28).toInt());
348    checkBox->setCheckState((Qt::CheckState)settings.value("refreshCheck", Qt::Checked).toInt());
349    settings.endGroup();
350
351    timerDisplay->display(spinBox->value());
352 }
353
354 /*
355  * Populate the text edit window in the current tab
356  */
357 void StorStat::populateCurrentTab(int index)
358 {
359    if (index == 0)
360       populateHeader();
361    if (index == 1)
362       populateWaitReservation();
363    if (index == 2)
364       populateDevices();
365    if (index == 3)
366       populateVolumes();
367    if (index == 4)
368       populateSpooling();
369    if (index == 5)
370       populateRunning();
371 }
372
373 /*
374  * execute mount in console
375  */
376 void StorStat::mountButtonPushed()
377 {
378    int haschanger = 3;
379
380    /* Set up query QString and header QStringList */
381    QString query("SELECT AutoChanger AS Changer"
382             " FROM Storage WHERE Name='" + m_storage + "'"
383             " ORDER BY Name" );
384
385    QStringList results;
386    /* This could be a log item */
387    if (mainWin->m_sqlDebug) {
388       Pmsg1(000, "Storage query cmd : %s\n",query.toUtf8().data());
389    }
390    if (m_console->sql_cmd(query, results)) {
391       int resultCount = results.count();
392       if (resultCount == 1){
393          QString resultline;
394          QString field;
395          QStringList fieldlist;
396          /* there will only be one of these */
397          foreach (resultline, results) {
398             fieldlist = resultline.split("\t");
399             int index = 0;
400             /* Iterate through fields in the record */
401             foreach (field, fieldlist) {
402                field = field.trimmed();  /* strip leading & trailing spaces */
403                haschanger = field.toInt();
404                index++;
405             }
406          }
407       }
408    }
409
410    Pmsg1(000, "haschanger is : %i\n", haschanger);
411    if (haschanger == 0){
412       /* no autochanger, just execute the command in the console */
413       QString cmd("mount storage=" + m_storage);
414       consoleCommand(cmd);
415    } else if (haschanger != 3) {
416       setConsoleCurrent();
417       /* if this storage is an autochanger, lets ask for the slot */
418       new mountDialog(m_console, m_storage);
419    }
420 }
421
422 /*
423  * execute umount in console
424  */
425 void StorStat::umountButtonPushed()
426 {
427    QString cmd("umount storage=" + m_storage);
428    consoleCommand(cmd);
429 }
430
431 /* Release a tape in the drive */
432 void StorStat::releaseButtonPushed()
433 {
434    QString cmd("release storage=");
435    cmd += m_storage;
436    consoleCommand(cmd);
437 }
438
439 /* Label Media populating current storage by default */
440 void StorStat::labelButtonPushed()
441 {
442    new labelPage(m_storage);
443 }