]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/qt-console/joblist/joblist.cpp
Oops. When I changed the contents of the field earlier, I forgot to make this change
[bacula/bacula] / bacula / src / qt-console / joblist / joblist.cpp
1 /*
2    Bacula® - The Network Backup Solution
3
4    Copyright (C) 2007-2008 Free Software Foundation Europe e.V.
5
6    The main author of Bacula is Kern Sibbald, with contributions from
7    many others, a complete list can be found in the file AUTHORS.
8    This program is Free Software; you can redistribute it and/or
9    modify it under the terms of version two of the GNU General Public
10    License as published by the Free Software Foundation and included
11    in the file LICENSE.
12
13    This program is distributed in the hope that it will be useful, but
14    WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16    General Public License for more details.
17
18    You should have received a copy of the GNU General Public License
19    along with this program; if not, write to the Free Software
20    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21    02110-1301, USA.
22
23    Bacula® is a registered trademark of John Walker.
24    The licensor of Bacula is the Free Software Foundation Europe
25    (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
26    Switzerland, email:ftf@fsfeurope.org.
27 */
28 /*
29  *   Version $Id$
30  *
31  *   Dirk Bartley, March 2007
32  */
33  
34 #include <QAbstractEventDispatcher>
35 #include <QTableWidgetItem>
36 #include "bat.h"
37 #include "joblist.h"
38 #include "restore.h"
39 #include "joblog/joblog.h"
40 #include "jobgraphs/jobplot.h"
41
42 /*
43  * Constructor for the class
44  */
45 JobList::JobList(const QString &mediaName, const QString &clientName,
46           const QString &jobName, const QString &filesetName, QTreeWidgetItem *parentTreeWidgetItem)
47 {
48    setupUi(this);
49    m_name = ""; /* treeWidgetName has a virtual override in this class */
50    m_mediaName = mediaName;
51    m_clientName = clientName;
52    m_jobName = jobName;
53    m_filesetName = filesetName;
54    m_filesetName = filesetName;
55    pgInitialize(parentTreeWidgetItem);
56    QTreeWidgetItem* thisitem = mainWin->getFromHash(this);
57    thisitem->setIcon(0,QIcon(QString::fromUtf8(":images/emblem-system.png")));
58
59    m_resultCount = 0;
60    m_populated = false;
61    m_closeable = false;
62    if ((m_mediaName != "") || (m_clientName != "") || (m_jobName != "") || (m_filesetName != ""))
63       m_closeable=true;
64    m_checkCurrentWidget = true;
65    createConnections();
66
67    /* Set Defaults for check and spin for limits */
68    limitCheckBox->setCheckState(mainWin->m_recordLimitCheck ? Qt::Checked : Qt::Unchecked);
69    limitSpinBox->setValue(mainWin->m_recordLimitVal);
70    daysCheckBox->setCheckState(mainWin->m_daysLimitCheck ? Qt::Checked : Qt::Unchecked);
71    daysSpinBox->setValue(mainWin->m_daysLimitVal);
72    dockPage();
73
74    QGridLayout *gridLayout = new QGridLayout(this);
75    gridLayout->setSpacing(6);
76    gridLayout->setMargin(9);
77    gridLayout->setObjectName(QString::fromUtf8("gridLayout"));
78
79    m_splitter = new QSplitter(Qt::Vertical, this);
80    QScrollArea *area = new QScrollArea();
81    area->setObjectName(QString::fromUtf8("area"));
82    area->setWidget(frame);
83    area->setWidgetResizable(true);
84    m_splitter->addWidget(mp_tableWidget);
85    m_splitter->addWidget(area);
86
87    gridLayout->addWidget(m_splitter, 0, 0, 1, 1);
88    readSettings();
89 }
90
91 /*
92  * Write the m_splitter settings in the destructor
93  */
94 JobList::~JobList()
95 {
96    writeSettings();
97 }
98
99 /*
100  * The Meat of the class.
101  * This function will populate the QTableWidget, mp_tablewidget, with
102  * QTableWidgetItems representing the results of a query for what jobs exist on
103  * the media name passed from the constructor stored in m_mediaName.
104  */
105 void JobList::populateTable()
106 {
107    QStringList results;
108    QString resultline;
109    QBrush blackBrush(Qt::black);
110
111    if (!m_console->preventInUseConnect())
112        return;
113
114    /* Can't do this in constructor because not neccesarily conected in constructor */
115    if (!m_populated) {
116       clientComboBox->addItem(tr("Any"));
117       clientComboBox->addItems(m_console->client_list);
118       int clientIndex = clientComboBox->findText(m_clientName, Qt::MatchExactly);
119       if (clientIndex != -1)
120          clientComboBox->setCurrentIndex(clientIndex);
121
122       QStringList volumeList;
123       m_console->getVolumeList(volumeList);
124       volumeComboBox->addItem(tr("Any"));
125       volumeComboBox->addItems(volumeList);
126       int volumeIndex = volumeComboBox->findText(m_mediaName, Qt::MatchExactly);
127       if (volumeIndex != -1) {
128          volumeComboBox->setCurrentIndex(volumeIndex);
129       }
130       jobComboBox->addItem(tr("Any"));
131       jobComboBox->addItems(m_console->job_list);
132       int jobIndex = jobComboBox->findText(m_jobName, Qt::MatchExactly);
133       if (jobIndex != -1) {
134          jobComboBox->setCurrentIndex(jobIndex);
135       }
136       levelComboBox->addItem(tr("Any"));
137       levelComboBox->addItems( QStringList() << "F" << "D" << "I");
138       purgedComboBox->addItem(tr("Any"));
139       purgedComboBox->addItems( QStringList() << "0" << "1");
140       fileSetComboBox->addItem(tr("Any"));
141       fileSetComboBox->addItems(m_console->fileset_list);
142       int filesetIndex = fileSetComboBox->findText(m_filesetName, Qt::MatchExactly);
143       if (filesetIndex != -1) {
144          fileSetComboBox->setCurrentIndex(filesetIndex);
145       }
146       QStringList statusLongList;
147       m_console->getStatusList(statusLongList);
148       statusComboBox->addItem(tr("Any"));
149       statusComboBox->addItems(statusLongList);
150    }
151
152    /* Set up query */
153    QString query("");
154    int volumeIndex = volumeComboBox->currentIndex();
155    if (volumeIndex != -1)
156       m_mediaName = volumeComboBox->itemText(volumeIndex);
157    QString distinct = "";
158    if (m_mediaName != tr("Any")) { distinct = "DISTINCT "; }
159    query += "SELECT " + distinct + "Job.Jobid AS Id, Job.Name AS JobName, " 
160             " Client.Name AS Client,"
161             " Job.Starttime AS JobStart, Job.Type AS JobType,"
162             " Job.Level AS BackupLevel, Job.Jobfiles AS FileCount,"
163             " Job.JobBytes AS Bytes,"
164             " Job.JobStatus AS Status, Status.JobStatusLong AS StatusLong,"
165             " Job.PurgedFiles AS Purged, FileSet.FileSet"
166             " FROM Job"
167             " JOIN Client ON (Client.ClientId=Job.ClientId)"
168             " JOIN Status ON (Job.JobStatus=Status.JobStatus)"
169             " LEFT OUTER JOIN FileSet ON (FileSet.FileSetId=Job.FileSetId) ";
170    QStringList conditions;
171    if (m_mediaName != tr("Any")) {
172       query += " LEFT OUTER JOIN JobMedia ON (JobMedia.JobId=Job.JobId) "
173                " LEFT OUTER JOIN Media ON (JobMedia.MediaId=Media.MediaId) ";
174       conditions.append("Media.VolumeName='" + m_mediaName + "'");
175    }
176    int clientIndex = clientComboBox->currentIndex();
177    if (clientIndex != -1)
178       m_clientName = clientComboBox->itemText(clientIndex);
179    if (m_clientName != tr("Any")) {
180       conditions.append("Client.Name='" + m_clientName + "'");
181    }
182    int jobIndex = jobComboBox->currentIndex();
183    if (jobIndex != -1)
184       m_jobName = jobComboBox->itemText(jobIndex);
185    if ((jobIndex != -1) && (jobComboBox->itemText(jobIndex) != tr("Any"))) {
186       conditions.append("Job.Name='" + jobComboBox->itemText(jobIndex) + "'");
187    }
188    int levelIndex = levelComboBox->currentIndex();
189    if ((levelIndex != -1) && (levelComboBox->itemText(levelIndex) != tr("Any"))) {
190       conditions.append("Job.Level='" + levelComboBox->itemText(levelIndex) + "'");
191    }
192    int statusIndex = statusComboBox->currentIndex();
193    if ((statusIndex != -1) && (statusComboBox->itemText(statusIndex) != tr("Any"))) {
194       conditions.append("Status.JobStatusLong='" + statusComboBox->itemText(statusIndex) + "'");
195    }
196    int purgedIndex = purgedComboBox->currentIndex();
197    if ((purgedIndex != -1) && (purgedComboBox->itemText(purgedIndex) != tr("Any"))) {
198       conditions.append("Job.PurgedFiles='" + purgedComboBox->itemText(purgedIndex) + "'");
199    }
200    int fileSetIndex = fileSetComboBox->currentIndex();
201    if (fileSetIndex != -1)
202       m_filesetName = fileSetComboBox->itemText(fileSetIndex);
203    if ((fileSetIndex != -1) && (fileSetComboBox->itemText(fileSetIndex) != tr("Any"))) {
204       conditions.append("FileSet.FileSet='" + fileSetComboBox->itemText(fileSetIndex) + "'");
205    }
206    /* If Limit check box For limit by days is checked  */
207    if (daysCheckBox->checkState() == Qt::Checked) {
208       QDateTime stamp = QDateTime::currentDateTime().addDays(-daysSpinBox->value());
209       QString since = stamp.toString(Qt::ISODate);
210       conditions.append("Job.Starttime>'" + since + "'");
211    }
212    bool first = true;
213    foreach (QString condition, conditions) {
214       if (first) {
215          query += " WHERE " + condition;
216          first = false;
217       } else {
218          query += " AND " + condition;
219       }
220    }
221    /* Descending */
222    query += " ORDER BY Job.Starttime DESC, Job.JobId DESC";
223    /* If Limit check box for limit records returned is checked  */
224    if (limitCheckBox->checkState() == Qt::Checked) {
225       QString limit;
226       limit.setNum(limitSpinBox->value());
227       query += " LIMIT " + limit;
228    }
229
230    /* Set up the Header for the table */
231    QStringList headerlist = (QStringList()
232       << tr("Job Id") << tr("Job Name") << tr("Client") << tr("Job Starttime") 
233       << tr("Job Type") << tr("Job Level") << tr("Job Files") 
234       << tr("Job Bytes") << tr("Job Status")  << tr("Purged") << tr("File Set"));
235    m_jobIdIndex = headerlist.indexOf(tr("Job Id"));
236    m_purgedIndex = headerlist.indexOf(tr("Purged"));
237    m_typeIndex = headerlist.indexOf(tr("Job Type"));
238    m_statusIndex = headerlist.indexOf(tr("Job Status"));
239    m_startIndex = headerlist.indexOf(tr("Job Starttime"));
240    m_filesIndex = headerlist.indexOf(tr("Job Files"));
241    m_bytesIndex = headerlist.indexOf(tr("Job Bytes"));
242    int jobLevelIndex = headerlist.indexOf(tr("Job Level"));
243
244    /* Initialize the QTableWidget */
245    m_checkCurrentWidget = false;
246    mp_tableWidget->clear();
247    m_checkCurrentWidget = true;
248    mp_tableWidget->setColumnCount(headerlist.size());
249    mp_tableWidget->setHorizontalHeaderLabels(headerlist);
250
251    if (mainWin->m_sqlDebug) {
252       Pmsg1(000, "Query cmd : %s\n",query.toUtf8().data());
253    }
254    if (m_console->sql_cmd(query, results)) {
255       m_resultCount = results.count();
256
257       QTableWidgetItem* p_tableitem;
258       QString field;
259       QStringList fieldlist;
260       mp_tableWidget->setRowCount(results.size());
261
262       int row = 0;
263       /* Iterate through the record returned from the query */
264       foreach (resultline, results) {
265          fieldlist = resultline.split("\t");
266          int column = 0;
267          bool m_statusIndexDone = false;
268          QString statusCode("");
269          /* Iterate through fields in the record */
270          foreach (field, fieldlist) {
271             field = field.trimmed();  /* strip leading & trailing spaces */
272             if ((column == m_statusIndex) && (!m_statusIndexDone)){
273                m_statusIndexDone = true;
274                statusCode = field;
275             } else {
276                p_tableitem = new QTableWidgetItem(field, 1);
277                p_tableitem->setFlags(Qt::ItemIsSelectable);
278                p_tableitem->setForeground(blackBrush);
279                mp_tableWidget->setItem(row, column, p_tableitem);
280                if (column == m_statusIndex)
281                   setStatusColor(p_tableitem, statusCode);
282                if (column == m_bytesIndex) {
283                   QString text;
284                   bool okay;
285                   qlonglong bytes = field.toULongLong(&okay);
286                   if (okay){
287                      QString test =  QString("%1").arg(bytes);
288                      mainWin->hrConvert(text, bytes);
289                      p_tableitem->setText(text);
290                   } else { Pmsg1(000, "conversion error %s\n", field.toUtf8().data()); }
291                } else if (column == m_purgedIndex) {
292                   bool okay;
293                   int isPurged = field.toInt(&okay);
294                   if (okay){
295                      if (isPurged) { p_tableitem->setText(tr("IS"));
296                      } else { p_tableitem->setText(tr("NOT")); }
297                   }
298                } else if (column == m_typeIndex) {
299                   if (field == "B") { p_tableitem->setText(tr("Backup")); }
300                   else if (field == "R") { p_tableitem->setText(tr("Restore")); }
301                } else if (column == jobLevelIndex) {
302                   if (field == "F") { p_tableitem->setText("Full"); }
303                   else if (field == "D") { p_tableitem->setText("Diff"); }
304                   else if (field == "I") { p_tableitem->setText("Incr"); }
305                }   
306                if ((column == m_bytesIndex) || (column == m_filesIndex)){
307                   p_tableitem->setTextAlignment(Qt::AlignRight);
308                }
309                column++;
310             }
311          }
312          row++;
313       }
314    } 
315    /* Resize the columns */
316    mp_tableWidget->resizeColumnsToContents();
317    mp_tableWidget->resizeRowsToContents();
318    mp_tableWidget->verticalHeader()->hide();
319    if ((m_mediaName != tr("Any")) && (m_resultCount == 0)){
320       /* for context sensitive searches, let the user know if there were no
321        * results */
322       QMessageBox::warning(this, "Bat",
323           tr("The Jobs query returned no results.\n"
324          "Press OK to continue?"), QMessageBox::Ok );
325    }
326 }
327
328 void JobList::setStatusColor(QTableWidgetItem *item, QString &field)
329 {
330    QString greenchars("TCR");
331    QString redchars("BEf");
332    QString yellowchars("eDAFSMmsjdctp");
333    if (greenchars.contains(field, Qt::CaseSensitive)) {
334       item->setBackground(Qt::green);
335    } else if (redchars.contains(field, Qt::CaseSensitive)) {
336       item->setBackground(Qt::red);
337    } else if (yellowchars.contains(field, Qt::CaseSensitive)){ 
338       item->setBackground(Qt::yellow);
339    }
340 }
341
342 /*
343  * When the treeWidgetItem in the page selector tree is singleclicked, Make sure
344  * The tree has been populated.
345  */
346 void JobList::PgSeltreeWidgetClicked()
347 {
348    if (!m_populated) {
349       populateTable();
350       m_populated=true;
351    }
352 }
353
354 /*
355  *  Virtual function override of pages function which is called when this page
356  *  is visible on the stack
357  */
358 void JobList::currentStackItem()
359 {
360    populateTable();
361    if (!m_populated) {
362       m_populated=true;
363    }
364 }
365
366 /*
367  * Virtual Function to return the name for the medialist tree widget
368  */
369 void JobList::treeWidgetName(QString &desc)
370 {
371    if ((m_mediaName == "") && (m_clientName == "") && (m_jobName == "") && (m_filesetName == "")) {
372       desc = "JobList";
373    } else {
374       desc = "JobList ";
375       if (m_mediaName != "" ) {
376          desc += "of Volume " + m_mediaName;
377       }
378       if (m_clientName != "" ) {
379          desc += "of Client " + m_clientName;
380       }
381       if (m_jobName != "" ) {
382          desc += "of Job " + m_jobName;
383       }
384       if (m_filesetName != "" ) {
385          desc += "of fileset " + m_filesetName;
386       }
387    }
388 }
389
390 /*
391  * This functions much line tableItemChanged for trees like the page selector,
392  * but I will do much less here
393  */
394 void JobList::tableItemChanged(QTableWidgetItem *currentItem, QTableWidgetItem * /*previousItem*/)
395 {
396    if (m_checkCurrentWidget) {
397       int row = currentItem->row();
398       QTableWidgetItem* jobitem = mp_tableWidget->item(row, 0);
399       m_currentJob = jobitem->text();
400       selectedJobsGet();
401
402       /* include purged action or not */
403       jobitem = mp_tableWidget->item(row, m_purgedIndex);
404       QString purged = jobitem->text();
405       mp_tableWidget->removeAction(actionPurgeFiles);
406       if (purged == "NOT") {
407          mp_tableWidget->addAction(actionPurgeFiles);
408       }
409       /* include restore from time and job action or not */
410       jobitem = mp_tableWidget->item(row, m_typeIndex);
411       QString type = jobitem->text();
412       mp_tableWidget->removeAction(actionRestoreFromJob);
413       mp_tableWidget->removeAction(actionRestoreFromTime);
414       if (type == "Backup") {
415          mp_tableWidget->addAction(actionRestoreFromJob);
416          mp_tableWidget->addAction(actionRestoreFromTime);
417       }
418       /* include cancel action or not */
419       jobitem = mp_tableWidget->item(row, m_statusIndex);
420       QString status = jobitem->text();
421       mp_tableWidget->removeAction(actionCancelJob);
422       if (status == "Running") {
423          mp_tableWidget->addAction(actionCancelJob);
424       }
425    }
426 }
427
428 /*
429  * Function to create connections for context sensitive menu for this and
430  * the page selector
431  */
432 void JobList::createConnections()
433 {
434    /* connect to the action specific to this pages class that shows up in the 
435     * page selector tree */
436    connect(actionRefreshJobList, SIGNAL(triggered()), this,
437                 SLOT(populateTable()));
438    connect(refreshButton, SIGNAL(pressed()), this, SLOT(populateTable()));
439    connect(graphButton, SIGNAL(pressed()), this, SLOT(graphTable()));
440    /* for the tableItemChanged to maintain m_currentJob */
441    connect(mp_tableWidget, SIGNAL(
442            currentItemChanged(QTableWidgetItem *, QTableWidgetItem *)),
443            this, SLOT(tableItemChanged(QTableWidgetItem *, QTableWidgetItem *)));
444
445    /* Do what is required for the local context sensitive menu */
446
447
448    /* setContextMenuPolicy is required */
449    mp_tableWidget->setContextMenuPolicy(Qt::ActionsContextMenu);
450
451    /* Add Actions */
452    mp_tableWidget->addAction(actionRefreshJobList);
453    mp_tableWidget->addAction(actionListJobid);
454    mp_tableWidget->addAction(actionListFilesOnJob);
455    mp_tableWidget->addAction(actionListJobMedia);
456    mp_tableWidget->addAction(actionListVolumes);
457    mp_tableWidget->addAction(actionDeleteJob);
458    mp_tableWidget->addAction(actionPurgeFiles);
459    mp_tableWidget->addAction(actionRestoreFromJob);
460    mp_tableWidget->addAction(actionRestoreFromTime);
461    mp_tableWidget->addAction(actionShowLogForJob);
462
463    /* Make Connections */
464    connect(actionListJobid, SIGNAL(triggered()), this,
465                 SLOT(consoleListJobid()));
466    connect(actionListFilesOnJob, SIGNAL(triggered()), this,
467                 SLOT(consoleListFilesOnJob()));
468    connect(actionListJobMedia, SIGNAL(triggered()), this,
469                 SLOT(consoleListJobMedia()));
470    connect(actionListVolumes, SIGNAL(triggered()), this,
471                 SLOT(consoleListVolumes()));
472    connect(actionDeleteJob, SIGNAL(triggered()), this,
473                 SLOT(consoleDeleteJob()));
474    connect(actionPurgeFiles, SIGNAL(triggered()), this,
475                 SLOT(consolePurgeFiles()));
476    connect(actionRestoreFromJob, SIGNAL(triggered()), this,
477                 SLOT(preRestoreFromJob()));
478    connect(actionRestoreFromTime, SIGNAL(triggered()), this,
479                 SLOT(preRestoreFromTime()));
480    connect(actionShowLogForJob, SIGNAL(triggered()), this,
481                 SLOT(showLogForJob()));
482    connect(actionCancelJob, SIGNAL(triggered()), this,
483                 SLOT(consoleCancelJob()));
484    connect(actionListJobTotals, SIGNAL(triggered()), this,
485                 SLOT(consoleListJobTotals()));
486
487    m_contextActions.append(actionRefreshJobList);
488    m_contextActions.append(actionListJobTotals);
489 }
490
491 /*
492  * Functions to respond to local context sensitive menu sending console commands
493  * If I could figure out how to make these one function passing a string, Yaaaaaa
494  */
495 void JobList::consoleListJobid()
496 {
497    QString cmd("list jobid=");
498    cmd += m_currentJob;
499    if (mainWin->m_longList) { cmd.prepend("l"); }
500    consoleCommand(cmd);
501 }
502 void JobList::consoleListFilesOnJob()
503 {
504    QString cmd("list files jobid=");
505    cmd += m_currentJob;
506    if (mainWin->m_longList) { cmd.prepend("l"); }
507    consoleCommand(cmd);
508 }
509 void JobList::consoleListJobMedia()
510 {
511    QString cmd("list jobmedia jobid=");
512    cmd += m_currentJob;
513    if (mainWin->m_longList) { cmd.prepend("l"); }
514    consoleCommand(cmd);
515 }
516 void JobList::consoleListVolumes()
517 {
518    QString cmd("list volumes jobid=");
519    cmd += m_currentJob;
520    if (mainWin->m_longList) { cmd.prepend("l"); }
521    consoleCommand(cmd);
522 }
523 void JobList::consoleListJobTotals()
524 {
525    QString cmd("list jobtotals");
526    if (mainWin->m_longList) { cmd.prepend("l"); }
527    consoleCommand(cmd);
528 }
529 void JobList::consoleDeleteJob()
530 {
531    if (QMessageBox::warning(this, "Bat",
532       tr("Are you sure you want to delete??  !!!.\n"
533 "This delete command is used to delete a Job record and all associated catalog"
534 " records that were created. This command operates only on the Catalog"
535 " database and has no effect on the actual data written to a Volume. This"
536 " command can be dangerous and we strongly recommend that you do not use"
537 " it unless you know what you are doing.  The Job and all its associated"
538 " records (File and JobMedia) will be deleted from the catalog."
539       "Press OK to proceed with delete operation.?"),
540       QMessageBox::Ok | QMessageBox::Cancel)
541       == QMessageBox::Cancel) { return; }
542
543    QString cmd("delete job jobid=");
544    cmd += m_selectedJobs;
545    consoleCommand(cmd);
546 }
547 void JobList::consolePurgeFiles()
548 {
549    if (QMessageBox::warning(this, "Bat",
550       tr("Are you sure you want to purge ??  !!!.\n"
551 "The Purge command will delete associated Catalog database records from Jobs and"
552 " Volumes without considering the retention period. Purge  works only on the"
553 " Catalog database and does not affect data written to Volumes. This command can"
554 " be dangerous because you can delete catalog records associated with current"
555 " backups of files, and we recommend that you do not use it unless you know what"
556 " you are doing.\n"
557       "Press OK to proceed with the purge operation?"),
558       QMessageBox::Ok | QMessageBox::Cancel)
559       == QMessageBox::Cancel) { return; }
560
561    QString cmd("purge files jobid=");
562    cmd += m_currentJob;
563    consoleCommand(cmd);
564 }
565
566 /*
567  * Subroutine to call preRestore to restore from a select job
568  */
569 void JobList::preRestoreFromJob()
570 {
571    new prerestorePage(m_currentJob, R_JOBIDLIST);
572 }
573
574 /*
575  * Subroutine to call preRestore to restore from a select job
576  */
577 void JobList::preRestoreFromTime()
578 {
579    new prerestorePage(m_currentJob, R_JOBDATETIME);
580 }
581
582 /*
583  * Subroutine to call class to show the log in the database from that job
584  */
585 void JobList::showLogForJob()
586 {
587    QTreeWidgetItem* pageSelectorTreeWidgetItem = mainWin->getFromHash(this);
588    new JobLog(m_currentJob, pageSelectorTreeWidgetItem);
589 }
590
591 /*
592  * Cancel a running job
593  */
594 void JobList::consoleCancelJob()
595 {
596    QString cmd("cancel jobid=");
597    cmd += m_currentJob;
598    consoleCommand(cmd);
599 }
600
601 /*
602  * Graph this table
603  */
604 void JobList::graphTable()
605 {
606    JobPlotPass pass;
607    pass.recordLimitCheck = limitCheckBox->checkState();
608    pass.daysLimitCheck = daysCheckBox->checkState();
609    pass.recordLimitSpin = limitSpinBox->value();
610    pass.daysLimitSpin = daysSpinBox->value();
611    pass.jobCombo = jobComboBox->currentText();
612    pass.clientCombo = clientComboBox->currentText();
613    pass.volumeCombo = volumeComboBox->currentText();
614    pass.fileSetCombo = fileSetComboBox->currentText();
615    pass.purgedCombo = purgedComboBox->currentText();
616    pass.levelCombo = levelComboBox->currentText();
617    pass.statusCombo = statusComboBox->currentText();
618    pass.use = true;
619    QTreeWidgetItem* pageSelectorTreeWidgetItem = mainWin->getFromHash(this);
620    new JobPlot(pageSelectorTreeWidgetItem, pass);
621 }
622 /*
623  * Save user settings associated with this page
624  */
625 void JobList::writeSettings()
626 {
627    QSettings settings(m_console->m_dir->name(), "bat");
628    settings.beginGroup(m_groupText);
629    settings.setValue(m_splitText, m_splitter->saveState());
630    settings.endGroup();
631 }
632
633 /*
634  * Read and restore user settings associated with this page
635  */
636 void JobList::readSettings()
637 {
638    m_groupText = "JobListPage";
639    m_splitText = "splitterSizes_1";
640    QSettings settings(m_console->m_dir->name(), "bat");
641    settings.beginGroup(m_groupText);
642    m_splitter->restoreState(settings.value(m_splitText).toByteArray());
643    settings.endGroup();
644 }
645
646 /*
647  * Function to fill m_selectedJobsCount and m_selectedJobs with selected values
648  */
649 void JobList::selectedJobsGet()
650 {
651    QList<int> rowList;
652    QList<QTableWidgetItem *> sitems = mp_tableWidget->selectedItems();
653    foreach (QTableWidgetItem *sitem, sitems) {
654       int row = sitem->row();
655       if (!rowList.contains(row)) {
656          rowList.append(row);
657       }
658    }
659
660    m_selectedJobs = "";
661    bool first = true;
662    foreach(int row, rowList) {
663       QTableWidgetItem * sitem = mp_tableWidget->item(row, m_jobIdIndex);
664       if (!first) m_selectedJobs.append(",");
665       else first = false;
666       m_selectedJobs.append(sitem->text());
667    }
668    m_selectedJobsCount = rowList.count();
669    if (m_selectedJobsCount > 1) {
670       QString text = QString("Delete list of %1 Jobs").arg(m_selectedJobsCount);
671       actionDeleteJob->setText(text);
672    } else {
673       actionDeleteJob->setText("Delete Single Job");
674    }
675 }