]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/qt-console/joblist/joblist.cpp
Allow table items to be selectable. If items are selected, then check to see if two
[bacula/bacula] / bacula / src / qt-console / joblist / joblist.cpp
1 /*
2    Bacula® - The Network Backup Solution
3
4    Copyright (C) 2007-2007 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("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("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("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("Any");
137       levelComboBox->addItems( QStringList() << "F" << "D" << "I");
138       purgedComboBox->addItem("Any");
139       purgedComboBox->addItems( QStringList() << "0" << "1");
140       fileSetComboBox->addItem("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("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 != "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 != "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 != "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) != "Any")) {
186       conditions.append("Job.Name='" + jobComboBox->itemText(jobIndex) + "'");
187    }
188    int levelIndex = levelComboBox->currentIndex();
189    if ((levelIndex != -1) && (levelComboBox->itemText(levelIndex) != "Any")) {
190       conditions.append("Job.Level='" + levelComboBox->itemText(levelIndex) + "'");
191    }
192    int statusIndex = statusComboBox->currentIndex();
193    if ((statusIndex != -1) && (statusComboBox->itemText(statusIndex) != "Any")) {
194       conditions.append("Status.JobStatusLong='" + statusComboBox->itemText(statusIndex) + "'");
195    }
196    int purgedIndex = purgedComboBox->currentIndex();
197    if ((purgedIndex != -1) && (purgedComboBox->itemText(purgedIndex) != "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) != "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       << "Job Id" << "Job Name" << "Client" << "Job Starttime" << "Job Type" 
233       << "Job Level" << "Job Files" << "Job Bytes" << "Job Status"  << "Purged" << "File Set" );
234    m_jobIdIndex = headerlist.indexOf("Job Id");
235    m_purgedIndex = headerlist.indexOf("Purged");
236    m_typeIndex = headerlist.indexOf("Job Type");
237    m_statusIndex = headerlist.indexOf("Job Status");
238    m_startIndex = headerlist.indexOf("Job Starttime");
239    m_filesIndex = headerlist.indexOf("Job Files");
240    m_bytesIndex = headerlist.indexOf("Job Bytes");
241
242    /* Initialize the QTableWidget */
243    m_checkCurrentWidget = false;
244    mp_tableWidget->clear();
245    m_checkCurrentWidget = true;
246    mp_tableWidget->setColumnCount(headerlist.size());
247    mp_tableWidget->setHorizontalHeaderLabels(headerlist);
248
249    if (mainWin->m_sqlDebug) {
250       Pmsg1(000, "Query cmd : %s\n",query.toUtf8().data());
251    }
252    if (m_console->sql_cmd(query, results)) {
253       m_resultCount = results.count();
254
255       QTableWidgetItem* p_tableitem;
256       QString field;
257       QStringList fieldlist;
258       mp_tableWidget->setRowCount(results.size());
259
260       int row = 0;
261       /* Iterate through the record returned from the query */
262       foreach (resultline, results) {
263          fieldlist = resultline.split("\t");
264          int column = 0;
265          bool m_statusIndexDone = false;
266          QString statusCode("");
267          /* Iterate through fields in the record */
268          foreach (field, fieldlist) {
269             field = field.trimmed();  /* strip leading & trailing spaces */
270             if ((column == m_statusIndex) && (!m_statusIndexDone)){
271                m_statusIndexDone = true;
272                statusCode = field;
273             } else {
274                p_tableitem = new QTableWidgetItem(field, 1);
275                p_tableitem->setFlags(Qt::ItemIsSelectable);
276                p_tableitem->setForeground(blackBrush);
277                mp_tableWidget->setItem(row, column, p_tableitem);
278                if (column == m_statusIndex)
279                   setStatusColor(p_tableitem, statusCode);
280                column++;
281             }
282          }
283          row++;
284       }
285    } 
286    /* Resize the columns */
287    mp_tableWidget->resizeColumnsToContents();
288    mp_tableWidget->resizeRowsToContents();
289    mp_tableWidget->verticalHeader()->hide();
290    if ((m_mediaName != "Any") && (m_resultCount == 0)){
291       /* for context sensitive searches, let the user know if there were no
292        * results */
293       QMessageBox::warning(this, tr("Bat"),
294           tr("The Jobs query returned no results.\n"
295          "Press OK to continue?"), QMessageBox::Ok );
296    }
297 }
298
299 void JobList::setStatusColor(QTableWidgetItem *item, QString &field)
300 {
301    QString greenchars("TCR");
302    QString redchars("BEf");
303    QString yellowchars("eDAFSMmsjdctp");
304    if (greenchars.contains(field, Qt::CaseSensitive)) {
305       item->setBackground(Qt::green);
306    } else if (redchars.contains(field, Qt::CaseSensitive)) {
307       item->setBackground(Qt::red);
308    } else if (yellowchars.contains(field, Qt::CaseSensitive)){ 
309       item->setBackground(Qt::yellow);
310    }
311 }
312
313 /*
314  * When the treeWidgetItem in the page selector tree is singleclicked, Make sure
315  * The tree has been populated.
316  */
317 void JobList::PgSeltreeWidgetClicked()
318 {
319    if (!m_populated) {
320       populateTable();
321       m_populated=true;
322    }
323 }
324
325 /*
326  *  Virtual function override of pages function which is called when this page
327  *  is visible on the stack
328  */
329 void JobList::currentStackItem()
330 {
331    populateTable();
332    if (!m_populated) {
333       m_populated=true;
334    }
335 }
336
337 /*
338  * Virtual Function to return the name for the medialist tree widget
339  */
340 void JobList::treeWidgetName(QString &desc)
341 {
342    if ((m_mediaName == "") && (m_clientName == "") && (m_jobName == "") && (m_filesetName == "")) {
343       desc = "JobList";
344    } else {
345       desc = "JobList ";
346       if (m_mediaName != "" ) {
347          desc += "of Volume " + m_mediaName;
348       }
349       if (m_clientName != "" ) {
350          desc += "of Client " + m_clientName;
351       }
352       if (m_jobName != "" ) {
353          desc += "of Job " + m_jobName;
354       }
355       if (m_filesetName != "" ) {
356          desc += "of fileset " + m_filesetName;
357       }
358    }
359 }
360
361 /*
362  * This functions much line tableItemChanged for trees like the page selector,
363  * but I will do much less here
364  */
365 void JobList::tableItemChanged(QTableWidgetItem *currentItem, QTableWidgetItem * /*previousItem*/)
366 {
367    if (m_checkCurrentWidget) {
368       int row = currentItem->row();
369       QTableWidgetItem* jobitem = mp_tableWidget->item(row, 0);
370       m_currentJob = jobitem->text();
371       selectedJobsGet();
372
373       /* include purged action or not */
374       jobitem = mp_tableWidget->item(row, m_purgedIndex);
375       QString purged = jobitem->text();
376       mp_tableWidget->removeAction(actionPurgeFiles);
377       if (purged == "0") {
378          mp_tableWidget->addAction(actionPurgeFiles);
379       }
380       /* include restore from time and job action or not */
381       jobitem = mp_tableWidget->item(row, m_typeIndex);
382       QString type = jobitem->text();
383       mp_tableWidget->removeAction(actionRestoreFromJob);
384       mp_tableWidget->removeAction(actionRestoreFromTime);
385       if (type == "B") {
386          mp_tableWidget->addAction(actionRestoreFromJob);
387          mp_tableWidget->addAction(actionRestoreFromTime);
388       }
389       /* include cancel action or not */
390       jobitem = mp_tableWidget->item(row, m_statusIndex);
391       QString status = jobitem->text();
392       mp_tableWidget->removeAction(actionCancelJob);
393       if (status == "Running") {
394          mp_tableWidget->addAction(actionCancelJob);
395       }
396    }
397 }
398
399 /*
400  * Function to create connections for context sensitive menu for this and
401  * the page selector
402  */
403 void JobList::createConnections()
404 {
405    /* connect to the action specific to this pages class that shows up in the 
406     * page selector tree */
407    connect(actionRefreshJobList, SIGNAL(triggered()), this,
408                 SLOT(populateTable()));
409    connect(refreshButton, SIGNAL(pressed()), this, SLOT(populateTable()));
410    connect(graphButton, SIGNAL(pressed()), this, SLOT(graphTable()));
411    /* for the tableItemChanged to maintain m_currentJob */
412    connect(mp_tableWidget, SIGNAL(
413            currentItemChanged(QTableWidgetItem *, QTableWidgetItem *)),
414            this, SLOT(tableItemChanged(QTableWidgetItem *, QTableWidgetItem *)));
415
416    /* Do what is required for the local context sensitive menu */
417
418
419    /* setContextMenuPolicy is required */
420    mp_tableWidget->setContextMenuPolicy(Qt::ActionsContextMenu);
421
422    /* Add Actions */
423    mp_tableWidget->addAction(actionRefreshJobList);
424    mp_tableWidget->addAction(actionListJobid);
425    mp_tableWidget->addAction(actionListFilesOnJob);
426    mp_tableWidget->addAction(actionListJobMedia);
427    mp_tableWidget->addAction(actionListVolumes);
428    mp_tableWidget->addAction(actionDeleteJob);
429    mp_tableWidget->addAction(actionPurgeFiles);
430    mp_tableWidget->addAction(actionRestoreFromJob);
431    mp_tableWidget->addAction(actionRestoreFromTime);
432    mp_tableWidget->addAction(actionShowLogForJob);
433
434    /* Make Connections */
435    connect(actionListJobid, SIGNAL(triggered()), this,
436                 SLOT(consoleListJobid()));
437    connect(actionListFilesOnJob, SIGNAL(triggered()), this,
438                 SLOT(consoleListFilesOnJob()));
439    connect(actionListJobMedia, SIGNAL(triggered()), this,
440                 SLOT(consoleListJobMedia()));
441    connect(actionListVolumes, SIGNAL(triggered()), this,
442                 SLOT(consoleListVolumes()));
443    connect(actionDeleteJob, SIGNAL(triggered()), this,
444                 SLOT(consoleDeleteJob()));
445    connect(actionPurgeFiles, SIGNAL(triggered()), this,
446                 SLOT(consolePurgeFiles()));
447    connect(actionRestoreFromJob, SIGNAL(triggered()), this,
448                 SLOT(preRestoreFromJob()));
449    connect(actionRestoreFromTime, SIGNAL(triggered()), this,
450                 SLOT(preRestoreFromTime()));
451    connect(actionShowLogForJob, SIGNAL(triggered()), this,
452                 SLOT(showLogForJob()));
453    connect(actionCancelJob, SIGNAL(triggered()), this,
454                 SLOT(consoleCancelJob()));
455    connect(actionListJobTotals, SIGNAL(triggered()), this,
456                 SLOT(consoleListJobTotals()));
457
458    m_contextActions.append(actionRefreshJobList);
459    m_contextActions.append(actionListJobTotals);
460 }
461
462 /*
463  * Functions to respond to local context sensitive menu sending console commands
464  * If I could figure out how to make these one function passing a string, Yaaaaaa
465  */
466 void JobList::consoleListJobid()
467 {
468    QString cmd("list jobid=");
469    cmd += m_currentJob;
470    if (mainWin->m_longList) { cmd.prepend("l"); }
471    consoleCommand(cmd);
472 }
473 void JobList::consoleListFilesOnJob()
474 {
475    QString cmd("list files jobid=");
476    cmd += m_currentJob;
477    if (mainWin->m_longList) { cmd.prepend("l"); }
478    consoleCommand(cmd);
479 }
480 void JobList::consoleListJobMedia()
481 {
482    QString cmd("list jobmedia jobid=");
483    cmd += m_currentJob;
484    if (mainWin->m_longList) { cmd.prepend("l"); }
485    consoleCommand(cmd);
486 }
487 void JobList::consoleListVolumes()
488 {
489    QString cmd("list volumes jobid=");
490    cmd += m_currentJob;
491    if (mainWin->m_longList) { cmd.prepend("l"); }
492    consoleCommand(cmd);
493 }
494 void JobList::consoleListJobTotals()
495 {
496    QString cmd("list jobtotals");
497    if (mainWin->m_longList) { cmd.prepend("l"); }
498    consoleCommand(cmd);
499 }
500 void JobList::consoleDeleteJob()
501 {
502    if (QMessageBox::warning(this, tr("Bat"),
503       tr("Are you sure you want to delete??  !!!.\n"
504 "This delete command is used to delete a Job record and all associated catalog"
505 " records that were created. This command operates only on the Catalog"
506 " database and has no effect on the actual data written to a Volume. This"
507 " command can be dangerous and we strongly recommend that you do not use"
508 " it unless you know what you are doing.  The Job and all its associated"
509 " records (File and JobMedia) will be deleted from the catalog."
510       "Press OK to proceed with delete operation.?"),
511       QMessageBox::Ok | QMessageBox::Cancel)
512       == QMessageBox::Cancel) { return; }
513
514    QString cmd("delete job jobid=");
515    cmd += m_selectedJobs;
516    consoleCommand(cmd);
517 }
518 void JobList::consolePurgeFiles()
519 {
520    if (QMessageBox::warning(this, tr("Bat"),
521       tr("Are you sure you want to purge ??  !!!.\n"
522 "The Purge command will delete associated Catalog database records from Jobs and"
523 " Volumes without considering the retention period. Purge  works only on the"
524 " Catalog database and does not affect data written to Volumes. This command can"
525 " be dangerous because you can delete catalog records associated with current"
526 " backups of files, and we recommend that you do not use it unless you know what"
527 " you are doing.\n"
528       "Press OK to proceed with the purge operation?"),
529       QMessageBox::Ok | QMessageBox::Cancel)
530       == QMessageBox::Cancel) { return; }
531
532    QString cmd("purge files jobid=");
533    cmd += m_currentJob;
534    consoleCommand(cmd);
535 }
536
537 /*
538  * Subroutine to call preRestore to restore from a select job
539  */
540 void JobList::preRestoreFromJob()
541 {
542    new prerestorePage(m_currentJob, R_JOBIDLIST);
543 }
544
545 /*
546  * Subroutine to call preRestore to restore from a select job
547  */
548 void JobList::preRestoreFromTime()
549 {
550    new prerestorePage(m_currentJob, R_JOBDATETIME);
551 }
552
553 /*
554  * Subroutine to call class to show the log in the database from that job
555  */
556 void JobList::showLogForJob()
557 {
558    QTreeWidgetItem* pageSelectorTreeWidgetItem = mainWin->getFromHash(this);
559    new JobLog(m_currentJob, pageSelectorTreeWidgetItem);
560 }
561
562 /*
563  * Cancel a running job
564  */
565 void JobList::consoleCancelJob()
566 {
567    QString cmd("cancel jobid=");
568    cmd += m_currentJob;
569    consoleCommand(cmd);
570 }
571
572 /*
573  * Graph this table
574  */
575 void JobList::graphTable()
576 {
577    JobPlotPass pass;
578    pass.recordLimitCheck = limitCheckBox->checkState();
579    pass.daysLimitCheck = daysCheckBox->checkState();
580    pass.recordLimitSpin = limitSpinBox->value();
581    pass.daysLimitSpin = daysSpinBox->value();
582    pass.jobCombo = jobComboBox->currentText();
583    pass.clientCombo = clientComboBox->currentText();
584    pass.volumeCombo = volumeComboBox->currentText();
585    pass.fileSetCombo = fileSetComboBox->currentText();
586    pass.purgedCombo = purgedComboBox->currentText();
587    pass.levelCombo = levelComboBox->currentText();
588    pass.statusCombo = statusComboBox->currentText();
589    pass.use = true;
590    QTreeWidgetItem* pageSelectorTreeWidgetItem = mainWin->getFromHash(this);
591    new JobPlot(pageSelectorTreeWidgetItem, pass);
592 }
593 /*
594  * Save user settings associated with this page
595  */
596 void JobList::writeSettings()
597 {
598    QSettings settings(m_console->m_dir->name(), "bat");
599    settings.beginGroup(m_groupText);
600    settings.setValue(m_splitText, m_splitter->saveState());
601    settings.endGroup();
602 }
603
604 /*
605  * Read and restore user settings associated with this page
606  */
607 void JobList::readSettings()
608 {
609    m_groupText = "JobListPage";
610    m_splitText = "splitterSizes_1";
611    QSettings settings(m_console->m_dir->name(), "bat");
612    settings.beginGroup(m_groupText);
613    m_splitter->restoreState(settings.value(m_splitText).toByteArray());
614    settings.endGroup();
615 }
616
617 /*
618  * Function to fill m_selectedJobsCount and m_selectedJobs with selected values
619  */
620 void JobList::selectedJobsGet()
621 {
622    QList<int> rowList;
623    QList<QTableWidgetItem *> sitems = mp_tableWidget->selectedItems();
624    foreach (QTableWidgetItem *sitem, sitems) {
625       int row = sitem->row();
626       if (!rowList.contains(row)) {
627          rowList.append(row);
628       }
629    }
630
631    m_selectedJobs = "";
632    bool first = true;
633    foreach(int row, rowList) {
634       QTableWidgetItem * sitem = mp_tableWidget->item(row, m_jobIdIndex);
635       if (!first) m_selectedJobs.append(",");
636       else first = false;
637       m_selectedJobs.append(sitem->text());
638    }
639    m_selectedJobsCount = rowList.count();
640    if (m_selectedJobsCount > 1) {
641       QString text = QString("Delete list of %1 Jobs").arg(m_selectedJobsCount);
642       actionDeleteJob->setText(text);
643    } else {
644       actionDeleteJob->setText("Delete Single Job");
645    }
646 }