]> git.sur5r.net Git - bacula/bacula/blobdiff - bacula/src/qt-console/job/job.cpp
Make qt-console compatible to Qt5 (Qt4 still work)
[bacula/bacula] / bacula / src / qt-console / job / job.cpp
index f5f2f7fb3c9e2e116ffb2c8535cfb84ecfa9f7f1..fce650035f8ca981fd3e27e43ada6e1c5859598e 100644 (file)
@@ -1,57 +1,63 @@
 /*
-   Bacula® - The Network Backup Solution
-
-   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
-   License as published by the Free Software Foundation and included
-   in the file LICENSE.
-
-   This program is distributed in the hope that it will be useful, but
-   WITHOUT ANY WARRANTY; without even the implied warranty of
-   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
-   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 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.
+   Bacula(R) - The Network Backup Solution
+
+   Copyright (C) 2000-2016 Kern Sibbald
+
+   The original author of Bacula is Kern Sibbald, with contributions
+   from many others, a complete list can be found in the file AUTHORS.
+
+   You may use this file and others of this release according to the
+   license defined in the LICENSE file, which includes the Affero General
+   Public License, v3.0 ("AGPLv3") and some additional permissions and
+   terms pursuant to its AGPLv3 Section 7.
+
+   This notice must be preserved when any source code is 
+   conveyed and/or propagated.
+
+   Bacula(R) is a registered trademark of Kern Sibbald.
 */
  
 #include "bat.h"
 #include "job.h"
 #include "util/fmtwidgetitem.h"
 #include "mediainfo/mediainfo.h"
+#include "run/run.h"
 
-Job::Job(QString &jobId, QTreeWidgetItem *parentTreeWidgetItem)
+Job::Job(QString &jobId, QTreeWidgetItem *parentTreeWidgetItem) : Pages()
 {
    setupUi(this);
-   m_closeable = true;
    pgInitialize(tr("Job"), parentTreeWidgetItem);
    QTreeWidgetItem* thisitem = mainWin->getFromHash(this);
    thisitem->setIcon(0,QIcon(QString::fromUtf8(":images/joblog.png")));
    m_cursor = new QTextCursor(textJobLog->document());
 
+   m_bwlimit = 0;
    m_jobId = jobId;
+   m_timer = NULL;
    getFont();
 
    connect(pbRefresh, SIGNAL(clicked()), this, SLOT(populateAll()));
    connect(pbDelete, SIGNAL(clicked()), this, SLOT(deleteJob()));
+   connect(pbCancel, SIGNAL(clicked()), this, SLOT(cancelJob()));
+   connect(pbRun, SIGNAL(clicked()), this, SLOT(rerun()));
    connect(list_Volume, SIGNAL(itemDoubleClicked(QListWidgetItem*)), this, SLOT(showInfoVolume(QListWidgetItem *)));
+   connect(spin_Bwlimit, SIGNAL(valueChanged(int)), this, SLOT(storeBwLimit(int)));
 
    populateAll();
    dockPage();
    setCurrent();
 }
 
+void Job::rerun()
+{
+   new runPage(label_Name->text(),
+               label_Level->text(),
+               label_Pool->text(),
+               QString(""),              // storage
+               label_Client->text(),
+               label_FileSet->text());
+}
+
 void Job::showInfoVolume(QListWidgetItem *item)
 {
    QString s= item->text();
@@ -81,6 +87,18 @@ void Job::deleteJob()
    closeStackPage();
 }
 
+void Job::cancelJob()
+{
+   if (QMessageBox::warning(this, "Bat",
+                            tr("Are you sure you want to cancel this job?"),
+                            QMessageBox::Ok | QMessageBox::Cancel)
+       == QMessageBox::Cancel) { return; }
+
+   QString cmd("cancel jobid=");
+   cmd += m_jobId;
+   consoleCommand(cmd, false);
+}
+
 void Job::getFont()
 {
    QFont font = textJobLog->font();
@@ -106,6 +124,7 @@ void Job::populateAll()
 
 /*
  * Populate the text in the window
+ * TODO: Just append new text instead of clearing the window
  */
 void Job::populateText()
 {
@@ -197,6 +216,167 @@ void Job::populateText()
   
 }
 
+void Job::storeBwLimit(int val)
+{
+   m_bwlimit = val;
+}
+
+void Job::updateRunInfo()
+{
+   QString cmd;
+   QStringList results;
+   QStringList lst;
+   bool parseit=false;
+
+#ifdef xxx
+   /* This doesn't seem like the right thing to do */
+   if (m_bwlimit >= 100) {
+      cmd = QString("setbandwidth limit=" + QString::number(m_bwlimit) 
+                    + " jobid=" + m_jobId);
+      m_console->dir_cmd(cmd, results);
+      results.clear();
+      m_bwlimit = 0;
+   }
+#endif
+
+   cmd = QString(".status client=\"" + m_client + "\" running");
+/*
+ *  JobId 5 Job backup.2010-12-21_09.28.17_03 is running.
+ *   VSS Full Backup Job started: 21-Dec-10 09:28
+ *   Files=4 Bytes=610,976 Bytes/sec=87,282 Errors=0
+ *   Files Examined=4
+ *   Processing file: /tmp/regress/build/po/de.po
+ *   SDReadSeqNo=5 fd=5
+ *
+ *  Or
+ *  JobId=5
+ *  Job=backup.2010-12-21_09.28.17_03
+ *  VSS=1
+ *  Files=4
+ *  Bytes=610976
+ *
+ */
+   QRegExp jobline("(JobId) (\\d+) Job ");
+   QRegExp itemline("([\\w /]+)[:=]\\s*(.+)");
+   QRegExp filesline("Files: Examined=([\\d,]+) Backed up=([\\d,])");
+   QRegExp oldline("Files=([\\d,]+) Bytes=([\\d,]+) Bytes/sec=([\\d,]+) Errors=([\\d,]+)");
+   QRegExp restoreline("Files: Restored=([\\d,]+) Expected=([\\d,]+) Completed=([\\d,]+)%");
+   QRegExp restoreline2("Files Examined=([\\d,]+) Expected Files=([\\d,]+) Percent Complete=([\\d,]+)");
+
+   QString com(",");
+   QString empty("");
+   
+   if (m_console->dir_cmd(cmd, results)) {
+      foreach (QString mline, results) {
+         foreach (QString line, mline.split("\n")) { 
+            line = line.trimmed();
+            if (oldline.indexIn(line) >= 0) {
+               if (parseit) {
+                  lst = oldline.capturedTexts();
+                  label_JobErrors->setText(lst[4]);
+                  label_Speed->setText(convertBytesSI(lst[3].replace(com, empty).toULongLong())+"/s");
+                  label_JobFiles->setText(lst[1]);
+                  label_JobBytes->setText(convertBytesSI(lst[2].replace(com, empty).toULongLong()));
+               }
+               continue;
+
+            } else if (filesline.indexIn(line) >= 0) {
+               if (parseit) {
+                  lst = filesline.capturedTexts(); // Will also catch Backed up
+                  label_FilesExamined->setText(lst[1]);
+               }
+               continue;
+
+// TODO: Need to be fixed
+//            } else if (restoreline2.indexIn(line) >= 0) {
+//               if (parseit) {
+//                  lst = filesline.capturedTexts();
+//                  label_FilesExamined->setText(lst[1]); // Can also handle Expected and Completed
+//               }
+//               continue;
+
+            } else if (jobline.indexIn(line) >= 0) {
+               lst = jobline.capturedTexts();
+               lst.removeFirst();
+
+            } else if (itemline.indexIn(line) >= 0) {
+               lst = itemline.capturedTexts();
+               lst.removeFirst();
+
+            } else {
+               if (mainWin->m_miscDebug) 
+                  Pmsg1(0, "bad line=%s\n", line.toUtf8().data());
+               continue;
+            }
+            if (lst.count() < 2) {
+               if (mainWin->m_miscDebug) 
+                  Pmsg2(0, "bad line=%s count=%d\n", line.toUtf8().data(), lst.count());
+            }
+            if (lst[0] == "JobId") {
+               if (lst[1] == m_jobId) {
+                  parseit = true;
+               } else {
+                  parseit = false;
+               }
+            }
+            if (!parseit) {
+               continue;
+            }
+            
+//         } else if (lst[0] == "Job") {
+//            grpRun->setTitle(lst[1]);
+            
+//               
+//         } else if (lst[0] == "VSS") {
+
+//         } else if (lst[0] == "Level") {
+//            Info->setText(lst[1]);
+//
+//         } else if (lst[0] == "JobType" || lst[0] == "Type") {
+//
+//         } else if (lst[0] == "JobStarted" || lst[0] == "StartTime") {
+//            Started->setText(lst[1]);
+
+#ifdef xxx
+            if (lst[0] == "Bwlimit") {
+               int val = lst[1].toInt();
+               if (val > 0) {
+                  chk_Bwlimit->setChecked(true);
+                  spin_Bwlimit->setEnabled(true);
+                  spin_Bwlimit->setValue(lst[1].toInt()/1024);
+               } else {
+                  chk_Bwlimit->setEnabled(false);
+                  spin_Bwlimit->setEnabled(false);
+                  spin_Bwlimit->setValue(0);
+               }
+#endif
+               
+            if (lst[0] == "Errors") {
+               label_JobErrors->setText(lst[1]);
+               
+            } else if (lst[0] == "Bytes/sec") {
+               label_Speed->setText(convertBytesSI(lst[1].toULongLong())+"/s");
+               
+            } else if (lst[0] == "Files" || lst[0] == "JobFiles") {
+               label_JobFiles->setText(lst[1]);
+               
+            } else if (lst[0] == "Bytes" || lst[0] == "JobBytes") {
+               label_JobBytes->setText(convertBytesSI(lst[1].toULongLong()));
+               
+            } else if (lst[0] == "Examined") {
+               label_FilesExamined->setText(lst[1]);
+
+            } else if (lst[0] == "Files Examined") {
+               label_FilesExamined->setText(lst[1]);
+               
+            } else if (lst[0] == "Processing file") {
+               label_CurrentFile->setText(lst[1]);
+            }
+         }
+      }
+   }
+}
+
 /*
  * Populate the text in the window
  */
@@ -205,43 +385,79 @@ void Job::populateForm()
    QString stat, err;
    char buf[256];
    QString query = 
-      "SELECT JobId, Job.Name, Level, Client.Name, Pool.Name, FileSet, SchedTime, StartTime, EndTime, "
-      "EndTime - StartTime AS Duration, JobBytes, JobFiles, JobErrors, JobStatus, PurgedFiles "
-      "FROM Job JOIN Client USING (ClientId) LEFT JOIN Pool USING (PoolId) "
-      "LEFT JOIN FileSet USING (FileSetId)"
+      "SELECT JobId, Job.Name, Level, Client.Name, Pool.Name, FileSet,"
+      "SchedTime, StartTime, EndTime, EndTime-StartTime AS Duration, "
+      "JobBytes, JobFiles, JobErrors, JobStatus, PurgedFiles "
+      "FROM Job JOIN Client USING (ClientId) "
+        "LEFT JOIN Pool ON (Job.PoolId = Pool.PoolId) "
+        "LEFT JOIN FileSet ON (Job.FileSetId = FileSet.FileSetId)"
       "WHERE JobId=" + m_jobId; 
    QStringList results;
    if (m_console->sql_cmd(query, results)) {
-      QString resultline;
+      QString resultline, duration;
       QStringList fieldlist;
 
       foreach (resultline, results) { // should have only one result
          fieldlist = resultline.split("\t");
+         if (fieldlist.size() != 15) {
+            Pmsg1(000, "Unexpected line %s", resultline.toUtf8().data());
+            continue;
+         }
          QStringListIterator fld(fieldlist);
          label_JobId->setText(fld.next());
          label_Name->setText(fld.next());
          
-         label_Level->setText(job_level_to_str(fld.next()[0].toAscii()));
+         label_Level->setText(job_level_to_str(fld.next()[0].toLatin1()));
 
-         label_Client->setText(fld.next());
+         m_client = fld.next();
+         label_Client->setText(m_client);
          label_Pool->setText(fld.next());
          label_FileSet->setText(fld.next());
          label_SchedTime->setText(fld.next());
          label_StartTime->setText(fld.next());
          label_EndTime->setText(fld.next());
-         label_Duration->setText(fld.next());
+         duration = fld.next();
+         /* 
+          * Note: if we have a negative duration, it is because the EndTime
+          *  is zero (i.e. the Job is still running).  We should use 
+          *  duration = StartTime - current_time
+          */
+         if (duration.left(1) == "-") {
+            duration = "0.0";
+         }
+         label_Duration->setText(duration);
 
          label_JobBytes->setText(convertBytesSI(fld.next().toULongLong()));
          label_JobFiles->setText(fld.next());
          err = fld.next();
          label_JobErrors->setText(err);
 
-         stat=fld.next();
+         stat = fld.next();
          if (stat == "T" && err.toInt() > 0) {
             stat = "W";
          }
+         if (stat == "R") {
+            pbDelete->setVisible(false);
+            pbCancel->setVisible(true);
+            grpRun->setVisible(true);
+            if (!m_timer) {
+               m_timer = new QTimer(this);
+               connect(m_timer, SIGNAL(timeout()), this, SLOT(populateAll()));
+               m_timer->start(30000);
+            }
+            updateRunInfo();
+         } else {
+            pbDelete->setVisible(true);
+            pbCancel->setVisible(false);
+            grpRun->setVisible(false);
+            if (m_timer) {
+               m_timer->stop();
+               delete m_timer;
+               m_timer = NULL;
+            }
+         }
          label_JobStatus->setPixmap(QPixmap(":/images/" + stat + ".png"));
-         jobstatus_to_ascii_gui(stat[0].toAscii(), buf, sizeof(buf));
+         jobstatus_to_ascii_gui(stat[0].toLatin1(), buf, sizeof(buf));
          stat = buf;
          label_JobStatus->setToolTip(stat);