From: Dirk H Bartley Date: Wed, 7 May 2008 01:13:27 +0000 (+0000) Subject: This is the patch as sent to me by Ricardo. X-Git-Tag: Release-7.0.0~4638 X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=aacb068dd0163b0e030053ccd992589e212e4353;p=bacula%2Fbacula This is the patch as sent to me by Ricardo. git-svn-id: https://bacula.svn.sourceforge.net/svnroot/bacula/trunk@6904 91ce42f0-d328-0410-95d8-f526ca767f89 --- diff --git a/bacula/src/qt-console/bat.pro.in b/bacula/src/qt-console/bat.pro.in index 385d6a2084..828836d692 100644 --- a/bacula/src/qt-console/bat.pro.in +++ b/bacula/src/qt-console/bat.pro.in @@ -139,6 +139,10 @@ SOURCES += status/clientstat.cpp HEADERS += status/storstat.h SOURCES += status/storstat.cpp +# Utility sources +HEADERS += util/fmtwidgetitem.h +SOURCES += util/fmtwidgetitem.cpp + INSTALLS += bins INSTALLS += confs diff --git a/bacula/src/qt-console/console/console.cpp b/bacula/src/qt-console/console/console.cpp index 14d823b015..ec0e03376c 100644 --- a/bacula/src/qt-console/console/console.cpp +++ b/bacula/src/qt-console/console/console.cpp @@ -314,7 +314,10 @@ bool Console::sql_cmd(const char *query, QStringList &results) 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(); } diff --git a/bacula/src/qt-console/medialist/medialist.cpp b/bacula/src/qt-console/medialist/medialist.cpp index 54bfc0a91f..10469ce83b 100644 --- a/bacula/src/qt-console/medialist/medialist.cpp +++ b/bacula/src/qt-console/medialist/medialist.cpp @@ -37,12 +37,14 @@ #include #include +#include #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() { @@ -74,7 +76,7 @@ MediaList::~MediaList() */ void MediaList::populateTree() { - QTreeWidgetItem *mediatreeitem, *pooltreeitem; + QTreeWidgetItem *pooltreeitem; if (!m_console->preventInUseConnect()) return; @@ -82,14 +84,8 @@ void MediaList::populateTree() QStringList headerlist = (QStringList() << tr("Volume Name") << tr("Id") << tr("Status") << tr("Enabled") << tr("Bytes") << tr("Files") << tr("Jobs") << tr("Retention") << tr("Media Type") << tr("Slot") << tr("Use Duration") - << tr("Max Jobs") << tr("Max Files") << tr("Max Bytes") << tr("Recycle") << tr("Enabled") + << tr("Max Jobs") << tr("Max Files") << tr("Max Bytes") << tr("Recycle") << tr("RecyclePool") << tr("Last Written")); - int statusIndex = headerlist.indexOf("Status"); - QStringList flaglist = (QStringList() - << "L" << "R" << "L" << "R" << "BR" << "R" - << "R" << "RS" << "L" << "R" << "RS" - << "R" << "R" << "BR" << "R" << "R" - << "L" << "L"); m_checkcurwidget = false; if (m_populated) @@ -123,11 +119,11 @@ void MediaList::populateTree() " 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)" @@ -140,50 +136,80 @@ void MediaList::populateTree() } 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"); - int index = 0; - mediatreeitem = new QTreeWidgetItem(pooltreeitem); + if (fieldlist.size() < 18) + continue; // some fields missing, ignore row + + int index = 0; + 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); - } - if (flaglist[index].contains("B")) { - QString text; - bool okay; - qlonglong bytes = field.toULongLong(&okay); - if (okay){ - QString test = QString("%1").arg(bytes); - mainWin->hrConvert(text, bytes); - mediatreeitem->setText(index, text); - } else { Pmsg1(000, "conversion error %s\n", field.toUtf8().data()); } - } - if (flaglist[index].contains("S")) { - QString text; - bool okay; - qlonglong seconds = field.toULongLong(&okay); - if (okay){ - QString test = QString("%1").arg(seconds); - mainWin->hrConvertSeconds(text, seconds); - mediatreeitem->setText(index, text); - } else { Pmsg1(000, "conversion error %s\n", field.toUtf8().data()); } - } - if (flaglist[index].contains("R")) - mediatreeitem->setTextAlignment(index, Qt::AlignRight); - } - 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 */ @@ -194,17 +220,6 @@ void MediaList::populateTree() } } -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! */ diff --git a/bacula/src/qt-console/medialist/medialist.h b/bacula/src/qt-console/medialist/medialist.h index ded7677c46..c162c80d73 100644 --- a/bacula/src/qt-console/medialist/medialist.h +++ b/bacula/src/qt-console/medialist/medialist.h @@ -65,7 +65,6 @@ private slots: private: void createContextMenu(); - void setStatusColor(QTreeWidgetItem *, QString &, int &); void writeExpandedSettings(); QString m_currentVolumeName; QString m_currentVolumeId; diff --git a/bacula/src/qt-console/storage/storage.cpp b/bacula/src/qt-console/storage/storage.cpp index 388b88c3bb..f6b45ccc9a 100644 --- a/bacula/src/qt-console/storage/storage.cpp +++ b/bacula/src/qt-console/storage/storage.cpp @@ -42,6 +42,7 @@ #include "label/label.h" #include "mount/mount.h" #include "status/storstat.h" +#include "util/fmtwidgetitem.h" Storage::Storage() { @@ -72,7 +73,7 @@ Storage::~Storage() */ void Storage::populateTree() { - QTreeWidgetItem *storageItem, *topItem; + QTreeWidgetItem *topItem; if (!m_console->preventInUseConnect()) return; @@ -81,8 +82,9 @@ void Storage::populateTree() mp_treeWidget->clear(); m_checkcurwidget = true; - QStringList headerlist = (QStringList() << tr("Storage Name") << tr("Storage Id") - << tr("Auto Changer")); + QStringList headerlist = (QStringList() << tr("Name") << tr("Id") + << tr("Changer") << tr("Slot") << tr("Status") << tr("Enabled") << tr("Pool") + << tr("Media Type") ); topItem = new QTreeWidgetItem(mp_treeWidget); topItem->setText(0, tr("Storage")); @@ -93,10 +95,9 @@ void Storage::populateTree() 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" @@ -118,16 +119,16 @@ void Storage::populateTree() /* 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()); } } } @@ -137,6 +138,61 @@ void Storage::populateTree() 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 diff --git a/bacula/src/qt-console/storage/storage.h b/bacula/src/qt-console/storage/storage.h index 2632637ad7..173bd03a4e 100644 --- a/bacula/src/qt-console/storage/storage.h +++ b/bacula/src/qt-console/storage/storage.h @@ -64,6 +64,7 @@ private slots: private: void createContextMenu(); + void mediaList(QTreeWidgetItem *parent, const QString &storageID); QString m_currentStorage; int m_currentAutoChanger; bool m_populated; diff --git a/bacula/src/qt-console/util/fmtwidgetitem.cpp b/bacula/src/qt-console/util/fmtwidgetitem.cpp new file mode 100644 index 0000000000..99cba81535 --- /dev/null +++ b/bacula/src/qt-console/util/fmtwidgetitem.cpp @@ -0,0 +1,146 @@ +/* + 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@fsfeurope.org. +*/ + +/* + * Version $Id$ + * + * Helper functions for tree widget formatting + * + * Riccardo Ghetta, May 2008 + * + */ + +#include +#include +#include +#include +#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::setBoolFld(int index, int fld, bool center) +{ + if (fld) + 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); + } +} diff --git a/bacula/src/qt-console/util/fmtwidgetitem.h b/bacula/src/qt-console/util/fmtwidgetitem.h new file mode 100644 index 0000000000..2f6c35a736 --- /dev/null +++ b/bacula/src/qt-console/util/fmtwidgetitem.h @@ -0,0 +1,155 @@ +#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@fsfeurope.org. +*/ +/* + * 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); + void setBoolFld(int index, int 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_ */ +#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@fsfeurope.org. +*/ +/* + * 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_ */