/*
- Bacula® - The Network Backup Solution
-
- 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 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.
+ Bacula(R) - The Network Backup Solution
+
+ Copyright (C) 2000-2016 Kern Sibbald
+
+ The original author of Bacula is Kern Sibbald, with contributions
+ from many others, a complete list can be found in the file AUTHORS.
+
+ You may use this file and others of this release according to the
+ license defined in the LICENSE file, which includes the Affero General
+ Public License, v3.0 ("AGPLv3") and some additional permissions and
+ terms pursuant to its AGPLv3 Section 7.
+
+ This notice must be preserved when any source code is
+ conveyed and/or propagated.
+
+ Bacula(R) is a registered trademark of Kern Sibbald.
*/
/*
- * Version $Id$
- *
* Clients Class
*
* Dirk Bartley, March 2007
*
*/
+#include "bat.h"
#include <QAbstractEventDispatcher>
#include <QMenu>
-#include "bat.h"
#include "clients/clients.h"
#include "run/run.h"
#include "status/clientstat.h"
+#include "util/fmtwidgetitem.h"
-Clients::Clients()
+Clients::Clients() : Pages()
{
setupUi(this);
m_name = tr("Clients");
m_populated = false;
m_checkcurwidget = true;
m_closeable = false;
+ m_firstpopulation = true;
/* add context sensitive menu items specific to this classto the page
* selector tree. m_contextActions is QList of QActions */
m_contextActions.append(actionRefreshClients);
createContextMenu();
- dockPage();
}
Clients::~Clients()
}
/*
- * The main meat of the class!! The function that querries the director and
+ * The main meat of the class!! The function that queries the director and
* creates the widgets with appropriate values.
*/
void Clients::populateTable()
{
- QTableWidgetItem *tableItem;
- QBrush blackBrush(Qt::black);
+ m_populated = true;
- if (!m_console->preventInUseConnect())
- return;
- m_checkcurwidget = false;
- tableWidget->clear();
- m_checkcurwidget = true;
+ Freeze frz(*tableWidget); /* disable updating*/
QStringList headerlist = (QStringList() << tr("Client Name") << tr("File Retention")
<< tr("Job Retention") << tr("AutoPrune") << tr("ClientId") << tr("Uname") );
+ int sortcol = headerlist.indexOf(tr("Client Name"));
+ Qt::SortOrder sortord = Qt::AscendingOrder;
+ if (tableWidget->rowCount()) {
+ sortcol = tableWidget->horizontalHeader()->sortIndicatorSection();
+ sortord = tableWidget->horizontalHeader()->sortIndicatorOrder();
+ }
+
+ m_checkcurwidget = false;
+ tableWidget->clear();
+ m_checkcurwidget = true;
+
tableWidget->setColumnCount(headerlist.count());
tableWidget->setHorizontalHeaderLabels(headerlist);
+ tableWidget->horizontalHeader()->setHighlightSections(false);
tableWidget->setRowCount(m_console->client_list.count());
tableWidget->verticalHeader()->hide();
- int row = 0;
-
+ tableWidget->setSelectionBehavior(QAbstractItemView::SelectRows);
+ tableWidget->setSelectionMode(QAbstractItemView::SingleSelection);
+ tableWidget->setSortingEnabled(false); /* rows move on insert if sorting enabled */
+ bool first = true;
+ QString client_comsep("");
foreach (QString clientName, m_console->client_list){
- /* Set up query QString and header QStringList */
+ if (first) {
+ client_comsep += "'" + clientName + "'";
+ first = false;
+ }
+ else
+ client_comsep += ",'" + clientName + "'";
+ }
+
+ if (client_comsep != "") {
QString query("");
query += "SELECT Name, FileRetention, JobRetention, AutoPrune, ClientId, Uname"
" FROM Client"
- " WHERE ";
- query += " Name='" + clientName + "'";
- query += " ORDER BY ClientId LIMIT 1";
+ " WHERE ClientId IN (SELECT MAX(ClientId) FROM Client WHERE";
+ query += " Name IN (" + client_comsep + ")";
+ query += " GROUP BY Name) ORDER BY Name";
QStringList results;
- /* This could be a log item */
- if (mainWin->m_sqlDebug) {
+ if (mainWin->m_sqlDebug)
Pmsg1(000, "Clients query cmd : %s\n",query.toUtf8().data());
- }
if (m_console->sql_cmd(query, results)) {
- int resultCount = results.count();
- if (resultCount){
- QString resultline;
- QString field;
- QStringList fieldlist;
- resultline = results[resultCount - 1];
- fieldlist = resultline.split("\t");
-
- int column = 0;
+ int row = 0;
+
+ /* Iterate through the record returned from the query */
+ foreach (QString resultline, results) {
+ QStringList fieldlist = resultline.split("\t");
+
+ if (fieldlist.size() < 5) { // Uname is checked after
+ Pmsg1(0, "Unexpected line %s\n", resultline.toUtf8().data());
+ continue;
+ }
+ if (m_firstpopulation) {
+ settingsOpenStatus(fieldlist[0]);
+ }
+
+ TableItemFormatter item(*tableWidget, row);
+
/* Iterate through fields in the record */
- foreach (field, fieldlist) {
- field = field.trimmed(); /* strip leading & trailing spaces */
- tableItem = new QTableWidgetItem(field, 1);
- tableItem->setFlags(Qt::ItemIsSelectable);
- tableItem->setForeground(blackBrush);
- tableItem->setData(Qt::UserRole, 1);
- tableWidget->setItem(row, column, tableItem);
- column++;
+ QStringListIterator fld(fieldlist);
+ int col = 0;
+
+ /* name */
+ item.setTextFld(col++, fld.next());
+
+ /* file retention */
+ item.setDurationFld(col++, fld.next());
+
+ /* job retention */
+ item.setDurationFld(col++, fld.next());
+
+ /* autoprune */
+ item.setBoolFld(col++, fld.next());
+
+ /* client id */
+ item.setNumericFld(col++, fld.next());
+
+ /* uname */
+ if (fld.hasNext()) {
+ item.setTextFld(col++, fld.next());
+ } else {
+ item.setTextFld(col++, "");
}
+
+ row++;
}
}
- row ++;
}
- /* Resize the columns */
- for(int cnter=0; cnter<headerlist.size(); cnter++) {
- tableWidget->resizeColumnToContents(cnter);
+ /* set default sorting */
+ tableWidget->sortByColumn(sortcol, sortord);
+ tableWidget->setSortingEnabled(true);
+
+ /* Resize rows and columns */
+ tableWidget->resizeColumnsToContents();
+ tableWidget->resizeRowsToContents();
+
+ /* make read only */
+ int rcnt = tableWidget->rowCount();
+ int ccnt = tableWidget->columnCount();
+ for(int r=0; r < rcnt; r++) {
+ for(int c=0; c < ccnt; c++) {
+ QTableWidgetItem* item = tableWidget->item(r, c);
+ if (item) {
+ item->setFlags(Qt::ItemFlags(item->flags() & (~Qt::ItemIsEditable)));
+ }
+ }
}
+ m_firstpopulation = false;
}
/*
{
if(!m_populated) {
populateTable();
- m_populated=true;
+ }
+ if (!isOnceDocked()) {
+ dockPage();
}
}
/* The Previous item */
if (previouswidgetitem) { /* avoid a segfault if first time */
tableWidget->removeAction(actionListJobsofClient);
- tableWidget->removeAction(actionStatusClientInConsole);
tableWidget->removeAction(actionStatusClientWindow);
tableWidget->removeAction(actionPurgeJobs);
tableWidget->removeAction(actionPrune);
/* set a hold variable to the client name in case the context sensitive
* menu is used */
tableWidget->addAction(actionListJobsofClient);
- tableWidget->addAction(actionStatusClientInConsole);
tableWidget->addAction(actionStatusClientWindow);
tableWidget->addAction(actionPurgeJobs);
tableWidget->addAction(actionPrune);
SLOT(populateTable()));
connect(actionListJobsofClient, SIGNAL(triggered()), this,
SLOT(showJobs()));
- connect(actionStatusClientInConsole, SIGNAL(triggered()), this,
- SLOT(consoleStatusClient()));
connect(actionStatusClientWindow, SIGNAL(triggered()), this,
SLOT(statusClientWindow()));
connect(actionPurgeJobs, SIGNAL(triggered()), this,
if(!m_populated) {
populateTable();
/* Create the context menu for the client table */
- m_populated=true;
}
}
void Clients::consolePurgeJobs()
{
if (QMessageBox::warning(this, "Bat",
- tr("Are you sure you want to purge ?? !!!.\n"
+ tr("Are you sure you want to purge all jobs of client \"%1\" ?\n"
"The Purge command will delete associated Catalog database records from Jobs and"
" Volumes without considering the retention period. Purge works only on the"
" Catalog database and does not affect data written to Volumes. This command can"
" you are doing.\n\n"
" Is there any way I can get you to click Cancel here? You really don't want to do"
" this\n\n"
- "Press OK to proceed with the purge operation?"),
- QMessageBox::Ok | QMessageBox::Cancel)
+ "Press OK to proceed with the purge operation?").arg(m_currentlyselected),
+ QMessageBox::Ok | QMessageBox::Cancel,
+ QMessageBox::Cancel)
== QMessageBox::Cancel) { return; }
QString cmd("purge jobs client=");
*/
void Clients::statusClientWindow()
{
- QTreeWidgetItem *parentItem = mainWin->getFromHash(this);
- new ClientStat(m_currentlyselected, parentItem);
+ /* if one exists, then just set it current */
+ bool found = false;
+ foreach(Pages *page, mainWin->m_pagehash) {
+ if (mainWin->currentConsole() == page->console()) {
+ if (page->name() == tr("Client Status %1").arg(m_currentlyselected)) {
+ found = true;
+ page->setCurrent();
+ }
+ }
+ }
+ if (!found) {
+ QTreeWidgetItem *parentItem = mainWin->getFromHash(this);
+ new ClientStat(m_currentlyselected, parentItem);
+ }
+}
+
+/*
+ * If first time, then check to see if there were status pages open the last time closed
+ * if so open
+ */
+void Clients::settingsOpenStatus(QString &client)
+{
+ QSettings settings(m_console->m_dir->name(), "bat");
+
+ settings.beginGroup("OpenOnExit");
+ QString toRead = "ClientStatus_" + client;
+ if (settings.value(toRead) == 1) {
+ new ClientStat(client, mainWin->getFromHash(this));
+ setCurrent();
+ mainWin->getFromHash(this)->setExpanded(true);
+ }
+ settings.endGroup();
}