]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/qt-console/clients/clients.cpp
Correct incorrect placement of trap for m_firstpopulated.
[bacula/bacula] / bacula / src / qt-console / clients / clients.cpp
1 /*
2    Bacula® - The Network Backup Solution
3
4    Copyright (C) 2007-2009 Free Software Foundation Europe e.V.
5
6    The main author of Bacula is Kern Sibbald, with contributions from
7    many others, a complete list can be found in the file AUTHORS.
8    This program is Free Software; you can redistribute it and/or
9    modify it under the terms of version two of the GNU General Public
10    License as published by the Free Software Foundation and included
11    in the file LICENSE.
12
13    This program is distributed in the hope that it will be useful, but
14    WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16    General Public License for more details.
17
18    You should have received a copy of the GNU General Public License
19    along with this program; if not, write to the Free Software
20    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21    02110-1301, USA.
22
23    Bacula® is a registered trademark of Kern Sibbald.
24    The licensor of Bacula is the Free Software Foundation Europe
25    (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
26    Switzerland, email:ftf@fsfeurope.org.
27 */
28  
29 /*
30  *   Version $Id$
31  *
32  *  Clients Class
33  *
34  *   Dirk Bartley, March 2007
35  *
36  */ 
37
38 #include "bat.h"
39 #include <QAbstractEventDispatcher>
40 #include <QMenu>
41 #include "clients/clients.h"
42 #include "run/run.h"
43 #include "status/clientstat.h"
44 #include "util/fmtwidgetitem.h"
45
46 Clients::Clients()
47 {
48    setupUi(this);
49    m_name = tr("Clients");
50    pgInitialize();
51    QTreeWidgetItem* thisitem = mainWin->getFromHash(this);
52    thisitem->setIcon(0,QIcon(QString::fromUtf8(":images/network-server.png")));
53
54    /* tableWidget, Storage Tree Tree Widget inherited from ui_client.h */
55    m_populated = false;
56    m_checkcurwidget = true;
57    m_closeable = false;
58    m_firstpopulation = true;
59    /* add context sensitive menu items specific to this classto the page
60     * selector tree. m_contextActions is QList of QActions */
61    m_contextActions.append(actionRefreshClients);
62    createContextMenu();
63    dockPage();
64 }
65
66 Clients::~Clients()
67 {
68 }
69
70 /*
71  * The main meat of the class!!  The function that querries the director and 
72  * creates the widgets with appropriate values.
73  */
74 void Clients::populateTable()
75 {
76    m_populated = true;
77
78    Freeze frz(*tableWidget); /* disable updating*/
79
80    QStringList headerlist = (QStringList() << tr("Client Name") << tr("File Retention")
81        << tr("Job Retention") << tr("AutoPrune") << tr("ClientId") << tr("Uname") );
82
83    int sortcol = headerlist.indexOf(tr("Client Name"));
84    Qt::SortOrder sortord = Qt::AscendingOrder;
85    if (tableWidget->rowCount()) {
86       sortcol = tableWidget->horizontalHeader()->sortIndicatorSection();
87       sortord = tableWidget->horizontalHeader()->sortIndicatorOrder();
88    }
89
90    m_checkcurwidget = false;
91    tableWidget->clear();
92    m_checkcurwidget = true;
93
94    tableWidget->setColumnCount(headerlist.count());
95    tableWidget->setHorizontalHeaderLabels(headerlist);
96    tableWidget->horizontalHeader()->setHighlightSections(false);
97    tableWidget->setRowCount(m_console->client_list.count());
98    tableWidget->verticalHeader()->hide();
99    tableWidget->setSelectionBehavior(QAbstractItemView::SelectRows);
100    tableWidget->setSelectionMode(QAbstractItemView::SingleSelection);
101    tableWidget->setSortingEnabled(false); /* rows move on insert if sorting enabled */
102    bool first = true;
103    QString client_comsep("");
104    foreach (QString clientName, m_console->client_list){
105       if (first) {
106          client_comsep += "'" + clientName + "'";
107          first = false;
108       }
109       else
110          client_comsep += ",'" + clientName + "'";
111    }
112
113    if (client_comsep != "") {
114       QString query("");
115       query += "SELECT Name, FileRetention, JobRetention, AutoPrune, ClientId, Uname"
116            " FROM Client"
117            " WHERE ClientId IN (SELECT MAX(ClientId) FROM Client WHERE";
118       query += " Name IN (" + client_comsep + ")";
119       query += " GROUP BY Name) ORDER BY Name";
120
121       QStringList results;
122       if (mainWin->m_sqlDebug)
123          Pmsg1(000, "Clients query cmd : %s\n",query.toUtf8().data());
124       if (m_console->sql_cmd(query, results)) {
125          int row = 0;
126
127          /* Iterate through the record returned from the query */
128          foreach (QString resultline, results) {
129             QStringList fieldlist = resultline.split("\t");
130
131             if (m_firstpopulation) {
132                settingsOpenStatus(fieldlist[0]);
133             }
134
135             TableItemFormatter item(*tableWidget, row);
136
137             /* Iterate through fields in the record */
138             QStringListIterator fld(fieldlist);
139             int col = 0;
140
141             /* name */
142             item.setTextFld(col++, fld.next());
143
144             /* file retention */
145             item.setDurationFld(col++, fld.next());
146
147             /* job retention */
148             item.setDurationFld(col++, fld.next());
149
150             /* autoprune */
151             item.setBoolFld(col++, fld.next());
152
153             /* client id */
154             item.setNumericFld(col++, fld.next());
155
156             /* uname */
157             item.setTextFld(col++, fld.next());
158
159             row++;
160          }
161       }
162    }
163    /* set default sorting */
164    tableWidget->sortByColumn(sortcol, sortord);
165    tableWidget->setSortingEnabled(true);
166    
167    /* Resize rows and columns */
168    tableWidget->resizeColumnsToContents();
169    tableWidget->resizeRowsToContents();
170
171    /* make read only */
172    int rcnt = tableWidget->rowCount();
173    int ccnt = tableWidget->columnCount();
174    for(int r=0; r < rcnt; r++) {
175       for(int c=0; c < ccnt; c++) {
176          QTableWidgetItem* item = tableWidget->item(r, c);
177          if (item) {
178             item->setFlags(Qt::ItemFlags(item->flags() & (~Qt::ItemIsEditable)));
179          }
180       }
181    }
182    m_firstpopulation = false;
183 }
184
185 /*
186  * When the treeWidgetItem in the page selector tree is singleclicked, Make sure
187  * The tree has been populated.
188  */
189 void Clients::PgSeltreeWidgetClicked()
190 {
191    if(!m_populated) {
192       populateTable();
193    }
194 }
195
196 /*
197  * Added to set the context menu policy based on currently active treeWidgetItem
198  * signaled by currentItemChanged
199  */
200 void Clients::tableItemChanged(QTableWidgetItem *currentwidgetitem, QTableWidgetItem *previouswidgetitem )
201 {
202    /* m_checkcurwidget checks to see if this is during a refresh, which will segfault */
203    if (m_checkcurwidget) {
204       int currentRow = currentwidgetitem->row();
205       QTableWidgetItem *currentrowzeroitem = tableWidget->item(currentRow, 0);
206       m_currentlyselected = currentrowzeroitem->text();
207
208       /* The Previous item */
209       if (previouswidgetitem) { /* avoid a segfault if first time */
210          tableWidget->removeAction(actionListJobsofClient);
211          tableWidget->removeAction(actionStatusClientInConsole);
212          tableWidget->removeAction(actionStatusClientWindow);
213          tableWidget->removeAction(actionPurgeJobs);
214          tableWidget->removeAction(actionPrune);
215       }
216
217       if (m_currentlyselected.length() != 0) {
218          /* set a hold variable to the client name in case the context sensitive
219           * menu is used */
220          tableWidget->addAction(actionListJobsofClient);
221          tableWidget->addAction(actionStatusClientInConsole);
222          tableWidget->addAction(actionStatusClientWindow);
223          tableWidget->addAction(actionPurgeJobs);
224          tableWidget->addAction(actionPrune);
225       }
226    }
227 }
228
229 /* 
230  * Setup a context menu 
231  * Made separate from populate so that it would not create context menu over and
232  * over as the tree is repopulated.
233  */
234 void Clients::createContextMenu()
235 {
236    tableWidget->setContextMenuPolicy(Qt::ActionsContextMenu);
237    tableWidget->addAction(actionRefreshClients);
238    /* for the tableItemChanged to maintain m_currentJob */
239    connect(tableWidget, SIGNAL(
240            currentItemChanged(QTableWidgetItem *, QTableWidgetItem *)),
241            this, SLOT(tableItemChanged(QTableWidgetItem *, QTableWidgetItem *)));
242
243    /* connect to the action specific to this pages class */
244    connect(actionRefreshClients, SIGNAL(triggered()), this,
245                 SLOT(populateTable()));
246    connect(actionListJobsofClient, SIGNAL(triggered()), this,
247                 SLOT(showJobs()));
248    connect(actionStatusClientInConsole, SIGNAL(triggered()), this,
249                 SLOT(consoleStatusClient()));
250    connect(actionStatusClientWindow, SIGNAL(triggered()), this,
251                 SLOT(statusClientWindow()));
252    connect(actionPurgeJobs, SIGNAL(triggered()), this,
253                 SLOT(consolePurgeJobs()));
254    connect(actionPrune, SIGNAL(triggered()), this,
255                 SLOT(prune()));
256 }
257
258 /*
259  * Function responding to actionListJobsofClient which calls mainwin function
260  * to create a window of a list of jobs of this client.
261  */
262 void Clients::showJobs()
263 {
264    QTreeWidgetItem *parentItem = mainWin->getFromHash(this);
265    mainWin->createPageJobList("", m_currentlyselected, "", "", parentItem);
266 }
267
268 /*
269  * Function responding to actionListJobsofClient which calls mainwin function
270  * to create a window of a list of jobs of this client.
271  */
272 void Clients::consoleStatusClient()
273 {
274    QString cmd("status client=");
275    cmd += m_currentlyselected;
276    consoleCommand(cmd);
277 }
278
279 /*
280  * Virtual function which is called when this page is visible on the stack
281  */
282 void Clients::currentStackItem()
283 {
284    if(!m_populated) {
285       populateTable();
286       /* Create the context menu for the client table */
287    }
288 }
289
290 /*
291  * Function responding to actionPurgeJobs 
292  */
293 void Clients::consolePurgeJobs()
294 {
295    if (QMessageBox::warning(this, "Bat",
296       tr("Are you sure you want to purge all jobs of client \"%1\" ?\n"
297 "The Purge command will delete associated Catalog database records from Jobs and"
298 " Volumes without considering the retention period. Purge  works only on the"
299 " Catalog database and does not affect data written to Volumes. This command can"
300 " be dangerous because you can delete catalog records associated with current"
301 " backups of files, and we recommend that you do not use it unless you know what"
302 " you are doing.\n\n"
303 " Is there any way I can get you to click Cancel here?  You really don't want to do"
304 " this\n\n"
305          "Press OK to proceed with the purge operation?").arg(m_currentlyselected),
306          QMessageBox::Ok | QMessageBox::Cancel,
307          QMessageBox::Cancel)
308       == QMessageBox::Cancel) { return; }
309
310    QString cmd("purge jobs client=");
311    cmd += m_currentlyselected;
312    consoleCommand(cmd);
313 }
314
315 /*
316  * Function responding to actionPrune
317  */
318 void Clients::prune()
319 {
320    new prunePage("", m_currentlyselected);
321 }
322
323 /*
324  * Function responding to action to create new client status window
325  */
326 void Clients::statusClientWindow()
327 {
328    /* if one exists, then just set it current */
329    bool found = false;
330    foreach(Pages *page, mainWin->m_pagehash) {
331       if (mainWin->currentConsole() == page->console()) {
332          if (page->name() == tr("Client Status %1").arg(m_currentlyselected)) {
333             found = true;
334             page->setCurrent();
335          }
336       }
337    }
338    if (!found) {
339       QTreeWidgetItem *parentItem = mainWin->getFromHash(this);
340       new ClientStat(m_currentlyselected, parentItem);
341    }
342 }
343
344 /*
345  * If first time, then check to see if there were status pages open the last time closed
346  * if so open
347  */
348 void Clients::settingsOpenStatus(QString &client)
349 {
350    QSettings settings(m_console->m_dir->name(), "bat");
351
352    settings.beginGroup("OpenOnExit");
353    QString toRead = "ClientStatus_" + client;
354    if (settings.value(toRead) == 1) {
355       Pmsg1(000, "Do open Client Status window for : %s\n", client.toUtf8().data());
356       new ClientStat(client, mainWin->getFromHash(this));
357       setCurrent();
358       mainWin->getFromHash(this)->setExpanded(true);
359    } else {
360       Pmsg1(000, "Do NOT open Client Status window for : %s\n", client.toUtf8().data());
361    }
362    settings.endGroup();
363 }