2 Bacula(R) - The Network Backup Solution
4 Copyright (C) 2000-2016 Kern Sibbald
6 The original author of Bacula is Kern Sibbald, with contributions
7 from many others, a complete list can be found in the file AUTHORS.
9 You may use this file and others of this release according to the
10 license defined in the LICENSE file, which includes the Affero General
11 Public License, v3.0 ("AGPLv3") and some additional permissions and
12 terms pursuant to its AGPLv3 Section 7.
14 This notice must be preserved when any source code is
15 conveyed and/or propagated.
17 Bacula(R) is a registered trademark of Kern Sibbald.
22 * Helper functions for tree widget formatting
24 * Riccardo Ghetta, May 2008
29 #include <QTreeWidgetItem>
30 #include <QTableWidget>
31 #include <QTableWidgetItem>
34 #include <QStringList>
37 #include "fmtwidgetitem.h"
39 /***********************************************
43 ***********************************************/
45 QString convertJobStatus(const QString &sts)
47 QString code( sts.trimmed() );
48 if ( code.size() != 1) {
49 return QObject::tr("Invalid job status %1").arg(sts);
53 jobstatus_to_ascii_gui( code[0].toLatin1(), buf, sizeof(buf));
58 * disable widget updating
60 Freeze::Freeze(QWidget &q):
63 qw->setUpdatesEnabled(false);
69 qw->setUpdatesEnabled(true);
74 /***********************************************
76 * ItemFormatterBase static members
78 ***********************************************/
80 ItemFormatterBase::BYTES_CONVERSION ItemFormatterBase::cnvFlag(BYTES_CONVERSION_IEC);
82 /* String to Electronic value based on K=1024 */
83 QString convertBytesIEC(qint64 qfld)
85 static const qint64 KB = Q_INT64_C(1024);
86 static const qint64 MB = (KB * KB);
87 static const qint64 GB = (MB * KB);
88 static const qint64 TB = (GB * KB);
89 static const qint64 PB = (TB * KB);
90 static const qint64 EB = (PB * KB);
92 /* note: division is integer, so to have some decimals we divide for a
93 smaller unit (e.g. GB for a TB number and so on) */
99 else if (qfld >= PB) {
103 else if (qfld >= TB) {
107 else if (qfld >= GB) {
111 else if (qfld >= MB) {
115 else if (qfld >= KB) {
119 /* plain bytes, no need to reformat */
120 return QString("%1 B").arg(qfld);
123 /* After dividing into a smaller value, we can safely convert from
124 * to a double double and use the extra room for decimals
126 return QString("%1 %2iB").arg(qfld / 1024.0, 0, 'f', 2).arg(suffix);
129 /* String to human value based on k=1000 */
130 QString convertBytesSI(qint64 qfld)
132 static const qint64 KB = Q_INT64_C(1000);
133 static const qint64 MB = (KB * KB);
134 static const qint64 GB = (MB * KB);
135 static const qint64 TB = (GB * KB);
136 static const qint64 PB = (TB * KB);
137 static const qint64 EB = (PB * KB);
139 /* Note: division is integer, so to have some decimals we divide for a
140 smaller unit (e.g. GB for a TB number and so on) */
146 else if (qfld >= PB) {
150 else if (qfld >= TB) {
154 else if (qfld >= GB) {
158 else if (qfld >= MB) {
162 else if (qfld >= KB) {
163 suffix = 'k'; /* SI uses lowercase k */
166 /* plain bytes, no need to reformat */
167 return QString("%1 B").arg(qfld);
170 /* having divided for a smaller unit, now we can safely convert to double and
171 use the extra room for decimals */
172 return QString("%1 %2B").arg(qfld / 1000.0, 0, 'f', 2).arg(suffix);
175 /***********************************************
177 * base formatting routines
179 ***********************************************/
181 ItemFormatterBase::ItemFormatterBase()
185 ItemFormatterBase::~ItemFormatterBase()
189 void ItemFormatterBase::setPercent(int index, float value)
192 bsnprintf(buf, sizeof(buf), "%.2f%%", value);
196 pix = ":images/0p.png";
197 } else if (value < 24) {
198 pix = ":images/16p.png";
199 } else if (value < 40) {
200 pix = ":images/32p.png";
201 } else if (value < 56) {
202 pix = ":images/48p.png";
203 } else if (value < 72) {
204 pix = ":images/64p.png";
205 } else if (value < 88) {
206 pix = ":images/80p.png";
208 pix = ":images/96p.png";
210 setPixmap(index, QPixmap(pix), val);
211 //setSortValue(index, (int) value);
212 //setBackground(index, Qt::green);
215 /* By default, the setPixmap implementation with tooltip don't implement
218 void ItemFormatterBase::setPixmap(int index, const QPixmap &pix,
219 const QString & /* tip */)
221 setPixmap(index, pix);
224 void ItemFormatterBase::setInChanger(int index, const QString &InChanger)
226 setPixmap(index, QPixmap(":images/inflag"+InChanger+".png"));
227 //setSortValue(index, InChanger.toInt() );
230 void ItemFormatterBase::setFileType(int index, const QString &type)
232 setPixmap(index, QPixmap(":images/"+type+".png"));
233 //setSortValue(index, InChanger.toInt() );
236 void ItemFormatterBase::setTextFld(int index, const QString &fld, bool center)
238 setText(index, fld.trimmed());
240 setTextAlignment(index, Qt::AlignCenter);
244 void ItemFormatterBase::setDateFld(int index, utime_t fld, bool center)
247 bstrutime(buf, sizeof(buf), fld);
248 setText(index, QString(buf).trimmed());
250 setTextAlignment(index, Qt::AlignCenter);
254 void ItemFormatterBase::setRightFld(int index, const QString &fld)
256 setText(index, fld.trimmed());
257 setTextAlignment(index, Qt::AlignRight | Qt::AlignVCenter);
260 void ItemFormatterBase::setBoolFld(int index, const QString &fld, bool center)
262 if (fld.trimmed().toInt())
263 setTextFld(index, QObject::tr("Yes"), center);
265 setTextFld(index, QObject::tr("No"), center);
268 void ItemFormatterBase::setBoolFld(int index, int fld, bool center)
271 setTextFld(index, QObject::tr("Yes"), center);
273 setTextFld(index, QObject::tr("No"), center);
276 void ItemFormatterBase::setNumericFld(int index, const QString &fld)
278 setRightFld(index, fld.trimmed());
279 setSortValue(index, fld.toDouble() );
282 void ItemFormatterBase::setNumericFld(int index, const QString &fld, const QVariant &sortval)
284 setRightFld(index, fld.trimmed());
285 setSortValue(index, sortval );
288 void ItemFormatterBase::setBytesFld(int index, const QString &fld)
290 qint64 qfld = fld.trimmed().toLongLong();
293 case BYTES_CONVERSION_NONE:
294 msg = QString::number(qfld);
296 case BYTES_CONVERSION_IEC:
297 msg = convertBytesIEC(qfld);
299 case BYTES_CONVERSION_SI:
300 msg = convertBytesSI(qfld);
307 setNumericFld(index, msg, QVariant(qfld));
310 void ItemFormatterBase::setDurationFld(int index, const QString &fld)
312 static const qint64 HOUR = Q_INT64_C(3600);
313 static const qint64 DAY = HOUR * 24;
314 static const qint64 WEEK = DAY * 7;
315 static const qint64 MONTH = DAY * 30;
316 static const qint64 YEAR = DAY * 365;
317 static const qint64 divs[] = { YEAR, MONTH, WEEK, DAY, HOUR };
318 static const char sufs[] = { 'y', 'm', 'w', 'd', 'h', '\0' };
320 qint64 dfld = fld.trimmed().toLongLong();
324 for (int pos = 0 ; sufs[pos] ; ++pos) {
325 if (dfld % divs[pos] == 0) {
334 msg = QString("%1%2").arg(dfld).arg(suffix);
336 /* previous check returned a number too big. The original specification perhaps
337 was mixed, like 1d 2h, so we try to match with this routine */
338 dfld = fld.trimmed().toLongLong();
340 for (int pos = 0 ; sufs[pos] ; ++pos) {
341 if (dfld / divs[pos] != 0) {
342 msg += QString(" %1%2").arg(dfld / divs[pos]).arg(sufs[pos]);
347 msg += QString(" %1s").arg(dfld);
350 setNumericFld(index, msg, QVariant(fld.trimmed().toLongLong()));
353 void ItemFormatterBase::setVolStatusFld(int index, const QString &fld, bool center)
355 QString mp(fld.trimmed());
356 setTextFld(index, volume_status_to_str(mp.toUtf8()), center);
358 if (mp == "Append" ) {
359 setBackground(index, Qt::green);
360 } else if (mp == "Error") {
361 setBackground(index, Qt::red);
362 } else if (mp == "Used" || mp == "Full"){
363 setBackground(index, Qt::yellow);
364 } else if (mp == "Read-only" || mp == "Disabled"){
365 setBackground(index, Qt::lightGray);
369 void ItemFormatterBase::setJobStatusFld(int index, const QString &status, bool center)
371 /* C (created, not yet running) uses the default background */
372 static QString greenchars("TR");
373 static QString redchars("BEf");
374 static QString yellowchars("eDAFSMmsjdctp");
376 setTextFld(index, convertJobStatus(status), center);
378 QString st(status.trimmed());
379 if (greenchars.contains(st, Qt::CaseSensitive)) {
380 setBackground(index, Qt::green);
381 } else if (redchars.contains(st, Qt::CaseSensitive)) {
382 setBackground(index, Qt::red);
383 } else if (yellowchars.contains(st, Qt::CaseSensitive)){
384 setBackground(index, Qt::yellow);
388 void ItemFormatterBase::setJobTypeFld(int index, const QString &fld, bool center)
390 QByteArray jtype(fld.trimmed().toLatin1());
392 setTextFld(index, job_type_to_str(jtype[0]), center);
394 setTextFld(index, "", center);
398 void ItemFormatterBase::setJobLevelFld(int index, const QString &fld, bool center)
400 QByteArray lvl(fld.trimmed().toLatin1());
402 setTextFld(index, job_level_to_str(lvl[0]), center);
404 setTextFld(index, "", center);
410 /***********************************************
412 * treeitem formatting routines
414 ***********************************************/
415 TreeItemFormatter::TreeItemFormatter(QTreeWidgetItem &parent, int indent_level):
417 wdg(new QTreeWidgetItem(&parent)),
422 void TreeItemFormatter::setText(int index, const QString &fld)
424 wdg->setData(index, Qt::UserRole, level);
425 wdg->setText(index, fld);
428 void TreeItemFormatter::setTextAlignment(int index, int align)
430 wdg->setTextAlignment(index, align);
433 void TreeItemFormatter::setBackground(int index, const QBrush &qb)
435 wdg->setBackground(index, qb);
438 /* at this time we don't sort trees, so this method does nothing */
439 void TreeItemFormatter::setSortValue(int /* index */, const QVariant & /* value */)
443 void TreeItemFormatter::setPixmap(int index, const QPixmap &pix)
445 wdg->setIcon(index, QIcon(pix));
448 /***********************************************
450 * Specialized table widget used for sorting
452 ***********************************************/
453 TableItemFormatter::BatSortingTableItem::BatSortingTableItem():
458 void TableItemFormatter::BatSortingTableItem::setSortData(const QVariant &d)
460 setData(SORTDATA_ROLE, d);
463 bool TableItemFormatter::BatSortingTableItem::operator< ( const QTableWidgetItem & o ) const
465 QVariant my = data(SORTDATA_ROLE);
466 QVariant other = o.data(SORTDATA_ROLE);
467 if (!my.isValid() || !other.isValid() || my.type() != other.type())
468 return QTableWidgetItem::operator< (o); /* invalid combination, revert to default sorting */
470 /* 64bit integers must be handled separately, others can be converted to double */
471 if (QVariant::ULongLong == my.type()) {
472 return my.toULongLong() < other.toULongLong();
473 } else if (QVariant::LongLong == my.type()) {
474 return my.toLongLong() < other.toLongLong();
475 } else if (my.canConvert(QVariant::Double)) {
476 return my.toDouble() < other.toDouble();
478 return QTableWidgetItem::operator< (o); /* invalid combination, revert to default sorting */
482 /***********************************************
484 * tableitem formatting routines
486 ***********************************************/
487 TableItemFormatter::TableItemFormatter(QTableWidget &tparent, int trow):
495 void TableItemFormatter::setPixmap(int index, const QPixmap &pix)
497 // Centered, but not sortable !
498 QLabel *lbl = new QLabel();
499 lbl->setAlignment(Qt::AlignCenter);
501 parent->setCellWidget(row, index, lbl);
504 void TableItemFormatter::setPixmap(int index, const QPixmap &pix,
507 // Centered, but not sortable !
508 QLabel *lbl = new QLabel();
509 lbl->setAlignment(Qt::AlignCenter);
511 if (!tips.isEmpty()) {
512 lbl->setToolTip(tips);
514 parent->setCellWidget(row, index, lbl);
516 // last = new BatSortingTableItem;
517 // parent->setItem(row, index, last);
518 // last->setIcon(pix);
521 void TableItemFormatter::setText(int col, const QString &fld)
523 last = new BatSortingTableItem;
524 parent->setItem(row, col, last);
528 void TableItemFormatter::setTextAlignment(int /*index*/, int align)
530 last->setTextAlignment(align);
533 void TableItemFormatter::setBackground(int /*index*/, const QBrush &qb)
535 last->setBackground(qb);
538 void TableItemFormatter::setSortValue(int /* index */, const QVariant &value )
540 last->setSortData(value);
543 QTableWidgetItem *TableItemFormatter::widget(int col)
545 return parent->item(row, col);
548 const QTableWidgetItem *TableItemFormatter::widget(int col) const
550 return parent->item(row, col);