]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/qt-console/joblist/joblist.cpp
Setting actions up like this I think is better. No restore from job or time
[bacula/bacula] / bacula / src / qt-console / joblist / joblist.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
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 Kern Sibbald.
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 "bat.h"
35 #include <QAbstractEventDispatcher>
36 #include <QTableWidgetItem>
37 #include "joblist.h"
38 #include "restore.h"
39 #include "joblog/joblog.h"
40 #ifdef HAVE_QWT
41 #include "jobgraphs/jobplot.h"
42 #endif
43 #include "util/fmtwidgetitem.h"
44 #include "util/comboutil.h"
45
46 /*
47  * Constructor for the class
48  */
49 JobList::JobList(const QString &mediaName, const QString &clientName,
50           const QString &jobName, const QString &filesetName, QTreeWidgetItem *parentTreeWidgetItem)
51 {
52    setupUi(this);
53    m_name = ""; /* treeWidgetName has a virtual override in this class */
54    m_mediaName = mediaName;
55    m_clientName = clientName;
56    m_jobName = jobName;
57    m_filesetName = filesetName;
58    m_filesetName = filesetName;
59    pgInitialize("", parentTreeWidgetItem);
60    QTreeWidgetItem* thisitem = mainWin->getFromHash(this);
61    thisitem->setIcon(0,QIcon(QString::fromUtf8(":images/emblem-system.png")));
62
63    m_resultCount = 0;
64    m_populated = false;
65    m_closeable = false;
66    if ((m_mediaName != "") || (m_clientName != "") || (m_jobName != "") || (m_filesetName != ""))
67       m_closeable=true;
68    m_checkCurrentWidget = true;
69    createConnections();
70
71    /* Set Defaults for check and spin for limits */
72    limitCheckBox->setCheckState(mainWin->m_recordLimitCheck ? Qt::Checked : Qt::Unchecked);
73    limitSpinBox->setValue(mainWin->m_recordLimitVal);
74    daysCheckBox->setCheckState(mainWin->m_daysLimitCheck ? Qt::Checked : Qt::Unchecked);
75    daysSpinBox->setValue(mainWin->m_daysLimitVal);
76    dockPage();
77
78    QGridLayout *gridLayout = new QGridLayout(this);
79    gridLayout->setSpacing(6);
80    gridLayout->setMargin(9);
81    gridLayout->setObjectName(QString::fromUtf8("gridLayout"));
82
83    m_splitter = new QSplitter(Qt::Vertical, this);
84    QScrollArea *area = new QScrollArea();
85    area->setObjectName(QString::fromUtf8("area"));
86    area->setWidget(frame);
87    area->setWidgetResizable(true);
88    m_splitter->addWidget(mp_tableWidget);
89    m_splitter->addWidget(area);
90
91    gridLayout->addWidget(m_splitter, 0, 0, 1, 1);
92    readSettings();
93 }
94
95 /*
96  * Write the m_splitter settings in the destructor
97  */
98 JobList::~JobList()
99 {
100    writeSettings();
101 }
102
103 /*
104  * The Meat of the class.
105  * This function will populate the QTableWidget, mp_tablewidget, with
106  * QTableWidgetItems representing the results of a query for what jobs exist on
107  * the media name passed from the constructor stored in m_mediaName.
108  */
109 void JobList::populateTable()
110 {
111    /* Can't do this in constructor because not neccesarily conected in constructor */
112    prepareFilterWidgets();
113    m_populated = true;
114
115    Freeze frz(*mp_tableWidget); /* disable updating*/
116
117    /* Set up query */
118    QString query;
119    fillQueryString(query);
120
121    /* Set up the Header for the table */
122    QStringList headerlist = (QStringList()
123       << tr("Job Id") << tr("Job Name") << tr("Client") << tr("Job Starttime") 
124       << tr("Job Type") << tr("Job Level") << tr("Job Files") 
125       << tr("Job Bytes") << tr("Job Status")  << tr("Purged") << tr("File Set")
126       << tr("Pool Name") << tr("First Volume") << tr("VolCount"));
127
128    m_jobIdIndex = headerlist.indexOf(tr("Job Id"));
129    m_purgedIndex = headerlist.indexOf(tr("Purged"));
130    m_typeIndex = headerlist.indexOf(tr("Job Type"));
131    m_statusIndex = headerlist.indexOf(tr("Job Status"));
132    m_startIndex = headerlist.indexOf(tr("Job Starttime"));
133    m_filesIndex = headerlist.indexOf(tr("Job Files"));
134    m_bytesIndex = headerlist.indexOf(tr("Job Bytes"));
135
136    /* Initialize the QTableWidget */
137    m_checkCurrentWidget = false;
138    mp_tableWidget->clear();
139    m_checkCurrentWidget = true;
140    mp_tableWidget->setColumnCount(headerlist.size());
141    mp_tableWidget->setHorizontalHeaderLabels(headerlist);
142    mp_tableWidget->horizontalHeader()->setHighlightSections(false);
143    mp_tableWidget->setSelectionBehavior(QAbstractItemView::SelectRows);
144    mp_tableWidget->setSortingEnabled(false); /* rows move on insert if sorting enabled */
145
146    if (mainWin->m_sqlDebug) {
147       Pmsg1(000, "Query cmd : %s\n",query.toUtf8().data());
148    }
149
150    QStringList results;
151    if (m_console->sql_cmd(query, results)) {
152       m_resultCount = results.count();
153
154       QStringList fieldlist;
155       mp_tableWidget->setRowCount(results.size());
156
157       int row = 0;
158       /* Iterate through the record returned from the query */
159       QString resultline;
160       foreach (resultline, results) {
161          fieldlist = resultline.split("\t");
162          if (fieldlist.size() < 13)
163             continue; /* some fields missing, ignore row */
164
165          TableItemFormatter jobitem(*mp_tableWidget, row);
166   
167          /* Iterate through fields in the record */
168          QStringListIterator fld(fieldlist);
169          int col = 0;
170
171          /* job id */
172          jobitem.setNumericFld(col++, fld.next());
173
174          /* job name */
175          jobitem.setTextFld(col++, fld.next());
176
177          /* client */
178          jobitem.setTextFld(col++, fld.next());
179
180          /* job starttime */
181          jobitem.setTextFld(col++, fld.next(), true);
182
183          /* job type */
184          jobitem.setJobTypeFld(col++, fld.next());
185
186          /* job level */
187          jobitem.setJobLevelFld(col++, fld.next());
188
189          /* job files */
190          jobitem.setNumericFld(col++, fld.next());
191
192          /* job bytes */
193          jobitem.setBytesFld(col++, fld.next());
194
195          /* job status */
196          jobitem.setJobStatusFld(col++, fld.next());
197
198          /* purged */
199          jobitem.setBoolFld(col++, fld.next());
200
201          /* fileset */
202          jobitem.setTextFld(col++, fld.next());
203
204          /* pool name */
205          jobitem.setTextFld(col++, fld.next());
206
207          /* First Media */
208          jobitem.setTextFld(col++, fld.next());
209
210          /* Medias count */
211          jobitem.setNumericFld(col++, fld.next());
212          row++;
213       }
214    } 
215    /* set default sorting */
216    mp_tableWidget->sortByColumn(m_jobIdIndex, Qt::DescendingOrder);
217    mp_tableWidget->setSortingEnabled(true);
218    
219    /* Resize the columns */
220    mp_tableWidget->resizeColumnsToContents();
221    mp_tableWidget->resizeRowsToContents();
222    mp_tableWidget->verticalHeader()->hide();
223    if ((m_mediaName != tr("Any")) && (m_resultCount == 0)){
224       /* for context sensitive searches, let the user know if there were no
225        * results */
226       QMessageBox::warning(this, "Bat",
227           tr("The Jobs query returned no results.\n"
228          "Press OK to continue?"), QMessageBox::Ok );
229    }
230
231    /* make read only */
232    int rcnt = mp_tableWidget->rowCount();
233    int ccnt = mp_tableWidget->columnCount();
234    for(int r=0; r < rcnt; r++) {
235       for(int c=0; c < ccnt; c++) {
236          QTableWidgetItem* item = mp_tableWidget->item(r, c);
237          if (item) {
238             item->setFlags(Qt::ItemFlags(item->flags() & (~Qt::ItemIsEditable)));
239          }
240       }
241    }
242 }
243
244 void JobList::prepareFilterWidgets()
245 {
246    if (!m_populated) {
247       clientComboBox->addItem(tr("Any"));
248       clientComboBox->addItems(m_console->client_list);
249       comboSel(clientComboBox, m_clientName);
250
251       QStringList volumeList;
252       getVolumeList(volumeList);
253       volumeComboBox->addItem(tr("Any"));
254       volumeComboBox->addItems(volumeList);
255       comboSel(volumeComboBox, m_mediaName);
256
257       jobComboBox->addItem(tr("Any"));
258       jobComboBox->addItems(m_console->job_list);
259       comboSel(jobComboBox, m_jobName);
260
261       levelComboFill(levelComboBox);
262
263       boolComboFill(purgedComboBox);
264
265       fileSetComboBox->addItem(tr("Any"));
266       fileSetComboBox->addItems(m_console->fileset_list);
267       comboSel(fileSetComboBox, m_filesetName);
268
269       poolComboBox->addItem(tr("Any"));
270       poolComboBox->addItems(m_console->pool_list);
271
272       jobStatusComboFill(statusComboBox);
273    }
274 }
275
276 void JobList::fillQueryString(QString &query)
277 {
278    query = "";
279    int volumeIndex = volumeComboBox->currentIndex();
280    if (volumeIndex != -1)
281       m_mediaName = volumeComboBox->itemText(volumeIndex);
282    QString distinct = "";
283    if (m_mediaName != tr("Any")) { distinct = "DISTINCT "; }
284    query += "SELECT " + distinct + "Job.JobId AS JobId, Job.Name AS JobName, " 
285             " Client.Name AS Client,"
286             " Job.Starttime AS JobStart, Job.Type AS JobType,"
287             " Job.Level AS BackupLevel, Job.Jobfiles AS FileCount,"
288             " Job.JobBytes AS Bytes, Job.JobStatus AS Status,"
289             " Job.PurgedFiles AS Purged, FileSet.FileSet,"
290             " Pool.Name AS Pool,"
291             " (SELECT Media.VolumeName FROM JobMedia JOIN Media ON JobMedia.MediaId=Media.MediaId WHERE JobMedia.JobId=Job.JobId ORDER BY JobMediaId LIMIT 1) AS FirdtVolume,"
292             " (SELECT count(DISTINCT MediaId) FROM JobMedia WHERE JobMedia.JobId=Job.JobId) AS Volumes"
293             " FROM Job"
294             " JOIN Client ON (Client.ClientId=Job.ClientId)"
295             " LEFT OUTER JOIN FileSet ON (FileSet.FileSetId=Job.FileSetId) "
296             " LEFT OUTER JOIN Pool ON Job.PoolId = Pool.PoolId ";
297    QStringList conditions;
298    if (m_mediaName != tr("Any")) {
299       query += " LEFT OUTER JOIN JobMedia ON (JobMedia.JobId=Job.JobId) "
300                " LEFT OUTER JOIN Media ON (JobMedia.MediaId=Media.MediaId) ";
301       conditions.append("Media.VolumeName='" + m_mediaName + "'");
302    }
303
304    comboCond(conditions, clientComboBox, "Client.Name");
305    comboCond(conditions, jobComboBox, "Job.Name");
306    levelComboCond(conditions, levelComboBox, "Job.Level");
307    jobStatusComboCond(conditions, statusComboBox, "Job.JobStatus");
308    boolComboCond(conditions, purgedComboBox, "Job.PurgedFiles");
309    comboCond(conditions, fileSetComboBox, "FileSet.FileSet");
310    comboCond(conditions, poolComboBox, "Pool.Name");
311
312    /* If Limit check box For limit by days is checked  */
313    if (daysCheckBox->checkState() == Qt::Checked) {
314       QDateTime stamp = QDateTime::currentDateTime().addDays(-daysSpinBox->value());
315       QString since = stamp.toString(Qt::ISODate);
316       conditions.append("Job.Starttime>'" + since + "'");
317    }
318    bool first = true;
319    foreach (QString condition, conditions) {
320       if (first) {
321          query += " WHERE " + condition;
322          first = false;
323       } else {
324          query += " AND " + condition;
325       }
326    }
327    /* Descending */
328    query += " ORDER BY Job.JobId DESC";
329    /* If Limit check box for limit records returned is checked  */
330    if (limitCheckBox->checkState() == Qt::Checked) {
331       QString limit;
332       limit.setNum(limitSpinBox->value());
333       query += " LIMIT " + limit;
334    }
335 }
336
337 /*
338  * When the treeWidgetItem in the page selector tree is singleclicked, Make sure
339  * The tree has been populated.
340  */
341 void JobList::PgSeltreeWidgetClicked()
342 {
343    if (!m_populated) {
344       populateTable();
345    }
346 }
347
348 /*
349  *  Virtual function override of pages function which is called when this page
350  *  is visible on the stack
351  */
352 void JobList::currentStackItem()
353 {
354 /*   if (!m_populated) populate every time user comes back to this object */
355       populateTable();
356 }
357
358 /*
359  * Virtual Function to return the name for the medialist tree widget
360  */
361 void JobList::treeWidgetName(QString &desc)
362 {
363    if (m_mediaName != "" ) {
364      desc = tr("JobList of Volume %1").arg(m_mediaName);
365    } else if (m_clientName != "" ) {
366      desc = tr("JobList of Client %1").arg(m_clientName);
367    } else if (m_jobName != "" ) {
368      desc = tr("JobList of Job %1").arg(m_jobName);
369    } else if (m_filesetName != "" ) {
370      desc = tr("JobList of fileset %1").arg(m_filesetName);
371    } else {
372      desc = tr("JobList");
373    }
374 }
375
376 /*
377  * Function to create connections for context sensitive menu for this and
378  * the page selector
379  */
380 void JobList::createConnections()
381 {
382    /* connect to the action specific to this pages class that shows up in the 
383     * page selector tree */
384    connect(actionRefreshJobList, SIGNAL(triggered()), this,
385                 SLOT(populateTable()));
386    connect(refreshButton, SIGNAL(pressed()), this, SLOT(populateTable()));
387 #ifdef HAVE_QWT
388    connect(graphButton, SIGNAL(pressed()), this, SLOT(graphTable()));
389 #else
390    graphButton->setEnabled(false);
391    graphButton->setVisible(false);
392 #endif
393    /* for the selectionChanged to maintain m_currentJob and a delete selection */
394    connect(mp_tableWidget, SIGNAL(itemSelectionChanged()), this, SLOT(selectionChanged()));
395
396    /* Do what is required for the local context sensitive menu */
397
398
399    /* setContextMenuPolicy is required */
400    mp_tableWidget->setContextMenuPolicy(Qt::ActionsContextMenu);
401
402    connect(actionListJobid, SIGNAL(triggered()), this,
403                 SLOT(consoleListJobid()));
404    connect(actionListFilesOnJob, SIGNAL(triggered()), this,
405                 SLOT(consoleListFilesOnJob()));
406    connect(actionListJobMedia, SIGNAL(triggered()), this,
407                 SLOT(consoleListJobMedia()));
408    connect(actionListVolumes, SIGNAL(triggered()), this,
409                 SLOT(consoleListVolumes()));
410    connect(actionDeleteJob, SIGNAL(triggered()), this,
411                 SLOT(consoleDeleteJob()));
412    connect(actionPurgeFiles, SIGNAL(triggered()), this,
413                 SLOT(consolePurgeFiles()));
414    connect(actionRestoreFromJob, SIGNAL(triggered()), this,
415                 SLOT(preRestoreFromJob()));
416    connect(actionRestoreFromTime, SIGNAL(triggered()), this,
417                 SLOT(preRestoreFromTime()));
418    connect(actionShowLogForJob, SIGNAL(triggered()), this,
419                 SLOT(showLogForJob()));
420    connect(actionCancelJob, SIGNAL(triggered()), this,
421                 SLOT(consoleCancelJob()));
422    connect(actionListJobTotals, SIGNAL(triggered()), this,
423                 SLOT(consoleListJobTotals()));
424
425    m_contextActions.append(actionRefreshJobList);
426    m_contextActions.append(actionListJobTotals);
427 }
428
429 /*
430  * Functions to respond to local context sensitive menu sending console commands
431  * If I could figure out how to make these one function passing a string, Yaaaaaa
432  */
433 void JobList::consoleListJobid()
434 {
435    QString cmd("list jobid=");
436    cmd += m_currentJob;
437    if (mainWin->m_longList) { cmd.prepend("l"); }
438    consoleCommand(cmd);
439 }
440 void JobList::consoleListFilesOnJob()
441 {
442    QString cmd("list files jobid=");
443    cmd += m_currentJob;
444    if (mainWin->m_longList) { cmd.prepend("l"); }
445    consoleCommand(cmd);
446 }
447 void JobList::consoleListJobMedia()
448 {
449    QString cmd("list jobmedia jobid=");
450    cmd += m_currentJob;
451    if (mainWin->m_longList) { cmd.prepend("l"); }
452    consoleCommand(cmd);
453 }
454 void JobList::consoleListVolumes()
455 {
456    QString cmd("list volumes jobid=");
457    cmd += m_currentJob;
458    if (mainWin->m_longList) { cmd.prepend("l"); }
459    consoleCommand(cmd);
460 }
461 void JobList::consoleListJobTotals()
462 {
463    QString cmd("list jobtotals");
464    if (mainWin->m_longList) { cmd.prepend("l"); }
465    consoleCommand(cmd);
466 }
467 void JobList::consoleDeleteJob()
468 {
469    if (QMessageBox::warning(this, "Bat",
470       tr("Are you sure you want to delete??  !!!.\n"
471 "This delete command is used to delete a Job record and all associated catalog"
472 " records that were created. This command operates only on the Catalog"
473 " database and has no effect on the actual data written to a Volume. This"
474 " command can be dangerous and we strongly recommend that you do not use"
475 " it unless you know what you are doing.  The Job and all its associated"
476 " records (File and JobMedia) will be deleted from the catalog."
477       "Press OK to proceed with delete operation.?"),
478       QMessageBox::Ok | QMessageBox::Cancel)
479       == QMessageBox::Cancel) { return; }
480
481    QString cmd("delete job jobid=");
482    cmd += m_selectedJobs;
483    consoleCommand(cmd);
484 }
485 void JobList::consolePurgeFiles()
486 {
487    if (QMessageBox::warning(this, "Bat",
488       tr("Are you sure you want to purge ??  !!!.\n"
489 "The Purge command will delete associated Catalog database records from Jobs and"
490 " Volumes without considering the retention period. Purge  works only on the"
491 " Catalog database and does not affect data written to Volumes. This command can"
492 " be dangerous because you can delete catalog records associated with current"
493 " backups of files, and we recommend that you do not use it unless you know what"
494 " you are doing.\n"
495       "Press OK to proceed with the purge operation?"),
496       QMessageBox::Ok | QMessageBox::Cancel)
497       == QMessageBox::Cancel) { return; }
498
499    foreach(QString job, m_selectedJobsList) {
500       QString cmd("purge files jobid=");
501       cmd += job;
502       consoleCommand(cmd);
503    }
504 }
505
506 /*
507  * Subroutine to call preRestore to restore from a select job
508  */
509 void JobList::preRestoreFromJob()
510 {
511    new prerestorePage(m_currentJob, R_JOBIDLIST);
512 }
513
514 /*
515  * Subroutine to call preRestore to restore from a select job
516  */
517 void JobList::preRestoreFromTime()
518 {
519    new prerestorePage(m_currentJob, R_JOBDATETIME);
520 }
521
522 /*
523  * Subroutine to call class to show the log in the database from that job
524  */
525 void JobList::showLogForJob()
526 {
527    QTreeWidgetItem* pageSelectorTreeWidgetItem = mainWin->getFromHash(this);
528    new JobLog(m_currentJob, pageSelectorTreeWidgetItem);
529 }
530
531 /*
532  * Cancel a running job
533  */
534 void JobList::consoleCancelJob()
535 {
536    QString cmd("cancel jobid=");
537    cmd += m_currentJob;
538    consoleCommand(cmd);
539 }
540
541 /*
542  * Graph this table
543  */
544 void JobList::graphTable()
545 {
546 #ifdef HAVE_QWT
547    JobPlotPass pass;
548    pass.recordLimitCheck = limitCheckBox->checkState();
549    pass.daysLimitCheck = daysCheckBox->checkState();
550    pass.recordLimitSpin = limitSpinBox->value();
551    pass.daysLimitSpin = daysSpinBox->value();
552    pass.jobCombo = jobComboBox->currentText();
553    pass.clientCombo = clientComboBox->currentText();
554    pass.volumeCombo = volumeComboBox->currentText();
555    pass.fileSetCombo = fileSetComboBox->currentText();
556    pass.purgedCombo = purgedComboBox->currentText();
557    pass.levelCombo = levelComboBox->currentText();
558    pass.statusCombo = statusComboBox->currentText();
559    pass.use = true;
560    QTreeWidgetItem* pageSelectorTreeWidgetItem = mainWin->getFromHash(this);
561    new JobPlot(pageSelectorTreeWidgetItem, pass);
562 #endif
563 }
564
565 /*
566  * Save user settings associated with this page
567  */
568 void JobList::writeSettings()
569 {
570    QSettings settings(m_console->m_dir->name(), "bat");
571    settings.beginGroup(m_groupText);
572    settings.setValue(m_splitText, m_splitter->saveState());
573    settings.endGroup();
574 }
575
576 /*
577  * Read and restore user settings associated with this page
578  */
579 void JobList::readSettings()
580 {
581    m_groupText = "JobListPage";
582    m_splitText = "splitterSizes_1";
583    QSettings settings(m_console->m_dir->name(), "bat");
584    settings.beginGroup(m_groupText);
585    m_splitter->restoreState(settings.value(m_splitText).toByteArray());
586    settings.endGroup();
587 }
588
589 /*
590  * Function to fill m_selectedJobsCount and m_selectedJobs with selected values
591  */
592 void JobList::selectionChanged()
593 {
594    QList<int> rowList;
595    QList<QTableWidgetItem *> sitems = mp_tableWidget->selectedItems();
596    foreach (QTableWidgetItem *sitem, sitems) {
597       int row = sitem->row();
598       if (!rowList.contains(row)) {
599          rowList.append(row);
600       }
601    }
602
603    m_selectedJobs = "";
604    m_selectedJobsList.clear();
605    bool first = true;
606    foreach(int row, rowList) {
607       QTableWidgetItem * sitem = mp_tableWidget->item(row, m_jobIdIndex);
608       if (!first) m_selectedJobs.append(",");
609       else first = false;
610       m_selectedJobs.append(sitem->text());
611       m_selectedJobsList.append(sitem->text());
612    }
613    m_selectedJobsCount = rowList.count();
614    if (m_selectedJobsCount > 1) {
615       QString text = QString( tr("Delete list of %1 Jobs")).arg(m_selectedJobsCount);
616       actionDeleteJob->setText(text);
617       text = QString( tr("Purge Files from list of %1 Jobs")).arg(m_selectedJobsCount);
618       actionPurgeFiles->setText(text);
619    } else {
620       actionDeleteJob->setText(tr("Delete Single Job"));
621       actionPurgeFiles->setText(tr("Purge Files from single job"));
622    }
623
624    /* remove all actions */
625    foreach(QAction* mediaAction, mp_tableWidget->actions()) {
626       mp_tableWidget->removeAction(mediaAction);
627    }
628
629    /* Add Actions */
630    mp_tableWidget->addAction(actionRefreshJobList);
631    if (m_selectedJobsCount == 1) {
632       mp_tableWidget->addAction(actionListJobid);
633       mp_tableWidget->addAction(actionListFilesOnJob);
634       mp_tableWidget->addAction(actionListJobMedia);
635       mp_tableWidget->addAction(actionListVolumes);
636       mp_tableWidget->addAction(actionRestoreFromJob);
637       mp_tableWidget->addAction(actionRestoreFromTime);
638       mp_tableWidget->addAction(actionShowLogForJob);
639    }
640    if (m_selectedJobsCount >= 1) {
641       mp_tableWidget->addAction(actionDeleteJob);
642       mp_tableWidget->addAction(actionPurgeFiles);
643    }
644
645    /* Make Connections */
646    if (m_checkCurrentWidget) {
647       int row = mp_tableWidget->currentRow();
648       QTableWidgetItem* jobitem = mp_tableWidget->item(row, 0);
649       m_currentJob = jobitem->text();
650
651       /* include purged action or not */
652       jobitem = mp_tableWidget->item(row, m_purgedIndex);
653       QString purged = jobitem->text();
654 /*      mp_tableWidget->removeAction(actionPurgeFiles);
655       if (purged == tr("No") ) {
656          mp_tableWidget->addAction(actionPurgeFiles);
657       }*/
658       /* include restore from time and job action or not */
659       jobitem = mp_tableWidget->item(row, m_typeIndex);
660       QString type = jobitem->text();
661       if (m_selectedJobsCount == 1) {
662          mp_tableWidget->removeAction(actionRestoreFromJob);
663          mp_tableWidget->removeAction(actionRestoreFromTime);
664          if (type == tr("Backup")) {
665             mp_tableWidget->addAction(actionRestoreFromJob);
666             mp_tableWidget->addAction(actionRestoreFromTime);
667          }
668       }
669       /* include cancel action or not */
670       jobitem = mp_tableWidget->item(row, m_statusIndex);
671       QString status = jobitem->text();
672       mp_tableWidget->removeAction(actionCancelJob);
673       if (status == tr("Running") || status == tr("Created, not yet running")) {
674          mp_tableWidget->addAction(actionCancelJob);
675       }
676    }
677 }