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 /* String to Electronic value based on K=1024 */
91 QString convertBytesIEC(qint64 qfld)
93 static const qint64 KB = Q_INT64_C(1024);
94 static const qint64 MB = (KB * KB);
95 static const qint64 GB = (MB * KB);
96 static const qint64 TB = (GB * KB);
97 static const qint64 PB = (TB * KB);
98 static const qint64 EB = (PB * KB);
100 /* note: division is integer, so to have some decimals we divide for a
101 smaller unit (e.g. GB for a TB number and so on) */
107 else if (qfld >= PB) {
111 else if (qfld >= TB) {
115 else if (qfld >= GB) {
119 else if (qfld >= MB) {
123 else if (qfld >= KB) {
127 /* plain bytes, no need to reformat */
128 return QString("%1 B").arg(qfld);
131 /* having divided for a smaller unit, now we can safely convert to double and
132 use the extra room for decimals */
133 return QString("%1 %2iB").arg(qfld / 1000.0, 0, 'f', 2).arg(suffix);
136 /* String to human value based on k=1000 */
137 QString convertBytesSI(qint64 qfld)
139 static const qint64 KB = Q_INT64_C(1000);
140 static const qint64 MB = (KB * KB);
141 static const qint64 GB = (MB * KB);
142 static const qint64 TB = (GB * KB);
143 static const qint64 PB = (TB * KB);
144 static const qint64 EB = (PB * KB);
146 /* note: division is integer, so to have some decimals we divide for a
147 smaller unit (e.g. GB for a TB number and so on) */
153 else if (qfld >= PB) {
157 else if (qfld >= TB) {
161 else if (qfld >= GB) {
165 else if (qfld >= MB) {
169 else if (qfld >= KB) {
170 suffix = 'k'; /* SI uses lowercase k */
173 /* plain bytes, no need to reformat */
174 return QString("%1 B").arg(qfld);
177 /* having divided for a smaller unit, now we can safely convert to double and
178 use the extra room for decimals */
179 return QString("%1 %2B").arg(qfld / 1000.0, 0, 'f', 2).arg(suffix);
182 /***********************************************
184 * base formatting routines
186 ***********************************************/
188 ItemFormatterBase::ItemFormatterBase()
192 ItemFormatterBase::~ItemFormatterBase()
196 void ItemFormatterBase::setPercent(int index, float value)
199 bsnprintf(buf, sizeof(buf), "%.2f%%", value);
203 pix = ":images/0p.png";
204 } else if (value < 24) {
205 pix = ":images/16p.png";
206 } else if (value < 40) {
207 pix = ":images/32p.png";
208 } else if (value < 56) {
209 pix = ":images/48p.png";
210 } else if (value < 72) {
211 pix = ":images/64p.png";
212 } else if (value < 88) {
213 pix = ":images/80p.png";
215 pix = ":images/96p.png";
217 setPixmap(index, QPixmap(pix), val);
218 //setSortValue(index, (int) value);
219 //setBackground(index, Qt::green);
222 /* By default, the setPixmap implementation with tooltip don't implement
225 void ItemFormatterBase::setPixmap(int index, const QPixmap &pix,
226 const QString & /* tip */)
228 setPixmap(index, pix);
231 void ItemFormatterBase::setInChanger(int index, const QString &InChanger)
233 setPixmap(index, QPixmap(":images/inflag"+InChanger+".png"));
234 //setSortValue(index, InChanger.toInt() );
237 void ItemFormatterBase::setFileType(int index, const QString &type)
239 setPixmap(index, QPixmap(":images/"+type+".png"));
240 //setSortValue(index, InChanger.toInt() );
243 void ItemFormatterBase::setTextFld(int index, const QString &fld, bool center)
245 setText(index, fld.trimmed());
247 setTextAlignment(index, Qt::AlignCenter);
251 void ItemFormatterBase::setDateFld(int index, utime_t fld, bool center)
254 bstrutime(buf, sizeof(buf), fld);
255 setText(index, QString(buf).trimmed());
257 setTextAlignment(index, Qt::AlignCenter);
261 void ItemFormatterBase::setRightFld(int index, const QString &fld)
263 setText(index, fld.trimmed());
264 setTextAlignment(index, Qt::AlignRight | Qt::AlignVCenter);
267 void ItemFormatterBase::setBoolFld(int index, const QString &fld, bool center)
269 if (fld.trimmed().toInt())
270 setTextFld(index, QObject::tr("Yes"), center);
272 setTextFld(index, QObject::tr("No"), center);
275 void ItemFormatterBase::setBoolFld(int index, int fld, bool center)
278 setTextFld(index, QObject::tr("Yes"), center);
280 setTextFld(index, QObject::tr("No"), center);
283 void ItemFormatterBase::setNumericFld(int index, const QString &fld)
285 setRightFld(index, fld.trimmed());
286 setSortValue(index, fld.toDouble() );
289 void ItemFormatterBase::setNumericFld(int index, const QString &fld, const QVariant &sortval)
291 setRightFld(index, fld.trimmed());
292 setSortValue(index, sortval );
295 void ItemFormatterBase::setBytesFld(int index, const QString &fld)
297 qint64 qfld = fld.trimmed().toLongLong();
300 case BYTES_CONVERSION_NONE:
301 msg = QString::number(qfld);
303 case BYTES_CONVERSION_IEC:
304 msg = convertBytesIEC(qfld);
306 case BYTES_CONVERSION_SI:
307 msg = convertBytesSI(qfld);
314 setNumericFld(index, msg, QVariant(qfld));
317 void ItemFormatterBase::setDurationFld(int index, const QString &fld)
319 static const qint64 HOUR = Q_INT64_C(3600);
320 static const qint64 DAY = HOUR * 24;
321 static const qint64 WEEK = DAY * 7;
322 static const qint64 MONTH = DAY * 30;
323 static const qint64 YEAR = DAY * 365;
324 static const qint64 divs[] = { YEAR, MONTH, WEEK, DAY, HOUR };
325 static const char sufs[] = { 'y', 'm', 'w', 'd', 'h', '\0' };
327 qint64 dfld = fld.trimmed().toLongLong();
331 for (int pos = 0 ; sufs[pos] ; ++pos) {
332 if (dfld % divs[pos] == 0) {
341 msg = QString("%1%2").arg(dfld).arg(suffix);
343 /* previous check returned a number too big. The original specification perhaps
344 was mixed, like 1d 2h, so we try to match with this routine */
345 dfld = fld.trimmed().toLongLong();
347 for (int pos = 0 ; sufs[pos] ; ++pos) {
348 if (dfld / divs[pos] != 0) {
349 msg += QString(" %1%2").arg(dfld / divs[pos]).arg(sufs[pos]);
354 msg += QString(" %1s").arg(dfld);
357 setNumericFld(index, msg, QVariant(fld.trimmed().toLongLong()));
360 void ItemFormatterBase::setVolStatusFld(int index, const QString &fld, bool center)
362 QString mp(fld.trimmed());
363 setTextFld(index, volume_status_to_str(mp.toUtf8()), center);
365 if (mp == "Append" ) {
366 setBackground(index, Qt::green);
367 } else if (mp == "Error") {
368 setBackground(index, Qt::red);
369 } else if (mp == "Used" || mp == "Full"){
370 setBackground(index, Qt::yellow);
371 } else if (mp == "Read-only" || mp == "Disabled"){
372 setBackground(index, Qt::lightGray);
376 void ItemFormatterBase::setJobStatusFld(int index, const QString &status, bool center)
378 /* C (created, not yet running) uses the default background */
379 static QString greenchars("TR");
380 static QString redchars("BEf");
381 static QString yellowchars("eDAFSMmsjdctp");
383 setTextFld(index, convertJobStatus(status), center);
385 QString st(status.trimmed());
386 if (greenchars.contains(st, Qt::CaseSensitive)) {
387 setBackground(index, Qt::green);
388 } else if (redchars.contains(st, Qt::CaseSensitive)) {
389 setBackground(index, Qt::red);
390 } else if (yellowchars.contains(st, Qt::CaseSensitive)){
391 setBackground(index, Qt::yellow);
395 void ItemFormatterBase::setJobTypeFld(int index, const QString &fld, bool center)
397 QByteArray jtype(fld.trimmed().toAscii());
399 setTextFld(index, job_type_to_str(jtype[0]), center);
401 setTextFld(index, "", center);
405 void ItemFormatterBase::setJobLevelFld(int index, const QString &fld, bool center)
407 QByteArray lvl(fld.trimmed().toAscii());
409 setTextFld(index, job_level_to_str(lvl[0]), center);
411 setTextFld(index, "", center);
417 /***********************************************
419 * treeitem formatting routines
421 ***********************************************/
422 TreeItemFormatter::TreeItemFormatter(QTreeWidgetItem &parent, int indent_level):
424 wdg(new QTreeWidgetItem(&parent)),
429 void TreeItemFormatter::setText(int index, const QString &fld)
431 wdg->setData(index, Qt::UserRole, level);
432 wdg->setText(index, fld);
435 void TreeItemFormatter::setTextAlignment(int index, int align)
437 wdg->setTextAlignment(index, align);
440 void TreeItemFormatter::setBackground(int index, const QBrush &qb)
442 wdg->setBackground(index, qb);
445 /* at this time we don't sort trees, so this method does nothing */
446 void TreeItemFormatter::setSortValue(int /* index */, const QVariant & /* value */)
450 void TreeItemFormatter::setPixmap(int index, const QPixmap &pix)
452 wdg->setIcon(index, QIcon(pix));
455 /***********************************************
457 * Specialized table widget used for sorting
459 ***********************************************/
460 TableItemFormatter::BatSortingTableItem::BatSortingTableItem():
465 void TableItemFormatter::BatSortingTableItem::setSortData(const QVariant &d)
467 setData(SORTDATA_ROLE, d);
470 bool TableItemFormatter::BatSortingTableItem::operator< ( const QTableWidgetItem & o ) const
472 QVariant my = data(SORTDATA_ROLE);
473 QVariant other = o.data(SORTDATA_ROLE);
474 if (!my.isValid() || !other.isValid() || my.type() != other.type())
475 return QTableWidgetItem::operator< (o); /* invalid combination, revert to default sorting */
477 /* 64bit integers must be handled separately, others can be converted to double */
478 if (QVariant::ULongLong == my.type()) {
479 return my.toULongLong() < other.toULongLong();
480 } else if (QVariant::LongLong == my.type()) {
481 return my.toLongLong() < other.toLongLong();
482 } else if (my.canConvert(QVariant::Double)) {
483 return my.toDouble() < other.toDouble();
485 return QTableWidgetItem::operator< (o); /* invalid combination, revert to default sorting */
489 /***********************************************
491 * tableitem formatting routines
493 ***********************************************/
494 TableItemFormatter::TableItemFormatter(QTableWidget &tparent, int trow):
502 void TableItemFormatter::setPixmap(int index, const QPixmap &pix)
504 // Centered, but not sortable !
505 QLabel *lbl = new QLabel();
506 lbl->setAlignment(Qt::AlignCenter);
508 parent->setCellWidget(row, index, lbl);
511 void TableItemFormatter::setPixmap(int index, const QPixmap &pix,
514 // Centered, but not sortable !
515 QLabel *lbl = new QLabel();
516 lbl->setAlignment(Qt::AlignCenter);
518 if (!tips.isEmpty()) {
519 lbl->setToolTip(tips);
521 parent->setCellWidget(row, index, lbl);
523 // last = new BatSortingTableItem;
524 // parent->setItem(row, index, last);
525 // last->setIcon(pix);
528 void TableItemFormatter::setText(int col, const QString &fld)
530 last = new BatSortingTableItem;
531 parent->setItem(row, col, last);
535 void TableItemFormatter::setTextAlignment(int /*index*/, int align)
537 last->setTextAlignment(align);
540 void TableItemFormatter::setBackground(int /*index*/, const QBrush &qb)
542 last->setBackground(qb);
545 void TableItemFormatter::setSortValue(int /* index */, const QVariant &value )
547 last->setSortData(value);
550 QTableWidgetItem *TableItemFormatter::widget(int col)
552 return parent->item(row, col);
555 const QTableWidgetItem *TableItemFormatter::widget(int col) const
557 return parent->item(row, col);