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>
36 #include "fmtwidgetitem.h"
38 /***********************************************
42 ***********************************************/
44 QString convertJobStatus(const QString &sts)
46 QString code( sts.trimmed() );
47 if ( code.size() != 1) {
48 return QObject::tr("Invalid job status %1").arg(sts);
52 jobstatus_to_ascii_gui( code[0].toAscii(), buf, sizeof(buf));
57 * disable widget updating
59 Freeze::Freeze(QWidget &q):
62 qw->setUpdatesEnabled(false);
68 qw->setUpdatesEnabled(true);
73 /***********************************************
75 * ItemFormatterBase static members
77 ***********************************************/
79 ItemFormatterBase::BYTES_CONVERSION ItemFormatterBase::cnvFlag(BYTES_CONVERSION_IEC);
81 /* String to Electronic value based on K=1024 */
82 QString convertBytesIEC(qint64 qfld)
84 static const qint64 KB = Q_INT64_C(1024);
85 static const qint64 MB = (KB * KB);
86 static const qint64 GB = (MB * KB);
87 static const qint64 TB = (GB * KB);
88 static const qint64 PB = (TB * KB);
89 static const qint64 EB = (PB * KB);
91 /* note: division is integer, so to have some decimals we divide for a
92 smaller unit (e.g. GB for a TB number and so on) */
98 else if (qfld >= PB) {
102 else if (qfld >= TB) {
106 else if (qfld >= GB) {
110 else if (qfld >= MB) {
114 else if (qfld >= KB) {
118 /* plain bytes, no need to reformat */
119 return QString("%1 B").arg(qfld);
122 /* After dividing into a smaller value, we can safely convert from
123 * to a double double and use the extra room for decimals
125 return QString("%1 %2iB").arg(qfld / 1024.0, 0, 'f', 2).arg(suffix);
128 /* String to human value based on k=1000 */
129 QString convertBytesSI(qint64 qfld)
131 static const qint64 KB = Q_INT64_C(1000);
132 static const qint64 MB = (KB * KB);
133 static const qint64 GB = (MB * KB);
134 static const qint64 TB = (GB * KB);
135 static const qint64 PB = (TB * KB);
136 static const qint64 EB = (PB * KB);
138 /* Note: division is integer, so to have some decimals we divide for a
139 smaller unit (e.g. GB for a TB number and so on) */
145 else if (qfld >= PB) {
149 else if (qfld >= TB) {
153 else if (qfld >= GB) {
157 else if (qfld >= MB) {
161 else if (qfld >= KB) {
162 suffix = 'k'; /* SI uses lowercase k */
165 /* plain bytes, no need to reformat */
166 return QString("%1 B").arg(qfld);
169 /* having divided for a smaller unit, now we can safely convert to double and
170 use the extra room for decimals */
171 return QString("%1 %2B").arg(qfld / 1000.0, 0, 'f', 2).arg(suffix);
174 /***********************************************
176 * base formatting routines
178 ***********************************************/
180 ItemFormatterBase::ItemFormatterBase()
184 ItemFormatterBase::~ItemFormatterBase()
188 void ItemFormatterBase::setPercent(int index, float value)
191 bsnprintf(buf, sizeof(buf), "%.2f%%", value);
195 pix = ":images/0p.png";
196 } else if (value < 24) {
197 pix = ":images/16p.png";
198 } else if (value < 40) {
199 pix = ":images/32p.png";
200 } else if (value < 56) {
201 pix = ":images/48p.png";
202 } else if (value < 72) {
203 pix = ":images/64p.png";
204 } else if (value < 88) {
205 pix = ":images/80p.png";
207 pix = ":images/96p.png";
209 setPixmap(index, QPixmap(pix), val);
210 //setSortValue(index, (int) value);
211 //setBackground(index, Qt::green);
214 /* By default, the setPixmap implementation with tooltip don't implement
217 void ItemFormatterBase::setPixmap(int index, const QPixmap &pix,
218 const QString & /* tip */)
220 setPixmap(index, pix);
223 void ItemFormatterBase::setInChanger(int index, const QString &InChanger)
225 setPixmap(index, QPixmap(":images/inflag"+InChanger+".png"));
226 //setSortValue(index, InChanger.toInt() );
229 void ItemFormatterBase::setFileType(int index, const QString &type)
231 setPixmap(index, QPixmap(":images/"+type+".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::setDateFld(int index, utime_t fld, bool center)
246 bstrutime(buf, sizeof(buf), fld);
247 setText(index, QString(buf).trimmed());
249 setTextAlignment(index, Qt::AlignCenter);
253 void ItemFormatterBase::setRightFld(int index, const QString &fld)
255 setText(index, fld.trimmed());
256 setTextAlignment(index, Qt::AlignRight | Qt::AlignVCenter);
259 void ItemFormatterBase::setBoolFld(int index, const QString &fld, bool center)
261 if (fld.trimmed().toInt())
262 setTextFld(index, QObject::tr("Yes"), center);
264 setTextFld(index, QObject::tr("No"), center);
267 void ItemFormatterBase::setBoolFld(int index, int fld, bool center)
270 setTextFld(index, QObject::tr("Yes"), center);
272 setTextFld(index, QObject::tr("No"), center);
275 void ItemFormatterBase::setNumericFld(int index, const QString &fld)
277 setRightFld(index, fld.trimmed());
278 setSortValue(index, fld.toDouble() );
281 void ItemFormatterBase::setNumericFld(int index, const QString &fld, const QVariant &sortval)
283 setRightFld(index, fld.trimmed());
284 setSortValue(index, sortval );
287 void ItemFormatterBase::setBytesFld(int index, const QString &fld)
289 qint64 qfld = fld.trimmed().toLongLong();
292 case BYTES_CONVERSION_NONE:
293 msg = QString::number(qfld);
295 case BYTES_CONVERSION_IEC:
296 msg = convertBytesIEC(qfld);
298 case BYTES_CONVERSION_SI:
299 msg = convertBytesSI(qfld);
306 setNumericFld(index, msg, QVariant(qfld));
309 void ItemFormatterBase::setDurationFld(int index, const QString &fld)
311 static const qint64 HOUR = Q_INT64_C(3600);
312 static const qint64 DAY = HOUR * 24;
313 static const qint64 WEEK = DAY * 7;
314 static const qint64 MONTH = DAY * 30;
315 static const qint64 YEAR = DAY * 365;
316 static const qint64 divs[] = { YEAR, MONTH, WEEK, DAY, HOUR };
317 static const char sufs[] = { 'y', 'm', 'w', 'd', 'h', '\0' };
319 qint64 dfld = fld.trimmed().toLongLong();
323 for (int pos = 0 ; sufs[pos] ; ++pos) {
324 if (dfld % divs[pos] == 0) {
333 msg = QString("%1%2").arg(dfld).arg(suffix);
335 /* previous check returned a number too big. The original specification perhaps
336 was mixed, like 1d 2h, so we try to match with this routine */
337 dfld = fld.trimmed().toLongLong();
339 for (int pos = 0 ; sufs[pos] ; ++pos) {
340 if (dfld / divs[pos] != 0) {
341 msg += QString(" %1%2").arg(dfld / divs[pos]).arg(sufs[pos]);
346 msg += QString(" %1s").arg(dfld);
349 setNumericFld(index, msg, QVariant(fld.trimmed().toLongLong()));
352 void ItemFormatterBase::setVolStatusFld(int index, const QString &fld, bool center)
354 QString mp(fld.trimmed());
355 setTextFld(index, volume_status_to_str(mp.toUtf8()), center);
357 if (mp == "Append" ) {
358 setBackground(index, Qt::green);
359 } else if (mp == "Error") {
360 setBackground(index, Qt::red);
361 } else if (mp == "Used" || mp == "Full"){
362 setBackground(index, Qt::yellow);
363 } else if (mp == "Read-only" || mp == "Disabled"){
364 setBackground(index, Qt::lightGray);
368 void ItemFormatterBase::setJobStatusFld(int index, const QString &status, bool center)
370 /* C (created, not yet running) uses the default background */
371 static QString greenchars("TR");
372 static QString redchars("BEf");
373 static QString yellowchars("eDAFSMmsjdctp");
375 setTextFld(index, convertJobStatus(status), center);
377 QString st(status.trimmed());
378 if (greenchars.contains(st, Qt::CaseSensitive)) {
379 setBackground(index, Qt::green);
380 } else if (redchars.contains(st, Qt::CaseSensitive)) {
381 setBackground(index, Qt::red);
382 } else if (yellowchars.contains(st, Qt::CaseSensitive)){
383 setBackground(index, Qt::yellow);
387 void ItemFormatterBase::setJobTypeFld(int index, const QString &fld, bool center)
389 QByteArray jtype(fld.trimmed().toAscii());
391 setTextFld(index, job_type_to_str(jtype[0]), center);
393 setTextFld(index, "", center);
397 void ItemFormatterBase::setJobLevelFld(int index, const QString &fld, bool center)
399 QByteArray lvl(fld.trimmed().toAscii());
401 setTextFld(index, job_level_to_str(lvl[0]), center);
403 setTextFld(index, "", center);
409 /***********************************************
411 * treeitem formatting routines
413 ***********************************************/
414 TreeItemFormatter::TreeItemFormatter(QTreeWidgetItem &parent, int indent_level):
416 wdg(new QTreeWidgetItem(&parent)),
421 void TreeItemFormatter::setText(int index, const QString &fld)
423 wdg->setData(index, Qt::UserRole, level);
424 wdg->setText(index, fld);
427 void TreeItemFormatter::setTextAlignment(int index, int align)
429 wdg->setTextAlignment(index, align);
432 void TreeItemFormatter::setBackground(int index, const QBrush &qb)
434 wdg->setBackground(index, qb);
437 /* at this time we don't sort trees, so this method does nothing */
438 void TreeItemFormatter::setSortValue(int /* index */, const QVariant & /* value */)
442 void TreeItemFormatter::setPixmap(int index, const QPixmap &pix)
444 wdg->setIcon(index, QIcon(pix));
447 /***********************************************
449 * Specialized table widget used for sorting
451 ***********************************************/
452 TableItemFormatter::BatSortingTableItem::BatSortingTableItem():
457 void TableItemFormatter::BatSortingTableItem::setSortData(const QVariant &d)
459 setData(SORTDATA_ROLE, d);
462 bool TableItemFormatter::BatSortingTableItem::operator< ( const QTableWidgetItem & o ) const
464 QVariant my = data(SORTDATA_ROLE);
465 QVariant other = o.data(SORTDATA_ROLE);
466 if (!my.isValid() || !other.isValid() || my.type() != other.type())
467 return QTableWidgetItem::operator< (o); /* invalid combination, revert to default sorting */
469 /* 64bit integers must be handled separately, others can be converted to double */
470 if (QVariant::ULongLong == my.type()) {
471 return my.toULongLong() < other.toULongLong();
472 } else if (QVariant::LongLong == my.type()) {
473 return my.toLongLong() < other.toLongLong();
474 } else if (my.canConvert(QVariant::Double)) {
475 return my.toDouble() < other.toDouble();
477 return QTableWidgetItem::operator< (o); /* invalid combination, revert to default sorting */
481 /***********************************************
483 * tableitem formatting routines
485 ***********************************************/
486 TableItemFormatter::TableItemFormatter(QTableWidget &tparent, int trow):
494 void TableItemFormatter::setPixmap(int index, const QPixmap &pix)
496 // Centered, but not sortable !
497 QLabel *lbl = new QLabel();
498 lbl->setAlignment(Qt::AlignCenter);
500 parent->setCellWidget(row, index, lbl);
503 void TableItemFormatter::setPixmap(int index, const QPixmap &pix,
506 // Centered, but not sortable !
507 QLabel *lbl = new QLabel();
508 lbl->setAlignment(Qt::AlignCenter);
510 if (!tips.isEmpty()) {
511 lbl->setToolTip(tips);
513 parent->setCellWidget(row, index, lbl);
515 // last = new BatSortingTableItem;
516 // parent->setItem(row, index, last);
517 // last->setIcon(pix);
520 void TableItemFormatter::setText(int col, const QString &fld)
522 last = new BatSortingTableItem;
523 parent->setItem(row, col, last);
527 void TableItemFormatter::setTextAlignment(int /*index*/, int align)
529 last->setTextAlignment(align);
532 void TableItemFormatter::setBackground(int /*index*/, const QBrush &qb)
534 last->setBackground(qb);
537 void TableItemFormatter::setSortValue(int /* index */, const QVariant &value )
539 last->setSortData(value);
542 QTableWidgetItem *TableItemFormatter::widget(int col)
544 return parent->item(row, col);
547 const QTableWidgetItem *TableItemFormatter::widget(int col) const
549 return parent->item(row, col);