]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/qt-console/util/fmtwidgetitem.cpp
Fix reference to uninitialized stack variable
[bacula/bacula] / bacula / src / qt-console / util / fmtwidgetitem.cpp
1 /*
2    Bacula® - The Network Backup Solution
3
4    Copyright (C) 2007-2010 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 three of the GNU Affero 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 Affero 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  *
31  *  Helper functions for tree widget formatting
32  *
33  *   Riccardo Ghetta, May 2008
34  *
35  */ 
36
37 #include "bat.h"
38 #include <QTreeWidgetItem>
39 #include <QTableWidget>
40 #include <QTableWidgetItem>
41 #include <QBrush>
42 #include <QString>
43 #include <QStringList>
44 #include <math.h>
45 #include "fmtwidgetitem.h"
46
47 /***********************************************
48  *
49  * common helpers
50  *
51  ***********************************************/
52
53 QString convertJobStatus(const QString &sts)
54 {
55    QString code( sts.trimmed() );
56    if ( code.size() != 1) {
57       return QObject::tr("Invalid job status %1").arg(sts);
58    }
59
60    char buf[256];
61    jobstatus_to_ascii_gui( code[0].toAscii(), buf, sizeof(buf));
62    return QString(buf);
63 }
64
65 /*
66  * disable widget updating
67  */
68 Freeze::Freeze(QWidget &q):
69 qw(&q)
70 {
71    qw->setUpdatesEnabled(false); 
72 }
73
74 Freeze::~Freeze()
75 {
76    if (qw) {
77       qw->setUpdatesEnabled(true); 
78       qw->update();
79    }
80 }
81
82 /***********************************************
83  *
84  * ItemFormatterBase static members
85  *
86  ***********************************************/
87
88 ItemFormatterBase::BYTES_CONVERSION ItemFormatterBase::cnvFlag(BYTES_CONVERSION_IEC);
89
90 QString convertBytesIEC(qint64 qfld)
91 {
92    static const qint64 KB = Q_INT64_C(1024);
93    static const qint64 MB = (KB * KB);
94    static const qint64 GB = (MB * KB);
95    static const qint64 TB = (GB * KB);
96    static const qint64 PB = (TB * KB);
97    static const qint64 EB = (PB * KB);
98
99    /* note: division is integer, so to have some decimals we divide for a
100       smaller unit (e.g. GB for a TB number and so on) */
101    char suffix;
102    if (qfld >= EB) {
103       qfld /= PB; 
104       suffix = 'E';
105    }
106    else if (qfld >= PB) {
107       qfld /= TB; 
108       suffix = 'P';
109    }
110    else if (qfld >= TB) {
111       qfld /= GB; 
112       suffix = 'T';
113    }
114    else if (qfld >= GB) {
115       qfld /= MB;
116       suffix = 'G';
117    }
118    else if (qfld >= MB) {
119       qfld /= KB;
120       suffix = 'M';
121    }
122    else if (qfld >= KB) {
123       suffix = 'K';
124    }
125    else  {
126       /* plain bytes, no need to reformat */
127       return QString("%1 B").arg(qfld); 
128    }
129
130    /* having divided for a smaller unit, now we can safely convert to double and
131       use the extra room for decimals */
132    return QString("%1 %2iB").arg(qfld / 1000.0, 0, 'f', 2).arg(suffix);
133 }
134
135 QString convertBytesSI(qint64 qfld)
136 {
137    static const qint64 KB = Q_INT64_C(1000);
138    static const qint64 MB = (KB * KB);
139    static const qint64 GB = (MB * KB);
140    static const qint64 TB = (GB * KB);
141    static const qint64 PB = (TB * KB);
142    static const qint64 EB = (PB * KB);
143
144    /* note: division is integer, so to have some decimals we divide for a
145       smaller unit (e.g. GB for a TB number and so on) */
146    char suffix;
147    if (qfld >= EB) {
148       qfld /= PB; 
149       suffix = 'E';
150    }
151    else if (qfld >= PB) {
152       qfld /= TB; 
153       suffix = 'P';
154    }
155    else if (qfld >= TB) {
156       qfld /= GB; 
157       suffix = 'T';
158    }
159    else if (qfld >= GB) {
160       qfld /= MB;
161       suffix = 'G';
162    }
163    else if (qfld >= MB) {
164       qfld /= KB;
165       suffix = 'M';
166    }
167    else if (qfld >= KB) {
168       suffix = 'k'; /* SI uses lowercase k */
169    }
170    else  {
171       /* plain bytes, no need to reformat */
172       return QString("%1 B").arg(qfld); 
173    }
174
175    /* having divided for a smaller unit, now we can safely convert to double and
176       use the extra room for decimals */
177    return QString("%1 %2B").arg(qfld / 1000.0, 0, 'f', 2).arg(suffix);
178 }
179
180 /***********************************************
181  *
182  * base formatting routines
183  *
184  ***********************************************/
185
186 ItemFormatterBase::ItemFormatterBase()
187 {
188 }
189
190 ItemFormatterBase::~ItemFormatterBase()
191 {
192 }
193
194 void ItemFormatterBase::setPercent(int index, float value)
195 {
196    char buf[100];
197    bsnprintf(buf, sizeof(buf), "%.2f%%", value);
198    QString val = buf;
199    QString pix;
200    if (value < 8) {
201       pix = ":images/0p.png";
202    } else if (value < 24) {
203       pix = ":images/16p.png";
204    } else if (value < 40) {
205       pix = ":images/32p.png";
206    } else if (value < 56) {
207       pix = ":images/48p.png";
208    } else if (value < 72) {
209       pix = ":images/64p.png";
210    } else if (value < 88) {
211       pix = ":images/80p.png";
212    } else {
213       pix = ":images/96p.png";
214    }
215    setPixmap(index, QPixmap(pix), val);
216    //setSortValue(index, (int) value);
217    //setBackground(index, Qt::green);
218 }
219
220 /* By default, the setPixmap implementation with tooltip don't implement
221  * the tooltip stuff
222  */
223 void ItemFormatterBase::setPixmap(int index, const QPixmap &pix, 
224                                   const QString & /* tip */)
225 {
226    setPixmap(index, pix);
227 }
228
229 void ItemFormatterBase::setInChanger(int index, const QString &InChanger)
230 {
231    setPixmap(index, QPixmap(":images/inflag"+InChanger+".png"));
232    //setSortValue(index, InChanger.toInt() );
233 }
234
235 void ItemFormatterBase::setFileType(int index, const QString &type)
236 {
237    setPixmap(index, QPixmap(":images/"+type+".png"));
238    //setSortValue(index, InChanger.toInt() );
239 }
240
241 void ItemFormatterBase::setTextFld(int index, const QString &fld, bool center)
242 {
243    setText(index, fld.trimmed());
244    if (center) {
245       setTextAlignment(index, Qt::AlignCenter);
246    }
247 }
248
249 void ItemFormatterBase::setDateFld(int index, utime_t fld, bool center)
250 {
251    char buf[200];
252    bstrutime(buf, sizeof(buf), fld);
253    setText(index, QString(buf).trimmed());
254    if (center) {
255       setTextAlignment(index, Qt::AlignCenter);
256    }
257 }
258
259 void ItemFormatterBase::setRightFld(int index, const QString &fld)
260 {
261    setText(index, fld.trimmed());
262    setTextAlignment(index, Qt::AlignRight | Qt::AlignVCenter);
263 }
264
265 void ItemFormatterBase::setBoolFld(int index, const QString &fld, bool center)
266 {
267    if (fld.trimmed().toInt())
268      setTextFld(index, QObject::tr("Yes"), center);
269    else
270      setTextFld(index, QObject::tr("No"), center);
271 }
272
273 void ItemFormatterBase::setBoolFld(int index, int fld, bool center)
274 {
275    if (fld)
276      setTextFld(index, QObject::tr("Yes"), center);
277    else
278      setTextFld(index, QObject::tr("No"), center);
279 }
280
281 void ItemFormatterBase::setNumericFld(int index, const QString &fld)
282 {
283    setRightFld(index, fld.trimmed());
284    setSortValue(index, fld.toDouble() );
285 }
286
287 void ItemFormatterBase::setNumericFld(int index, const QString &fld, const QVariant &sortval)
288 {
289    setRightFld(index, fld.trimmed());
290    setSortValue(index, sortval );
291 }
292
293 void ItemFormatterBase::setBytesFld(int index, const QString &fld)
294 {
295    qint64 qfld = fld.trimmed().toLongLong();
296    QString msg;
297    switch (cnvFlag) {
298    case BYTES_CONVERSION_NONE:
299       msg = QString::number(qfld);
300       break;
301    case BYTES_CONVERSION_IEC:
302       msg = convertBytesIEC(qfld);
303       break;
304    case BYTES_CONVERSION_SI:
305       msg = convertBytesSI(qfld);
306       break;
307    default:
308       msg = " ";
309       break;
310    }
311
312    setNumericFld(index, msg, qfld);
313 }
314
315 void ItemFormatterBase::setDurationFld(int index, const QString &fld)
316 {
317    static const qint64 HOUR = Q_INT64_C(3600);
318    static const qint64 DAY = HOUR * 24;
319    static const qint64 WEEK = DAY * 7;
320    static const qint64 MONTH = DAY * 30;
321    static const qint64 YEAR = DAY * 365;
322    static const qint64 divs[] = { YEAR, MONTH, WEEK, DAY, HOUR };
323    static const char sufs[] = { 'y', 'm', 'w', 'd', 'h', '\0' };
324
325    qint64 dfld = fld.trimmed().toLongLong();
326
327    char suffix = 's';
328    if (dfld) {
329       for (int pos = 0 ; sufs[pos] ; ++pos) {
330           if (dfld % divs[pos] == 0) {
331              dfld /= divs[pos];
332              suffix = sufs[pos];
333              break;
334           }
335       }
336    }
337    QString msg;
338    if (dfld < 100) {
339       msg = QString("%1%2").arg(dfld).arg(suffix);
340    } else {
341       /* previous check returned a number too big. The original specification perhaps
342          was mixed, like 1d 2h, so we try to match with this routine */
343       dfld = fld.trimmed().toLongLong();
344       msg = "";
345       for (int pos = 0 ; sufs[pos] ; ++pos) {
346           if (dfld / divs[pos] != 0) {
347              msg += QString(" %1%2").arg(dfld / divs[pos]).arg(sufs[pos]);
348              dfld %= divs[pos];
349           }
350       }
351       if (dfld)
352          msg += QString(" %1s").arg(dfld);
353    }
354
355    setNumericFld(index, msg, fld.trimmed().toLongLong());
356 }
357
358 void ItemFormatterBase::setVolStatusFld(int index, const QString &fld, bool center)
359 {
360   QString mp(fld.trimmed());
361    setTextFld(index, volume_status_to_str(mp.toUtf8()), center);
362
363    if (mp == "Append" ) {
364       setBackground(index, Qt::green);
365    } else if (mp == "Error") {
366       setBackground(index, Qt::red);
367    } else if (mp == "Used" || mp == "Full"){
368       setBackground(index, Qt::yellow);
369    } else if (mp == "Read-only" || mp == "Disabled"){
370       setBackground(index, Qt::lightGray);
371    }
372 }
373
374 void ItemFormatterBase::setJobStatusFld(int index, const QString &status, bool center)
375 {
376    /* C (created, not yet running) uses the default background */
377    static QString greenchars("TR");
378    static QString redchars("BEf");
379    static QString yellowchars("eDAFSMmsjdctp");
380
381    setTextFld(index, convertJobStatus(status), center);
382
383    QString st(status.trimmed());
384    if (greenchars.contains(st, Qt::CaseSensitive)) {
385       setBackground(index, Qt::green);
386    } else if (redchars.contains(st, Qt::CaseSensitive)) {
387       setBackground(index, Qt::red);
388    } else if (yellowchars.contains(st, Qt::CaseSensitive)){ 
389       setBackground(index, Qt::yellow);
390    }
391 }
392
393 void ItemFormatterBase::setJobTypeFld(int index, const QString &fld, bool center)
394 {
395    QByteArray jtype(fld.trimmed().toAscii());
396    if (jtype.size()) {
397       setTextFld(index, job_type_to_str(jtype[0]), center);
398    } else {
399       setTextFld(index, "", center);
400    }
401 }
402
403 void ItemFormatterBase::setJobLevelFld(int index, const QString &fld, bool center)
404 {
405    QByteArray lvl(fld.trimmed().toAscii());
406    if (lvl.size()) {
407       setTextFld(index, job_level_to_str(lvl[0]), center);
408    } else {
409       setTextFld(index, "", center);
410    }
411 }
412
413
414
415 /***********************************************
416  *
417  * treeitem formatting routines
418  *
419  ***********************************************/
420 TreeItemFormatter::TreeItemFormatter(QTreeWidgetItem &parent, int indent_level):
421 ItemFormatterBase(),
422 wdg(new QTreeWidgetItem(&parent)),
423 level(indent_level)
424 {
425 }
426
427 void TreeItemFormatter::setText(int index, const QString &fld)
428 {
429    wdg->setData(index, Qt::UserRole, level);
430    wdg->setText(index, fld);
431 }
432
433 void TreeItemFormatter::setTextAlignment(int index, int align)
434 {
435    wdg->setTextAlignment(index, align);
436 }
437
438 void TreeItemFormatter::setBackground(int index, const QBrush &qb)
439 {
440    wdg->setBackground(index, qb);
441 }
442
443 /* at this time we don't sort trees, so this method does nothing */
444 void TreeItemFormatter::setSortValue(int /* index */, const QVariant & /* value */)
445 {
446 }
447
448 void TreeItemFormatter::setPixmap(int index, const QPixmap &pix)
449 {
450    wdg->setIcon(index, QIcon(pix));
451 }
452
453 /***********************************************
454  *
455  * Specialized table widget used for sorting
456  *
457  ***********************************************/
458 TableItemFormatter::BatSortingTableItem::BatSortingTableItem():
459 QTableWidgetItem(1)
460 {
461 }
462
463 void TableItemFormatter::BatSortingTableItem::setSortData(const QVariant &d)
464 {
465    setData(SORTDATA_ROLE, d);
466 }
467
468 bool TableItemFormatter::BatSortingTableItem::operator< ( const QTableWidgetItem & o ) const 
469 {
470    QVariant my = data(SORTDATA_ROLE);
471    QVariant other = o.data(SORTDATA_ROLE);
472    if (!my.isValid() || !other.isValid() || my.type() != other.type())
473       return QTableWidgetItem::operator< (o); /* invalid combination, revert to default sorting */
474
475    /* 64bit integers must be handled separately, others can be converted to double */
476    if (QVariant::ULongLong == my.type()) {
477       return my.toULongLong() < other.toULongLong(); 
478    } else if (QVariant::LongLong == my.type()) {
479       return my.toLongLong() < other.toLongLong(); 
480    } else if (my.canConvert(QVariant::Double)) {
481       return my.toDouble() < other.toDouble(); 
482    } else {
483       return QTableWidgetItem::operator< (o); /* invalid combination, revert to default sorting */
484    }
485 }
486
487 /***********************************************
488  *
489  * tableitem formatting routines
490  *
491  ***********************************************/
492 TableItemFormatter::TableItemFormatter(QTableWidget &tparent, int trow):
493 ItemFormatterBase(),
494 parent(&tparent),
495 row(trow),
496 last(NULL)
497 {
498 }
499
500 void TableItemFormatter::setPixmap(int index, const QPixmap &pix)
501 {
502 // Centered, but not sortable !
503    QLabel *lbl = new QLabel();
504    lbl->setAlignment(Qt::AlignCenter);
505    lbl->setPixmap(pix);
506    parent->setCellWidget(row, index, lbl);
507 }
508
509 void TableItemFormatter::setPixmap(int index, const QPixmap &pix, 
510                                    const QString &tips)
511 {
512 // Centered, but not sortable !
513    QLabel *lbl = new QLabel();
514    lbl->setAlignment(Qt::AlignCenter);
515    lbl->setPixmap(pix);
516    if (!tips.isEmpty()) {
517       lbl->setToolTip(tips);
518    }
519    parent->setCellWidget(row, index, lbl);
520
521 //   last = new BatSortingTableItem;
522 //   parent->setItem(row, index, last);
523 //   last->setIcon(pix);
524 }
525
526 void TableItemFormatter::setText(int col, const QString &fld)
527 {
528    last = new BatSortingTableItem;
529    parent->setItem(row, col, last);
530    last->setText(fld);
531 }
532
533 void TableItemFormatter::setTextAlignment(int /*index*/, int align)
534 {
535    last->setTextAlignment(align);
536 }
537
538 void TableItemFormatter::setBackground(int /*index*/, const QBrush &qb)
539 {
540    last->setBackground(qb);
541 }
542
543 void TableItemFormatter::setSortValue(int /* index */, const QVariant &value )
544 {
545    last->setSortData(value);
546 }
547
548 QTableWidgetItem *TableItemFormatter::widget(int col)
549 {
550    return parent->item(row, col);
551 }
552
553 const QTableWidgetItem *TableItemFormatter::widget(int col) const
554 {
555    return parent->item(row, col);
556 }