--- /dev/null
+# This file provides information about the External dependencies required by
+# Bacula.
+#
+# There are four fields delimited by |.  Only the first two fields are 
+# required.  The other two are used when the top level directory of the
+# archive is not the same as the file name with any suffixes removed.
+#
+# Field 1 is the name of the dependency.  It is used to define the
+# name of the three variables which are assigned the values of fields 2 to 4.
+#
+# Field 2 is the URL of the archive.  It is assigned to the variable
+# URL_[field1].
+#
+# Field 3 is the top directory of the archive or the name of a directory that
+# must be created and the archive extracted into it.  It is assigned to the 
+# variable DIR_[field1].
+#
+# Field 4 indicates if the directory specified in field 3 must be created 
+# first and the archive extracted into it.  It is assigned to the variable
+# MKD_[field1]
+#
+QWT|http://www.bacula.org/depkgs/qwt-5.0.2.tar.bz2|qwt-5.0.2|1
+#
+# Original location
+#
+#QWT|http://superb-west.dl.sourceforge.net/sourceforge/qwt/qwt-5.0.2.tar.bz2|qwt-5.0.2|1
 
 If you want to build it, you need Qt4 loaded and setup as your
 default Qt or with the appropriate Qt Environment variables set.
 
+6/24/07
+There is now one dependancy, it is qwt.  It compiles just fine with
+either qwt-5.0.2 or qwt-5.0.1.  If you run the command 
+
+  ./build-depkgs-qt-console
+
+It should download and run the appropriate commands to build and install qwt
+for you.  The script will download the package into a subdirectory named     
+depkgs. Then it will configure, make and install qwt.  The installation will
+go into a subdirectory named qwt in the main qt-console directory.
+
 To build bat, you simply enter:
 
   qmake
          
 Design decisions:
 - If possible all code for a particular component will be kept in
-  and appropriate subdirectory.
+  an appropriate subdirectory.
 - All private class variables are named "m_xxx" this makes it very
   clear if one is referencing a class variable or a local.
 - All signal/slots are connected by explict code (most all are
 
 ========================================================
 This release or next:
 
-A window showing a list of schedule resources. 
+A page showing a list of schedule resources. 
 
-A list of message resources??
+A page list of message resources??
 
 Kern discussed windows showing statistics like web based interfaces.
 
 Add a status client window.  Keep updating showing what file is being
 processed.
 
+Documentation, Documentation, Documentaion.  Help.  Add help documentation.
+Have context sensitve help.
+
 bRestore add code to get working.
 
 May be in brestore, find a file by name, find a directory by name
 
+Interfaces to commands like bextract, bscan, bcopy, btape?????
+
 Is there a way to query the director/database for whether a storage is currently
 mounted so I am not presenting both mount and unmount to the user??
    Yes, but it requires being able to directly connect to the SD (at least
 
 TARGET = bat
 DEPENDPATH += .
 INCLUDEPATH += . ./console ./restore ./select
-INCLUDEPATH += ..
-LIBS        += -L../lib
+INCLUDEPATH += .. ./qwt/include
+LIBS        += -L../lib            
 LIBS        += -lbac
 LIBS        += -lssl -lcrypto
+LIBS        += -L./qwt/lib -lqwt
 RESOURCES = main.qrc
 MOC_DIR = moc
 OBJECTS_DIR = obj
 FORMS += clients/clients.ui storage/storage.ui fileset/fileset.ui
 FORMS += joblog/joblog.ui jobs/jobs.ui
 FORMS += help/help.ui
+FORMS += jobgraphs/jobplotcontrols.ui
 
 HEADERS += mainwin.h bat.h bat_conf.h qstd.h
 SOURCES += main.cpp bat_conf.cpp mainwin.cpp qstd.cpp
 HEADERS += restore/restoretree.h
 SOURCES += restore/restoretree.cpp
 
+## Job Step Graphs
+HEADERS += jobgraphs/jobplot.h
+SOURCES += jobgraphs/jobplot.cpp
 
 # Help dialog
 HEADERS += help/help.h
 
--- /dev/null
+#!/bin/sh
+#
+#  This file is driven by the parameters that are defined in
+#    the file External-qt-console
+#
+
+usage()
+{
+   echo "usage: $0 [-h] [-C] [<dependency 1>] [<dependency 2>] ..."
+   echo "       -h      Displays this usage"
+   echo "       -C      Clobbers (overwrites) the source code by "
+   echo "               reextracting the archive and reapplying the"
+   echo "               patches."
+   echo ""
+   echo "<dependency N> Optional dependency, If none are given then all"
+   echo "               of them will be built."
+   echo ""
+   echo "Valid dependencies are:"
+   grep -v '^#' < External-qt-console | cut -d'|' -f1 | cut -d'_' -f1 | tr A-Z a-z | sort -u | awk '{ print "        " $1 }'
+}
+
+CLOBBER_SOURCE=
+
+while getopts "hHC" opt; do
+   case ${opt} in
+   H|h|\?) usage;exit 1;;
+   C)      CLOBBER_SOURCE=true;;
+   esac
+done
+
+[ ${OPTIND} -gt 1 ] && shift `expr ${OPTIND} - 1`
+
+cwd=`pwd`
+cd `dirname $0`
+SCRIPT_DIR=`pwd`
+
+TOP_DIR=`pwd`
+
+[ ! -e ${TOP_DIR}/depkgs ] && mkdir ${TOP_DIR}/depkgs
+cd ${TOP_DIR}/depkgs
+DEPPKG_DIR=`pwd`
+
+OLD_IFS=${IFS};IFS="|";
+while read package url dir mkd; do
+   case ${package} in
+   \#*) ;;
+   *) eval "URL_${package}=${url};DIR_${package}=${dir};MKD_${package}=${mkd}";;
+   esac
+done < ${SCRIPT_DIR}/External-qt-console
+IFS=${OLD_IFS};unset OLD_IFS
+
+get_source()
+{
+   URL=$1
+   SRC_DIR=$2
+   MAKE_DIR=$3
+   ARCHIVE=`basename ${URL}`
+echo "in get_source URL is $URL SRC_DIR is $SRC_DIR MAKE_DIR is $MAKE_DIR ARCHIVE is $ARCHIVE"
+        
+   case ${ARCHIVE} in
+   *.tar.gz)       ARCHIVER="tar xzf";    [ -z "${SRC_DIR}" ] && SRC_DIR=`expr "${ARCHIVE}" : '\(.*\)\.tar\.gz'`;;
+   *.tar.bz2)      ARCHIVER="tar xjf";    [ -z "${SRC_DIR}" ] && SRC_DIR=`expr "${ARCHIVE}" : '\(.*\)\.tar\.bz2'`;;
+   *.zip)          ARCHIVER="unzip -q";   [ -z "${SRC_DIR}" ] && SRC_DIR=`expr "${ARCHIVE}" : '\(.*\)\.zip'`;;
+   *.exe)          ARCHIVER="";           [ -z "${SRC_DIR}" ] && SRC_DIR=`expr "${ARCHIVE}" : '\(.*\)\.zip'`;;
+   *)              echo "Unsupported archive type - $ARCHIVE"; exit 1;;
+   esac
+   
+   cd ${DEPPKG_DIR}/src
+   
+   if [ ! -e "${ARCHIVE}" ]
+   then 
+      echo "Downloading ${URL}"
+      if wget --passive-ftp "${URL}"
+      then
+          :
+      else
+         echo "Unable to download ${ARCHIVE}"
+         exit 1
+      fi
+   fi
+
+   [ -z "${ARCHIVER}" ] && return 0
+
+   if [ ! -e "${SRC_DIR}" -o "${CLOBBER_SOURCE}" = "true" ]
+   then
+      rm -rf ${SRC_DIR}
+      echo "Extracting ${ARCHIVE}"
+      if [ "${MAKE_DIR}" = "true" ]
+      then
+         mkdir ${SRC_DIR}
+         cd ${SRC_DIR}
+         ${ARCHIVER} ../${ARCHIVE} > ../${ARCHIVE}.log 2>&1
+      else
+         ${ARCHIVER} ${ARCHIVE} > ${ARCHIVE}.log 2>&1
+         cd ${SRC_DIR}
+      fi
+      return 0
+   fi
+
+   cd ${SRC_DIR}
+   return 1
+}
+
+parse_output()
+{
+   sed -ne '/\\$/N' -e 's/\\\n//' -e 's/\t\+/ /g' -e 's/ \+/ /g' \
+       -e '/ error: /p' \
+       -e "s%.*Entering directory[ ]\\+.${DEPPKG_DIR}/\\([^ ]\+\).%Entering \\1%p" \
+       -e "s%.*Leaving directory[ ]\\+.${DEPPKG_DIR}/\\([^ ]\+.\).%Leaving \\1%p" \
+       -e '/gcc \|g\+\+ \|ar /!d' \
+       -e 's/ \(\.\.\/\)\+/ /g' \
+       -e 's/.* \([^ ]\+\(\.c\|\.cpp\|\.cc\|\.cxx\)\)\( .*\|\)$/Compiling \1/p' \
+       -e 's/.* \([^ ]\+\.s\)\( .*\|\)$/Assembling \1/p' \
+       -e 's/.*ar [^ ]\+ \([^ ]\+\)\(\( [^ ]\+\.o\)\+\)/Updating \1 -\2/p' \
+       -e 's/.* -o \([^ ]\+\)\( .*\|\)$/Linking \1/p'
+}
+
+do_patch()
+{
+   PATCH_FILE=${SCRIPT_DIR}/patches/$1; shift
+   
+   if patch -f -p0 "$@" >>patch.log < ${PATCH_FILE}
+   then
+     :
+   else
+      echo "Patch failed - Check `pwd`/patch.log" > /dev/tty
+      exit 1
+   fi
+}
+
+do_make()
+{
+   if make -f "$@" 2>&1
+   then
+       :
+   else
+      echo "Make failed - Check `pwd`/make.log" > /dev/tty
+      exit 1
+   fi | tee -a make.log #| parse_output
+}
+
+process_qwt()
+{
+   get_source "${URL_QWT}" "${DIR_QWT}" "${MKD_QWT}"
+   echo "Building qwt"
+   echo "${DEPPKG_DIR}"
+   pwd
+   > make.log
+   echo "unix {" >${TOP_DIR}/depkgs/qwt-5.0.2/qwtconfig.pri                    
+   echo " INSTALLBASE = ${TOP_DIR}/qwt" >>${TOP_DIR}/depkgs/qwt-5.0.2/qwtconfig.pri
+   echo "}" >>${TOP_DIR}/depkgs/qwt-5.0.2/qwtconfig.pri
+   cat ${TOP_DIR}/qwtconfig.pri >>${TOP_DIR}/depkgs/qwt-5.0.2/qwtconfig.pri
+   qmake 
+   do_make Makefile
+   echo "Installing" 
+   do_make Makefile install
+}
+
+if [ "$#" -eq 0 ]
+then
+   process_qwt
+else
+   for dependency in "$@"
+   do
+      eval "process_${dependency}"
+   done
+
+fi
 
    QString cmd("reload");
    consoleCommand(cmd);
 }
+
+/* Function to get a list of volumes */
+void Console::getVolumeList(QStringList &volumeList)
+{
+   QString query("SELECT VolumeName AS Media FROM Media ORDER BY Media");
+   if (mainWin->m_sqlDebug) {
+      Pmsg1(000, "Query cmd : %s\n",query.toUtf8().data());
+   }
+   QStringList results;
+   if (sql_cmd(query, results)) {
+      QString field;
+      QStringList fieldlist;
+      /* Iterate through the lines of results. */
+      foreach (QString resultline, results) {
+         fieldlist = resultline.split("\t");
+         volumeList.append(fieldlist[0]);
+      } /* foreach resultline */
+   } /* if results from query */
+}
+
+/* Function to get a list of volumes */
+void Console::getStatusList(QStringList &statusLongList)
+{
+   QString statusQuery("SELECT JobStatusLong FROM Status");
+   if (mainWin->m_sqlDebug) {
+      Pmsg1(000, "Query cmd : %s\n",statusQuery.toUtf8().data());
+   }
+   QStringList statusResults;
+   if (sql_cmd(statusQuery, statusResults)) {
+      QString field;
+      QStringList fieldlist;
+      /* Iterate through the lines of results. */
+      foreach (QString resultline, statusResults) {
+         fieldlist = resultline.split("\t");
+         statusLongList.append(fieldlist[0]);
+      } /* foreach resultline */
+   } /* if results from statusquery */
+}
 
    void getDirResName(QString &);
    void startTimer();
    void stopTimer();
+   void getVolumeList(QStringList &);
+   void getStatusList(QStringList &);
 
    QStringList job_list;
    QStringList client_list;
 
--- /dev/null
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://web.resource.org/cc/"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:xlink="http://www.w3.org/1999/xlink"
+   xmlns:sodipodi="http://inkscape.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   width="48px"
+   height="48px"
+   id="svg1306"
+   sodipodi:version="0.32"
+   inkscape:version="0.43"
+   sodipodi:docbase="/home/dbartley/src/bacula/src/qt-console/images"
+   sodipodi:docname="graph1.svg"
+   inkscape:export-filename="/home/dbartley/src/bacula/src/qt-console/images/graph1.png"
+   inkscape:export-xdpi="60"
+   inkscape:export-ydpi="60">
+  <defs
+     id="defs1308">
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient5060"
+       id="radialGradient5031"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(-2.774389,0,0,1.969706,112.7623,-872.8854)"
+       cx="605.71429"
+       cy="486.64789"
+       fx="605.71429"
+       fy="486.64789"
+       r="117.14286" />
+    <linearGradient
+       inkscape:collect="always"
+       id="linearGradient5060">
+      <stop
+         style="stop-color:black;stop-opacity:1;"
+         offset="0"
+         id="stop5062" />
+      <stop
+         style="stop-color:black;stop-opacity:0;"
+         offset="1"
+         id="stop5064" />
+    </linearGradient>
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient5060"
+       id="radialGradient5029"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(2.774389,0,0,1.969706,-1891.633,-872.8854)"
+       cx="605.71429"
+       cy="486.64789"
+       fx="605.71429"
+       fy="486.64789"
+       r="117.14286" />
+    <linearGradient
+       id="linearGradient5048">
+      <stop
+         style="stop-color:black;stop-opacity:0;"
+         offset="0"
+         id="stop5050" />
+      <stop
+         id="stop5056"
+         offset="0.5"
+         style="stop-color:black;stop-opacity:1;" />
+      <stop
+         style="stop-color:black;stop-opacity:0;"
+         offset="1"
+         id="stop5052" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient5048"
+       id="linearGradient5027"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(2.774389,0,0,1.969706,-1892.179,-872.8854)"
+       x1="302.85715"
+       y1="366.64789"
+       x2="302.85715"
+       y2="609.50507" />
+    <linearGradient
+       inkscape:collect="always"
+       id="linearGradient2223">
+      <stop
+         style="stop-color:#ffffff;stop-opacity:1;"
+         offset="0"
+         id="stop2225" />
+      <stop
+         style="stop-color:#ffffff;stop-opacity:0;"
+         offset="1"
+         id="stop2229" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient2222">
+      <stop
+         style="stop-color:#5187d6;stop-opacity:1;"
+         offset="0"
+         id="stop2224" />
+      <stop
+         style="stop-color:#1e4580;stop-opacity:1;"
+         offset="1"
+         id="stop2227" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient3090">
+      <stop
+         style="stop-color:#626c07;stop-opacity:1;"
+         offset="0"
+         id="stop3092" />
+      <stop
+         style="stop-color:#313603;stop-opacity:1;"
+         offset="1"
+         id="stop3094" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       id="linearGradient2238">
+      <stop
+         style="stop-color:#ffffff;stop-opacity:1;"
+         offset="0"
+         id="stop2240" />
+      <stop
+         style="stop-color:#ffffff;stop-opacity:0;"
+         offset="1"
+         id="stop2242" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient2224">
+      <stop
+         style="stop-color:#32342f;stop-opacity:0.54639173;"
+         offset="0.0000000"
+         id="stop2226" />
+      <stop
+         style="stop-color:#32342f;stop-opacity:0;"
+         offset="1"
+         id="stop2228" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient2214">
+      <stop
+         style="stop-color:#a9aaa7;stop-opacity:1.0000000;"
+         offset="0.0000000"
+         id="stop2216" />
+      <stop
+         style="stop-color:#676964;stop-opacity:1.0000000;"
+         offset="1.0000000"
+         id="stop2218" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient2206">
+      <stop
+         style="stop-color:#c3c6c0;stop-opacity:1.0000000;"
+         offset="0.0000000"
+         id="stop2208" />
+      <stop
+         style="stop-color:#e8eae6;stop-opacity:1.0000000;"
+         offset="1.0000000"
+         id="stop2210" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient2198">
+      <stop
+         style="stop-color:#32342f;stop-opacity:1;"
+         offset="0"
+         id="stop2200" />
+      <stop
+         style="stop-color:#171816;stop-opacity:1.0000000;"
+         offset="1.0000000"
+         id="stop2202" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       id="linearGradient2180">
+      <stop
+         style="stop-color:#ffffff;stop-opacity:1;"
+         offset="0"
+         id="stop2182" />
+      <stop
+         style="stop-color:#ffffff;stop-opacity:0;"
+         offset="1"
+         id="stop2184" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2206"
+       id="linearGradient2212"
+       x1="25.861118"
+       y1="26.133587"
+       x2="18.300278"
+       y2="19.567596"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(0.952387,0.000000,0.000000,1.018339,1.142599,-1.941627)" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2214"
+       id="linearGradient2220"
+       x1="0.0012142062"
+       y1="24.012266"
+       x2="47.998765"
+       y2="24.012266"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(0.952387,0.000000,0.000000,1.018339,1.142599,-1.941627)" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2224"
+       id="radialGradient2230"
+       cx="24.041630"
+       cy="42.242130"
+       fx="24.041630"
+       fy="42.242130"
+       r="17.576654"
+       gradientTransform="matrix(1.000000,0.000000,0.000000,0.304598,-5.757924e-16,29.37527)"
+       gradientUnits="userSpaceOnUse" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2238"
+       id="linearGradient2244"
+       x1="20.338758"
+       y1="19.636894"
+       x2="46.092255"
+       y2="39.708324"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(0.952387,0.000000,0.000000,1.015657,1.142599,-0.876325)" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2180"
+       id="linearGradient1340"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(3.809547,0.000000,0.000000,1.750325,-16.00036,-15.78719)"
+       x1="8.8207808"
+       y1="12.53757"
+       x2="12.499243"
+       y2="24.238262" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2222"
+       id="radialGradient2229"
+       cx="23.994133"
+       cy="32.266911"
+       fx="23.994133"
+       fy="32.266911"
+       r="19.088932"
+       gradientTransform="matrix(2.15837,-3.097402e-23,1.894086e-23,2.190642,-27.7082,-31.42032)"
+       gradientUnits="userSpaceOnUse" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2223"
+       id="linearGradient2231"
+       x1="35.694206"
+       y1="37.333858"
+       x2="15.044075"
+       y2="5.9588566"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(1.021281,0,0,1.303897,-8.127563e-2,-1.256846)" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2180"
+       id="linearGradient1378"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(3.809547,0,0,1.750325,-16.00036,-15.78719)"
+       x1="8.8207808"
+       y1="12.53757"
+       x2="12.499243"
+       y2="24.238262" />
+  </defs>
+  <sodipodi:namedview
+     id="base"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="0.25490196"
+     inkscape:pageopacity="0.0"
+     inkscape:pageshadow="2"
+     inkscape:zoom="11.645833"
+     inkscape:cx="24"
+     inkscape:cy="23.64158"
+     inkscape:current-layer="layer1"
+     showgrid="false"
+     inkscape:grid-bbox="true"
+     inkscape:document-units="px"
+     inkscape:window-width="1064"
+     inkscape:window-height="724"
+     inkscape:window-x="55"
+     inkscape:window-y="0"
+     inkscape:showpageshadow="false"
+     fill="#204a87" />
+  <metadata
+     id="metadata1311">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:title>System Monitor</dc:title>
+        <dc:date>2005-10-10</dc:date>
+        <dc:creator>
+          <cc:Agent>
+            <dc:title>Andreas Nilsson</dc:title>
+          </cc:Agent>
+        </dc:creator>
+        <dc:subject>
+          <rdf:Bag>
+            <rdf:li>system</rdf:li>
+            <rdf:li>monitor</rdf:li>
+            <rdf:li>performance</rdf:li>
+          </rdf:Bag>
+        </dc:subject>
+        <cc:license
+           rdf:resource="http://creativecommons.org/licenses/by-sa/2.0/" />
+        <dc:contributor>
+          <cc:Agent>
+            <dc:title>Jakub Steiner</dc:title>
+          </cc:Agent>
+        </dc:contributor>
+      </cc:Work>
+      <cc:License
+         rdf:about="http://creativecommons.org/licenses/by-sa/2.0/">
+        <cc:permits
+           rdf:resource="http://web.resource.org/cc/Reproduction" />
+        <cc:permits
+           rdf:resource="http://web.resource.org/cc/Distribution" />
+        <cc:requires
+           rdf:resource="http://web.resource.org/cc/Notice" />
+        <cc:requires
+           rdf:resource="http://web.resource.org/cc/Attribution" />
+        <cc:permits
+           rdf:resource="http://web.resource.org/cc/DerivativeWorks" />
+        <cc:requires
+           rdf:resource="http://web.resource.org/cc/ShareAlike" />
+      </cc:License>
+    </rdf:RDF>
+  </metadata>
+  <g
+     id="layer1"
+     inkscape:label="Layer 1"
+     inkscape:groupmode="layer">
+    <rect
+       style="opacity:1;fill:url(#radialGradient2229);fill-opacity:1;fill-rule:evenodd;stroke:#173562;stroke-width:1.38827848;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       id="rect1314"
+       width="45.370602"
+       height="45.727844"
+       x="1.3947006"
+       y="1.3883106"
+       rx="1.6946707"
+       ry="1.694671" />
+    <g
+       id="g1372"
+       transform="matrix(1,0,0,1.49637,0,-5.262305)">
+      <path
+         sodipodi:nodetypes="ccccccccccccccccc"
+         id="path2188"
+         d="M 12.390689,20.935247 L 6.3688614,20.935247 L 6.3688614,22.152253 L 14.087646,22.152253 L 15.493568,16.239132 L 18.956082,29.936652 L 22.164804,19.116952 L 25.059348,25.028755 L 28.946308,21.516786 L 41.654736,21.516786 L 41.654736,19.457141 L 28.505235,19.457141 L 25.335019,22.596741 L 22.059557,15.937588 L 19.049723,24.112486 L 15.78119,11.248712 L 12.390689,20.935247 z "
+         style="opacity:1;fill:#ecffd9;fill-opacity:1;fill-rule:evenodd;stroke:#c3ea9b;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:0.41618497" />
+      <g
+         id="g1366">
+        <path
+           sodipodi:nodetypes="ccccccccccccccccc"
+           id="path3088"
+           d="M 11.515689,20.012278 L 6.3688614,20.012278 L 6.3688614,23.061029 L 14.962646,22.936029 L 15.618568,19.893387 L 18.963229,32.601726 L 22.539804,21.135091 L 25.059348,26.551191 L 29.321308,22.442609 L 41.654736,22.317609 L 40.904736,18.408071 L 28.505235,18.283071 L 25.460019,21.456026 L 22.059557,13.665616 L 19.424723,20.604266 L 15.90619,8.333659 L 11.515689,20.012278 z "
+           style="opacity:0.38068183;fill:#ecffd9;fill-opacity:1;fill-rule:evenodd;stroke:#c3ea9b;stroke-width:1.00000036;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.41618497" />
+        <path
+           style="opacity:0.43181817;fill:url(#linearGradient1378);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+           d="M 6.84375,6.96875 L 6.84375,15.795073 C 10.513653,16.483179 14.582567,16.875 18.875,16.875 C 27.810295,16.875 35.812258,15.21019 41.15625,12.596829 L 41.15625,6.96875 L 6.84375,6.96875 z "
+           id="rect2178"
+           sodipodi:nodetypes="ccsccc" />
+      </g>
+    </g>
+    <rect
+       ry="2.5696716"
+       rx="2.5696716"
+       y="4.7877154"
+       x="4.3298464"
+       height="39.959457"
+       width="40.187263"
+       id="rect2221"
+       style="opacity:0.57386361;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient2231);stroke-width:1.15396917;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
+  </g>
+</svg>
 
--- /dev/null
+/*
+   Bacula® - The Network Backup Solution
+
+   Copyright (C) 2000-2007 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 John Walker.
+   The licensor of Bacula is the Free Software Foundation Europe
+   (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
+   Switzerland, email:ftf@fsfeurope.org.
+*/
+ 
+/*
+ *   Version $Id: jobplot.cpp 4230 2007-02-21 20:07:37Z kerns $
+ *
+ *  JobPlots Class
+ *
+ *   Dirk Bartley, March 2007
+ *
+ */ 
+
+#include <QtGui>
+#include "bat.h"
+#include "jobgraphs/jobplot.h"
+
+
+JobPlotPass::JobPlotPass()
+{
+   use = false;
+}
+
+JobPlotPass& JobPlotPass::operator=(const JobPlotPass &cp)
+{
+   use = cp.use;
+   recordLimitCheck = cp.recordLimitCheck;
+   daysLimitCheck = cp.daysLimitCheck;
+   recordLimitSpin = cp.recordLimitSpin;
+   daysLimitSpin = cp.daysLimitSpin;
+   jobCombo = cp.jobCombo;
+   clientCombo = cp.clientCombo;
+   volumeCombo = cp.volumeCombo;
+   fileSetCombo = cp.fileSetCombo;
+   purgedCombo = cp.purgedCombo;
+   levelCombo = cp.levelCombo;
+   statusCombo = cp.statusCombo;
+   return *this;
+}
+
+/*
+ * Constructor for the controls class which inherits QScrollArea and a ui header
+ */
+JobPlotControls::JobPlotControls()
+{
+   setupUi(this);
+}
+
+/*
+ * Constructor, this class does not inherit anything but pages.
+ */
+JobPlot::JobPlot(QTreeWidgetItem *parentTreeWidgetItem, JobPlotPass &passVals)
+{
+   setupUserInterface();
+   m_name = "Job Plot";
+   pgInitialize(parentTreeWidgetItem);
+   readSplitterSettings();
+   QTreeWidgetItem* thisitem = mainWin->getFromHash(this);
+   thisitem->setIcon(0,QIcon(QString::fromUtf8(":images/graph1.png")));
+   m_drawn = false;
+
+   /* this invokes the pass values = operator function */
+   m_pass = passVals;
+   m_closeable = true;
+   dockPage();
+   /* If the values of the controls are predetermined (from joblist), then set
+    * this class as current window at the front of the stack */
+   if (m_pass.use)
+      setCurrent();
+   m_jobPlot->replot();
+}
+
+/*
+ * Kill, crush Destroy
+ */
+JobPlot::~JobPlot()
+{
+   writeSettings();
+   m_pjd.clear();
+}
+
+/*
+ * This is called when the page selector has this page selected
+ */
+void JobPlot::currentStackItem()
+{
+   if (!m_drawn) {
+      setupControls();
+      reGraph();
+      m_drawn=true;
+   }
+
+}
+
+/*
+ * Slot for the refrehs push button, also called from constructor.
+ */
+void JobPlot::reGraph()
+{
+   /* clear m_pjd */
+   m_pjd.clear();
+   runQuery();
+   m_jobPlot->clear();
+   addCurve();
+   m_jobPlot->replot();
+}
+
+/*
+ * Setup the control widgets for the graph, this are the objects from JobPlotControls
+ */
+void JobPlot::setupControls()
+{
+   QStringList graphType = QStringList() << /* "Fitted" <<*/ "Sticks" << "Lines" << "Steps" << "None";
+   controls->plotTypeCombo->addItems(graphType);
+   QStringList symbolType = QStringList() << "Ellipse" << "Rect" << "Diamond" << "Triangle"
+            << "DTrianle" << "UTriangle" << "LTriangle" << "RTriangle" << "Cross" << "XCross"
+            << "HLine" << "Vline" << "Star1" << "Star2" << "Hexagon" << "None";
+   controls->fileSymbolTypeCombo->addItems(symbolType);
+   controls->byteSymbolTypeCombo->addItems(symbolType);
+   readControlSettings();
+
+   controls->fileCheck->setCheckState(Qt::Checked);
+   controls->byteCheck->setCheckState(Qt::Checked);
+   connect(controls->plotTypeCombo, SIGNAL(currentIndexChanged(QString)), this, SLOT(setPlotType(QString)));
+   connect(controls->fileSymbolTypeCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(setFileSymbolType(int)));
+   connect(controls->byteSymbolTypeCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(setByteSymbolType(int)));
+   connect(controls->fileCheck, SIGNAL(stateChanged(int)), this, SLOT(fileCheckChanged(int)));
+   connect(controls->byteCheck, SIGNAL(stateChanged(int)), this, SLOT(byteCheckChanged(int)));
+   connect(controls->refreshButton, SIGNAL(pressed()), this, SLOT(reGraph()));
+
+   controls->clientComboBox->addItem("Any");
+   controls->clientComboBox->addItems(m_console->client_list);
+
+   QStringList volumeList;
+   m_console->getVolumeList(volumeList);
+   controls->volumeComboBox->addItem("Any");
+   controls->volumeComboBox->addItems(volumeList);
+   controls->jobComboBox->addItem("Any");
+   controls->jobComboBox->addItems(m_console->job_list);
+   controls->levelComboBox->addItem("Any");
+   controls->levelComboBox->addItems( QStringList() << "F" << "D" << "I");
+   controls->purgedComboBox->addItem("Any");
+   controls->purgedComboBox->addItems( QStringList() << "0" << "1");
+   controls->fileSetComboBox->addItem("Any");
+   controls->fileSetComboBox->addItems(m_console->fileset_list);
+   QStringList statusLongList;
+   m_console->getStatusList(statusLongList);
+   controls->statusComboBox->addItem("Any");
+   controls->statusComboBox->addItems(statusLongList);
+
+   if (m_pass.use) {
+      controls->limitCheckBox->setCheckState(m_pass.recordLimitCheck);
+      controls->limitSpinBox->setValue(m_pass.recordLimitSpin);
+      controls->daysCheckBox->setCheckState(m_pass.daysLimitCheck);
+      controls->daysSpinBox->setValue(m_pass.daysLimitSpin);
+      int jobIndex = controls->jobComboBox->findText(m_pass.jobCombo, Qt::MatchExactly); 
+      if (jobIndex != -1)
+         controls->jobComboBox->setCurrentIndex(jobIndex);
+      int clientIndex = controls->clientComboBox->findText(m_pass.clientCombo, Qt::MatchExactly);
+      if (clientIndex != -1)
+         controls->clientComboBox->setCurrentIndex(clientIndex);
+      int volumeIndex = controls->volumeComboBox->findText(m_pass.volumeCombo, Qt::MatchExactly);
+      if (volumeIndex != -1)
+         controls->volumeComboBox->setCurrentIndex(volumeIndex);
+      int filesetIndex = controls->fileSetComboBox->findText(m_pass.fileSetCombo, Qt::MatchExactly);
+      if (filesetIndex != -1)
+         controls->fileSetComboBox->setCurrentIndex(filesetIndex);
+      int purgedIndex = controls->purgedComboBox->findText(m_pass.purgedCombo, Qt::MatchExactly); 
+      if (purgedIndex != -1)
+         controls->purgedComboBox->setCurrentIndex(purgedIndex);
+      int levelIndex = controls->levelComboBox->findText(m_pass.levelCombo, Qt::MatchExactly); 
+      if (levelIndex != -1)
+         controls->levelComboBox->setCurrentIndex(levelIndex);
+      int statusIndex = controls->statusComboBox->findText(m_pass.statusCombo, Qt::MatchExactly); 
+      if (statusIndex != -1)
+         controls->statusComboBox->setCurrentIndex(statusIndex);
+   } else {
+      /* Set Defaults for check and spin for limits */
+      controls->limitCheckBox->setCheckState(mainWin->m_recordLimitCheck ? Qt::Checked : Qt::Unchecked);
+      controls->limitSpinBox->setValue(mainWin->m_recordLimitVal);
+      controls->daysCheckBox->setCheckState(mainWin->m_daysLimitCheck ? Qt::Checked : Qt::Unchecked);
+      controls->daysSpinBox->setValue(mainWin->m_daysLimitVal);
+   } 
+}
+
+/*
+ * Setup the control widgets for the graph, this are the objects from JobPlotControls
+ */
+void JobPlot::runQuery()
+{
+   /* Set up query */
+   QString query("");
+   query += "SELECT DISTINCT "
+            " Job.Starttime AS JobStart,"
+            " Job.Jobfiles AS FileCount,"
+            " Job.JobBytes AS Bytes,"
+            " Job.JobId AS JobId"
+            " FROM Job"
+            " LEFT OUTER JOIN Client ON (Client.ClientId=Job.ClientId)"
+            " LEFT OUTER JOIN FileSet ON (FileSet.FileSetId=Job.FileSetId)"
+            " LEFT OUTER JOIN Status ON (Job.JobStatus=Status.JobStatus)"
+            " LEFT OUTER JOIN JobMedia ON (JobMedia.JobId=Job.JobId)"
+            " LEFT OUTER JOIN Media ON (JobMedia.MediaId=Media.MediaId)";
+   QStringList conditions;
+   int jobIndex = controls->jobComboBox->currentIndex();
+   if ((jobIndex != -1) && (controls->jobComboBox->itemText(jobIndex) != "Any"))
+      conditions.append("Job.Name='" + controls->jobComboBox->itemText(jobIndex) + "'");
+   int clientIndex = controls->clientComboBox->currentIndex();
+   if ((clientIndex != -1) && (controls->clientComboBox->itemText(clientIndex) != "Any"))
+      conditions.append("Client.Name='" + controls->clientComboBox->itemText(clientIndex) + "'");
+   int volumeIndex = controls->volumeComboBox->currentIndex();
+   if ((volumeIndex != -1) && (controls->volumeComboBox->itemText(volumeIndex) != "Any"))
+      conditions.append("Media.VolumeName='" + controls->volumeComboBox->itemText(volumeIndex) + "'");
+   int fileSetIndex = controls->fileSetComboBox->currentIndex();
+   if ((fileSetIndex != -1) && (controls->fileSetComboBox->itemText(fileSetIndex) != "Any"))
+      conditions.append("FileSet.FileSet='" + controls->fileSetComboBox->itemText(fileSetIndex) + "'");
+   int purgedIndex = controls->purgedComboBox->currentIndex();
+   if ((purgedIndex != -1) && (controls->purgedComboBox->itemText(purgedIndex) != "Any"))
+      conditions.append("Job.PurgedFiles='" + controls->purgedComboBox->itemText(purgedIndex) + "'");
+   int levelIndex = controls->levelComboBox->currentIndex();
+   if ((levelIndex != -1) && (controls->levelComboBox->itemText(levelIndex) != "Any"))
+      conditions.append("Job.Level='" + controls->levelComboBox->itemText(levelIndex) + "'");
+   int statusIndex = controls->statusComboBox->currentIndex();
+   if ((statusIndex != -1) && (controls->statusComboBox->itemText(statusIndex) != "Any"))
+      conditions.append("Status.JobStatusLong='" + controls->statusComboBox->itemText(statusIndex) + "'");
+   /* If Limit check box For limit by days is checked  */
+   if (controls->daysCheckBox->checkState() == Qt::Checked) {
+      QDateTime stamp = QDateTime::currentDateTime().addDays(-controls->daysSpinBox->value());
+      QString since = stamp.toString(Qt::ISODate);
+      conditions.append("Job.Starttime>'" + since + "'");
+   }
+   bool first = true;
+   foreach (QString condition, conditions) {
+      if (first) {
+         query += " WHERE " + condition;
+         first = false;
+      } else {
+         query += " AND " + condition;
+      }
+   }
+   /* Descending */
+   query += " ORDER BY Job.Starttime DESC, Job.JobId DESC";
+   /* If Limit check box for limit records returned is checked  */
+   if (controls->limitCheckBox->checkState() == Qt::Checked) {
+      QString limit;
+      limit.setNum(controls->limitSpinBox->value());
+      query += " LIMIT " + limit;
+   }
+
+   if (mainWin->m_sqlDebug) {
+      Pmsg1(000, "Query cmd : %s\n",query.toUtf8().data());
+   }
+   QString resultline;
+   QStringList results;
+   if (m_console->sql_cmd(query, results)) {
+
+      QString field;
+      QStringList fieldlist;
+   
+      int row = 0;
+      /* Iterate through the record returned from the query */
+      foreach (resultline, results) {
+         PlotJobData *plotJobData = new PlotJobData();
+         fieldlist = resultline.split("\t");
+         int column = 0;
+         QString statusCode("");
+         /* Iterate through fields in the record */
+         foreach (field, fieldlist) {
+            field = field.trimmed();  /* strip leading & trailing spaces */
+            if (column == 0) {
+               plotJobData->dt = QDateTime::fromString(field, mainWin->m_dtformat);
+            } else if (column == 1) {
+               plotJobData->files = field.toDouble();
+            } else if (column == 2) {
+               plotJobData->bytes = field.toDouble();
+            }
+            column++;
+            m_pjd.prepend(plotJobData);
+         }
+         row++;
+      }
+   } 
+   if ((controls->volumeComboBox->itemText(volumeIndex) != "Any") && (results.count() == 0)){
+      /* for context sensitive searches, let the user know if there were no
+       *        * results */
+      QMessageBox::warning(this, tr("Bat"),
+          tr("The Jobs query returned no results.\n"
+         "Press OK to continue?"), QMessageBox::Ok );
+   }
+}
+
+/*
+ * The user interface that used to be in the ui header.  I wanted to have a
+ * scroll area which is not in designer.
+ */
+void JobPlot::setupUserInterface()
+{
+   QSizePolicy sizePolicy(static_cast<QSizePolicy::Policy>(1), static_cast<QSizePolicy::Policy>(5));
+   sizePolicy.setHorizontalStretch(0);
+   sizePolicy.setVerticalStretch(0);
+   sizePolicy.setVerticalStretch(0);
+   sizePolicy.setVerticalPolicy(QSizePolicy::Ignored);
+   sizePolicy.setHorizontalPolicy(QSizePolicy::Ignored);
+   m_gridLayout = new QGridLayout(this);
+   m_gridLayout->setSpacing(6);
+   m_gridLayout->setMargin(9);
+   m_gridLayout->setObjectName(QString::fromUtf8("m_gridLayout"));
+   m_splitter = new QSplitter(this);
+   m_splitter->setObjectName(QString::fromUtf8("m_splitter"));
+   m_splitter->setOrientation(Qt::Horizontal);
+   m_jobPlot = new QwtPlot(m_splitter);
+   m_jobPlot->setObjectName(QString::fromUtf8("m_jobPlot"));
+   m_jobPlot->setSizePolicy(sizePolicy);
+   m_jobPlot->setMinimumSize(QSize(0, 0));
+   QScrollArea *area = new QScrollArea(m_splitter);
+   area->setObjectName(QString::fromUtf8("area"));
+   controls = new JobPlotControls();
+   area->setWidget(controls);
+   
+   m_splitter->addWidget(m_jobPlot);
+   m_splitter->addWidget(area);
+
+   m_gridLayout->addWidget(m_splitter, 0, 0, 1, 1);
+}
+
+/*
+ * Add the curves to the plot
+ */
+void JobPlot::addCurve()
+{
+   m_jobPlot->setTitle("Files and Bytes backed up");
+   m_jobPlot->insertLegend(new QwtLegend(), QwtPlot::RightLegend);
+
+   // Set axis titles
+   m_jobPlot->enableAxis(QwtPlot::yRight);
+   m_jobPlot->setAxisTitle(QwtPlot::yRight, "<-- Bytes Kb");
+   m_jobPlot->setAxisTitle(m_jobPlot->xBottom, "date of backup -->");
+   m_jobPlot->setAxisTitle(m_jobPlot->yLeft, "Number of Files -->");
+   m_jobPlot->setAxisScaleDraw(QwtPlot::xBottom, new DateTimeScaleDraw());
+
+   // Insert new curves
+   m_fileCurve = new QwtPlotCurve("Files");
+   m_fileCurve->setPen(QPen(Qt::red));
+   m_fileCurve->setCurveType(m_fileCurve->Yfx);
+   m_fileCurve->setYAxis(QwtPlot::yLeft);
+
+   m_byteCurve = new QwtPlotCurve("Bytes");
+   m_byteCurve->setPen(QPen(Qt::blue));
+   m_byteCurve->setCurveType(m_byteCurve->Yfx);
+   m_byteCurve->setYAxis(QwtPlot::yRight);
+   setPlotType(controls->plotTypeCombo->currentText());
+   setFileSymbolType(controls->fileSymbolTypeCombo->currentIndex());
+   setByteSymbolType(controls->byteSymbolTypeCombo->currentIndex());
+
+   m_fileCurve->attach(m_jobPlot);
+   m_byteCurve->attach(m_jobPlot);
+
+   // attach data
+   int size = m_pjd.count();
+   double tval[size];
+   double fval[size];
+   double bval[size];
+   int j = 0;
+   foreach (PlotJobData* plotJobData, m_pjd) {
+//      printf("%.0f %.0f %s\n", plotJobData->bytes, plotJobData->files,
+//              plotJobData->dt.toString(mainWin->m_dtformat).toUtf8().data());
+      fval[j] = plotJobData->files;
+      bval[j] = plotJobData->bytes / 1024;
+      tval[j] = plotJobData->dt.toTime_t();
+//      printf("%i %.0f %.0f %.0f\n", j, tval[j], fval[j], bval[j]);
+      j++;
+   }
+   m_fileCurve->setData(tval,fval,size);
+   m_byteCurve->setData(tval,bval,size);
+
+   for (int year=2000; year<2010; year++) {
+      for (int month=1; month<=12; month++) {
+         QString monthBegin;
+         if (month > 9) {
+            QTextStream(&monthBegin) << year << "-" << month << "-01 00:00:00";
+         } else {
+            QTextStream(&monthBegin) << year << "-0" << month << "-01 00:00:00";
+         }
+         QDateTime mdt = QDateTime::fromString(monthBegin, mainWin->m_dtformat);
+         double monbeg = mdt.toTime_t();
+   
+         //  ...a vertical line at the first of each month
+         QwtPlotMarker *mX = new QwtPlotMarker();
+         mX->setLabel(mdt.toString("MMM-d"));
+         mX->setLabelAlignment(Qt::AlignRight|Qt::AlignTop);
+         mX->setLineStyle(QwtPlotMarker::VLine);
+         QPen pen(Qt::darkGray);
+         pen.setStyle(Qt::DashDotDotLine);
+         mX->setLinePen(pen);
+         mX->setXValue(monbeg);
+         mX->attach(m_jobPlot);
+      }
+   }
+}
+
+/*
+ * slot to respond to the plot type combo changing
+ */
+void JobPlot::setPlotType(QString currentText)
+{
+   QwtPlotCurve::CurveStyle style;
+   if (currentText == "Fitted") {
+      style = QwtPlotCurve::Lines;
+      m_fileCurve->setCurveAttribute(QwtPlotCurve::Fitted);
+      m_byteCurve->setCurveAttribute(QwtPlotCurve::Fitted);
+   } else if (currentText == "Sticks") {
+      style = QwtPlotCurve::Sticks;
+   } else if (currentText == "Lines") {
+      style = QwtPlotCurve::Lines;
+      m_fileCurve->setCurveAttribute(QwtPlotCurve::Fitted);
+      m_byteCurve->setCurveAttribute(QwtPlotCurve::Fitted);
+   } else if (currentText == "Steps") {
+      style = QwtPlotCurve::Steps;
+   } else if (currentText == "None") {
+      style = QwtPlotCurve::NoCurve;
+   }
+   m_fileCurve->setStyle(style);
+   m_byteCurve->setStyle(style);
+   m_jobPlot->replot();
+}
+
+/*
+ * slot to respond to the symbol type combo changing
+ */
+void JobPlot::setFileSymbolType(int index)
+{
+   setSymbolType(index, 0);
+}
+
+void JobPlot::setByteSymbolType(int index)
+{
+   setSymbolType(index, 1);
+}
+void JobPlot::setSymbolType(int index, int type)
+{
+   QwtSymbol sym;
+   sym.setPen(QColor(Qt::black));
+   sym.setSize(7);
+   if (index == 0) {
+      sym.setStyle(QwtSymbol::Ellipse);
+   } else if (index == 1) {
+      sym.setStyle(QwtSymbol::Rect);
+   } else if (index == 2) {
+      sym.setStyle(QwtSymbol::Diamond);
+   } else if (index == 3) {
+      sym.setStyle(QwtSymbol::Triangle);
+   } else if (index == 4) {
+      sym.setStyle(QwtSymbol::DTriangle);
+   } else if (index == 5) {
+      sym.setStyle(QwtSymbol::UTriangle);
+   } else if (index == 6) {
+      sym.setStyle(QwtSymbol::LTriangle);
+   } else if (index == 7) {
+      sym.setStyle(QwtSymbol::RTriangle);
+   } else if (index == 8) {
+      sym.setStyle(QwtSymbol::Cross);
+   } else if (index == 9) {
+      sym.setStyle(QwtSymbol::XCross);
+   } else if (index == 10) {
+      sym.setStyle(QwtSymbol::HLine);
+   } else if (index == 11) {
+      sym.setStyle(QwtSymbol::VLine);
+   } else if (index == 12) {
+      sym.setStyle(QwtSymbol::Star1);
+   } else if (index == 13) {
+      sym.setStyle(QwtSymbol::Star2);
+   } else if (index == 14) {
+      sym.setStyle(QwtSymbol::Hexagon);
+   }
+   if (type == 0) {
+      sym.setBrush(QColor(Qt::yellow));
+      m_fileCurve->setSymbol(sym);
+   }
+   if (type == 1) {
+      sym.setBrush(QColor(Qt::blue));
+      m_byteCurve->setSymbol(sym);
+   }
+   m_jobPlot->replot();
+}
+
+/*
+ * slot to respond to the file check box changing state
+ */
+void JobPlot::fileCheckChanged(int newstate)
+{
+   if (newstate == Qt::Unchecked) {
+      m_fileCurve->detach();
+      m_jobPlot->enableAxis(QwtPlot::yLeft, false);
+   } else {
+      m_fileCurve->attach(m_jobPlot);
+      m_jobPlot->enableAxis(QwtPlot::yLeft);
+   }
+   m_jobPlot->replot();
+}
+
+/*
+ * slot to respond to the byte check box changing state
+ */
+void JobPlot::byteCheckChanged(int newstate)
+{
+   if (newstate == Qt::Unchecked) {
+      m_byteCurve->detach();
+      m_jobPlot->enableAxis(QwtPlot::yRight, false);
+   } else {
+      m_byteCurve->attach(m_jobPlot);
+      m_jobPlot->enableAxis(QwtPlot::yRight);
+   }
+   m_jobPlot->replot();
+}
+
+/*
+ * Save user settings associated with this page
+ */
+void JobPlot::writeSettings()
+{
+   QSettings settings(m_console->m_dir->name(), "bat");
+   settings.beginGroup("JobPlot");
+   settings.setValue("m_splitterSizes", m_splitter->saveState());
+   settings.setValue("fileSymbolTypeCombo", controls->fileSymbolTypeCombo->currentText());
+   settings.setValue("byteSymbolTypeCombo", controls->byteSymbolTypeCombo->currentText());
+   settings.setValue("plotTypeCombo", controls->plotTypeCombo->currentText());
+   settings.endGroup();
+}
+
+/* 
+ * Read settings values for Controls
+ */
+void JobPlot::readControlSettings()
+{
+   QSettings settings(m_console->m_dir->name(), "bat");
+   settings.beginGroup("JobPlot");
+   int fileSymbolTypeIndex = controls->fileSymbolTypeCombo->findText(settings.value("fileSymbolTypeCombo").toString(), Qt::MatchExactly);
+   if (fileSymbolTypeIndex == -1) fileSymbolTypeIndex = 2;
+      controls->fileSymbolTypeCombo->setCurrentIndex(fileSymbolTypeIndex);
+   int byteSymbolTypeIndex = controls->byteSymbolTypeCombo->findText(settings.value("byteSymbolTypeCombo").toString(), Qt::MatchExactly);
+   if (byteSymbolTypeIndex == -1) byteSymbolTypeIndex = 3;
+      controls->byteSymbolTypeCombo->setCurrentIndex(byteSymbolTypeIndex);
+   int plotTypeIndex = controls->plotTypeCombo->findText(settings.value("plotTypeCombo").toString(), Qt::MatchExactly);
+   if (plotTypeIndex == -1) plotTypeIndex = 2;
+      controls->plotTypeCombo->setCurrentIndex(plotTypeIndex);
+   settings.endGroup();
+}
+
+/*
+ * Read and restore user settings associated with this page
+ */
+void JobPlot::readSplitterSettings()
+{
+   QSettings settings(m_console->m_dir->name(), "bat");
+   settings.beginGroup("JobPlot");
+   m_splitter->restoreState(settings.value("m_splitterSizes").toByteArray());
+   settings.endGroup();
+}
 
--- /dev/null
+#ifndef _JOBPLOT_H_
+#define _JOBPLOT_H_
+/*
+   Bacula® - The Network Backup Solution
+
+   Copyright (C) 2000-2007 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 John Walker.
+   The licensor of Bacula is the Free Software Foundation Europe
+   (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
+   Switzerland, email:ftf@fsfeurope.org.
+*/
+/*
+ *   Version $Id: jobstep.h 4992 2007-06-07 14:46:43Z kerns $
+ *
+ *   Dirk Bartley, March 2007
+ */
+
+#include <QtGui>
+#include "pages.h"
+#include "ui_jobplotcontrols.h"
+#include <qwt_data.h>
+#include <qwt_legend.h>
+#include <qwt_plot_curve.h>
+#include <qwt_plot.h>
+#include <qwt_plot_marker.h>
+#include <qwt_plot_curve.h>
+#include <qwt_symbol.h>
+#include <qwt_scale_map.h>
+#include <qwt_scale_draw.h>
+#include <qwt_text.h>
+
+/*
+ * Structure to hold data items of jobs when and how much.
+ * If I worked at it I could eliminate this.  It's just the way it evolved.
+ */
+struct PlotJobData
+{
+   double files;
+   double bytes;
+   QDateTime dt;
+};
+
+/*
+ * Class for the purpose of having a single object to pass data to the JobPlot
+ * Constructor.  The other option was a constructor with this many passed 
+ * values or some sort of code to parse a list.  I liked this best at the time.
+ */
+class JobPlotPass
+{
+public:
+   JobPlotPass();
+   JobPlotPass& operator=(const JobPlotPass&);
+   bool use;
+   Qt::CheckState recordLimitCheck;
+   Qt::CheckState daysLimitCheck;
+   int recordLimitSpin;
+   int daysLimitSpin;
+   QString jobCombo;
+   QString clientCombo;
+   QString volumeCombo;
+   QString fileSetCombo;
+   QString purgedCombo;
+   QString levelCombo;
+   QString statusCombo;
+};
+
+/*
+ *Class to Change the display of the time scale to display dates.
+ */
+class DateTimeScaleDraw : public QwtScaleDraw
+{
+public:
+   virtual QwtText label(double v) const
+   {
+      QDateTime dtlabel(QDateTime::fromTime_t((uint)v));
+      return dtlabel.toString("M-d-yy");
+   }
+};
+
+/*
+ * These are the user interface control widgets as a separate class.
+ * Separately for the purpos of having the controls in a Scroll Area.
+ */
+class JobPlotControls : public QWidget, public Ui::JobPlotControlsForm
+{
+   Q_OBJECT
+
+public:
+   JobPlotControls();
+};
+
+/*
+ * The main class
+ */
+class JobPlot : public Pages
+{
+   Q_OBJECT 
+
+public:
+   JobPlot(QTreeWidgetItem *parentTreeWidgetItem, JobPlotPass &);
+   ~JobPlot();
+   virtual void currentStackItem();
+
+private slots:
+   void setPlotType(QString);
+   void setFileSymbolType(int);
+   void setByteSymbolType(int);
+   void fileCheckChanged(int);
+   void byteCheckChanged(int);
+   void reGraph();
+
+private:
+   void setSymbolType(int, int type);
+   void addCurve();
+   void writeSettings();
+   void readSplitterSettings();
+   void readControlSettings();
+   void setupControls();
+   void runQuery();
+   bool m_drawn;
+   JobPlotPass m_pass;
+   JobPlotControls* controls;
+   QList<PlotJobData *> m_pjd;
+   QwtPlotCurve *m_fileCurve;
+   QwtPlotCurve *m_byteCurve;
+   /* from the user interface before using scroll area */
+   void setupUserInterface();
+   QGridLayout *m_gridLayout;
+   QSplitter *m_splitter;
+   QwtPlot *m_jobPlot;
+};
+
+#endif /* _JOBPLOT_H_ */
 
--- /dev/null
+<ui version="4.0" >
+ <class>JobPlotControlsForm</class>
+ <widget class="QWidget" name="JobPlotControlsForm" >
+  <property name="geometry" >
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>254</width>
+    <height>422</height>
+   </rect>
+  </property>
+  <property name="sizePolicy" >
+   <sizepolicy>
+    <hsizetype>5</hsizetype>
+    <vsizetype>0</vsizetype>
+    <horstretch>0</horstretch>
+    <verstretch>0</verstretch>
+   </sizepolicy>
+  </property>
+  <property name="minimumSize" >
+   <size>
+    <width>0</width>
+    <height>0</height>
+   </size>
+  </property>
+  <property name="windowTitle" >
+   <string>Form</string>
+  </property>
+  <layout class="QGridLayout" >
+   <property name="margin" >
+    <number>9</number>
+   </property>
+   <property name="spacing" >
+    <number>6</number>
+   </property>
+   <item row="14" column="0" colspan="2" >
+    <spacer>
+     <property name="orientation" >
+      <enum>Qt::Vertical</enum>
+     </property>
+     <property name="sizeHint" >
+      <size>
+       <width>236</width>
+       <height>16</height>
+      </size>
+     </property>
+    </spacer>
+   </item>
+   <item row="0" column="0" colspan="2" >
+    <layout class="QHBoxLayout" >
+     <property name="margin" >
+      <number>0</number>
+     </property>
+     <property name="spacing" >
+      <number>6</number>
+     </property>
+     <item>
+      <spacer>
+       <property name="orientation" >
+        <enum>Qt::Horizontal</enum>
+       </property>
+       <property name="sizeHint" >
+        <size>
+         <width>21</width>
+         <height>20</height>
+        </size>
+       </property>
+      </spacer>
+     </item>
+     <item>
+      <layout class="QVBoxLayout" >
+       <property name="margin" >
+        <number>0</number>
+       </property>
+       <property name="spacing" >
+        <number>6</number>
+       </property>
+       <item>
+        <widget class="QCheckBox" name="fileCheck" >
+         <property name="text" >
+          <string>File Data</string>
+         </property>
+        </widget>
+       </item>
+       <item>
+        <widget class="QCheckBox" name="byteCheck" >
+         <property name="text" >
+          <string>By te Data</string>
+         </property>
+        </widget>
+       </item>
+      </layout>
+     </item>
+     <item>
+      <spacer>
+       <property name="orientation" >
+        <enum>Qt::Horizontal</enum>
+       </property>
+       <property name="sizeHint" >
+        <size>
+         <width>21</width>
+         <height>20</height>
+        </size>
+       </property>
+      </spacer>
+     </item>
+    </layout>
+   </item>
+   <item row="13" column="0" colspan="2" >
+    <layout class="QHBoxLayout" >
+     <property name="margin" >
+      <number>0</number>
+     </property>
+     <property name="spacing" >
+      <number>6</number>
+     </property>
+     <item>
+      <spacer>
+       <property name="orientation" >
+        <enum>Qt::Horizontal</enum>
+       </property>
+       <property name="sizeHint" >
+        <size>
+         <width>40</width>
+         <height>20</height>
+        </size>
+       </property>
+      </spacer>
+     </item>
+     <item>
+      <widget class="QPushButton" name="refreshButton" >
+       <property name="maximumSize" >
+        <size>
+         <width>65</width>
+         <height>20</height>
+        </size>
+       </property>
+       <property name="text" >
+        <string>Refresh</string>
+       </property>
+       <property name="icon" >
+        <iconset resource="../main.qrc" >:/images/view-refresh.svg</iconset>
+       </property>
+      </widget>
+     </item>
+     <item>
+      <spacer>
+       <property name="orientation" >
+        <enum>Qt::Horizontal</enum>
+       </property>
+       <property name="sizeHint" >
+        <size>
+         <width>40</width>
+         <height>20</height>
+        </size>
+       </property>
+      </spacer>
+     </item>
+    </layout>
+   </item>
+   <item row="9" column="1" >
+    <widget class="QComboBox" name="fileSetComboBox" />
+   </item>
+   <item row="10" column="1" >
+    <widget class="QComboBox" name="purgedComboBox" />
+   </item>
+   <item row="8" column="1" >
+    <widget class="QComboBox" name="volumeComboBox" />
+   </item>
+   <item row="7" column="1" >
+    <widget class="QComboBox" name="clientComboBox" />
+   </item>
+   <item row="11" column="1" >
+    <widget class="QComboBox" name="levelComboBox" />
+   </item>
+   <item row="12" column="1" >
+    <widget class="QComboBox" name="statusComboBox" />
+   </item>
+   <item row="6" column="1" >
+    <widget class="QComboBox" name="jobComboBox" />
+   </item>
+   <item row="1" column="1" >
+    <widget class="QComboBox" name="plotTypeCombo" />
+   </item>
+   <item row="5" column="1" >
+    <widget class="QSpinBox" name="daysSpinBox" >
+     <property name="sizePolicy" >
+      <sizepolicy>
+       <hsizetype>5</hsizetype>
+       <vsizetype>0</vsizetype>
+       <horstretch>0</horstretch>
+       <verstretch>0</verstretch>
+      </sizepolicy>
+     </property>
+     <property name="singleStep" >
+      <number>7</number>
+     </property>
+    </widget>
+   </item>
+   <item row="4" column="1" >
+    <widget class="QSpinBox" name="limitSpinBox" >
+     <property name="sizePolicy" >
+      <sizepolicy>
+       <hsizetype>5</hsizetype>
+       <vsizetype>0</vsizetype>
+       <horstretch>0</horstretch>
+       <verstretch>0</verstretch>
+      </sizepolicy>
+     </property>
+     <property name="maximum" >
+      <number>10000</number>
+     </property>
+     <property name="minimum" >
+      <number>1</number>
+     </property>
+     <property name="singleStep" >
+      <number>25</number>
+     </property>
+    </widget>
+   </item>
+   <item row="2" column="1" >
+    <widget class="QComboBox" name="fileSymbolTypeCombo" />
+   </item>
+   <item row="3" column="1" >
+    <widget class="QComboBox" name="byteSymbolTypeCombo" />
+   </item>
+   <item row="12" column="0" >
+    <widget class="QLabel" name="statusLabel" >
+     <property name="text" >
+      <string>Status</string>
+     </property>
+    </widget>
+   </item>
+   <item row="11" column="0" >
+    <widget class="QLabel" name="levelLabel" >
+     <property name="text" >
+      <string>Level</string>
+     </property>
+    </widget>
+   </item>
+   <item row="10" column="0" >
+    <widget class="QLabel" name="purgedLabel" >
+     <property name="text" >
+      <string>Purged</string>
+     </property>
+    </widget>
+   </item>
+   <item row="9" column="0" >
+    <widget class="QLabel" name="fileSetLabel" >
+     <property name="maximumSize" >
+      <size>
+       <width>16777215</width>
+       <height>20</height>
+      </size>
+     </property>
+     <property name="text" >
+      <string>FileSet</string>
+     </property>
+    </widget>
+   </item>
+   <item row="8" column="0" >
+    <widget class="QLabel" name="volumeLabel" >
+     <property name="text" >
+      <string>Volume</string>
+     </property>
+    </widget>
+   </item>
+   <item row="7" column="0" >
+    <widget class="QLabel" name="clientsLabel" >
+     <property name="text" >
+      <string>Client</string>
+     </property>
+    </widget>
+   </item>
+   <item row="6" column="0" >
+    <widget class="QLabel" name="jobLabel" >
+     <property name="text" >
+      <string>Job</string>
+     </property>
+    </widget>
+   </item>
+   <item row="5" column="0" >
+    <widget class="QCheckBox" name="daysCheckBox" >
+     <property name="text" >
+      <string>Days Limit</string>
+     </property>
+    </widget>
+   </item>
+   <item row="4" column="0" >
+    <widget class="QCheckBox" name="limitCheckBox" >
+     <property name="sizePolicy" >
+      <sizepolicy>
+       <hsizetype>0</hsizetype>
+       <vsizetype>0</vsizetype>
+       <horstretch>0</horstretch>
+       <verstretch>0</verstretch>
+      </sizepolicy>
+     </property>
+     <property name="text" >
+      <string>Record Limit</string>
+     </property>
+    </widget>
+   </item>
+   <item row="3" column="0" >
+    <widget class="QLabel" name="label_2" >
+     <property name="text" >
+      <string>Byte Symbol Type</string>
+     </property>
+    </widget>
+   </item>
+   <item row="2" column="0" >
+    <widget class="QLabel" name="label_3" >
+     <property name="text" >
+      <string>File Symbol Type</string>
+     </property>
+    </widget>
+   </item>
+   <item row="1" column="0" >
+    <widget class="QLabel" name="label" >
+     <property name="text" >
+      <string>Graph Type</string>
+     </property>
+    </widget>
+   </item>
+  </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
 
 #include "joblist.h"
 #include "restore.h"
 #include "joblog/joblog.h"
+#include "jobgraphs/jobplot.h"
 
 /*
  * Constructor for the class
 
    /* Can't do this in constructor because not neccesarily conected in constructor */
    if (!m_populated) {
-      clientsComboBox->addItem("Any");
-      clientsComboBox->addItems(m_console->client_list);
-      int clientIndex = clientsComboBox->findText(m_clientName, Qt::MatchExactly);
+      clientComboBox->addItem("Any");
+      clientComboBox->addItems(m_console->client_list);
+      int clientIndex = clientComboBox->findText(m_clientName, Qt::MatchExactly);
       if (clientIndex != -1)
-         clientsComboBox->setCurrentIndex(clientIndex);
+         clientComboBox->setCurrentIndex(clientIndex);
 
-      QString query("SELECT VolumeName AS Media FROM Media ORDER BY Media");
-      if (mainWin->m_sqlDebug) {
-         Pmsg1(000, "Query cmd : %s\n",query.toUtf8().data());
-      }
-      QStringList results, volumeList;
-      if (m_console->sql_cmd(query, results)) {
-         QString field;
-         QStringList fieldlist;
-         /* Iterate through the lines of results. */
-         foreach (QString resultline, results) {
-            fieldlist = resultline.split("\t");
-            volumeList.append(fieldlist[0]);
-         } /* foreach resultline */
-      } /* if results from query */
+      QStringList volumeList;
+      m_console->getVolumeList(volumeList);
       volumeComboBox->addItem("Any");
       volumeComboBox->addItems(volumeList);
       int volumeIndex = volumeComboBox->findText(m_mediaName, Qt::MatchExactly);
       levelComboBox->addItems( QStringList() << "F" << "D" << "I");
       purgedComboBox->addItem("Any");
       purgedComboBox->addItems( QStringList() << "0" << "1");
-      statusComboBox->addItem("Any");
       fileSetComboBox->addItem("Any");
       fileSetComboBox->addItems(m_console->fileset_list);
       int filesetIndex = fileSetComboBox->findText(m_filesetName, Qt::MatchExactly);
       if (filesetIndex != -1) {
          fileSetComboBox->setCurrentIndex(filesetIndex);
       }
-      QString statusQuery("SELECT JobStatusLong FROM Status");
-      if (mainWin->m_sqlDebug) {
-         Pmsg1(000, "Query cmd : %s\n",query.toUtf8().data());
-      }
-      QStringList statusResults, statusLongList;
-      if (m_console->sql_cmd(statusQuery, statusResults)) {
-         QString field;
-         QStringList fieldlist;
-         /* Iterate through the lines of results. */
-         foreach (QString resultline, statusResults) {
-            fieldlist = resultline.split("\t");
-            statusLongList.append(fieldlist[0]);
-         } /* foreach resultline */
-      } /* if results from statusquery */
+      QStringList statusLongList;
+      m_console->getStatusList(statusLongList);
+      statusComboBox->addItem("Any");
       statusComboBox->addItems(statusLongList);
    }
 
    if (m_mediaName != "Any") {
       conditions.append("Media.VolumeName='" + m_mediaName + "'");
    }
-   int clientIndex = clientsComboBox->currentIndex();
+   int clientIndex = clientComboBox->currentIndex();
    if (clientIndex != -1)
-      m_clientName = clientsComboBox->itemText(clientIndex);
+      m_clientName = clientComboBox->itemText(clientIndex);
    if (m_clientName != "Any") {
       conditions.append("Client.Name='" + m_clientName + "'");
    }
    m_purgedIndex = headerlist.indexOf("Purged");
    m_typeIndex = headerlist.indexOf("Job Type");
    m_statusIndex = headerlist.indexOf("Job Status");
+   m_startIndex = headerlist.indexOf("Job Starttime");
+   m_filesIndex = headerlist.indexOf("Job Files");
+   m_bytesIndex = headerlist.indexOf("Job Bytes");
 
    /* Initialize the QTableWidget */
    m_checkCurrentWidget = false;
    connect(actionRefreshJobList, SIGNAL(triggered()), this,
                 SLOT(populateTable()));
    connect(refreshButton, SIGNAL(pressed()), this, SLOT(populateTable()));
+   connect(graphButton, SIGNAL(pressed()), this, SLOT(graphTable()));
    /* for the tableItemChanged to maintain m_currentJob */
    connect(mp_tableWidget, SIGNAL(
            currentItemChanged(QTableWidgetItem *, QTableWidgetItem *)),
    cmd += m_currentJob;
    consoleCommand(cmd);
 }
+
+/*
+ * Graph this table
+ */
+void JobList::graphTable()
+{
+   JobPlotPass pass;
+   pass.recordLimitCheck = limitCheckBox->checkState();
+   pass.daysLimitCheck = daysCheckBox->checkState();
+   pass.recordLimitSpin = limitSpinBox->value();
+   pass.daysLimitSpin = daysSpinBox->value();
+   pass.jobCombo = jobComboBox->currentText();
+   pass.clientCombo = clientComboBox->currentText();
+   pass.volumeCombo = volumeComboBox->currentText();
+   pass.fileSetCombo = fileSetComboBox->currentText();
+   pass.purgedCombo = purgedComboBox->currentText();
+   pass.levelCombo = levelComboBox->currentText();
+   pass.statusCombo = statusComboBox->currentText();
+   pass.use = true;
+   QTreeWidgetItem* pageSelectorTreeWidgetItem = mainWin->getFromHash(this);
+   new JobPlot(pageSelectorTreeWidgetItem, pass);
+}
 
    void preRestoreFromTime();
    void showLogForJob();
    void consoleCancelJob();
+   void graphTable();
 
 private:
    void createConnections();
    int m_purgedIndex;
    int m_typeIndex;
    int m_statusIndex;
+   int m_startIndex;
+   int m_bytesIndex;
+   int m_filesIndex;
 };
 
 #endif /* _JOBLIST_H_ */
 
    <rect>
     <x>0</x>
     <y>0</y>
-    <width>607</width>
-    <height>390</height>
+    <width>545</width>
+    <height>276</height>
    </rect>
   </property>
   <property name="windowTitle" >
      <property name="spacing" >
       <number>6</number>
      </property>
-     <item rowspan="2" row="0" column="1" >
+     <item row="1" column="4" >
+      <layout class="QGridLayout" >
+       <property name="margin" >
+        <number>0</number>
+       </property>
+       <property name="spacing" >
+        <number>6</number>
+       </property>
+       <item row="0" column="0" >
+        <layout class="QGridLayout" >
+         <property name="margin" >
+          <number>0</number>
+         </property>
+         <property name="spacing" >
+          <number>3</number>
+         </property>
+         <item row="0" column="0" >
+          <widget class="QPushButton" name="refreshButton" >
+           <property name="maximumSize" >
+            <size>
+             <width>65</width>
+             <height>20</height>
+            </size>
+           </property>
+           <property name="text" >
+            <string>Refresh</string>
+           </property>
+           <property name="icon" >
+            <iconset resource="../main.qrc" >:/images/view-refresh.svg</iconset>
+           </property>
+          </widget>
+         </item>
+         <item row="1" column="0" >
+          <widget class="QPushButton" name="graphButton" >
+           <property name="maximumSize" >
+            <size>
+             <width>65</width>
+             <height>20</height>
+            </size>
+           </property>
+           <property name="text" >
+            <string>Graph</string>
+           </property>
+           <property name="icon" >
+            <iconset resource="../main.qrc" >:/images/graph1.png</iconset>
+           </property>
+          </widget>
+         </item>
+        </layout>
+       </item>
+       <item row="0" column="1" >
+        <spacer>
+         <property name="orientation" >
+          <enum>Qt::Horizontal</enum>
+         </property>
+         <property name="sizeType" >
+          <enum>QSizePolicy::Ignored</enum>
+         </property>
+         <property name="sizeHint" >
+          <size>
+           <width>16</width>
+           <height>20</height>
+          </size>
+         </property>
+        </spacer>
+       </item>
+      </layout>
+     </item>
+     <item rowspan="2" row="0" column="3" >
       <layout class="QVBoxLayout" >
        <property name="margin" >
         <number>0</number>
           <number>6</number>
          </property>
          <item>
-          <widget class="QLabel" name="clientsLabel" >
+          <widget class="QLabel" name="statusLabel" >
            <property name="text" >
-            <string>Clients</string>
+            <string>Status</string>
            </property>
           </widget>
          </item>
          <item>
-          <widget class="QComboBox" name="clientsComboBox" />
+          <widget class="QComboBox" name="statusComboBox" />
          </item>
         </layout>
        </item>
           <number>6</number>
          </property>
          <item>
-          <widget class="QLabel" name="volumeLabel" >
+          <widget class="QLabel" name="purgedLabel" >
            <property name="text" >
-            <string>Volume</string>
+            <string>Purged</string>
            </property>
           </widget>
          </item>
          <item>
-          <widget class="QComboBox" name="volumeComboBox" />
+          <widget class="QComboBox" name="purgedComboBox" />
          </item>
         </layout>
        </item>
        </property>
        <item>
         <widget class="QLabel" name="fileSetLabel" >
+         <property name="maximumSize" >
+          <size>
+           <width>16777215</width>
+           <height>20</height>
+          </size>
+         </property>
          <property name="text" >
           <string>FileSet</string>
          </property>
        </item>
       </layout>
      </item>
-     <item rowspan="2" row="0" column="3" >
+     <item rowspan="2" row="0" column="1" >
       <layout class="QVBoxLayout" >
        <property name="margin" >
         <number>0</number>
           <number>6</number>
          </property>
          <item>
-          <widget class="QLabel" name="statusLabel" >
+          <widget class="QLabel" name="clientsLabel" >
            <property name="text" >
-            <string>Status</string>
+            <string>Clients</string>
            </property>
           </widget>
          </item>
          <item>
-          <widget class="QComboBox" name="statusComboBox" />
+          <widget class="QComboBox" name="clientComboBox" />
          </item>
         </layout>
        </item>
           <number>6</number>
          </property>
          <item>
-          <widget class="QLabel" name="purgedLabel" >
+          <widget class="QLabel" name="volumeLabel" >
            <property name="text" >
-            <string>Purged</string>
+            <string>Volume</string>
            </property>
           </widget>
          </item>
          <item>
-          <widget class="QComboBox" name="purgedComboBox" />
+          <widget class="QComboBox" name="volumeComboBox" />
          </item>
         </layout>
        </item>
        </item>
       </layout>
      </item>
-     <item row="1" column="4" >
-      <layout class="QGridLayout" >
-       <property name="margin" >
-        <number>0</number>
-       </property>
-       <property name="spacing" >
-        <number>6</number>
-       </property>
-       <item row="0" column="0" >
-        <widget class="QPushButton" name="refreshButton" >
-         <property name="maximumSize" >
-          <size>
-           <width>65</width>
-           <height>16777215</height>
-          </size>
-         </property>
-         <property name="text" >
-          <string>Refresh</string>
-         </property>
-         <property name="icon" >
-          <iconset resource="../main.qrc" >:/images/view-refresh.svg</iconset>
-         </property>
-        </widget>
-       </item>
-       <item row="0" column="1" >
-        <spacer>
-         <property name="orientation" >
-          <enum>Qt::Horizontal</enum>
-         </property>
-         <property name="sizeType" >
-          <enum>QSizePolicy::Ignored</enum>
-         </property>
-         <property name="sizeHint" >
-          <size>
-           <width>16</width>
-           <height>20</height>
-          </size>
-         </property>
-        </spacer>
-       </item>
-       <item row="1" column="0" >
-        <spacer>
-         <property name="orientation" >
-          <enum>Qt::Vertical</enum>
-         </property>
-         <property name="sizeType" >
-          <enum>QSizePolicy::Ignored</enum>
-         </property>
-         <property name="sizeHint" >
-          <size>
-           <width>20</width>
-           <height>16</height>
-          </size>
-         </property>
-        </spacer>
-       </item>
-      </layout>
-     </item>
     </layout>
    </item>
    <item row="0" column="0" >
 
  *
  */ 
 
-//#include <QAbstractEventDispatcher>
-//#include <QMenu>
 #include "bat.h"
 #include "jobs/jobs.h"
+#include "run/run.h"
 
 Jobs::Jobs()
 {
       << "Client" << "Storage" << "Where" << "Level" << "Type" << "FileSet" 
       << "Catalog" << "Enabled");
 
+   m_typeIndex = headerlist.indexOf("Type");
    topItem = new QTreeWidgetItem(mp_treeWidget);
    topItem->setText(0, "Jobs");
    topItem->setData(0, Qt::UserRole, 0);
    if (m_checkcurwidget) {
       /* The Previous item */
       if (previouswidgetitem) { /* avoid a segfault if first time */
-         int treedepth = previouswidgetitem->data(0, Qt::UserRole).toInt();
-         if (treedepth == 1){
-            mp_treeWidget->removeAction(actionConsoleListFiles);
-            mp_treeWidget->removeAction(actionConsoleListVolumes);
-            mp_treeWidget->removeAction(actionConsoleListNextVolume);
-            mp_treeWidget->removeAction(actionConsoleEnableJob);
-            mp_treeWidget->removeAction(actionConsoleDisableJob);
-            mp_treeWidget->removeAction(actionConsoleCancel);
-            mp_treeWidget->removeAction(actionJobListQuery);
+         foreach(QAction* jobAction, mp_treeWidget->actions()) {
+            mp_treeWidget->removeAction(jobAction);
          }
       }
 
          mp_treeWidget->addAction(actionConsoleDisableJob);
          mp_treeWidget->addAction(actionConsoleCancel);
          mp_treeWidget->addAction(actionJobListQuery);
+         if (currentwidgetitem->text(m_typeIndex) == "Backup")
+            mp_treeWidget->addAction(actionRunJob);
       }
    }
 }
    connect(actionConsoleDisableJob, SIGNAL(triggered()), this, SLOT(consoleDisable()));
    connect(actionConsoleCancel, SIGNAL(triggered()), this, SLOT(consoleCancel()));
    connect(actionJobListQuery, SIGNAL(triggered()), this, SLOT(listJobs()));
+   connect(actionRunJob, SIGNAL(triggered()), this, SLOT(runJob()));
 }
 
 /*
    QTreeWidgetItem *parentItem = mainWin->getFromHash(this);
    mainWin->createPageJobList("", "", m_currentlyselected, "", parentItem);
 }
+
+/*
+ * Open a new job run page with the currentley selected "Backup" job 
+ * defaulted In
+ */
+void Jobs::runJob()
+{
+   new runPage(m_currentlyselected);
+}
 
    void consoleDisable();
    void consoleCancel();
    void listJobs();
+   void runJob();
 
 private:
    void createContextMenu();
    QString m_currentlyselected;
    bool m_populated;
    bool m_checkcurwidget;
+   int m_typeIndex;
 };
 
 #endif /* _JOBS_H_ */
 
     <string>Cancel Job Command</string>
    </property>
   </action>
+  <action name="actionRunJob" >
+   <property name="icon" >
+    <iconset resource="../main.qrc" >:/images/run.png</iconset>
+   </property>
+   <property name="text" >
+    <string>RunJob</string>
+   </property>
+  </action>
  </widget>
  <resources>
   <include location="../main.qrc" />
 
         <file>images/estimate-job.svg</file>
         <file>images/folder.png</file>
         <file>images/folder.svg</file>
+        <file>images/graph1.png</file>
         <file>images/help-browser.svg</file>
         <file>images/home.png</file>
         <file>images/joblog.png</file>
 
    <addaction name="actionLabel" />
    <addaction name="actionRestore" />
    <addaction name="actionRun" />
-   <addaction name="actionUndock" />
    <addaction name="actionEstimate" />
    <addaction name="actionBrowse" />
+   <addaction name="actionJobPlot" />
+   <addaction name="actionUndock" />
   </widget>
   <widget class="QDockWidget" name="dockWidget" >
    <property name="sizePolicy" >
     <string>Browse</string>
    </property>
   </action>
+  <action name="actionJobPlot" >
+   <property name="icon" >
+    <iconset resource="main.qrc" >:/images/graph1.png</iconset>
+   </property>
+   <property name="text" >
+    <string>JobPlot</string>
+   </property>
+  </action>
  </widget>
  <resources>
   <include location="main.qrc" />
 
 #include "restore/restoretree.h"
 #include "help/help.h"
 #include "jobs/jobs.h"
+#include "jobgraphs/jobplot.h"
 
 /* 
  * Daemon message callback
 
 MainWin::MainWin(QWidget *parent) : QMainWindow(parent)
 {
+   m_isClosing = false;
    m_dtformat = "yyyy-MM-dd HH:mm:ss";
    mainWin = this;
    setupUi(this);                     /* Setup UI defined by main.ui (designer) */
       new MediaList();
       new Storage();
       new restoreTree();
+      JobPlotPass pass;
+      pass.use = false;
+      new JobPlot(NULL, pass);
 
       treeWidget->expandItem(topItem);
       stackedWidget->setCurrentWidget(m_currentConsole);
    connect(actionRun, SIGNAL(triggered()), this,  SLOT(runButtonClicked()));
    connect(actionEstimate, SIGNAL(triggered()), this,  SLOT(estimateButtonClicked()));
    connect(actionBrowse, SIGNAL(triggered()), this,  SLOT(browseButtonClicked()));
+   connect(actionJobPlot, SIGNAL(triggered()), this,  SLOT(jobPlotButtonClicked()));
    connect(actionRestore, SIGNAL(triggered()), this,  SLOT(restoreButtonClicked()));
    connect(actionUndock, SIGNAL(triggered()), this,  SLOT(undockWindowButton()));
    connect(actionToggleDock, SIGNAL(triggered()), this,  SLOT(toggleDockContextWindow()));
  */
 void MainWin::closeEvent(QCloseEvent *event)
 {
+   m_isClosing = true;
    writeSettings();
+   /* close all non console pages, this will call settings in destructors */
+   foreach(Pages *page, m_pagehash) {
+      if (page !=  page->console()) {
+         page->console()->setCurrent();
+         page->closeStackPage();
+      }
+   }
+   /* close the console pages and terminate connection */
    foreach(Console *console, m_consoleHash){
       console->writeSettings();
       console->terminate();
+      console->closeStackPage();
    }
    event->accept();
-   foreach(Pages *page, m_pagehash) {
-      if (!page->isDocked())
-         page->close();
-   }
 }
 
 void MainWin::writeSettings()
  */
 void MainWin::treeItemChanged(QTreeWidgetItem *currentitem, QTreeWidgetItem *previousitem)
 {
+   if (m_isClosing) return; /* if closing the application, do nothing here */
+
    Pages *previousPage, *nextPage;
    Console *previousConsole, *nextConsole;
 
 
 void MainWin::runButtonClicked() 
 {
-   new runPage();
+   new runPage("");
 }
 
 void MainWin::estimateButtonClicked() 
    new prerestorePage();
 }
 
+void MainWin::jobPlotButtonClicked()
+{
+   JobPlotPass pass;
+   pass.use = false;
+   new JobPlot(NULL, pass);
+}
+
 /*
  * The user just finished typing a line in the command line edit box
  */
  */
 void MainWin::stackItemChanged(int)
 {
+   if (m_isClosing) return; /* if closing the application, do nothing here */
    Pages* page = (Pages*)stackedWidget->currentWidget();
    /* run the virtual function in case this class overrides it */
    page->currentStackItem();
 
    void runButtonClicked();
    void estimateButtonClicked();
    void browseButtonClicked();
+   void jobPlotButtonClicked();
    void restoreButtonClicked();
    void undockWindowButton();
    void treeItemChanged(QTreeWidgetItem *, QTreeWidgetItem *);
    QStringList m_cmd_history;
    int m_cmd_last;
    QTreeWidgetItem *m_firstItem;
+   bool m_isClosing;
 };
 
 #include "ui_prefs.h"
 
--- /dev/null
+
+# 
+# Inserted by build script
+#
+# unix {
+#    INSTALLBASE    = /usr
+#}
+#
+#win32 {
+#    INSTALLBASE    = C:/Qwt-5.0.2
+#}
+
+target.path    = $$INSTALLBASE/lib
+headers.path   = $$INSTALLBASE/include
+# doc.path       = $$INSTALLBASE/doc
+
+######################################################################
+# qmake internal options
+######################################################################
+
+CONFIG           += qt     # Also for Qtopia Core!
+CONFIG           += warn_on
+CONFIG           += thread
+
+######################################################################
+# release/debug mode
+# The designer plugin is always built in release mode.
+# If want to change this, you have to edit designer/designer.pro.
+######################################################################
+
+CONFIG           += release     # release/debug
+
+######################################################################
+# Build the static/shared libraries.
+# If QwtDll is enabled, a shared library is built, otherwise
+# it will be a static library.
+######################################################################
+
+# CONFIG           += QwtDll
+
+######################################################################
+# QwtPlot enables all classes, that are needed to use the QwtPlot 
+# widget. 
+######################################################################
+
+CONFIG       += QwtPlot
+
+######################################################################
+# QwtWidgets enables all classes, that are needed to use the all other
+# widgets (sliders, dials, ...), beside QwtPlot. 
+######################################################################
+
+# CONFIG     += QwtWidgets
+
+######################################################################
+# If you want to display svg imageson the plot canvas, enable the 
+# line below. Note that Qwt needs the svg+xml, when enabling 
+# QwtSVGItem.
+######################################################################
+
+#CONFIG     += QwtSVGItem
+
+######################################################################
+# If you have a commercial license you can use the MathML renderer
+# of the Qt solutions package to enable MathML support in Qwt.
+# So if you want this, copy qtmmlwidget.h + qtmmlwidget.cpp to
+# textengines/mathml and enable the line below.
+######################################################################
+
+#CONFIG     += QwtMathML
+
+######################################################################
+# If you want to build the Qwt designer plugin, 
+# enable the line below.
+# Otherwise you have to build it from the designer directory.
+######################################################################
+
+# CONFIG     += QwtDesigner
+
+######################################################################
+# If you want to auto build the examples, enable the line below
+# Otherwise you have to build them from the examples directory.
+######################################################################
+
+# CONFIG     += QwtExamples
+unix {
+ INSTALLBASE = /home/kern/bacula/x/src/qt-console/qwt
+}
 
 /*
  * Setup all the combo boxes and display the dialog
  */
-runPage::runPage()
+runPage::runPage(const QString &defJob)
 {
    QDateTime dt;
 
    dockPage();
    setCurrent();
    this->show();
+   if (defJob != "")
+      jobCombo->setCurrentIndex(jobCombo->findText(defJob, Qt::MatchExactly));
 }
 
 void runPage::okButtonPushed()
 
    Q_OBJECT 
 
 public:
-   runPage();
+   runPage(const QString &defJob);
 
 public slots:
    void okButtonPushed();