X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=bacula%2Fsrc%2Fqt-console%2Fclients%2Fclients.cpp;h=37f288a94f0fb943a02cdd730846353ed68fa28e;hb=513c2c6cf9c7991273cf3330404575aafae6d8a2;hp=81ec330bf79535c3d4e8016e78d9e78d12e1be74;hpb=d82f42248a6cf071e946814fe21dcb61ff436c29;p=bacula%2Fbacula diff --git a/bacula/src/qt-console/clients/clients.cpp b/bacula/src/qt-console/clients/clients.cpp index 81ec330bf7..37f288a94f 100644 --- a/bacula/src/qt-console/clients/clients.cpp +++ b/bacula/src/qt-console/clients/clients.cpp @@ -1,61 +1,54 @@ /* - 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 plus additions - that are listed 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: client.cpp 4230 2007-02-21 20:07:37Z kerns $ - * * Clients Class * * Dirk Bartley, March 2007 * */ +#include "bat.h" #include #include -#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 = "Clients"; + m_name = tr("Clients"); pgInitialize(); QTreeWidgetItem* thisitem = mainWin->getFromHash(this); thisitem->setIcon(0,QIcon(QString::fromUtf8(":images/network-server.png"))); - /* mp_treeWidget, Storage Tree Tree Widget inherited from ui_client.h */ + /* tableWidget, Storage Tree Tree Widget inherited from ui_client.h */ 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(); } Clients::~Clients() @@ -63,76 +56,126 @@ 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::populateTree() +void Clients::populateTable() { - QTreeWidgetItem *clientItem, *topItem; + m_populated = true; - if (!m_console->preventInUseConnect()) - return; - m_checkcurwidget = false; - mp_treeWidget->clear(); - m_checkcurwidget = true; + Freeze frz(*tableWidget); /* disable updating*/ - QStringList headerlist = (QStringList() << "Client Name" << "File Retention" - << "Job Retention" << "AutoPrune" << "ClientId" << "Uname" ); + QStringList headerlist = (QStringList() << tr("Client Name") << tr("File Retention") + << tr("Job Retention") << tr("AutoPrune") << tr("ClientId") << tr("Uname") ); - topItem = new QTreeWidgetItem(mp_treeWidget); - topItem->setText(0, "Clients"); - topItem->setData(0, Qt::UserRole, 0); - topItem->setExpanded(true); + int sortcol = headerlist.indexOf(tr("Client Name")); + Qt::SortOrder sortord = Qt::AscendingOrder; + if (tableWidget->rowCount()) { + sortcol = tableWidget->horizontalHeader()->sortIndicatorSection(); + sortord = tableWidget->horizontalHeader()->sortIndicatorOrder(); + } - mp_treeWidget->setColumnCount(headerlist.count()); - mp_treeWidget->setHeaderLabels(headerlist); + 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(); + 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){ - clientItem = new QTreeWidgetItem(topItem); - clientItem->setText(0, clientName); - clientItem->setData(0, Qt::UserRole, 1); - clientItem->setExpanded(true); + if (first) { + client_comsep += "'" + clientName + "'"; + first = false; + } + else + client_comsep += ",'" + clientName + "'"; + } - /* Set up query QString and header QStringList */ + if (client_comsep != "") { QString query(""); - query += "SELECT FileRetention, JobRetention, AutoPrune, ClientId, Uname" + query += "SELECT Name, FileRetention, JobRetention, AutoPrune, ClientId, Uname" " FROM Client" - " WHERE "; - query += " Name='" + clientName + "'"; - query += " ORDER BY Name"; + " 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 == 1){ - QString resultline; - QString field; - QStringList fieldlist; - /* 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 */ - clientItem->setData(index+1, Qt::UserRole, 1); - /* Put media fields under the pool tree item */ - clientItem->setData(index+1, Qt::UserRole, 1); - clientItem->setText(index+1, field); - index++; - } + 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 */ + 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++; } } } - /* Resize the columns */ - for(int cnter=0; cnterresizeColumnToContents(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; } /* @@ -142,9 +185,10 @@ void Clients::populateTree() void Clients::PgSeltreeWidgetClicked() { if(!m_populated) { - populateTree(); - createContextMenu(); - m_populated=true; + populateTable(); + } + if (!isOnceDocked()) { + dockPage(); } } @@ -152,30 +196,29 @@ void Clients::PgSeltreeWidgetClicked() * Added to set the context menu policy based on currently active treeWidgetItem * signaled by currentItemChanged */ -void Clients::treeItemChanged(QTreeWidgetItem *currentwidgetitem, QTreeWidgetItem *previouswidgetitem ) +void Clients::tableItemChanged(QTableWidgetItem *currentwidgetitem, QTableWidgetItem *previouswidgetitem ) { /* m_checkcurwidget checks to see if this is during a refresh, which will segfault */ if (m_checkcurwidget) { + int currentRow = currentwidgetitem->row(); + QTableWidgetItem *currentrowzeroitem = tableWidget->item(currentRow, 0); + m_currentlyselected = currentrowzeroitem->text(); + /* 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(actionListJobsofClient); - mp_treeWidget->removeAction(actionStatusClientInConsole); - mp_treeWidget->removeAction(actionPurgeJobs); - mp_treeWidget->removeAction(actionPrune); - } + tableWidget->removeAction(actionListJobsofClient); + tableWidget->removeAction(actionStatusClientWindow); + tableWidget->removeAction(actionPurgeJobs); + tableWidget->removeAction(actionPrune); } - int treedepth = currentwidgetitem->data(0, Qt::UserRole).toInt(); - if (treedepth == 1){ + if (m_currentlyselected.length() != 0) { /* set a hold variable to the client name in case the context sensitive * menu is used */ - m_currentlyselected=currentwidgetitem->text(0); - mp_treeWidget->addAction(actionListJobsofClient); - mp_treeWidget->addAction(actionStatusClientInConsole); - mp_treeWidget->addAction(actionPurgeJobs); - mp_treeWidget->addAction(actionPrune); + tableWidget->addAction(actionListJobsofClient); + tableWidget->addAction(actionStatusClientWindow); + tableWidget->addAction(actionPurgeJobs); + tableWidget->addAction(actionPrune); } } } @@ -187,18 +230,20 @@ void Clients::treeItemChanged(QTreeWidgetItem *currentwidgetitem, QTreeWidgetIte */ void Clients::createContextMenu() { - mp_treeWidget->setContextMenuPolicy(Qt::ActionsContextMenu); - mp_treeWidget->addAction(actionRefreshClients); - connect(mp_treeWidget, SIGNAL( - currentItemChanged(QTreeWidgetItem *, QTreeWidgetItem *)), - this, SLOT(treeItemChanged(QTreeWidgetItem *, QTreeWidgetItem *))); + tableWidget->setContextMenuPolicy(Qt::ActionsContextMenu); + tableWidget->addAction(actionRefreshClients); + /* for the tableItemChanged to maintain m_currentJob */ + connect(tableWidget, SIGNAL( + currentItemChanged(QTableWidgetItem *, QTableWidgetItem *)), + this, SLOT(tableItemChanged(QTableWidgetItem *, QTableWidgetItem *))); + /* connect to the action specific to this pages class */ connect(actionRefreshClients, SIGNAL(triggered()), this, - SLOT(populateTree())); + 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, SLOT(consolePurgeJobs())); connect(actionPrune, SIGNAL(triggered()), this, @@ -211,9 +256,8 @@ void Clients::createContextMenu() */ void Clients::showJobs() { - QString emptymedia(""); QTreeWidgetItem *parentItem = mainWin->getFromHash(this); - mainWin->createPageJobList(emptymedia, m_currentlyselected, parentItem); + mainWin->createPageJobList("", m_currentlyselected, "", "", parentItem); } /* @@ -233,10 +277,8 @@ void Clients::consoleStatusClient() void Clients::currentStackItem() { if(!m_populated) { - populateTree(); - /* Create the context menu for the client tree */ - createContextMenu(); - m_populated=true; + populateTable(); + /* Create the context menu for the client table */ } } @@ -245,18 +287,19 @@ void Clients::currentStackItem() */ void Clients::consolePurgeJobs() { - if (QMessageBox::warning(this, tr("Bat"), - tr("Are you sure you want to purge ?? !!!.\n" + if (QMessageBox::warning(this, "Bat", + 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" " be dangerous because you can delete catalog records associated with current" " backups of files, and we recommend that you do not use it unless you know what" " you are doing.\n\n" -" Is there any way I can get you to Click cancel here. You really don't want to do" +" 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="); @@ -272,3 +315,41 @@ void Clients::prune() new prunePage("", m_currentlyselected); } +/* + * Function responding to action to create new client status window + */ +void Clients::statusClientWindow() +{ + /* 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(); +}