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