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 three of the GNU Affero 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 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
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);
217 //setBackground(index, Qt::green);
220 /* By default, the setPixmap implementation with tooltip don't implement
223 void ItemFormatterBase::setPixmap(int index, const QPixmap &pix,
224 const QString & /* tip */)
226 setPixmap(index, pix);
229 void ItemFormatterBase::setInChanger(int index, const QString &InChanger)
231 setPixmap(index, QPixmap(":images/inflag"+InChanger+".png"));
232 //setSortValue(index, InChanger.toInt() );
235 void ItemFormatterBase::setFileType(int index, const QString &type)
237 setPixmap(index, QPixmap(":images/"+type+".png"));
238 //setSortValue(index, InChanger.toInt() );
241 void ItemFormatterBase::setTextFld(int index, const QString &fld, bool center)
243 setText(index, fld.trimmed());
245 setTextAlignment(index, Qt::AlignCenter);
249 void ItemFormatterBase::setDateFld(int index, utime_t fld, bool center)
252 bstrutime(buf, sizeof(buf), fld);
253 setText(index, QString(buf).trimmed());
255 setTextAlignment(index, Qt::AlignCenter);
259 void ItemFormatterBase::setRightFld(int index, const QString &fld)
261 setText(index, fld.trimmed());
262 setTextAlignment(index, Qt::AlignRight | Qt::AlignVCenter);
265 void ItemFormatterBase::setBoolFld(int index, const QString &fld, bool center)
267 if (fld.trimmed().toInt())
268 setTextFld(index, QObject::tr("Yes"), center);
270 setTextFld(index, QObject::tr("No"), center);
273 void ItemFormatterBase::setBoolFld(int index, int fld, bool center)
276 setTextFld(index, QObject::tr("Yes"), center);
278 setTextFld(index, QObject::tr("No"), center);
281 void ItemFormatterBase::setNumericFld(int index, const QString &fld)
283 setRightFld(index, fld.trimmed());
284 setSortValue(index, fld.toDouble() );
287 void ItemFormatterBase::setNumericFld(int index, const QString &fld, const QVariant &sortval)
289 setRightFld(index, fld.trimmed());
290 setSortValue(index, sortval );
293 void ItemFormatterBase::setBytesFld(int index, const QString &fld)
295 qint64 qfld = fld.trimmed().toLongLong();
298 case BYTES_CONVERSION_NONE:
299 msg = QString::number(qfld);
301 case BYTES_CONVERSION_IEC:
302 msg = convertBytesIEC(qfld);
304 case BYTES_CONVERSION_SI:
305 msg = convertBytesSI(qfld);
309 setNumericFld(index, msg, qfld);
312 void ItemFormatterBase::setDurationFld(int index, const QString &fld)
314 static const qint64 HOUR = Q_INT64_C(3600);
315 static const qint64 DAY = HOUR * 24;
316 static const qint64 WEEK = DAY * 7;
317 static const qint64 MONTH = DAY * 30;
318 static const qint64 YEAR = DAY * 365;
319 static const qint64 divs[] = { YEAR, MONTH, WEEK, DAY, HOUR };
320 static const char sufs[] = { 'y', 'm', 'w', 'd', 'h', '\0' };
322 qint64 dfld = fld.trimmed().toLongLong();
326 for (int pos = 0 ; sufs[pos] ; ++pos) {
327 if (dfld % divs[pos] == 0) {
336 msg = QString("%1%2").arg(dfld).arg(suffix);
338 /* previous check returned a number too big. The original specification perhaps
339 was mixed, like 1d 2h, so we try to match with this routine */
340 dfld = fld.trimmed().toLongLong();
342 for (int pos = 0 ; sufs[pos] ; ++pos) {
343 if (dfld / divs[pos] != 0) {
344 msg += QString(" %1%2").arg(dfld / divs[pos]).arg(sufs[pos]);
349 msg += QString(" %1s").arg(dfld);
352 setNumericFld(index, msg, fld.trimmed().toLongLong());
355 void ItemFormatterBase::setVolStatusFld(int index, const QString &fld, bool center)
357 QString mp(fld.trimmed());
358 setTextFld(index, volume_status_to_str(mp.toUtf8()), center);
360 if (mp == "Append" ) {
361 setBackground(index, Qt::green);
362 } else if (mp == "Error") {
363 setBackground(index, Qt::red);
364 } else if (mp == "Used" || mp == "Full"){
365 setBackground(index, Qt::yellow);
366 } else if (mp == "Read-only" || mp == "Disabled"){
367 setBackground(index, Qt::lightGray);
371 void ItemFormatterBase::setJobStatusFld(int index, const QString &status, bool center)
373 /* C (created, not yet running) uses the default background */
374 static QString greenchars("TR");
375 static QString redchars("BEf");
376 static QString yellowchars("eDAFSMmsjdctp");
378 setTextFld(index, convertJobStatus(status), center);
380 QString st(status.trimmed());
381 if (greenchars.contains(st, Qt::CaseSensitive)) {
382 setBackground(index, Qt::green);
383 } else if (redchars.contains(st, Qt::CaseSensitive)) {
384 setBackground(index, Qt::red);
385 } else if (yellowchars.contains(st, Qt::CaseSensitive)){
386 setBackground(index, Qt::yellow);
390 void ItemFormatterBase::setJobTypeFld(int index, const QString &fld, bool center)
392 QByteArray jtype(fld.trimmed().toAscii());
394 setTextFld(index, job_type_to_str(jtype[0]), center);
396 setTextFld(index, "", center);
400 void ItemFormatterBase::setJobLevelFld(int index, const QString &fld, bool center)
402 QByteArray lvl(fld.trimmed().toAscii());
404 setTextFld(index, job_level_to_str(lvl[0]), center);
406 setTextFld(index, "", center);
412 /***********************************************
414 * treeitem formatting routines
416 ***********************************************/
417 TreeItemFormatter::TreeItemFormatter(QTreeWidgetItem &parent, int indent_level):
419 wdg(new QTreeWidgetItem(&parent)),
424 void TreeItemFormatter::setText(int index, const QString &fld)
426 wdg->setData(index, Qt::UserRole, level);
427 wdg->setText(index, fld);
430 void TreeItemFormatter::setTextAlignment(int index, int align)
432 wdg->setTextAlignment(index, align);
435 void TreeItemFormatter::setBackground(int index, const QBrush &qb)
437 wdg->setBackground(index, qb);
440 /* at this time we don't sort trees, so this method does nothing */
441 void TreeItemFormatter::setSortValue(int /* index */, const QVariant & /* value */)
445 void TreeItemFormatter::setPixmap(int index, const QPixmap &pix)
447 wdg->setIcon(index, QIcon(pix));
450 /***********************************************
452 * Specialized table widget used for sorting
454 ***********************************************/
455 TableItemFormatter::BatSortingTableItem::BatSortingTableItem():
460 void TableItemFormatter::BatSortingTableItem::setSortData(const QVariant &d)
462 setData(SORTDATA_ROLE, d);
465 bool TableItemFormatter::BatSortingTableItem::operator< ( const QTableWidgetItem & o ) const
467 QVariant my = data(SORTDATA_ROLE);
468 QVariant other = o.data(SORTDATA_ROLE);
469 if (!my.isValid() || !other.isValid() || my.type() != other.type())
470 return QTableWidgetItem::operator< (o); /* invalid combination, revert to default sorting */
472 /* 64bit integers must be handled separately, others can be converted to double */
473 if (QVariant::ULongLong == my.type()) {
474 return my.toULongLong() < other.toULongLong();
475 } else if (QVariant::LongLong == my.type()) {
476 return my.toLongLong() < other.toLongLong();
477 } else if (my.canConvert(QVariant::Double)) {
478 return my.toDouble() < other.toDouble();
480 return QTableWidgetItem::operator< (o); /* invalid combination, revert to default sorting */
484 /***********************************************
486 * tableitem formatting routines
488 ***********************************************/
489 TableItemFormatter::TableItemFormatter(QTableWidget &tparent, int trow):
497 void TableItemFormatter::setPixmap(int index, const QPixmap &pix)
499 // Centered, but not sortable !
500 QLabel *lbl = new QLabel();
501 lbl->setAlignment(Qt::AlignCenter);
503 parent->setCellWidget(row, index, lbl);
506 void TableItemFormatter::setPixmap(int index, const QPixmap &pix,
509 // Centered, but not sortable !
510 QLabel *lbl = new QLabel();
511 lbl->setAlignment(Qt::AlignCenter);
513 if (!tips.isEmpty()) {
514 lbl->setToolTip(tips);
516 parent->setCellWidget(row, index, lbl);
518 // last = new BatSortingTableItem;
519 // parent->setItem(row, index, last);
520 // last->setIcon(pix);
523 void TableItemFormatter::setText(int col, const QString &fld)
525 last = new BatSortingTableItem;
526 parent->setItem(row, col, last);
530 void TableItemFormatter::setTextAlignment(int /*index*/, int align)
532 last->setTextAlignment(align);
535 void TableItemFormatter::setBackground(int /*index*/, const QBrush &qb)
537 last->setBackground(qb);
540 void TableItemFormatter::setSortValue(int /* index */, const QVariant &value )
542 last->setSortData(value);
545 QTableWidgetItem *TableItemFormatter::widget(int col)
547 return parent->item(row, col);
550 const QTableWidgetItem *TableItemFormatter::widget(int col) const
552 return parent->item(row, col);