]> git.sur5r.net Git - bacula/bacula/blobdiff - bacula/src/qt-console/clients/clients.cpp
Change copyright as per agreement with FSFE
[bacula/bacula] / bacula / src / qt-console / clients / clients.cpp
index e38e7e4c392151b100c1e1f2d29cbfca77456762..37f288a94f0fb943a02cdd730846353ed68fa28e 100644 (file)
@@ -1,48 +1,38 @@
 /*
-   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");
@@ -54,11 +44,11 @@ Clients::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()
@@ -66,71 +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::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;
 }
 
 /*
@@ -141,7 +186,9 @@ void Clients::PgSeltreeWidgetClicked()
 {
    if(!m_populated) {
       populateTable();
-      m_populated=true;
+   }
+   if (!isOnceDocked()) {
+      dockPage();
    }
 }
 
@@ -160,7 +207,6 @@ void Clients::tableItemChanged(QTableWidgetItem *currentwidgetitem, QTableWidget
       /* 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);
@@ -170,7 +216,6 @@ void Clients::tableItemChanged(QTableWidgetItem *currentwidgetitem, QTableWidget
          /* 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);
@@ -197,8 +242,6 @@ void Clients::createContextMenu()
                 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,
@@ -236,7 +279,6 @@ void Clients::currentStackItem()
    if(!m_populated) {
       populateTable();
       /* Create the context menu for the client table */
-      m_populated=true;
    }
 }
 
@@ -246,7 +288,7 @@ void Clients::currentStackItem()
 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"
@@ -255,8 +297,9 @@ void Clients::consolePurgeJobs()
 " 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=");
@@ -277,6 +320,36 @@ void Clients::prune()
  */
 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();
 }