/*
Bacula® - The Network Backup Solution
- Copyright (C) 2000-2007 Free Software Foundation Europe e.V.
+ Copyright (C) 2007-2008 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 plus additions
- that are listed in the file LICENSE.
+ 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
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA.
- Bacula® is a registered trademark of John Walker.
+ Bacula® is a registered trademark of Kern Sibbald.
The licensor of Bacula is the Free Software Foundation Europe
(FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
Switzerland, email:ftf@fsfeurope.org.
*/
/*
- * Version $Id: medialist.cpp 4230 2007-02-21 20:07:37Z kerns $
+ * Version $Id$
*
* MediaList Class
*
#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()
{
setupUi(this);
- m_name = "Media";
+ m_name = tr("Media");
pgInitialize();
QTreeWidgetItem* thisitem = mainWin->getFromHash(this);
- thisitem->setIcon(0,QIcon(QString::fromUtf8(":images/cartridge.svg")));
+ thisitem->setIcon(0,QIcon(QString::fromUtf8(":images/cartridge.png")));
/* mp_treeWidget, Storage Tree Tree Widget inherited from ui_medialist.h */
m_populated = false;
MediaList::~MediaList()
{
+ if (m_populated)
+ writeExpandedSettings();
}
/*
*/
void MediaList::populateTree()
{
- QTreeWidgetItem *mediatreeitem, *pooltreeitem, *topItem;
+ if (m_populated)
+ writeExpandedSettings();
+ m_populated = true;
if (!m_console->preventInUseConnect())
return;
+ Freeze frz(*mp_treeWidget); /* disable updating*/
+
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"
- << "RecyclePool" << "Last Written");
- int statusIndex = headerlist.indexOf("Status");
+ << 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("RecyclePool") << tr("Last Written"));
m_checkcurwidget = false;
mp_treeWidget->clear();
m_checkcurwidget = true;
mp_treeWidget->setColumnCount(headerlist.count());
- topItem = new QTreeWidgetItem(mp_treeWidget);
- topItem->setText(0, "Pools");
- topItem->setData(0, Qt::UserRole, 0);
- topItem->setExpanded(true);
+ m_topItem = new QTreeWidgetItem(mp_treeWidget);
+ m_topItem->setText(0, tr("Pools"));
+ m_topItem->setData(0, Qt::UserRole, 0);
+ m_topItem->setExpanded(true);
mp_treeWidget->setHeaderLabels(headerlist);
+ QSettings settings(m_console->m_dir->name(), "bat");
+ settings.beginGroup("MediaListTreeExpanded");
QString query;
+ QTreeWidgetItem *pooltreeitem;
foreach (QString pool_listItem, m_console->pool_list) {
- pooltreeitem = new QTreeWidgetItem(topItem);
+ pooltreeitem = new QTreeWidgetItem(m_topItem);
pooltreeitem->setText(0, pool_listItem);
pooltreeitem->setData(0, Qt::UserRole, 1);
- pooltreeitem->setExpanded(true);
+ if(settings.contains(pool_listItem)) {
+ pooltreeitem->setExpanded(settings.value(pool_listItem).toBool());
+ } else {
+ pooltreeitem->setExpanded(true);
+ }
query = "SELECT Media.VolumeName AS Media, "
" Media.MediaId AS Id, Media.VolStatus AS VolStatus,"
" 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"
- " LEFT OUTER JOIN Pool ON (Media.PoolId=Pool.PoolId)"
- " LEFT OUTER JOIN Pool AS Pol ON (Media.recyclepoolid=Pol.PoolId)"
+ " JOIN Pool ON (Media.PoolId=Pool.PoolId)"
+ " LEFT OUTER JOIN Pool AS Pol ON (Media.RecyclePoolId=Pol.PoolId)"
" WHERE";
query += " Pool.Name='" + pool_listItem + "'";
query += " ORDER BY Media";
}
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;
+ TreeItemFormatter 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 */
+ settings.endGroup();
/* Resize the columns */
for(int cnter=0; cnter<headerlist.count(); cnter++) {
mp_treeWidget->resizeColumnToContents(cnter);
}
}
-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!
*/
if (!m_populated) {
populateTree();
createContextMenu();
- m_populated=true;
}
}
if (m_checkcurwidget) {
/* The Previous item */
if (previouswidgetitem) { /* avoid a segfault if first time */
- mp_treeWidget->removeAction(actionEditVolume);
- mp_treeWidget->removeAction(actionListJobsOnVolume);
- mp_treeWidget->removeAction(actionDeleteVolume);
- mp_treeWidget->removeAction(actionPruneVolume);
- mp_treeWidget->removeAction(actionPurgeVolume);
- mp_treeWidget->removeAction(actionRelabelVolume);
- mp_treeWidget->removeAction(actionAllVolumesFromPool);
+ foreach(QAction* mediaAction, mp_treeWidget->actions()) {
+ mp_treeWidget->removeAction(mediaAction);
+ }
}
int treedepth = currentwidgetitem->data(0, Qt::UserRole).toInt();
m_currentVolumeName=currentwidgetitem->text(0);
+ mp_treeWidget->addAction(actionRefreshMediaList);
if (treedepth == 2){
m_currentVolumeId=currentwidgetitem->text(1);
mp_treeWidget->addAction(actionEditVolume);
mp_treeWidget->addAction(actionPruneVolume);
mp_treeWidget->addAction(actionPurgeVolume);
mp_treeWidget->addAction(actionRelabelVolume);
+ mp_treeWidget->addAction(actionVolumeFromPool);
} else if (treedepth == 1) {
-/* *******FIXME******
- * I can't seem to get "All volumes from pool" or "Volume from pool" to work
- * in one sentence command. Works when you do it one step at a time vi console
mp_treeWidget->addAction(actionAllVolumesFromPool);
-*/
}
}
}
void MediaList::createContextMenu()
{
mp_treeWidget->setContextMenuPolicy(Qt::ActionsContextMenu);
- mp_treeWidget->addAction(actionRefreshMediaList);
connect(actionEditVolume, SIGNAL(triggered()), this, SLOT(editVolume()));
connect(actionListJobsOnVolume, SIGNAL(triggered()), this, SLOT(showJobs()));
connect(actionDeleteVolume, SIGNAL(triggered()), this, SLOT(deleteVolume()));
/* connect to the action specific to this pages class */
connect(actionRefreshMediaList, SIGNAL(triggered()), this,
SLOT(populateTree()));
+ connect(actionAllVolumes, SIGNAL(triggered()), this, SLOT(allVolumes()));
connect(actionAllVolumesFromPool, SIGNAL(triggered()), this, SLOT(allVolumesFromPool()));
+ connect(actionVolumeFromPool, SIGNAL(triggered()), this, SLOT(volumeFromPool()));
}
/*
populateTree();
/* Create the context menu for the medialist tree */
createContextMenu();
- m_populated=true;
}
}
*/
void MediaList::deleteVolume()
{
- if (QMessageBox::warning(this, tr("Bat"),
+ if (QMessageBox::warning(this, "Bat",
tr("Are you sure you want to delete?? !!!.\n"
"This delete command is used to delete a Volume record and all associated catalog"
" records that were created. This command operates only on the Catalog"
*/
void MediaList::purgeVolume()
{
- if (QMessageBox::warning(this, tr("Bat"),
+ if (QMessageBox::warning(this, "Bat",
tr("Are you sure you want to purge ?? !!!.\n"
"The Purge command will delete associated Catalog database records from Jobs and"
" Volumes without considering the retention period. Purge works only on the"
*/
void MediaList::allVolumesFromPool()
{
- QString cmd("update pool=");
- cmd += m_currentVolumeName + " All Volumes From Pool";
+ QString cmd = "update volume AllFromPool=" + m_currentVolumeName;
+ consoleCommand(cmd);
+ populateTree();
+}
+
+void MediaList::allVolumes()
+{
+ QString cmd = "update volume allfrompools";
+ consoleCommand(cmd);
+ populateTree();
+}
+
+/*
+ * Called from the signal of the context sensitive menu to purge!
+ */
+void MediaList::volumeFromPool()
+{
+ QTreeWidgetItem *currentItem = mp_treeWidget->currentItem();
+ QTreeWidgetItem *parent = currentItem->parent();
+ QString pool = parent->text(0);
+ QString cmd;
+ cmd = "update volume=" + m_currentVolumeName + " frompool=" + pool;
consoleCommand(cmd);
populateTree();
}
+
+/*
+ * Write settings to save expanded states of the pools
+ */
+void MediaList::writeExpandedSettings()
+{
+ if (m_topItem) {
+ QSettings settings(m_console->m_dir->name(), "bat");
+ settings.beginGroup("MediaListTreeExpanded");
+ int childcount = m_topItem->childCount();
+ for (int cnt=0; cnt<childcount; cnt++) {
+ QTreeWidgetItem *poolitem = m_topItem->child(cnt);
+ settings.setValue(poolitem->text(0), poolitem->isExpanded());
+ }
+ settings.endGroup();
+ }
+}