]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/qt-console/joblist/joblist.cpp
Add warning dialogs before purging and befoe deleting volumes and jobs.
[bacula/bacula] / bacula / src / qt-console / joblist / joblist.cpp
1 /*
2    Bacula® - The Network Backup Solution
3
4    Copyright (C) 2000-2007 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 plus additions
11    that are listed 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 John Walker.
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  *   Version $Id: joblist.h 4230 2007-02-21 20:07:37Z kerns $
30  *
31  *   Dirk Bartley, March 2007
32  */
33  
34 #include <QAbstractEventDispatcher>
35 #include <QTableWidgetItem>
36 #include "bat.h"
37 #include "joblist.h"
38 #include "restore.h"
39
40 /*
41  * Constructor for the class
42  */
43 JobList::JobList(QString &mediaName, QString &clientname,
44          QTreeWidgetItem *parentTreeWidgetItem)
45 {
46    setupUi(this);
47    m_name = "Clients";
48    m_mediaName = mediaName;
49    m_clientName = clientname;
50    pgInitialize(parentTreeWidgetItem);
51    m_resultCount = 0;
52    m_populated = false;
53    m_closeable = false;
54    m_checkCurrentWidget = true;
55    createConnections();
56
57    /* Set Defaults for check and spin for limits */
58    limitCheckBox->setCheckState(Qt::Checked);
59    limitSpinBox->setValue(150);
60    daysCheckBox->setCheckState(Qt::Unchecked);
61    daysSpinBox->setValue(30);
62 }
63
64 /*
65  * The Meat of the class.
66  * This function will populate the QTableWidget, mp_tablewidget, with
67  * QTableWidgetItems representing the results of a query for what jobs exist on
68  * the media name passed from the constructor stored in m_mediaName.
69  */
70 void JobList::populateTable()
71 {
72    QStringList results;
73    QString resultline;
74    QBrush blackBrush(Qt::black);
75
76    /* Can't do this in constructor because not neccesarily conected in constructor */
77    if (!m_populated) {
78       clientsComboBox->addItem("");
79       clientsComboBox->addItems(m_console->client_list);
80       int clientIndex = clientsComboBox->findText(m_clientName, Qt::MatchExactly);
81       if (clientIndex != -1)
82          clientsComboBox->setCurrentIndex(clientIndex);
83
84       /* Not m_console->volume_list will query database */
85       QString query("SELECT VolumeName AS Media FROM Media ORDER BY Media");
86       QStringList results, volumeList;
87       if (m_console->sql_cmd(query, results)) {
88          QString field;
89          QStringList fieldlist;
90          /* Iterate through the lines of results. */
91          foreach (QString resultline, results) {
92             fieldlist = resultline.split("\t");
93             volumeList.append(fieldlist[0]);
94          } /* foreach resultline */
95       } /* if results from query */
96       volumeComboBox->addItem("");
97       volumeComboBox->addItems(volumeList);
98       int volumeIndex = volumeComboBox->findText(m_mediaName, Qt::MatchExactly);
99       if (volumeIndex != -1) {
100          volumeComboBox->setCurrentIndex(volumeIndex);
101       }
102    }
103
104    /* Set up query QString and header QStringList */
105    QString query("");
106    query += "SELECT DISTINCT Job.Jobid AS Id, Job.Name AS JobName, Client.Name AS Client,"
107             " Job.Starttime AS JobStart, Job.Type AS JobType,"
108             " Job.Level AS BackupLevel, Job.Jobfiles AS FileCount,"
109             " Job.JobBytes AS Bytes, Job.JobStatus AS Status"
110             " FROM Job, JobMedia, Media, Client"
111             " WHERE JobMedia.JobId=Job.JobId and JobMedia.MediaId=Media.MediaId"
112             " and Client.ClientId=Job.ClientId";
113    int volumeIndex = volumeComboBox->currentIndex();
114    if (volumeIndex != -1)
115       m_mediaName = volumeComboBox->itemText(volumeIndex);
116    if (m_mediaName != "") {
117       query += " AND Media.VolumeName='" + m_mediaName + "'";
118       m_closeable=true;
119    }
120    int clientIndex = clientsComboBox->currentIndex();
121    if (clientIndex != -1)
122       m_clientName = clientsComboBox->itemText(clientIndex);
123    if (m_clientName != "") {
124       query += " AND Client.Name='" + m_clientName + "'";
125       m_closeable=true;
126    }
127    /* If Limit check box For limit by days is checked  */
128    if (daysCheckBox->checkState() == Qt::Checked) {
129       QDateTime stamp = QDateTime::currentDateTime().addDays(-daysSpinBox->value());
130       QString since = stamp.toString(Qt::ISODate);
131       query += " AND Job.Starttime>'" + since + "'";
132    }
133    /* Descending */
134    query += " ORDER BY Job.Starttime DESC";
135    /* If Limit check box for limit records returned is checked  */
136    if (limitCheckBox->checkState() == Qt::Checked) {
137       QString limit;
138       limit.setNum(limitSpinBox->value());
139       query += " LIMIT " + limit;
140    }
141    QStringList headerlist = (QStringList()
142       << "Job Id" << "Job Name" << "Client" << "Job Starttime" << "Job Type" 
143       << "Job Level" << "Job Files" << "Job Bytes" << "Job Status"  );
144
145    /* Initialize the QTableWidget */
146    m_checkCurrentWidget = false;
147    mp_tableWidget->clear();
148    m_checkCurrentWidget = true;
149    mp_tableWidget->setColumnCount(headerlist.size());
150    mp_tableWidget->setHorizontalHeaderLabels(headerlist);
151
152    /*  This could be a user preference debug message?? */
153    //printf("Query cmd : %s\n",query.toUtf8().data());
154    if (m_console->sql_cmd(query, results)) {
155       m_resultCount = results.count();
156
157       QTableWidgetItem* p_tableitem;
158       QString field;
159       QStringList fieldlist;
160       mp_tableWidget->setRowCount(results.size());
161
162       int row = 0;
163       /* Iterate through the record returned from the query */
164       foreach (resultline, results) {
165          fieldlist = resultline.split("\t");
166          int column = 0;
167          /* Iterate through fields in the record */
168          foreach (field, fieldlist) {
169             field = field.trimmed();  /* strip leading & trailing spaces */
170             p_tableitem = new QTableWidgetItem(field,1);
171             p_tableitem->setFlags(0);
172             p_tableitem->setForeground(blackBrush);
173             mp_tableWidget->setItem(row, column, p_tableitem);
174             column++;
175          }
176          row++;
177       }
178    } 
179    /* Resize the columns */
180    mp_tableWidget->resizeColumnsToContents();
181    mp_tableWidget->resizeRowsToContents();
182    mp_tableWidget->verticalHeader()->hide();
183    if ((m_mediaName != "") && (m_resultCount == 0)){
184       /* for context sensitive searches, let the user know if there were no
185        * results */
186       QMessageBox::warning(this, tr("Bat"),
187           tr("The Jobs query returned no results.\n"
188          "Press OK to continue?"), QMessageBox::Ok );
189    }
190 }
191
192 /*
193  * When the treeWidgetItem in the page selector tree is singleclicked, Make sure
194  * The tree has been populated.
195  */
196 void JobList::PgSeltreeWidgetClicked()
197 {
198    if (!m_populated) {
199       populateTable();
200       m_populated=true;
201    }
202 }
203
204 /*
205  *  Virtual function override of pages function which is called when this page
206  *  is visible on the stack
207  */
208 void JobList::currentStackItem()
209 {
210    if (!m_populated) {
211       populateTable();
212       m_contextActions.append(actionRefreshJobList);
213       m_populated=true;
214    }
215 }
216
217 /*
218  * Virtual Function to return the name for the medialist tree widget
219  */
220 void JobList::treeWidgetName(QString &desc)
221 {
222    if ((m_mediaName == "") && (m_clientName == "")) {
223       desc = "Jobs";
224    } else {
225       desc = "Jobs ";
226       if (m_mediaName != "" ) {
227          desc += "on Volume " + m_mediaName;
228       }
229       if (m_clientName != "" ) {
230          desc += "of Client " + m_clientName;
231       }
232    }
233 }
234
235 /*
236  * This functions much line tableItemChanged for trees like the page selector,
237  * but I will do much less here
238  */
239 void JobList::tableItemChanged(QTableWidgetItem *currentItem, QTableWidgetItem * /*previousItem*/)
240 {
241    if (m_checkCurrentWidget) {
242       int row = currentItem->row();
243       QTableWidgetItem* jobitem = mp_tableWidget->item(row, 0);
244       m_currentJob = jobitem->text();
245    }
246 }
247
248 /*
249  * Function to create connections for context sensitive menu for this and
250  * the page selector
251  */
252 void JobList::createConnections()
253 {
254    /* connect to the action specific to this pages class that shows up in the 
255     * page selector tree */
256    connect(actionRefreshJobList, SIGNAL(triggered()), this,
257                 SLOT(populateTable()));
258    connect(refreshButton, SIGNAL(pressed()), this, SLOT(populateTable()));
259    /* for the tableItemChanged to maintain m_currentJob */
260    connect(mp_tableWidget, SIGNAL(
261            currentItemChanged(QTableWidgetItem *, QTableWidgetItem *)),
262            this, SLOT(tableItemChanged(QTableWidgetItem *, QTableWidgetItem *)));
263
264    /* Do what is required for the local context sensitive menu */
265
266
267    /* setContextMenuPolicy is required */
268    mp_tableWidget->setContextMenuPolicy(Qt::ActionsContextMenu);
269
270    /* Add Actions */
271    mp_tableWidget->addAction(actionRefreshJobList);
272    mp_tableWidget->addAction(actionLongListJob);
273    mp_tableWidget->addAction(actionListJobid);
274    mp_tableWidget->addAction(actionListFilesOnJob);
275    mp_tableWidget->addAction(actionListJobMedia);
276    mp_tableWidget->addAction(actionListVolumes);
277    mp_tableWidget->addAction(actionDeleteJob);
278    mp_tableWidget->addAction(actionPurgeFiles);
279    mp_tableWidget->addAction(actionRestoreFromJob);
280
281    /* Make Connections */
282    connect(actionLongListJob, SIGNAL(triggered()), this,
283                 SLOT(consoleLongListJob()));
284    connect(actionListJobid, SIGNAL(triggered()), this,
285                 SLOT(consoleListJobid()));
286    connect(actionListFilesOnJob, SIGNAL(triggered()), this,
287                 SLOT(consoleListFilesOnJob()));
288    connect(actionListJobMedia, SIGNAL(triggered()), this,
289                 SLOT(consoleListJobMedia()));
290    connect(actionListVolumes, SIGNAL(triggered()), this,
291                 SLOT(consoleListVolumes()));
292    connect(actionDeleteJob, SIGNAL(triggered()), this,
293                 SLOT(consoleDeleteJob()));
294    connect(actionPurgeFiles, SIGNAL(triggered()), this,
295                 SLOT(consolePurgeFiles()));
296    connect(actionRestoreFromJob, SIGNAL(triggered()), this,
297                 SLOT(preRestoreFromJob()));
298 }
299
300 /*
301  * Functions to respond to local context sensitive menu sending console commands
302  * If I could figure out how to make these one function passing a string, Yaaaaaa
303  */
304 void JobList::consoleLongListJob()
305 {
306    QString cmd("llist jobid=");
307    cmd += m_currentJob;
308    consoleCommand(cmd);
309 }
310 void JobList::consoleListJobid()
311 {
312    QString cmd("list jobid=");
313    cmd += m_currentJob;
314    consoleCommand(cmd);
315 }
316 void JobList::consoleListFilesOnJob()
317 {
318    QString cmd("list files jobid=");
319    cmd += m_currentJob;
320    consoleCommand(cmd);
321 }
322 void JobList::consoleListJobMedia()
323 {
324    QString cmd("list jobmedia jobid=");
325    cmd += m_currentJob;
326    consoleCommand(cmd);
327 }
328 void JobList::consoleListVolumes()
329 {
330    QString cmd("list volumes jobid=");
331    cmd += m_currentJob;
332    consoleCommand(cmd);
333 }
334 void JobList::consoleDeleteJob()
335 {
336    if (QMessageBox::warning(this, tr("Bat"),
337       tr("Are you sure you want to delete??  !!!.\n"
338 "This delete command is used to delete a Job record and all associated catalog"
339 " records that were created. This command operates only on the Catalog"
340 " database and has no effect on the actual data written to a Volume. This"
341 " command can be dangerous and we strongly recommend that you do not use"
342 " it unless you know what you are doing.  The Job and all its associated"
343 " records (File and JobMedia) will be deleted from the catalog."
344       "Press OK to proceed with delete operation.?"),
345       QMessageBox::Ok | QMessageBox::Cancel)
346       == QMessageBox::Cancel) { return; }
347
348    QString cmd("delete job jobid=");
349    cmd += m_currentJob;
350    consoleCommand(cmd);
351 }
352 void JobList::consolePurgeFiles()
353 {
354    if (QMessageBox::warning(this, tr("Bat"),
355       tr("Are you sure you want to purge ??  !!!.\n"
356 "The Purge command will delete associated Catalog database records from Jobs and"
357 " Volumes without considering the retention period. Purge  works only on the"
358 " Catalog database and does not affect data written to Volumes. This command can"
359 " be dangerous because you can delete catalog records associated with current"
360 " backups of files, and we recommend that you do not use it unless you know what"
361 " you are doing.\n"
362       "Press OK to proceed with the purge operation?"),
363       QMessageBox::Ok | QMessageBox::Cancel)
364       == QMessageBox::Cancel) { return; }
365
366    QString cmd("purge files jobid=");
367    cmd += m_currentJob;
368    consoleCommand(cmd);
369 }
370
371 /*
372  * Subroutine to call preRestore to restore from a select job
373  */
374 void JobList::preRestoreFromJob()
375 {
376    new prerestorePage(m_currentJob);
377 }