[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Bacula-devel] Patch: formatting for media and storage trees on bat


Hi,
the attached patch adds formatting to fields in bat media and storage trees.
It's purely cosmetical, no functional changes.
Highlights:
- bytes columns are shown as TB,GB,MB,KB instead of plain bytes
- durations which are an exact multiple of years,months,weeks,days or hours are formatted accordingly, with a trailing y,m,w,d,h
- slot column shown only for in-changer media
- storage view shows also in-changer media

Patch against 2.2 branch (rev 6850)

Regards,
Riccardo Ghetta

Index: bacula/src/qt-console/storage/storage.cpp
===================================================================
--- bacula/src/qt-console/storage/storage.cpp	(revision 6850)
+++ bacula/src/qt-console/storage/storage.cpp	(working copy)
@@ -41,6 +41,7 @@
 #include "storage.h"
 #include "label/label.h"
 #include "../mount/mount.h"
+#include "util/fmtwidgetitem.h"
 
 Storage::Storage()
 {
@@ -71,7 +72,7 @@
  */
 void Storage::populateTree()
 {
-   QTreeWidgetItem *storageItem, *topItem;
+   QTreeWidgetItem *topItem;
 
    if (!m_console->preventInUseConnect())
        return;
@@ -80,8 +81,9 @@
    mp_treeWidget->clear();
    m_checkcurwidget = true;
 
-   QStringList headerlist = (QStringList() << "Storage Name" << "Storage Id"
-       << "Auto Changer");
+   QStringList headerlist = (QStringList() << "Name" << "Id"
+       << "Changer" << "Slot" << "Status" << "Enabled" << "Pool" 
+       << "Media Type");
 
    topItem = new QTreeWidgetItem(mp_treeWidget);
    topItem->setText(0, "Storage");
@@ -92,10 +94,9 @@
    mp_treeWidget->setHeaderLabels(headerlist);
 
    foreach(QString storageName, m_console->storage_list){
-      storageItem = new QTreeWidgetItem(topItem);
-      storageItem->setText(0, storageName);
-      storageItem->setData(0, Qt::UserRole, 1);
-      storageItem->setExpanded(true);
+      ItemFormatter storageItem(*topItem, 1);
+      storageItem.setTextFld(0, storageName);
+      storageItem.widget()->setExpanded(true);
 
       /* Set up query QString and header QStringList */
       QString query("SELECT StorageId AS ID, AutoChanger AS Changer"
@@ -117,26 +118,83 @@
             /* there will only be one of these */
             foreach (resultline, results) {
                fieldlist = resultline.split("\t");
-               int index = 0;
-               /* Iterate through fields in the record */
-               foreach (field, fieldlist) {
-                  field = field.trimmed();  /* strip leading & trailing spaces */
-                  storageItem->setData(index+1, Qt::UserRole, 1);
-                  /* Put media fields under the pool tree item */
-                  storageItem->setData(index+1, Qt::UserRole, 1);
-                  storageItem->setText(index+1, field);
-                  index++;
-               }
+               int index = 1;
+	       QStringListIterator fld(fieldlist);
+
+	       /* storage id */
+	       storageItem.setNumericFld(index++, fld.next() );
+
+	       /* changer */
+	       storageItem.setBoolFld(index++, fld.next() );
+
+	       mediaList(storageItem.widget(), fieldlist.first());
             }
          }
       }
    }
    /* Resize the columns */
-   for(int cnter=1; cnter<headerlist.size(); cnter++) {
+   for(int cnter=0; cnter<headerlist.size(); cnter++) {
       mp_treeWidget->resizeColumnToContents(cnter);
    }
 }
 
+void Storage::mediaList(QTreeWidgetItem *parent, const QString &storageID)
+{
+   QString query("SELECT Media.VolumeName AS Media, Media.Slot AS Slot,"
+                 " Media.VolStatus AS VolStatus, Media.Enabled AS Enabled,"
+		 " Pool.Name AS MediaPool, Media.MediaType AS MediaType" 
+                 " From Media"
+		 " JOIN Pool ON (Media.PoolId=Pool.PoolId)"
+		 " WHERE Media.StorageId='" + storageID + "'"
+		 " AND Media.InChanger<>0"
+		 " ORDER BY Media.Slot");
+
+   QStringList results;
+   /* This could be a log item */
+   if (mainWin->m_sqlDebug) {
+      Pmsg1(000, "Storage query cmd : %s\n",query.toUtf8().data());
+   }
+   if (m_console->sql_cmd(query, results)) {
+      QString resultline;
+      QString field;
+      QStringList fieldlist;
+ 
+      foreach (resultline, results) {
+         fieldlist = resultline.split("\t");
+	 if (fieldlist.size() < 6)
+	   continue; 
+
+         /* Iterate through fields in the record */
+         QStringListIterator fld(fieldlist);
+         int index = 0;
+	 ItemFormatter fmt(*parent, 2);
+
+         /* volname */
+         fmt.setTextFld(index++, fld.next()); 
+
+	 /* skip the next two columns, unused by media */
+	 index += 2;
+
+	 /* slot */
+	 fmt.setNumericFld(index++, fld.next());
+
+	 /* status */
+	 fmt.setVolStatusFld(index++, fld.next());
+
+         /* enabled */
+         fmt.setBoolFld(index++, fld.next()); 
+
+         /* pool */
+         fmt.setTextFld(index++, fld.next()); 
+
+         /* media type */
+         fmt.setTextFld(index++, fld.next()); 
+
+      }
+   }
+}
+
+
 /*
  * When the treeWidgetItem in the page selector tree is singleclicked, Make sure
  * The tree has been populated.
Index: bacula/src/qt-console/storage/storage.h
===================================================================
--- bacula/src/qt-console/storage/storage.h	(revision 6850)
+++ bacula/src/qt-console/storage/storage.h	(working copy)
@@ -63,6 +63,7 @@
 
 private:
    void createContextMenu();
+   void mediaList(QTreeWidgetItem *parent, const QString &storageID);
    QString m_currentStorage;
    int m_currentAutoChanger;
    bool m_populated;
Index: bacula/src/qt-console/medialist/medialist.h
===================================================================
--- bacula/src/qt-console/medialist/medialist.h	(revision 6850)
+++ bacula/src/qt-console/medialist/medialist.h	(working copy)
@@ -65,7 +65,6 @@
 
 private:
    void createContextMenu();
-   void setStatusColor(QTreeWidgetItem *, QString &, int &);
    QString m_currentVolumeName;
    QString m_currentVolumeId;
    bool m_populated;
Index: bacula/src/qt-console/medialist/medialist.cpp
===================================================================
--- bacula/src/qt-console/medialist/medialist.cpp	(revision 6850)
+++ bacula/src/qt-console/medialist/medialist.cpp	(working copy)
@@ -37,12 +37,14 @@
 
 #include <QAbstractEventDispatcher>
 #include <QMenu>
+#include <math.h>
 #include "bat.h"
 #include "medialist.h"
 #include "mediaedit/mediaedit.h"
 #include "joblist/joblist.h"
 #include "relabel/relabel.h"
 #include "run/run.h"
+#include "util/fmtwidgetitem.h"
 
 MediaList::MediaList()
 {
@@ -66,13 +68,14 @@
 {
 }
 
+
 /*
  * The main meat of the class!!  The function that querries the director and 
  * creates the widgets with appropriate values.
  */
 void MediaList::populateTree()
 {
-   QTreeWidgetItem *mediatreeitem, *pooltreeitem, *topItem;
+   QTreeWidgetItem *pooltreeitem, *topItem;
 
    if (!m_console->preventInUseConnect())
        return;
@@ -80,9 +83,8 @@
    QStringList headerlist = (QStringList()
       << "Volume Name" << "Id" << "Status" << "Enabled" << "Bytes" << "Files"
       << "Jobs" << "Retention" << "Media Type" << "Slot" << "Use Duration"
-      << "Max Jobs" << "Max Files" << "Max Bytes" << "Recycle" << "Enabled"
+      << "Max Jobs" << "Max Files" << "Max Bytes" << "Recycle" 
       << "RecyclePool" << "Last Written");
-   int statusIndex = headerlist.indexOf("Status");
 
    m_checkcurwidget = false;
    mp_treeWidget->clear();
@@ -108,11 +110,11 @@
          " Media.Enabled AS Enabled, Media.VolBytes AS Bytes,"
          " Media.VolFiles AS FileCount, Media.VolJobs AS JobCount,"
          " Media.VolRetention AS VolumeRetention, Media.MediaType AS MediaType,"
-         " Media.Slot AS Slot, Media.VolUseDuration AS UseDuration,"
+         " Media.InChanger AS InChanger, Media.Slot AS Slot, "
+         " Media.VolUseDuration AS UseDuration,"
          " Media.MaxVolJobs AS MaxJobs, Media.MaxVolFiles AS MaxFiles,"
          " Media.MaxVolBytes AS MaxBytes, Media.Recycle AS Recycle,"
-         " Media.Enabled AS enabled, Pol.Name AS RecyclePool,"
-         " Media.LastWritten AS LastWritten"
+         " Pol.Name AS RecyclePool, Media.LastWritten AS LastWritten"
          " FROM Media"
          " JOIN Pool ON (Media.PoolId=Pool.PoolId)"
          " LEFT OUTER JOIN Pool AS Pol ON (Media.RecyclePoolId=Pol.PoolId)"
@@ -125,28 +127,80 @@
       }
       QStringList results;
       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");
+
+	    if (fieldlist.size() < 18)
+	       continue; // some fields missing, ignore row
+
             int index = 0;
-            mediatreeitem = new QTreeWidgetItem(pooltreeitem);
+	    ItemFormatter mediaitem(*pooltreeitem, 2);
 
             /* Iterate through fields in the record */
-            foreach (field, fieldlist) {
-               field = field.trimmed();  /* strip leading & trailing spaces */
-               if (field != "") {
-                  mediatreeitem->setData(index, Qt::UserRole, 2);
-                  mediatreeitem->setData(index, Qt::UserRole, 2);
-                  mediatreeitem->setText(index, field);
-                  if (index == statusIndex) {
-                     setStatusColor(mediatreeitem, field, index);
-                  }
-               }
-               index++;
-            } /* foreach field */
+	    QStringListIterator fld(fieldlist);
+
+	    /* volname */
+            mediaitem.setTextFld(index++, fld.next()); 
+
+	    /* id */
+            mediaitem.setNumericFld(index++, fld.next()); 
+
+	    /* status */
+            mediaitem.setVolStatusFld(index++, fld.next());
+
+	    /* enabled */
+ 	    mediaitem.setBoolFld(index++, fld.next());
+
+            /* bytes */
+ 	    mediaitem.setBytesFld(index++, fld.next());
+
+	    /* files */
+            mediaitem.setNumericFld(index++, fld.next()); 
+
+	    /* jobs */
+            mediaitem.setNumericFld(index++, fld.next()); 
+
+	    /* retention */
+	    mediaitem.setDurationFld(index++, fld.next());
+
+	    /* media type */
+            mediaitem.setTextFld(index++, fld.next()); 
+
+	    /* inchanger + slot */
+	    int inchanger = fld.next().toInt();
+            if (inchanger) {
+               mediaitem.setNumericFld(index++, fld.next()); 
+            }
+            else {
+               /* volume not in changer, show blank slot */
+               mediaitem.setNumericFld(index++, ""); 
+               fld.next();
+	    }
+
+	    /* use duration */
+	    mediaitem.setDurationFld(index++, fld.next());
+
+	    /* max jobs */
+            mediaitem.setNumericFld(index++, fld.next()); 
+
+	    /* max files */
+            mediaitem.setNumericFld(index++, fld.next()); 
+
+            /* max bytes */
+ 	    mediaitem.setBytesFld(index++, fld.next());
+
+	    /* recycle */
+ 	    mediaitem.setBoolFld(index++, fld.next());
+
+	    /* recycle pool */
+            mediaitem.setTextFld(index++, fld.next()); 
+
+	    /* last written */
+            mediaitem.setTextFld(index++, fld.next()); 
+
          } /* foreach resultline */
       } /* if results from query */
    } /* foreach pool_listItem */
@@ -156,17 +210,6 @@
    }
 }
 
-void MediaList::setStatusColor(QTreeWidgetItem *item, QString &field, int &index)
-{
-   if (field == "Append" ) {
-      item->setBackground(index, Qt::green);
-   } else if (field == "Error") {
-      item->setBackground(index, Qt::red);
-   } else if ((field == "Used") || ("Full")){
-      item->setBackground(index, Qt::yellow);
-   }
-}
-
 /*
  * Called from the signal of the context sensitive menu!
  */
Index: bacula/src/qt-console/console/console.cpp
===================================================================
--- bacula/src/qt-console/console/console.cpp	(revision 6850)
+++ bacula/src/qt-console/console/console.cpp	(working copy)
@@ -314,7 +314,10 @@
    pm_strcat(cmd, "\"");
    write(cmd.c_str());
    while ((stat = read()) > 0) {
-      if (mainWin->m_displayAll) display_text(msg());
+      if (mainWin->m_displayAll) {
+         display_text(msg());
+	 display_text("\n");
+      }
       strip_trailing_junk(msg());
       results << msg();
    }
Index: bacula/src/qt-console/bat.pro.in
===================================================================
--- bacula/src/qt-console/bat.pro.in	(revision 6850)
+++ bacula/src/qt-console/bat.pro.in	(working copy)
@@ -124,6 +124,10 @@
 HEADERS += help/help.h
 SOURCES += help/help.cpp
 
+# Utility sources
+HEADERS += util/fmtwidgetitem.h
+SOURCES += util/fmtwidgetitem.cpp
+
 INSTALLS += bins
 INSTALLS += confs
 
Index: bacula/src/qt-console/util/fmtwidgetitem.h
===================================================================
--- bacula/src/qt-console/util/fmtwidgetitem.h	(revision 0)
+++ bacula/src/qt-console/util/fmtwidgetitem.h	(revision 0)
@@ -0,0 +1,77 @@
+#ifndef _FMTWIDGETITEM_H_
+#define _FMTWIDGETITEM_H_
+/*
+   Bacula® - The Network Backup Solution
+
+   Copyright (C) 2007-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@xxxxxxxxxxxxxx
+*/
+/*
+ *   Version $Id$
+ *
+ *   TreeView formatting helpers - Riccardo Ghetta, May 2008 
+ */
+
+class QTreeWidgetItem;
+class QString;
+
+/*
+ * This class can be used instead of QTreeWidgetItem (it allocates one internally,
+ * to format data fields.
+ * All setXXXFld routines receive a column index and the unformatted string value.
+ */
+class ItemFormatter
+{
+public:
+
+   ItemFormatter(QTreeWidgetItem &parent, int indent_level);
+
+   /* Prints Yes if fld is != 0, No otherwise. Centers field if center true*/
+   void setBoolFld(int index, const QString &fld, bool center = true);
+
+   /* Normal text field. Centers field if center true*/
+   void setTextFld(int index, const QString &fld, bool center = false);
+
+   /* Right-aligned text field.*/
+   void setNumericFld(int index, const QString &fld);
+
+   /* fld value interpreted as bytes and formatted with size suffixes */
+   void setBytesFld(int index, const QString &fld);
+
+   /* fld value interpreted as seconds and formatted with y,m,w,h suffixes */
+   void setDurationFld(int index, const QString &fld);
+
+   /* fld value interpreted as volume status. Colored accordingly */
+   void setVolStatusFld(int index, const QString &fld, bool center = true);
+
+   /* access internal widget */
+   QTreeWidgetItem *widget() { return wdg; }
+   const QTreeWidgetItem *widget() const { return wdg; }
+
+private:
+   QTreeWidgetItem *wdg;
+   int level;
+};
+
+#endif /* _FMTWIDGETITEM_H_ */

Property changes on: bacula/src/qt-console/util/fmtwidgetitem.h
___________________________________________________________________
Name: svn:eol-style
   + native

Index: bacula/src/qt-console/util/fmtwidgetitem.cpp
===================================================================
--- bacula/src/qt-console/util/fmtwidgetitem.cpp	(revision 0)
+++ bacula/src/qt-console/util/fmtwidgetitem.cpp	(revision 0)
@@ -0,0 +1,139 @@
+/*
+   Bacula® - The Network Backup Solution
+
+   Copyright (C) 2007-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@xxxxxxxxxxxxxx
+*/
+ 
+/*
+ *   Version $Id$
+ *
+ *  Helper functions for tree widget formatting
+ *
+ *   Riccardo Ghetta, May 2008
+ *
+ */ 
+
+#include <QTreeWidgetItem>
+#include <QString>
+#include <QStringList>
+#include <math.h>
+#include "fmtwidgetitem.h"
+
+ItemFormatter::ItemFormatter(QTreeWidgetItem &parent, int indent_level):
+wdg(new QTreeWidgetItem(&parent)),
+level(indent_level)
+{
+}
+
+void ItemFormatter::setBoolFld(int index, const QString &fld, bool center)
+{
+   if (fld.trimmed().toInt())
+     setTextFld(index, "Yes", center);
+   else
+     setTextFld(index, "No", center);
+}
+
+void ItemFormatter::setTextFld(int index, const QString &fld, bool center)
+{
+   wdg->setData(index, Qt::UserRole, level);
+   if (center) {
+      wdg->setTextAlignment(index, Qt::AlignHCenter);
+   }
+   wdg->setText(index, fld.trimmed());
+}
+
+void ItemFormatter::setNumericFld(int index, const QString &fld)
+{
+   wdg->setData(index, Qt::UserRole, level);
+   wdg->setTextAlignment(index, Qt::AlignRight);
+   wdg->setText(index, fld.trimmed());
+}
+
+void ItemFormatter::setBytesFld(int index, const QString &fld)
+{
+   static const double KB = 1024.0;
+   static const double MB = KB * KB;
+   static const double GB = MB * KB;
+   static const double TB = GB * KB;
+
+   double dfld = fld.trimmed().toDouble();
+   QString msg;
+   if (dfld >= TB)
+      msg = QString("%1TB").arg(dfld / TB, 0, 'f', 2);
+   else if (dfld >= GB)
+      msg = QString("%1GB").arg(dfld / GB, 0, 'f', 2);
+   else if (dfld >= MB)
+      msg = QString("%1MB").arg(dfld / MB, 0, 'f', 2);
+   else if (dfld >= KB)
+      msg = QString("%1KB").arg(dfld / KB, 0, 'f', 2);
+   else
+      msg = QString::number(dfld, 'f', 0);
+ 
+   wdg->setData(index, Qt::UserRole, level);
+   wdg->setTextAlignment(index, Qt::AlignRight);
+   wdg->setText(index, msg);
+}
+
+void ItemFormatter::setDurationFld(int index, const QString &fld)
+{
+   static const double HOUR = 3600;
+   static const double DAY = HOUR * 24;
+   static const double WEEK = DAY * 7;
+   static const double MONTH = DAY * 30;
+   static const double YEAR = DAY * 365;
+
+   double dfld = fld.trimmed().toDouble();
+   QString msg;
+   if (fmod(dfld, YEAR) == 0)
+      msg = QString("%1y").arg(dfld / YEAR, 0, 'f', 0);
+   else if (fmod(dfld, MONTH) == 0)
+      msg = QString("%1m").arg(dfld / MONTH, 0, 'f', 0);
+   else if (fmod(dfld, WEEK) == 0)
+      msg = QString("%1w").arg(dfld / WEEK, 0, 'f', 0);
+   else if (fmod(dfld, DAY) == 0)
+      msg = QString("%1d").arg(dfld / DAY, 0, 'f', 0);
+   else if (fmod(dfld, HOUR) == 0)
+      msg = QString("%1h").arg(dfld / HOUR, 0, 'f', 0);
+   else
+      msg = QString("%1s").arg(dfld, 0, 'f', 0);
+ 
+   wdg->setData(index, Qt::UserRole, level);
+   wdg->setTextAlignment(index, Qt::AlignRight);
+   wdg->setText(index, msg);
+}
+
+void ItemFormatter::setVolStatusFld(int index, const QString &fld, bool center)
+{
+  setTextFld(index, fld, center);
+
+   if (fld == "Append" ) {
+      wdg->setBackground(index, Qt::green);
+   } else if (fld == "Error") {
+      wdg->setBackground(index, Qt::red);
+   } else if (fld == "Used" || fld == "Full"){
+      wdg->setBackground(index, Qt::yellow);
+   }
+}
+

Property changes on: bacula/src/qt-console/util/fmtwidgetitem.cpp
___________________________________________________________________
Name: svn:eol-style
   + native

-------------------------------------------------------------------------
This SF.net email is sponsored by the 2008 JavaOne(SM) Conference 
Don't miss this year's exciting event. There's still time to save $100. 
Use priority code J8TL2D2. 
http://ad.doubleclick.net/clk;198757673;13503038;p?http://java.sun.com/javaone
_______________________________________________
Bacula-devel mailing list
Bacula-devel@xxxxxxxxxxxxxxxxxxxxx
https://lists.sourceforge.net/lists/listinfo/bacula-devel


This mailing list archive is a service of Copilotco.