1 /*
2 Bacula(R) - The Network Backup Solution
3
4 Copyright (C) 2000-2020 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 "dirstat.h"
28
29 static bool working = false; /* prevent timer recursion */
30
31 /*
32 * Constructor for the class
33 */
DirStat()34 DirStat::DirStat() : Pages()
35 {
36 setupUi(this);
37 m_name = tr("Director Status");
38 pgInitialize();
39 QTreeWidgetItem* thisitem = mainWin->getFromHash(this);
40 thisitem->setIcon(0,QIcon(QString::fromUtf8(":images/status.png")));
41 m_cursor = new QTextCursor(textEdit->document());
42
43 m_timer = new QTimer(this);
44 readSettings();
45 m_timer->start(1000);
46
47 createConnections();
48 setCurrent();
49 }
50
getFont()51 void DirStat::getFont()
52 {
53 QFont font = textEdit->font();
54
55 QString dirname;
56 m_console->getDirResName(dirname);
57 QSettings settings(dirname, "bat");
58 settings.beginGroup("Console");
59 font.setFamily(settings.value("consoleFont", "Courier").value<QString>());
60 font.setPointSize(settings.value("consolePointSize", 10).toInt());
61 font.setFixedPitch(settings.value("consoleFixedPitch", true).toBool());
62 settings.endGroup();
63 textEdit->setFont(font);
64 }
65
66 /*
67 * Write the m_splitter settings in the destructor
68 */
~DirStat()69 DirStat::~DirStat()
70 {
71 writeSettings();
72 }
73
74 /*
75 * Populate all tables and header widgets
76 */
populateAll()77 void DirStat::populateAll()
78 {
79 populateHeader();
80 populateTerminated();
81 populateScheduled();
82 populateRunning();
83 }
84
85 /*
86 * Timer is triggered, see if is current and repopulate.
87 */
timerTriggered()88 void DirStat::timerTriggered()
89 {
90 double value = timerDisplay->value();
91 value -= 1;
92 if (value <= 0 && !working) {
93 working = true;
94 value = spinBox->value();
95 bool iscurrent = mainWin->tabWidget->currentIndex() == mainWin->tabWidget->indexOf(this);
96 if (((isDocked() && iscurrent) || ((!isDocked()) && isOnceDocked())) && (checkBox->checkState() == Qt::Checked)) {
97 populateAll();
98 }
99 working = false;
100 }
101 timerDisplay->display(value);
102 }
103
104 /*
105 * Populate header text widget
106 */
populateHeader()107 void DirStat::populateHeader()
108 {
109 QString command = QString(".status dir header");
110 if (mainWin->m_commandDebug)
111 Pmsg1(000, "sending command : %s\n",command.toUtf8().data());
112 QStringList results;
113 textEdit->clear();
114
115 if (m_console->dir_cmd(command, results)) {
116 foreach (QString line, results) {
117 line += "\n";
118 textEdit->insertPlainText(line);
119 }
120 }
121 }
122
123 /*
124 * Populate teminated table
125 */
populateTerminated()126 void DirStat::populateTerminated()
127 {
128 QString command = QString(".status dir terminated");
129 if (mainWin->m_commandDebug)
130 Pmsg1(000, "sending command : %s\n",command.toUtf8().data());
131 QStringList results;
132 QBrush blackBrush(Qt::black);
133
134 terminatedTable->clear();
135 QStringList headerlist = (QStringList()
136 << tr("Job Id") << tr("Job Level") << tr("Job Files")
137 << tr("Job Bytes") << tr("Job Status") << tr("Job Time")
138 << tr("Job Name"));
139 QStringList flaglist = (QStringList()
140 << "R" << "L" << "R" << "R" << "LC"
141 << "L" << "L");
142
143 terminatedTable->setColumnCount(headerlist.size());
144 terminatedTable->setHorizontalHeaderLabels(headerlist);
145
146 if (m_console->dir_cmd(command, results)) {
147 int row = 0;
148 QTableWidgetItem* p_tableitem;
149 terminatedTable->setRowCount(results.size());
150 foreach (QString line, results) {
151 /* Iterate through the record returned from the query */
152 QStringList fieldlist = line.split("\t");
153 int column = 0;
154 QString statusCode("");
155 /* Iterate through fields in the record */
156 foreach (QString field, fieldlist) {
157 field = field.trimmed(); /* strip leading & trailing spaces */
158 p_tableitem = new QTableWidgetItem(field, 1);
159 p_tableitem->setForeground(blackBrush);
160 p_tableitem->setFlags(0);
161 if (flaglist[column].contains("R"))
162 p_tableitem->setTextAlignment(Qt::AlignRight);
163 if (flaglist[column].contains("C")) {
164 if (field == "OK")
165 p_tableitem->setBackground(Qt::green);
166 else
167 p_tableitem->setBackground(Qt::red);
168 }
169 terminatedTable->setItem(results.size() - row - 1, column, p_tableitem);
170 column += 1;
171 }
172 row += 1;
173 }
174 }
175 terminatedTable->resizeColumnsToContents();
176 terminatedTable->resizeRowsToContents();
177 terminatedTable->verticalHeader()->hide();
178 }
179
180 /*
181 * Populate scheduled table
182 */
populateScheduled()183 void DirStat::populateScheduled()
184 {
185 QString command = QString(".status dir scheduled");
186 if (mainWin->m_commandDebug)
187 Pmsg1(000, "sending command : %s\n",command.toUtf8().data());
188 QStringList results;
189 QBrush blackBrush(Qt::black);
190
191 scheduledTable->clear();
192 QStringList headerlist = (QStringList()
193 << tr("Job Level") << tr("Job Type") << tr("Priority") << tr("Job Time")
194 << tr("Job Name") << tr("Volume"));
195 QStringList flaglist = (QStringList()
196 << "L" << "L" << "R" << "L" << "L" << "L");
197
198 scheduledTable->setColumnCount(headerlist.size());
199 scheduledTable->setHorizontalHeaderLabels(headerlist);
200 scheduledTable->setSelectionBehavior(QAbstractItemView::SelectRows);
201 scheduledTable->setSelectionMode(QAbstractItemView::SingleSelection);
202
203 if (m_console->dir_cmd(command, results)) {
204 int row = 0;
205 QTableWidgetItem* p_tableitem;
206 scheduledTable->setRowCount(results.size());
207 foreach (QString line, results) {
208 /* Iterate through the record returned from the query */
209 QStringList fieldlist = line.split("\t");
210 int column = 0;
211 QString statusCode("");
212 /* Iterate through fields in the record */
213 foreach (QString field, fieldlist) {
214 field = field.trimmed(); /* strip leading & trailing spaces */
215 p_tableitem = new QTableWidgetItem(field, 1);
216 p_tableitem->setForeground(blackBrush);
217 scheduledTable->setItem(row, column, p_tableitem);
218 column += 1;
219 }
220 row += 1;
221 }
222 }
223 scheduledTable->resizeColumnsToContents();
224 scheduledTable->resizeRowsToContents();
225 scheduledTable->verticalHeader()->hide();
226 }
227
228 /*
229 * Populate running table
230 */
populateRunning()231 void DirStat::populateRunning()
232 {
233 QString command = QString(".status dir running");
234 if (mainWin->m_commandDebug)
235 Pmsg1(000, "sending command : %s\n",command.toUtf8().data());
236 QStringList results;
237 QBrush blackBrush(Qt::black);
238
239 runningTable->clear();
240 QStringList headerlist = (QStringList()
241 << tr("Job Id") << tr("Job Level") << tr("Job Data") << tr("Job Info"));
242
243 runningTable->setColumnCount(headerlist.size());
244 runningTable->setHorizontalHeaderLabels(headerlist);
245 runningTable->setSelectionBehavior(QAbstractItemView::SelectRows);
246
247 if (m_console->dir_cmd(command, results)) {
248 int row = 0;
249 QTableWidgetItem* p_tableitem;
250 runningTable->setRowCount(results.size());
251 foreach (QString line, results) {
252 /* Iterate through the record returned from the query */
253 QStringList fieldlist = line.split("\t");
254 int column = 0;
255 QString statusCode("");
256 /* Iterate through fields in the record */
257 foreach (QString field, fieldlist) {
258 field = field.trimmed(); /* strip leading & trailing spaces */
259 p_tableitem = new QTableWidgetItem(field, 1);
260 p_tableitem->setForeground(blackBrush);
261 runningTable->setItem(row, column, p_tableitem);
262 column += 1;
263 }
264 row += 1;
265 }
266 }
267 runningTable->resizeColumnsToContents();
268 runningTable->resizeRowsToContents();
269 runningTable->verticalHeader()->hide();
270 }
271
272 /*
273 * When the treeWidgetItem in the page selector tree is singleclicked, Make sure
274 * The tree has been populated.
275 */
PgSeltreeWidgetClicked()276 void DirStat::PgSeltreeWidgetClicked()
277 {
278 if (!m_populated) {
279 populateAll();
280 m_populated=true;
281 }
282 if (!isOnceDocked()) {
283 dockPage();
284 }
285 }
286
287 /*
288 * Virtual function override of pages function which is called when this page
289 * is visible on the stack
290 */
currentStackItem()291 void DirStat::currentStackItem()
292 {
293 populateAll();
294 timerDisplay->display(spinBox->value());
295 if (!m_populated) {
296 m_populated=true;
297 }
298 }
299
300 /*
301 * Function to create connections for context sensitive menu for this and
302 * the page selector
303 */
createConnections()304 void DirStat::createConnections()
305 {
306 connect(actionRefresh, SIGNAL(triggered()), this, SLOT(populateAll()));
307 connect(actionCancelRunning, SIGNAL(triggered()), this, SLOT(consoleCancelJob()));
308 connect(actionDisableScheduledJob, SIGNAL(triggered()), this, SLOT(consoleDisableJob()));
309 connect(m_timer, SIGNAL(timeout()), this, SLOT(timerTriggered()));
310
311 scheduledTable->setContextMenuPolicy(Qt::ActionsContextMenu);
312 scheduledTable->addAction(actionRefresh);
313 scheduledTable->addAction(actionDisableScheduledJob);
314 terminatedTable->setContextMenuPolicy(Qt::ActionsContextMenu);
315 terminatedTable->addAction(actionRefresh);
316 runningTable->setContextMenuPolicy(Qt::ActionsContextMenu);
317 runningTable->addAction(actionRefresh);
318 runningTable->addAction(actionCancelRunning);
319 }
320
321 /*
322 * Save user settings associated with this page
323 */
writeSettings()324 void DirStat::writeSettings()
325 {
326 QSettings settings(m_console->m_dir->name(), "bat");
327 settings.beginGroup(m_groupText);
328 settings.setValue(m_splitText, splitter->saveState());
329 settings.setValue("refreshInterval", spinBox->value());
330 settings.setValue("refreshCheck", checkBox->checkState());
331 settings.endGroup();
332 }
333
334 /*
335 * Read and restore user settings associated with this page
336 */
readSettings()337 void DirStat::readSettings()
338 {
339 m_groupText = "DirStatPage";
340 m_splitText = "splitterSizes_0";
341 QSettings settings(m_console->m_dir->name(), "bat");
342 settings.beginGroup(m_groupText);
343 if (settings.contains(m_splitText)) { splitter->restoreState(settings.value(m_splitText).toByteArray()); }
344 spinBox->setValue(settings.value("refreshInterval", 28).toInt());
345 checkBox->setCheckState((Qt::CheckState)settings.value("refreshCheck", Qt::Checked).toInt());
346 settings.endGroup();
347
348 timerDisplay->display(spinBox->value());
349 }
350
351 /*
352 * Cancel a running job
353 */
consoleCancelJob()354 void DirStat::consoleCancelJob()
355 {
356 QList<int> rowList;
357 QList<QTableWidgetItem *> sitems = runningTable->selectedItems();
358 foreach (QTableWidgetItem *sitem, sitems) {
359 int row = sitem->row();
360 if (!rowList.contains(row)) {
361 rowList.append(row);
362 }
363 }
364
365 QStringList selectedJobsList;
366 foreach(int row, rowList) {
367 QTableWidgetItem * sitem = runningTable->item(row, 0);
368 selectedJobsList.append(sitem->text());
369 }
370 foreach( QString job, selectedJobsList )
371 {
372 QString cmd("cancel jobid=");
373 cmd += job;
374 consoleCommand(cmd);
375 }
376 }
377
378 /*
379 * Disable a scheduled Job
380 */
consoleDisableJob()381 void DirStat::consoleDisableJob()
382 {
383 int currentrow = scheduledTable->currentRow();
384 QTableWidgetItem *item = scheduledTable->item(currentrow, 4);
385 if (item) {
386 QString text = item->text();
387 QString cmd("disable job=\"");
388 cmd += text + '"';
389 consoleCommand(cmd);
390 }
391 }
392