]> git.sur5r.net Git - bacula/bacula/blobdiff - bacula/src/qt-console/joblist/joblist.cpp
First cut of bat rerun a Job from Jobs Run
[bacula/bacula] / bacula / src / qt-console / joblist / joblist.cpp
index 3c1707a9c1ab859caa45ad77d7970bbc8c3729fc..2cffc47ef170edfa342e8811ded318836f76dd04 100644 (file)
@@ -1,12 +1,12 @@
 /*
    Bacula® - The Network Backup Solution
 
-   Copyright (C) 2007-2008 Free Software Foundation Europe e.V.
+   Copyright (C) 2007-2009 Free Software Foundation Europe e.V.
 
    The main author of Bacula is Kern Sibbald, with contributions from
    many others, a complete list can be found in the file AUTHORS.
    This program is Free Software; you can redistribute it and/or
-   modify it under the terms of version two of the GNU General Public
+   modify it under the terms of version three of the GNU Affero General Public
    License as published by the Free Software Foundation and included
    in the file LICENSE.
 
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
    General Public License for more details.
 
-   You should have received a copy of the GNU General Public License
+   You should have received a copy of the GNU Affero General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
 
-   Bacula® is a registered trademark of John Walker.
+   Bacula® is a registered trademark of Kern Sibbald.
    The licensor of Bacula is the Free Software Foundation Europe
    (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
    Switzerland, email:ftf@fsfeurope.org.
  *   Dirk Bartley, March 2007
  */
  
+#include "bat.h"
 #include <QAbstractEventDispatcher>
 #include <QTableWidgetItem>
-#include "bat.h"
 #include "joblist.h"
 #include "restore.h"
+#include "job/job.h"
 #include "joblog/joblog.h"
 #ifdef HAVE_QWT
 #include "jobgraphs/jobplot.h"
@@ -50,12 +51,11 @@ JobList::JobList(const QString &mediaName, const QString &clientName,
           const QString &jobName, const QString &filesetName, QTreeWidgetItem *parentTreeWidgetItem)
 {
    setupUi(this);
-   m_name = ""; /* treeWidgetName has a virtual override in this class */
+   m_name = "Jobs Run"; /* treeWidgetName has a virtual override in this class */
    m_mediaName = mediaName;
    m_clientName = clientName;
    m_jobName = jobName;
    m_filesetName = filesetName;
-   m_filesetName = filesetName;
    pgInitialize("", parentTreeWidgetItem);
    QTreeWidgetItem* thisitem = mainWin->getFromHash(this);
    thisitem->setIcon(0,QIcon(QString::fromUtf8(":images/emblem-system.png")));
@@ -63,17 +63,16 @@ JobList::JobList(const QString &mediaName, const QString &clientName,
    m_resultCount = 0;
    m_populated = false;
    m_closeable = false;
-   if ((m_mediaName != "") || (m_clientName != "") || (m_jobName != "") || (m_filesetName != ""))
+   if ((m_mediaName != "") || (m_clientName != "") || (m_jobName != "") || (m_filesetName != "")) {
       m_closeable=true;
+   }
    m_checkCurrentWidget = true;
-   createConnections();
 
    /* Set Defaults for check and spin for limits */
    limitCheckBox->setCheckState(mainWin->m_recordLimitCheck ? Qt::Checked : Qt::Unchecked);
    limitSpinBox->setValue(mainWin->m_recordLimitVal);
    daysCheckBox->setCheckState(mainWin->m_daysLimitCheck ? Qt::Checked : Qt::Unchecked);
    daysSpinBox->setValue(mainWin->m_daysLimitVal);
-   dockPage();
 
    QGridLayout *gridLayout = new QGridLayout(this);
    gridLayout->setSpacing(6);
@@ -85,11 +84,13 @@ JobList::JobList(const QString &mediaName, const QString &clientName,
    area->setObjectName(QString::fromUtf8("area"));
    area->setWidget(frame);
    area->setWidgetResizable(true);
-   m_splitter->addWidget(mp_tableWidget);
    m_splitter->addWidget(area);
+   m_splitter->addWidget(mp_tableWidget);
 
    gridLayout->addWidget(m_splitter, 0, 0, 1, 1);
+   createConnections();
    readSettings();
+   if (m_closeable) { dockPage(); }
 }
 
 /*
@@ -108,11 +109,11 @@ JobList::~JobList()
  */
 void JobList::populateTable()
 {
-   if (!m_console->preventInUseConnect())
-       return;
-
    /* Can't do this in constructor because not neccesarily conected in constructor */
    prepareFilterWidgets();
+   m_populated = true;
+
+   Freeze frz(*mp_tableWidget); /* disable updating*/
 
    /* Set up query */
    QString query;
@@ -122,7 +123,8 @@ void JobList::populateTable()
    QStringList headerlist = (QStringList()
       << tr("Job Id") << tr("Job Name") << tr("Client") << tr("Job Starttime") 
       << tr("Job Type") << tr("Job Level") << tr("Job Files") 
-      << tr("Job Bytes") << tr("Job Status")  << tr("Purged") << tr("File Set"));
+      << tr("Job Bytes") << tr("Job Status")  << tr("Purged") << tr("File Set")
+      << tr("Pool Name") << tr("First Volume") << tr("VolCount"));
 
    m_jobIdIndex = headerlist.indexOf(tr("Job Id"));
    m_purgedIndex = headerlist.indexOf(tr("Purged"));
@@ -131,6 +133,10 @@ void JobList::populateTable()
    m_startIndex = headerlist.indexOf(tr("Job Starttime"));
    m_filesIndex = headerlist.indexOf(tr("Job Files"));
    m_bytesIndex = headerlist.indexOf(tr("Job Bytes"));
+   m_levelIndex = headerlist.indexOf(tr("Job Level"));
+   m_nameIndex = headerlist.indexOf(tr("Job Name"));
+   m_filesetIndex = headerlist.indexOf(tr("File Set"));
+   m_clientIndex = headerlist.indexOf(tr("Client"));
 
    /* Initialize the QTableWidget */
    m_checkCurrentWidget = false;
@@ -158,48 +164,56 @@ void JobList::populateTable()
       QString resultline;
       foreach (resultline, results) {
          fieldlist = resultline.split("\t");
-         if (fieldlist.size() < 12)
-           continue; /* some fields missing, ignore row */
+         if (fieldlist.size() < 13)
+            continue; /* some fields missing, ignore row */
 
-        TableItemFormatter jobitem(*mp_tableWidget, row);
+         TableItemFormatter jobitem(*mp_tableWidget, row);
   
          /* Iterate through fields in the record */
-        QStringListIterator fld(fieldlist);
+         QStringListIterator fld(fieldlist);
          int col = 0;
 
-        /* job id */
+         /* job id */
          jobitem.setNumericFld(col++, fld.next());
 
-        /* job name */
+         /* job name */
          jobitem.setTextFld(col++, fld.next());
 
-        /* client */
+         /* client */
          jobitem.setTextFld(col++, fld.next());
 
-        /* job starttime */
+         /* job starttime */
          jobitem.setTextFld(col++, fld.next(), true);
 
-        /* job type */
+         /* job type */
          jobitem.setJobTypeFld(col++, fld.next());
 
-        /* job level */
+         /* job level */
          jobitem.setJobLevelFld(col++, fld.next());
 
-        /* job files */
+         /* job files */
          jobitem.setNumericFld(col++, fld.next());
 
-        /* job bytes */
+         /* job bytes */
          jobitem.setBytesFld(col++, fld.next());
 
-        /* job status */
+         /* job status */
          jobitem.setJobStatusFld(col++, fld.next());
 
-        /* purged */
-        jobitem.setBoolFld(col++, fld.next());
+         /* purged */
+         jobitem.setBoolFld(col++, fld.next());
+
+         /* fileset */
+         jobitem.setTextFld(col++, fld.next());
+
+         /* pool name */
+         jobitem.setTextFld(col++, fld.next());
 
-        /* fileset */
+         /* First Media */
          jobitem.setTextFld(col++, fld.next());
 
+         /* Medias count */
+         jobitem.setNumericFld(col++, fld.next());
          row++;
       }
    } 
@@ -218,6 +232,9 @@ void JobList::populateTable()
           tr("The Jobs query returned no results.\n"
          "Press OK to continue?"), QMessageBox::Ok );
    }
+
+   /* make read only */
+   mp_tableWidget->setEditTriggers(QAbstractItemView::NoEditTriggers);
 }
 
 void JobList::prepareFilterWidgets()
@@ -228,7 +245,7 @@ void JobList::prepareFilterWidgets()
       comboSel(clientComboBox, m_clientName);
 
       QStringList volumeList;
-      m_console->getVolumeList(volumeList);
+      getVolumeList(volumeList);
       volumeComboBox->addItem(tr("Any"));
       volumeComboBox->addItems(volumeList);
       comboSel(volumeComboBox, m_mediaName);
@@ -245,6 +262,9 @@ void JobList::prepareFilterWidgets()
       fileSetComboBox->addItems(m_console->fileset_list);
       comboSel(fileSetComboBox, m_filesetName);
 
+      poolComboBox->addItem(tr("Any"));
+      poolComboBox->addItems(m_console->pool_list);
+
       jobStatusComboFill(statusComboBox);
    }
 }
@@ -257,15 +277,19 @@ void JobList::fillQueryString(QString &query)
       m_mediaName = volumeComboBox->itemText(volumeIndex);
    QString distinct = "";
    if (m_mediaName != tr("Any")) { distinct = "DISTINCT "; }
-   query += "SELECT " + distinct + "Job.Jobid AS Id, Job.Name AS JobName, " 
+   query += "SELECT " + distinct + "Job.JobId AS JobId, Job.Name AS JobName, " 
             " Client.Name AS Client,"
             " Job.Starttime AS JobStart, Job.Type AS JobType,"
             " Job.Level AS BackupLevel, Job.Jobfiles AS FileCount,"
             " Job.JobBytes AS Bytes, Job.JobStatus AS Status,"
-            " Job.PurgedFiles AS Purged, FileSet.FileSet"
+            " Job.PurgedFiles AS Purged, FileSet.FileSet,"
+            " Pool.Name AS Pool,"
+            " (SELECT Media.VolumeName FROM JobMedia JOIN Media ON JobMedia.MediaId=Media.MediaId WHERE JobMedia.JobId=Job.JobId ORDER BY JobMediaId LIMIT 1) AS FirstVolume,"
+            " (SELECT count(DISTINCT MediaId) FROM JobMedia WHERE JobMedia.JobId=Job.JobId) AS Volumes"
             " FROM Job"
             " JOIN Client ON (Client.ClientId=Job.ClientId)"
-            " LEFT OUTER JOIN FileSet ON (FileSet.FileSetId=Job.FileSetId) ";
+            " LEFT OUTER JOIN FileSet ON (FileSet.FileSetId=Job.FileSetId) "
+            " LEFT OUTER JOIN Pool ON Job.PoolId = Pool.PoolId ";
    QStringList conditions;
    if (m_mediaName != tr("Any")) {
       query += " LEFT OUTER JOIN JobMedia ON (JobMedia.JobId=Job.JobId) "
@@ -279,12 +303,19 @@ void JobList::fillQueryString(QString &query)
    jobStatusComboCond(conditions, statusComboBox, "Job.JobStatus");
    boolComboCond(conditions, purgedComboBox, "Job.PurgedFiles");
    comboCond(conditions, fileSetComboBox, "FileSet.FileSet");
+   comboCond(conditions, poolComboBox, "Pool.Name");
 
    /* If Limit check box For limit by days is checked  */
    if (daysCheckBox->checkState() == Qt::Checked) {
       QDateTime stamp = QDateTime::currentDateTime().addDays(-daysSpinBox->value());
       QString since = stamp.toString(Qt::ISODate);
-      conditions.append("Job.Starttime>'" + since + "'");
+      conditions.append("Job.Starttime > '" + since + "'");
+   }
+   if (filterCopyCheckBox->checkState() == Qt::Checked) {
+      conditions.append("Job.Type != 'c'" );
+   }
+   if (filterMigrationCheckBox->checkState() == Qt::Checked) {
+      conditions.append("Job.Type != 'g'" );
    }
    bool first = true;
    foreach (QString condition, conditions) {
@@ -313,7 +344,20 @@ void JobList::PgSeltreeWidgetClicked()
 {
    if (!m_populated) {
       populateTable();
-      m_populated=true;
+      /* Lets make sure the splitter is not all the way to size index 0 == 0 */
+      QList<int> sizes = m_splitter->sizes();
+      if (sizes[0] == 0) {
+         int frameMax = frame->maximumHeight();
+         int sizeSum = 0;
+         foreach(int size, sizes) { sizeSum += size; }
+         int tabHeight = mainWin->tabWidget->geometry().height();
+         sizes[0] = frameMax;
+         sizes[1] = tabHeight - frameMax;
+         m_splitter->setSizes(sizes);
+      }
+   }
+   if (!isOnceDocked()) {
+      dockPage();
    }
 }
 
@@ -323,10 +367,8 @@ void JobList::PgSeltreeWidgetClicked()
  */
 void JobList::currentStackItem()
 {
-   populateTable();
-   if (!m_populated) {
-      m_populated=true;
-   }
+/*   if (!m_populated) populate every time user comes back to this object */
+      populateTable();
 }
 
 /*
@@ -335,52 +377,15 @@ void JobList::currentStackItem()
 void JobList::treeWidgetName(QString &desc)
 {
    if (m_mediaName != "" ) {
-     desc = tr("JobList of Volume %1").arg(m_mediaName);
+     desc = tr("Jobs Run on Volume %1").arg(m_mediaName);
    } else if (m_clientName != "" ) {
-     desc = tr("JobList of Client %1").arg(m_clientName);
+     desc = tr("Jobs Run from Client %1").arg(m_clientName);
    } else if (m_jobName != "" ) {
-     desc = tr("JobList of Job %1").arg(m_jobName);
+     desc = tr("Jobs Run of Job %1").arg(m_jobName);
    } else if (m_filesetName != "" ) {
-     desc = tr("JobList of fileset %1").arg(m_filesetName);
+     desc = tr("Jobs Run with fileset %1").arg(m_filesetName);
    } else {
-     desc = tr("JobList");
-   }
-}
-
-/*
- * This functions much line tableItemChanged for trees like the page selector,
- * but I will do much less here
- */
-void JobList::tableItemChanged(QTableWidgetItem *currentItem, QTableWidgetItem * /*previousItem*/)
-{
-   if (m_checkCurrentWidget) {
-      int row = currentItem->row();
-      QTableWidgetItem* jobitem = mp_tableWidget->item(row, 0);
-      m_currentJob = jobitem->text();
-
-      /* include purged action or not */
-      jobitem = mp_tableWidget->item(row, m_purgedIndex);
-      QString purged = jobitem->text();
-      mp_tableWidget->removeAction(actionPurgeFiles);
-      if (purged == tr("No") ) {
-         mp_tableWidget->addAction(actionPurgeFiles);
-      }
-      /* include restore from time and job action or not */
-      jobitem = mp_tableWidget->item(row, m_typeIndex);
-      QString type = jobitem->text();
-      mp_tableWidget->removeAction(actionRestoreFromJob);
-      mp_tableWidget->removeAction(actionRestoreFromTime);
-      if (type == tr("Backup")) {
-         mp_tableWidget->addAction(actionRestoreFromJob);
-         mp_tableWidget->addAction(actionRestoreFromTime);
-      }
-      /* include cancel action or not */
-      jobitem = mp_tableWidget->item(row, m_statusIndex);
-      QString status = jobitem->text();
-      mp_tableWidget->removeAction(actionCancelJob);
-      if (status == tr("Running") || status == tr("Created, not yet running")) {
-         mp_tableWidget->addAction(actionCancelJob);
-      }
+     desc = tr("Jobs Run");
    }
 }
 
@@ -392,8 +397,7 @@ void JobList::createConnections()
 {
    /* connect to the action specific to this pages class that shows up in the 
     * page selector tree */
-   connect(actionRefreshJobList, SIGNAL(triggered()), this,
-                SLOT(populateTable()));
+   connect(actionRefreshJobList, SIGNAL(triggered()), this, SLOT(populateTable()));
    connect(refreshButton, SIGNAL(pressed()), this, SLOT(populateTable()));
 #ifdef HAVE_QWT
    connect(graphButton, SIGNAL(pressed()), this, SLOT(graphTable()));
@@ -401,14 +405,9 @@ void JobList::createConnections()
    graphButton->setEnabled(false);
    graphButton->setVisible(false);
 #endif
-   /* for the tableItemChanged to maintain m_currentJob */
-   connect(mp_tableWidget, SIGNAL(
-           currentItemChanged(QTableWidgetItem *, QTableWidgetItem *)),
-           this, SLOT(tableItemChanged(QTableWidgetItem *, QTableWidgetItem *)));
-
-   /* for the tableItemChanged to maintain a delete selection */
-   connect(mp_tableWidget, SIGNAL( itemSelectionChanged()),
-           this, SLOT(selectedJobsGet()) );
+   /* for the selectionChanged to maintain m_currentJob and a delete selection */
+   connect(mp_tableWidget, SIGNAL(itemSelectionChanged()), this, SLOT(selectionChanged()));
+   connect(mp_tableWidget, SIGNAL(itemDoubleClicked(QTableWidgetItem*)), this, SLOT(showInfoForJob()));
 
    /* Do what is required for the local context sensitive menu */
 
@@ -416,41 +415,18 @@ void JobList::createConnections()
    /* setContextMenuPolicy is required */
    mp_tableWidget->setContextMenuPolicy(Qt::ActionsContextMenu);
 
-   /* Add Actions */
-   mp_tableWidget->addAction(actionRefreshJobList);
-   mp_tableWidget->addAction(actionListJobid);
-   mp_tableWidget->addAction(actionListFilesOnJob);
-   mp_tableWidget->addAction(actionListJobMedia);
-   mp_tableWidget->addAction(actionListVolumes);
-   mp_tableWidget->addAction(actionDeleteJob);
-   mp_tableWidget->addAction(actionPurgeFiles);
-   mp_tableWidget->addAction(actionRestoreFromJob);
-   mp_tableWidget->addAction(actionRestoreFromTime);
-   mp_tableWidget->addAction(actionShowLogForJob);
-
-   /* Make Connections */
-   connect(actionListJobid, SIGNAL(triggered()), this,
-                SLOT(consoleListJobid()));
-   connect(actionListFilesOnJob, SIGNAL(triggered()), this,
-                SLOT(consoleListFilesOnJob()));
-   connect(actionListJobMedia, SIGNAL(triggered()), this,
-                SLOT(consoleListJobMedia()));
-   connect(actionListVolumes, SIGNAL(triggered()), this,
-                SLOT(consoleListVolumes()));
-   connect(actionDeleteJob, SIGNAL(triggered()), this,
-                SLOT(consoleDeleteJob()));
-   connect(actionPurgeFiles, SIGNAL(triggered()), this,
-                SLOT(consolePurgeFiles()));
-   connect(actionRestoreFromJob, SIGNAL(triggered()), this,
-                SLOT(preRestoreFromJob()));
-   connect(actionRestoreFromTime, SIGNAL(triggered()), this,
-                SLOT(preRestoreFromTime()));
-   connect(actionShowLogForJob, SIGNAL(triggered()), this,
-                SLOT(showLogForJob()));
-   connect(actionCancelJob, SIGNAL(triggered()), this,
-                SLOT(consoleCancelJob()));
-   connect(actionListJobTotals, SIGNAL(triggered()), this,
-                SLOT(consoleListJobTotals()));
+   connect(actionListFilesOnJob, SIGNAL(triggered()), this, SLOT(consoleListFilesOnJob()));
+   connect(actionListJobMedia, SIGNAL(triggered()), this, SLOT(consoleListJobMedia()));
+   connect(actionDeleteJob, SIGNAL(triggered()), this, SLOT(consoleDeleteJob()));
+   connect(actionRestartJob, SIGNAL(triggered()), this, SLOT(consoleRestartJob()));
+   connect(actionPurgeFiles, SIGNAL(triggered()), this, SLOT(consolePurgeFiles()));
+   connect(actionRestoreFromJob, SIGNAL(triggered()), this, SLOT(preRestoreFromJob()));
+   connect(actionRestoreFromTime, SIGNAL(triggered()), this, SLOT(preRestoreFromTime()));
+   connect(actionShowLogForJob, SIGNAL(triggered()), this, SLOT(showLogForJob()));
+   connect(actionShowInfoForJob, SIGNAL(triggered()), this, SLOT(showInfoForJob()));
+   connect(actionCancelJob, SIGNAL(triggered()), this, SLOT(consoleCancelJob()));
+   connect(actionListJobTotals, SIGNAL(triggered()), this, SLOT(consoleListJobTotals()));
+   connect(m_splitter, SIGNAL(splitterMoved(int, int)), this, SLOT(splitterMoved(int, int)));
 
    m_contextActions.append(actionRefreshJobList);
    m_contextActions.append(actionListJobTotals);
@@ -460,13 +436,6 @@ void JobList::createConnections()
  * Functions to respond to local context sensitive menu sending console commands
  * If I could figure out how to make these one function passing a string, Yaaaaaa
  */
-void JobList::consoleListJobid()
-{
-   QString cmd("list jobid=");
-   cmd += m_currentJob;
-   if (mainWin->m_longList) { cmd.prepend("l"); }
-   consoleCommand(cmd);
-}
 void JobList::consoleListFilesOnJob()
 {
    QString cmd("list files jobid=");
@@ -481,19 +450,14 @@ void JobList::consoleListJobMedia()
    if (mainWin->m_longList) { cmd.prepend("l"); }
    consoleCommand(cmd);
 }
-void JobList::consoleListVolumes()
-{
-   QString cmd("list volumes jobid=");
-   cmd += m_currentJob;
-   if (mainWin->m_longList) { cmd.prepend("l"); }
-   consoleCommand(cmd);
-}
+
 void JobList::consoleListJobTotals()
 {
    QString cmd("list jobtotals");
    if (mainWin->m_longList) { cmd.prepend("l"); }
    consoleCommand(cmd);
 }
+
 void JobList::consoleDeleteJob()
 {
    if (QMessageBox::warning(this, "Bat",
@@ -510,8 +474,26 @@ void JobList::consoleDeleteJob()
 
    QString cmd("delete job jobid=");
    cmd += m_selectedJobs;
-   consoleCommand(cmd);
+   consoleCommand(cmd, false);
+   populateTable();
 }
+
+void JobList::consoleRestartJob()
+{
+   QString cmd;
+
+   cmd = tr("run job=\"%1\" client=\"%2\" level=%3").arg(m_jobName).arg(m_clientName).arg(m_levelName);
+   if (m_filesetName != "" && m_filesetName != "*None*") {
+      cmd += tr(" fileset=\"%1\"").arg(m_filesetName);
+   }
+
+   if (mainWin->m_commandDebug) Pmsg1(000, "Run cmd : %s\n",cmd.toUtf8().data());
+   consoleCommand(cmd, false);
+   populateTable();
+}
+
+
+
 void JobList::consolePurgeFiles()
 {
    if (QMessageBox::warning(this, "Bat",
@@ -526,9 +508,14 @@ void JobList::consolePurgeFiles()
       QMessageBox::Ok | QMessageBox::Cancel)
       == QMessageBox::Cancel) { return; }
 
-   QString cmd("purge files jobid=");
-   cmd += m_currentJob;
-   consoleCommand(cmd);
+   m_console->m_warningPrevent = true;
+   foreach(QString job, m_selectedJobsList) {
+      QString cmd("purge files jobid=");
+      cmd += job;
+      consoleCommand(cmd, false);
+   }
+   m_console->m_warningPrevent = false;
+   populateTable();
 }
 
 /*
@@ -556,6 +543,15 @@ void JobList::showLogForJob()
    new JobLog(m_currentJob, pageSelectorTreeWidgetItem);
 }
 
+/*
+ * Subroutine to call class to show the log in the database from that job
+ */
+void JobList::showInfoForJob(QTableWidgetItem * /*item*/)
+{
+   QTreeWidgetItem* pageSelectorTreeWidgetItem = mainWin->getFromHash(this);
+   new Job(m_currentJob, pageSelectorTreeWidgetItem);
+}
+
 /*
  * Cancel a running job
  */
@@ -598,6 +594,8 @@ void JobList::writeSettings()
    QSettings settings(m_console->m_dir->name(), "bat");
    settings.beginGroup(m_groupText);
    settings.setValue(m_splitText, m_splitter->saveState());
+   settings.setValue("FilterCopyCheckState", filterCopyCheckBox->checkState());
+   settings.setValue("FilterMigrationCheckState", filterMigrationCheckBox->checkState());
    settings.endGroup();
 }
 
@@ -607,17 +605,21 @@ void JobList::writeSettings()
 void JobList::readSettings()
 {
    m_groupText = "JobListPage";
-   m_splitText = "splitterSizes_1";
+   m_splitText = "splitterSizes_2";
    QSettings settings(m_console->m_dir->name(), "bat");
    settings.beginGroup(m_groupText);
-   m_splitter->restoreState(settings.value(m_splitText).toByteArray());
+   if (settings.contains(m_splitText)) {
+      m_splitter->restoreState(settings.value(m_splitText).toByteArray());
+   }
+   filterCopyCheckBox->setCheckState((Qt::CheckState)settings.value("FilterCopyCheckState").toInt());
+   filterMigrationCheckBox->setCheckState((Qt::CheckState)settings.value("FilterMigrationCheckState").toInt());
    settings.endGroup();
 }
 
 /*
  * Function to fill m_selectedJobsCount and m_selectedJobs with selected values
  */
-void JobList::selectedJobsGet()
+void JobList::selectionChanged()
 {
    QList<int> rowList;
    QList<QTableWidgetItem *> sitems = mp_tableWidget->selectedItems();
@@ -629,18 +631,108 @@ void JobList::selectedJobsGet()
    }
 
    m_selectedJobs = "";
+   m_selectedJobsList.clear();
    bool first = true;
    foreach(int row, rowList) {
       QTableWidgetItem * sitem = mp_tableWidget->item(row, m_jobIdIndex);
       if (!first) m_selectedJobs.append(",");
       else first = false;
       m_selectedJobs.append(sitem->text());
+      m_selectedJobsList.append(sitem->text());
    }
    m_selectedJobsCount = rowList.count();
    if (m_selectedJobsCount > 1) {
-     QString text = QString( tr("Delete list of %1 Jobs")).arg(m_selectedJobsCount);
-       actionDeleteJob->setText(text);
+      QString text = QString( tr("Delete list of %1 Jobs")).arg(m_selectedJobsCount);
+      actionDeleteJob->setText(text);
+      text = QString( tr("Purge Files from list of %1 Jobs")).arg(m_selectedJobsCount);
+      actionPurgeFiles->setText(text);
    } else {
-     actionDeleteJob->setText(tr("Delete Single Job"));
+      actionDeleteJob->setText(tr("Delete Single Job"));
+      actionPurgeFiles->setText(tr("Purge Files from single job"));
+   }
+
+   /* remove all actions */
+   foreach(QAction* mediaAction, mp_tableWidget->actions()) {
+      mp_tableWidget->removeAction(mediaAction);
+   }
+
+   /* Add Actions */
+   mp_tableWidget->addAction(actionRefreshJobList);
+   if (m_selectedJobsCount == 1) {
+      mp_tableWidget->addAction(actionListFilesOnJob);
+      mp_tableWidget->addAction(actionListJobMedia);
+      mp_tableWidget->addAction(actionRestartJob);
+      mp_tableWidget->addAction(actionRestoreFromJob);
+      mp_tableWidget->addAction(actionRestoreFromTime);
+      mp_tableWidget->addAction(actionShowLogForJob);
+      mp_tableWidget->addAction(actionShowInfoForJob);
+   }
+   if (m_selectedJobsCount >= 1) {
+      mp_tableWidget->addAction(actionDeleteJob);
+      mp_tableWidget->addAction(actionPurgeFiles);
+   }
+
+   /* Make Connections */
+   if (m_checkCurrentWidget) {
+      int row = mp_tableWidget->currentRow();
+      QTableWidgetItem* jobitem = mp_tableWidget->item(row, 0);
+      m_currentJob = jobitem->text();    /* get JobId */
+      jobitem = mp_tableWidget->item(row, m_clientIndex);
+      m_clientName = jobitem->text();    /* get Client Name */
+      jobitem = mp_tableWidget->item(row, m_nameIndex);
+      m_jobName = jobitem->text();    /* get Job Name */
+      jobitem = mp_tableWidget->item(row, m_levelIndex);
+      m_levelName = jobitem->text();    /* get level */
+      jobitem = mp_tableWidget->item(row, m_filesetIndex);
+      if (jobitem) {
+         m_filesetName = jobitem->text();    /* get FileSet Name */
+      } else {
+         m_filesetName = "";
+      }
+
+      /* include purged action or not */
+      jobitem = mp_tableWidget->item(row, m_purgedIndex);
+      QString purged = jobitem->text();
+/*      mp_tableWidget->removeAction(actionPurgeFiles);
+      if (purged == tr("No") ) {
+         mp_tableWidget->addAction(actionPurgeFiles);
+      }*/
+
+      /* include restore from time and job action or not */
+      jobitem = mp_tableWidget->item(row, m_typeIndex);
+      QString type = jobitem->text();
+      if (m_selectedJobsCount == 1) {
+         mp_tableWidget->removeAction(actionRestoreFromJob);
+         mp_tableWidget->removeAction(actionRestoreFromTime);
+         if (type == tr("Backup")) {
+            mp_tableWidget->addAction(actionRestoreFromJob);
+            mp_tableWidget->addAction(actionRestoreFromTime);
+         }
+      }
+
+      /* include cancel action or not */
+      jobitem = mp_tableWidget->item(row, m_statusIndex);
+      QString status = jobitem->text();
+      mp_tableWidget->removeAction(actionCancelJob);
+      if (status == tr("Running") || status == tr("Created, not yet running")) {
+         mp_tableWidget->addAction(actionCancelJob);
+      }
+   }
+}
+
+/*
+ *  Function to prevent the splitter from making index 0 of the size larger than it
+ *  needs to be
+ */
+void JobList::splitterMoved(int /*pos*/, int /*index*/)
+{
+   int frameMax = frame->maximumHeight();
+   QList<int> sizes = m_splitter->sizes();
+   int sizeSum = 0;
+   foreach(int size, sizes) { sizeSum += size; }
+   if (sizes[0] > frameMax) {
+      sizes[0] = frameMax;
+      sizes[1] = sizeSum - frameMax;
+      m_splitter->setSizes(sizes);
    }
 }