2 Bacula® - The Network Backup Solution
4 Copyright (C) 2007-2010 Free Software Foundation Europe e.V.
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
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.
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
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.
31 * Helper functions for tree widget formatting
33 * Riccardo Ghetta, May 2008
38 #include <QTreeWidgetItem>
39 #include <QTableWidget>
40 #include <QTableWidgetItem>
43 #include <QStringList>
45 #include "fmtwidgetitem.h"
47 /***********************************************
51 ***********************************************/
53 QString convertJobStatus(const QString &sts)
55 QString code( sts.trimmed() );
56 if ( code.size() != 1) {
57 return QObject::tr("Invalid job status %1").arg(sts);
61 jobstatus_to_ascii_gui( code[0].toAscii(), buf, sizeof(buf));
66 * disable widget updating
68 Freeze::Freeze(QWidget &q):
71 qw->setUpdatesEnabled(false);
77 qw->setUpdatesEnabled(true);
82 /***********************************************
84 * ItemFormatterBase static members
86 ***********************************************/
88 ItemFormatterBase::BYTES_CONVERSION ItemFormatterBase::cnvFlag(BYTES_CONVERSION_IEC);
90 QString convertBytesIEC(qint64 qfld)
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);
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) */
106 else if (qfld >= PB) {
110 else if (qfld >= TB) {
114 else if (qfld >= GB) {
118 else if (qfld >= MB) {
122 else if (qfld >= KB) {
126 /* plain bytes, no need to reformat */
127 return QString("%1 B").arg(qfld);
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);
135 QString convertBytesSI(qint64 qfld)
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);
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) */
151 else if (qfld >= PB) {
155 else if (qfld >= TB) {
159 else if (qfld >= GB) {
163 else if (qfld >= MB) {
167 else if (qfld >= KB) {
168 suffix = 'k'; /* SI uses lowercase k */
171 /* plain bytes, no need to reformat */
172 return QString("%1 B").arg(qfld);
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);
180 /***********************************************
182 * base formatting routines
184 ***********************************************/
186 ItemFormatterBase::ItemFormatterBase()
190 ItemFormatterBase::~ItemFormatterBase()
194 void ItemFormatterBase::setPercent(int index, float value)
197 bsnprintf(buf, sizeof(buf), "%.2f%%", value);
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";
213 pix = ":images/96p.png";
215 setPixmap(index, QPixmap(pix), val);
216 setSortValue(index, (int) value);
219 /* By default, the setPixmap implementation with tooltip don't implement
222 void ItemFormatterBase::setPixmap(int index, const QPixmap &pix,
225 setPixmap(index, pix);
228 void ItemFormatterBase::setInChanger(int index, const QString &InChanger)
231 QPixmap(":images/inflag"+InChanger+".png"));
232 setSortValue(index, InChanger.toInt() );
235 void ItemFormatterBase::setTextFld(int index, const QString &fld, bool center)
237 setText(index, fld.trimmed());
239 setTextAlignment(index, Qt::AlignCenter);
243 void ItemFormatterBase::setRightFld(int index, const QString &fld)
245 setText(index, fld.trimmed());
246 setTextAlignment(index, Qt::AlignRight | Qt::AlignVCenter);
249 void ItemFormatterBase::setBoolFld(int index, const QString &fld, bool center)
251 if (fld.trimmed().toInt())
252 setTextFld(index, QObject::tr("Yes"), center);
254 setTextFld(index, QObject::tr("No"), center);
257 void ItemFormatterBase::setBoolFld(int index, int fld, bool center)
260 setTextFld(index, QObject::tr("Yes"), center);
262 setTextFld(index, QObject::tr("No"), center);
265 void ItemFormatterBase::setNumericFld(int index, const QString &fld)
267 setRightFld(index, fld.trimmed());
268 setSortValue(index, fld.toDouble() );
271 void ItemFormatterBase::setNumericFld(int index, const QString &fld, const QVariant &sortval)
273 setRightFld(index, fld.trimmed());
274 setSortValue(index, sortval );
277 void ItemFormatterBase::setBytesFld(int index, const QString &fld)
279 qint64 qfld = fld.trimmed().toLongLong();
282 case BYTES_CONVERSION_NONE:
283 msg = QString::number(qfld);
285 case BYTES_CONVERSION_IEC:
286 msg = convertBytesIEC(qfld);
288 case BYTES_CONVERSION_SI:
289 msg = convertBytesSI(qfld);
293 setNumericFld(index, msg, qfld);
296 void ItemFormatterBase::setDurationFld(int index, const QString &fld)
298 static const qint64 HOUR = Q_INT64_C(3600);
299 static const qint64 DAY = HOUR * 24;
300 static const qint64 WEEK = DAY * 7;
301 static const qint64 MONTH = DAY * 30;
302 static const qint64 YEAR = DAY * 365;
303 static const qint64 divs[] = { YEAR, MONTH, WEEK, DAY, HOUR };
304 static const char sufs[] = { 'y', 'm', 'w', 'd', 'h', '\0' };
306 qint64 dfld = fld.trimmed().toLongLong();
310 for (int pos = 0 ; sufs[pos] ; ++pos) {
311 if (dfld % divs[pos] == 0) {
320 msg = QString("%1%2").arg(dfld).arg(suffix);
322 /* previous check returned a number too big. The original specification perhaps
323 was mixed, like 1d 2h, so we try to match with this routine */
324 dfld = fld.trimmed().toLongLong();
326 for (int pos = 0 ; sufs[pos] ; ++pos) {
327 if (dfld / divs[pos] != 0) {
328 msg += QString(" %1%2").arg(dfld / divs[pos]).arg(sufs[pos]);
333 msg += QString(" %1s").arg(dfld);
336 setNumericFld(index, msg, fld.trimmed().toLongLong());
339 void ItemFormatterBase::setVolStatusFld(int index, const QString &fld, bool center)
341 QString mp(fld.trimmed());
342 setTextFld(index, volume_status_to_str(mp.toUtf8()), center);
344 if (mp == "Append" ) {
345 setBackground(index, Qt::green);
346 } else if (mp == "Error") {
347 setBackground(index, Qt::red);
348 } else if (mp == "Used" || mp == "Full"){
349 setBackground(index, Qt::yellow);
350 } else if (mp == "Read-only" || mp == "Disabled"){
351 setBackground(index, Qt::lightGray);
355 void ItemFormatterBase::setJobStatusFld(int index, const QString &status, bool center)
357 /* C (created, not yet running) uses the default background */
358 static QString greenchars("TR");
359 static QString redchars("BEf");
360 static QString yellowchars("eDAFSMmsjdctp");
362 setTextFld(index, convertJobStatus(status), center);
364 QString st(status.trimmed());
365 if (greenchars.contains(st, Qt::CaseSensitive)) {
366 setBackground(index, Qt::green);
367 } else if (redchars.contains(st, Qt::CaseSensitive)) {
368 setBackground(index, Qt::red);
369 } else if (yellowchars.contains(st, Qt::CaseSensitive)){
370 setBackground(index, Qt::yellow);
374 void ItemFormatterBase::setJobTypeFld(int index, const QString &fld, bool center)
376 QByteArray jtype(fld.trimmed().toAscii());
378 setTextFld(index, job_type_to_str(jtype[0]), center);
380 setTextFld(index, "", center);
384 void ItemFormatterBase::setJobLevelFld(int index, const QString &fld, bool center)
386 QByteArray lvl(fld.trimmed().toAscii());
388 setTextFld(index, job_level_to_str(lvl[0]), center);
390 setTextFld(index, "", center);
396 /***********************************************
398 * treeitem formatting routines
400 ***********************************************/
401 TreeItemFormatter::TreeItemFormatter(QTreeWidgetItem &parent, int indent_level):
403 wdg(new QTreeWidgetItem(&parent)),
408 void TreeItemFormatter::setText(int index, const QString &fld)
410 wdg->setData(index, Qt::UserRole, level);
411 wdg->setText(index, fld);
414 void TreeItemFormatter::setTextAlignment(int index, int align)
416 wdg->setTextAlignment(index, align);
419 void TreeItemFormatter::setBackground(int index, const QBrush &qb)
421 wdg->setBackground(index, qb);
424 /* at this time we don't sort trees, so this method does nothing */
425 void TreeItemFormatter::setSortValue(int /* index */, const QVariant & /* value */)
429 void TreeItemFormatter::setPixmap(int index, const QPixmap &pix)
431 wdg->setIcon(index, QIcon(pix));
434 /***********************************************
436 * Specialized table widget used for sorting
438 ***********************************************/
439 TableItemFormatter::BatSortingTableItem::BatSortingTableItem():
444 void TableItemFormatter::BatSortingTableItem::setSortData(const QVariant &d)
446 setData(SORTDATA_ROLE, d);
449 bool TableItemFormatter::BatSortingTableItem::operator< ( const QTableWidgetItem & o ) const
451 QVariant my = data(SORTDATA_ROLE);
452 QVariant other = o.data(SORTDATA_ROLE);
453 if (!my.isValid() || !other.isValid() || my.type() != other.type())
454 return QTableWidgetItem::operator< (o); /* invalid combination, revert to default sorting */
456 /* 64bit integers must be handled separately, others can be converted to double */
457 if (QVariant::ULongLong == my.type()) {
458 return my.toULongLong() < other.toULongLong();
459 } else if (QVariant::LongLong == my.type()) {
460 return my.toLongLong() < other.toLongLong();
461 } else if (my.canConvert(QVariant::Double)) {
462 return my.toDouble() < other.toDouble();
464 return QTableWidgetItem::operator< (o); /* invalid combination, revert to default sorting */
468 /***********************************************
470 * tableitem formatting routines
472 ***********************************************/
473 TableItemFormatter::TableItemFormatter(QTableWidget &tparent, int trow):
481 void TableItemFormatter::setPixmap(int index, const QPixmap &pix)
483 // Centered, but not sortable !
484 QLabel *lbl = new QLabel();
485 lbl->setAlignment(Qt::AlignCenter);
487 parent->setCellWidget(row, index, lbl);
490 void TableItemFormatter::setPixmap(int index, const QPixmap &pix,
493 // Centered, but not sortable !
494 QLabel *lbl = new QLabel();
495 lbl->setAlignment(Qt::AlignCenter);
497 if (!tips.isEmpty()) {
498 lbl->setToolTip(tips);
500 parent->setCellWidget(row, index, lbl);
502 // last = new BatSortingTableItem;
503 // parent->setItem(row, index, last);
504 // last->setIcon(pix);
507 void TableItemFormatter::setText(int col, const QString &fld)
509 last = new BatSortingTableItem;
510 parent->setItem(row, col, last);
514 void TableItemFormatter::setTextAlignment(int /*index*/, int align)
516 last->setTextAlignment(align);
519 void TableItemFormatter::setBackground(int /*index*/, const QBrush &qb)
521 last->setBackground(qb);
524 void TableItemFormatter::setSortValue(int /* index */, const QVariant &value )
526 last->setSortData(value);
529 QTableWidgetItem *TableItemFormatter::widget(int col)
531 return parent->item(row, col);
534 const QTableWidgetItem *TableItemFormatter::widget(int col) const
536 return parent->item(row, col);