]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/qt-console/job/job.cpp
bat: Add a re-run button on job info page, that allows to
[bacula/bacula] / bacula / src / qt-console / job / job.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 #include "bat.h"
30 #include "job.h"
31 #include "util/fmtwidgetitem.h"
32 #include "mediainfo/mediainfo.h"
33 #include "run/run.h"
34
35 Job::Job(QString &jobId, QTreeWidgetItem *parentTreeWidgetItem)
36 {
37    setupUi(this);
38    m_closeable = true;
39    pgInitialize(tr("Job"), parentTreeWidgetItem);
40    QTreeWidgetItem* thisitem = mainWin->getFromHash(this);
41    thisitem->setIcon(0,QIcon(QString::fromUtf8(":images/joblog.png")));
42    m_cursor = new QTextCursor(textJobLog->document());
43
44    m_jobId = jobId;
45    getFont();
46
47    connect(pbRefresh, SIGNAL(clicked()), this, SLOT(populateAll()));
48    connect(pbDelete, SIGNAL(clicked()), this, SLOT(deleteJob()));
49    connect(pbRun, SIGNAL(clicked()), this, SLOT(rerun()));
50    connect(list_Volume, SIGNAL(itemDoubleClicked(QListWidgetItem*)), this, SLOT(showInfoVolume(QListWidgetItem *)));
51
52    populateAll();
53    dockPage();
54    setCurrent();
55 }
56
57 void Job::rerun()
58 {
59    new runPage(label_Name->text(),
60                label_Level->text(),
61                label_Pool->text(),
62                QString(""),              // storage
63                label_Client->text(),
64                label_FileSet->text());
65 }
66
67 void Job::showInfoVolume(QListWidgetItem *item)
68 {
69    QString s= item->text();
70    QTreeWidgetItem* pageSelectorTreeWidgetItem = mainWin->getFromHash(this);
71
72    MediaInfo *m = new MediaInfo(pageSelectorTreeWidgetItem, s);
73    connect(m, SIGNAL(destroyed()), this, SLOT(populateTree()));
74 }
75
76 void Job::deleteJob()
77 {
78    if (QMessageBox::warning(this, "Bat",
79       tr("Are you sure you want to delete??  !!!.\n"
80 "This delete command is used to delete a Job record and all associated catalog"
81 " records that were created. This command operates only on the Catalog"
82 " database and has no effect on the actual data written to a Volume. This"
83 " command can be dangerous and we strongly recommend that you do not use"
84 " it unless you know what you are doing.  The Job and all its associated"
85 " records (File and JobMedia) will be deleted from the catalog."
86       "Press OK to proceed with delete operation.?"),
87       QMessageBox::Ok | QMessageBox::Cancel)
88       == QMessageBox::Cancel) { return; }
89
90    QString cmd("delete job jobid=");
91    cmd += m_jobId;
92    consoleCommand(cmd, false);
93    closeStackPage();
94 }
95
96 void Job::getFont()
97 {
98    QFont font = textJobLog->font();
99
100    QString dirname;
101    m_console->getDirResName(dirname);
102    QSettings settings(dirname, "bat");
103    settings.beginGroup("Console");
104    font.setFamily(settings.value("consoleFont", "Courier").value<QString>());
105    font.setPointSize(settings.value("consolePointSize", 10).toInt());
106    font.setFixedPitch(settings.value("consoleFixedPitch", true).toBool());
107    settings.endGroup();
108    textJobLog->setFont(font);
109 }
110
111 void Job::populateAll()
112 {
113 // Pmsg0(50, "populateAll()\n");
114    populateText();
115    populateForm();
116    populateVolumes();
117 }
118
119 /*
120  * Populate the text in the window
121  */
122 void Job::populateText()
123 {
124    textJobLog->clear();
125    QString query;
126    query = "SELECT Time, LogText FROM Log WHERE JobId='" + m_jobId + "' order by Time";
127
128    /* This could be a log item */
129    if (mainWin->m_sqlDebug) {
130       Pmsg1(000, "Log query cmd : %s\n", query.toUtf8().data());
131    }
132   
133    QStringList results;
134    if (m_console->sql_cmd(query, results)) {
135
136       if (!results.size()) {
137          QMessageBox::warning(this, tr("Bat"),
138             tr("There were no results!\n"
139                "It is possible you may need to add \"catalog = all\" "
140                "to the Messages resource for this job.\n"), QMessageBox::Ok);
141          return;
142       } 
143
144       QString jobstr("JobId "); /* FIXME: should this be translated ? */
145       jobstr += m_jobId;
146
147       QString htmlbuf("<html><body><pre>");
148   
149       /* Iterate through the lines of results. */
150       QString field;
151       QStringList fieldlist;
152       QString lastTime;
153       QString lastSvc;
154       foreach (QString resultline, results) {
155          fieldlist = resultline.split("\t");
156          
157          if (fieldlist.size() < 2)
158             continue;
159
160          QString curTime = fieldlist[0].trimmed();
161
162          field = fieldlist[1].trimmed();
163          int colon = field.indexOf(":");
164          if (colon > 0) {
165             /* string is like <service> <jobId xxxx>: ..." 
166              * we split at ':' then remove the jobId xxxx string (always the same) */ 
167             QString curSvc(field.left(colon).replace(jobstr,"").trimmed());
168             if (curSvc == lastSvc  && curTime == lastTime) {
169                curTime.clear();
170                curSvc.clear(); 
171             } else {
172                lastTime = curTime;
173                lastSvc = curSvc;
174             }
175 //          htmlbuf += "<td>" + curTime + "</td>";
176             htmlbuf += "\n" + curSvc + " ";
177
178             /* rest of string is marked as pre-formatted (here trimming should
179              * be avoided, to preserve original formatting) */
180             QString msg(field.mid(colon+2));
181             if (msg.startsWith( tr("Error:")) ) { /* FIXME: should really be translated ? */
182                /* error msg, use a specific class */
183                htmlbuf += "</pre><pre class=err>" + msg + "</pre><pre>";
184             } else {
185                htmlbuf += msg ;
186             }
187          } else {
188             /* non standard string, place as-is */
189             if (curTime == lastTime) {
190                curTime.clear();
191             } else {
192                lastTime = curTime;
193             }
194 //          htmlbuf += "<td>" + curTime + "</td>";
195             htmlbuf += "\n" + field ;
196          }
197   
198       } /* foreach resultline */
199
200       htmlbuf += "</pre></body></html>";
201
202       /* full text ready. Here a custom sheet is used to align columns */
203       QString logSheet(".err {color:#FF0000;}");
204       textJobLog->document()->setDefaultStyleSheet(logSheet);
205       textJobLog->document()->setHtml(htmlbuf); 
206       textJobLog->moveCursor(QTextCursor::Start);
207
208    } /* if results from query */
209   
210 }
211
212 /*
213  * Populate the text in the window
214  */
215 void Job::populateForm()
216 {
217    QString stat, err;
218    char buf[256];
219    QString query = 
220       "SELECT JobId, Job.Name, Level, Client.Name, Pool.Name, FileSet, SchedTime, StartTime, EndTime, "
221       "EndTime - StartTime AS Duration, JobBytes, JobFiles, JobErrors, JobStatus, PurgedFiles "
222       "FROM Job JOIN Client USING (ClientId) LEFT JOIN Pool USING (PoolId) "
223       "LEFT JOIN FileSet USING (FileSetId)"
224       "WHERE JobId=" + m_jobId; 
225    QStringList results;
226    if (m_console->sql_cmd(query, results)) {
227       QString resultline;
228       QStringList fieldlist;
229
230       foreach (resultline, results) { // should have only one result
231          fieldlist = resultline.split("\t");
232          QStringListIterator fld(fieldlist);
233          label_JobId->setText(fld.next());
234          label_Name->setText(fld.next());
235          
236          label_Level->setText(job_level_to_str(fld.next()[0].toAscii()));
237
238          label_Client->setText(fld.next());
239          label_Pool->setText(fld.next());
240          label_FileSet->setText(fld.next());
241          label_SchedTime->setText(fld.next());
242          label_StartTime->setText(fld.next());
243          label_EndTime->setText(fld.next());
244          label_Duration->setText(fld.next());
245
246          label_JobBytes->setText(convertBytesSI(fld.next().toULongLong()));
247          label_JobFiles->setText(fld.next());
248          err = fld.next();
249          label_JobErrors->setText(err);
250
251          stat=fld.next();
252          if (stat == "T" && err.toInt() > 0) {
253             stat = "W";
254          }
255          label_JobStatus->setPixmap(QPixmap(":/images/" + stat + ".png"));
256          jobstatus_to_ascii_gui(stat[0].toAscii(), buf, sizeof(buf));
257          stat = buf;
258          label_JobStatus->setToolTip(stat);
259
260          chkbox_PurgedFiles->setCheckState(fld.next().toInt()?Qt::Checked:Qt::Unchecked);
261       }
262    }
263 }
264   
265 void Job::populateVolumes()
266 {
267
268    QString query = 
269       "SELECT DISTINCT VolumeName, InChanger, Slot "
270       "FROM Job JOIN JobMedia USING (JobId) JOIN Media USING (MediaId) "
271       "WHERE JobId=" + m_jobId + " ORDER BY VolumeName "; 
272    if (mainWin->m_sqlDebug) Pmsg1(0, "Query cmd : %s\n",query.toUtf8().data());
273          
274
275    QStringList results;
276    if (m_console->sql_cmd(query, results)) {
277       QString resultline;
278       QStringList fieldlist;
279       list_Volume->clear();
280       foreach (resultline, results) { // should have only one result
281          fieldlist = resultline.split("\t");
282          QStringListIterator fld(fieldlist);
283 //         QListWidgetItem(QIcon(":/images/inchanger" + fld.next() + ".png"), 
284 //                         fld.next(), list_Volume);
285          list_Volume->addItem(fld.next());
286       }
287    }
288 }
289
290 //QListWidgetItem ( const QIcon & icon, const QString & text, QListWidget * parent = 0, int type = Type )