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