]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/qt-console/clients/clients.cpp
d336f4e2fe2b0d92eccf3cde5d94126216714862
[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 }
64
65 Clients::~Clients()
66 {
67 }
68
69 /*
70  * The main meat of the class!!  The function that querries the director and 
71  * creates the widgets with appropriate values.
72  */
73 void Clients::populateTable()
74 {
75    m_populated = true;
76
77    Freeze frz(*tableWidget); /* disable updating*/
78
79    QStringList headerlist = (QStringList() << tr("Client Name") << tr("File Retention")
80        << tr("Job Retention") << tr("AutoPrune") << tr("ClientId") << tr("Uname") );
81
82    int sortcol = headerlist.indexOf(tr("Client Name"));
83    Qt::SortOrder sortord = Qt::AscendingOrder;
84    if (tableWidget->rowCount()) {
85       sortcol = tableWidget->horizontalHeader()->sortIndicatorSection();
86       sortord = tableWidget->horizontalHeader()->sortIndicatorOrder();
87    }
88
89    m_checkcurwidget = false;
90    tableWidget->clear();
91    m_checkcurwidget = true;
92
93    tableWidget->setColumnCount(headerlist.count());
94    tableWidget->setHorizontalHeaderLabels(headerlist);
95    tableWidget->horizontalHeader()->setHighlightSections(false);
96    tableWidget->setRowCount(m_console->client_list.count());
97    tableWidget->verticalHeader()->hide();
98    tableWidget->setSelectionBehavior(QAbstractItemView::SelectRows);
99    tableWidget->setSelectionMode(QAbstractItemView::SingleSelection);
100    tableWidget->setSortingEnabled(false); /* rows move on insert if sorting enabled */
101    bool first = true;
102    QString client_comsep("");
103    foreach (QString clientName, m_console->client_list){
104       if (first) {
105          client_comsep += "'" + clientName + "'";
106          first = false;
107       }
108       else
109          client_comsep += ",'" + clientName + "'";
110    }
111
112    if (client_comsep != "") {
113       QString query("");
114       query += "SELECT Name, FileRetention, JobRetention, AutoPrune, ClientId, Uname"
115            " FROM Client"
116            " WHERE ClientId IN (SELECT MAX(ClientId) FROM Client WHERE";
117       query += " Name IN (" + client_comsep + ")";
118       query += " GROUP BY Name) ORDER BY Name";
119
120       QStringList results;
121       if (mainWin->m_sqlDebug)
122          Pmsg1(000, "Clients query cmd : %s\n",query.toUtf8().data());
123       if (m_console->sql_cmd(query, results)) {
124          int row = 0;
125
126          /* Iterate through the record returned from the query */
127          foreach (QString resultline, results) {
128             QStringList fieldlist = resultline.split("\t");
129
130             if (m_firstpopulation) {
131                settingsOpenStatus(fieldlist[0]);
132             }
133
134             TableItemFormatter item(*tableWidget, row);
135
136             /* Iterate through fields in the record */
137             QStringListIterator fld(fieldlist);
138             int col = 0;
139
140             /* name */
141             item.setTextFld(col++, fld.next());
142
143             /* file retention */
144             item.setDurationFld(col++, fld.next());
145
146             /* job retention */
147             item.setDurationFld(col++, fld.next());
148
149             /* autoprune */
150             item.setBoolFld(col++, fld.next());
151
152             /* client id */
153             item.setNumericFld(col++, fld.next());
154
155             /* uname */
156             item.setTextFld(col++, fld.next());
157
158             row++;
159          }
160       }
161    }
162    /* set default sorting */
163    tableWidget->sortByColumn(sortcol, sortord);
164    tableWidget->setSortingEnabled(true);
165    
166    /* Resize rows and columns */
167    tableWidget->resizeColumnsToContents();
168    tableWidget->resizeRowsToContents();
169
170    /* make read only */
171    int rcnt = tableWidget->rowCount();
172    int ccnt = tableWidget->columnCount();
173    for(int r=0; r < rcnt; r++) {
174       for(int c=0; c < ccnt; c++) {
175          QTableWidgetItem* item = tableWidget->item(r, c);
176          if (item) {
177             item->setFlags(Qt::ItemFlags(item->flags() & (~Qt::ItemIsEditable)));
178          }
179       }
180    }
181    m_firstpopulation = false;
182 }
183
184 /*
185  * When the treeWidgetItem in the page selector tree is singleclicked, Make sure
186  * The tree has been populated.
187  */
188 void Clients::PgSeltreeWidgetClicked()
189 {
190    if(!m_populated) {
191       populateTable();
192    }
193    if (!isOnceDocked()) {
194       dockPage();
195    }
196 }
197
198 /*
199  * Added to set the context menu policy based on currently active treeWidgetItem
200  * signaled by currentItemChanged
201  */
202 void Clients::tableItemChanged(QTableWidgetItem *currentwidgetitem, QTableWidgetItem *previouswidgetitem )
203 {
204    /* m_checkcurwidget checks to see if this is during a refresh, which will segfault */
205    if (m_checkcurwidget) {
206       int currentRow = currentwidgetitem->row();
207       QTableWidgetItem *currentrowzeroitem = tableWidget->item(currentRow, 0);
208       m_currentlyselected = currentrowzeroitem->text();
209
210       /* The Previous item */
211       if (previouswidgetitem) { /* avoid a segfault if first time */
212          tableWidget->removeAction(actionListJobsofClient);
213          tableWidget->removeAction(actionStatusClientWindow);
214          tableWidget->removeAction(actionPurgeJobs);
215          tableWidget->removeAction(actionPrune);
216       }
217
218       if (m_currentlyselected.length() != 0) {
219          /* set a hold variable to the client name in case the context sensitive
220           * menu is used */
221          tableWidget->addAction(actionListJobsofClient);
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(actionStatusClientWindow, SIGNAL(triggered()), this,
249                 SLOT(statusClientWindow()));
250    connect(actionPurgeJobs, SIGNAL(triggered()), this,
251                 SLOT(consolePurgeJobs()));
252    connect(actionPrune, SIGNAL(triggered()), this,
253                 SLOT(prune()));
254 }
255
256 /*
257  * Function responding to actionListJobsofClient which calls mainwin function
258  * to create a window of a list of jobs of this client.
259  */
260 void Clients::showJobs()
261 {
262    QTreeWidgetItem *parentItem = mainWin->getFromHash(this);
263    mainWin->createPageJobList("", m_currentlyselected, "", "", parentItem);
264 }
265
266 /*
267  * Function responding to actionListJobsofClient which calls mainwin function
268  * to create a window of a list of jobs of this client.
269  */
270 void Clients::consoleStatusClient()
271 {
272    QString cmd("status client=");
273    cmd += m_currentlyselected;
274    consoleCommand(cmd);
275 }
276
277 /*
278  * Virtual function which is called when this page is visible on the stack
279  */
280 void Clients::currentStackItem()
281 {
282    if(!m_populated) {
283       populateTable();
284       /* Create the context menu for the client table */
285    }
286 }
287
288 /*
289  * Function responding to actionPurgeJobs 
290  */
291 void Clients::consolePurgeJobs()
292 {
293    if (QMessageBox::warning(this, "Bat",
294       tr("Are you sure you want to purge all jobs of client \"%1\" ?\n"
295 "The Purge command will delete associated Catalog database records from Jobs and"
296 " Volumes without considering the retention period. Purge  works only on the"
297 " Catalog database and does not affect data written to Volumes. This command can"
298 " be dangerous because you can delete catalog records associated with current"
299 " backups of files, and we recommend that you do not use it unless you know what"
300 " you are doing.\n\n"
301 " Is there any way I can get you to click Cancel here?  You really don't want to do"
302 " this\n\n"
303          "Press OK to proceed with the purge operation?").arg(m_currentlyselected),
304          QMessageBox::Ok | QMessageBox::Cancel,
305          QMessageBox::Cancel)
306       == QMessageBox::Cancel) { return; }
307
308    QString cmd("purge jobs client=");
309    cmd += m_currentlyselected;
310    consoleCommand(cmd);
311 }
312
313 /*
314  * Function responding to actionPrune
315  */
316 void Clients::prune()
317 {
318    new prunePage("", m_currentlyselected);
319 }
320
321 /*
322  * Function responding to action to create new client status window
323  */
324 void Clients::statusClientWindow()
325 {
326    /* if one exists, then just set it current */
327    bool found = false;
328    foreach(Pages *page, mainWin->m_pagehash) {
329       if (mainWin->currentConsole() == page->console()) {
330          if (page->name() == tr("Client Status %1").arg(m_currentlyselected)) {
331             found = true;
332             page->setCurrent();
333          }
334       }
335    }
336    if (!found) {
337       QTreeWidgetItem *parentItem = mainWin->getFromHash(this);
338       new ClientStat(m_currentlyselected, parentItem);
339    }
340 }
341
342 /*
343  * If first time, then check to see if there were status pages open the last time closed
344  * if so open
345  */
346 void Clients::settingsOpenStatus(QString &client)
347 {
348    QSettings settings(m_console->m_dir->name(), "bat");
349
350    settings.beginGroup("OpenOnExit");
351    QString toRead = "ClientStatus_" + client;
352    if (settings.value(toRead) == 1) {
353       new ClientStat(client, mainWin->getFromHash(this));
354       setCurrent();
355       mainWin->getFromHash(this)->setExpanded(true);
356    }
357    settings.endGroup();
358 }