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);
312 setNumericFld(index, msg, qfld);
315 void ItemFormatterBase::setDurationFld(int index, const QString &fld)
317 static const qint64 HOUR = Q_INT64_C(3600);
318 static const qint64 DAY = HOUR * 24;
319 static const qint64 WEEK = DAY * 7;
320 static const qint64 MONTH = DAY * 30;
321 static const qint64 YEAR = DAY * 365;
322 static const qint64 divs[] = { YEAR, MONTH, WEEK, DAY, HOUR };
323 static const char sufs[] = { 'y', 'm', 'w', 'd', 'h', '\0' };
325 qint64 dfld = fld.trimmed().toLongLong();
329 for (int pos = 0 ; sufs[pos] ; ++pos) {
330 if (dfld % divs[pos] == 0) {
339 msg = QString("%1%2").arg(dfld).arg(suffix);
341 /* previous check returned a number too big. The original specification perhaps
342 was mixed, like 1d 2h, so we try to match with this routine */
343 dfld = fld.trimmed().toLongLong();
345 for (int pos = 0 ; sufs[pos] ; ++pos) {
346 if (dfld / divs[pos] != 0) {
347 msg += QString(" %1%2").arg(dfld / divs[pos]).arg(sufs[pos]);
352 msg += QString(" %1s").arg(dfld);
355 setNumericFld(index, msg, fld.trimmed().toLongLong());
358 void ItemFormatterBase::setVolStatusFld(int index, const QString &fld, bool center)
360 QString mp(fld.trimmed());
361 setTextFld(index, volume_status_to_str(mp.toUtf8()), center);
363 if (mp == "Append" ) {
364 setBackground(index, Qt::green);
365 } else if (mp == "Error") {
366 setBackground(index, Qt::red);
367 } else if (mp == "Used" || mp == "Full"){
368 setBackground(index, Qt::yellow);
369 } else if (mp == "Read-only" || mp == "Disabled"){
370 setBackground(index, Qt::lightGray);
374 void ItemFormatterBase::setJobStatusFld(int index, const QString &status, bool center)
376 /* C (created, not yet running) uses the default background */
377 static QString greenchars("TR");
378 static QString redchars("BEf");
379 static QString yellowchars("eDAFSMmsjdctp");
381 setTextFld(index, convertJobStatus(status), center);
383 QString st(status.trimmed());
384 if (greenchars.contains(st, Qt::CaseSensitive)) {
385 setBackground(index, Qt::green);
386 } else if (redchars.contains(st, Qt::CaseSensitive)) {
387 setBackground(index, Qt::red);
388 } else if (yellowchars.contains(st, Qt::CaseSensitive)){
389 setBackground(index, Qt::yellow);
393 void ItemFormatterBase::setJobTypeFld(int index, const QString &fld, bool center)
395 QByteArray jtype(fld.trimmed().toAscii());
397 setTextFld(index, job_type_to_str(jtype[0]), center);
399 setTextFld(index, "", center);
403 void ItemFormatterBase::setJobLevelFld(int index, const QString &fld, bool center)
405 QByteArray lvl(fld.trimmed().toAscii());
407 setTextFld(index, job_level_to_str(lvl[0]), center);
409 setTextFld(index, "", center);
415 /***********************************************
417 * treeitem formatting routines
419 ***********************************************/
420 TreeItemFormatter::TreeItemFormatter(QTreeWidgetItem &parent, int indent_level):
422 wdg(new QTreeWidgetItem(&parent)),
427 void TreeItemFormatter::setText(int index, const QString &fld)
429 wdg->setData(index, Qt::UserRole, level);
430 wdg->setText(index, fld);
433 void TreeItemFormatter::setTextAlignment(int index, int align)
435 wdg->setTextAlignment(index, align);
438 void TreeItemFormatter::setBackground(int index, const QBrush &qb)
440 wdg->setBackground(index, qb);
443 /* at this time we don't sort trees, so this method does nothing */
444 void TreeItemFormatter::setSortValue(int /* index */, const QVariant & /* value */)
448 void TreeItemFormatter::setPixmap(int index, const QPixmap &pix)
450 wdg->setIcon(index, QIcon(pix));
453 /***********************************************
455 * Specialized table widget used for sorting
457 ***********************************************/
458 TableItemFormatter::BatSortingTableItem::BatSortingTableItem():
463 void TableItemFormatter::BatSortingTableItem::setSortData(const QVariant &d)
465 setData(SORTDATA_ROLE, d);
468 bool TableItemFormatter::BatSortingTableItem::operator< ( const QTableWidgetItem & o ) const
470 QVariant my = data(SORTDATA_ROLE);
471 QVariant other = o.data(SORTDATA_ROLE);
472 if (!my.isValid() || !other.isValid() || my.type() != other.type())
473 return QTableWidgetItem::operator< (o); /* invalid combination, revert to default sorting */
475 /* 64bit integers must be handled separately, others can be converted to double */
476 if (QVariant::ULongLong == my.type()) {
477 return my.toULongLong() < other.toULongLong();
478 } else if (QVariant::LongLong == my.type()) {
479 return my.toLongLong() < other.toLongLong();
480 } else if (my.canConvert(QVariant::Double)) {
481 return my.toDouble() < other.toDouble();
483 return QTableWidgetItem::operator< (o); /* invalid combination, revert to default sorting */
487 /***********************************************
489 * tableitem formatting routines
491 ***********************************************/
492 TableItemFormatter::TableItemFormatter(QTableWidget &tparent, int trow):
500 void TableItemFormatter::setPixmap(int index, const QPixmap &pix)
502 // Centered, but not sortable !
503 QLabel *lbl = new QLabel();
504 lbl->setAlignment(Qt::AlignCenter);
506 parent->setCellWidget(row, index, lbl);
509 void TableItemFormatter::setPixmap(int index, const QPixmap &pix,
512 // Centered, but not sortable !
513 QLabel *lbl = new QLabel();
514 lbl->setAlignment(Qt::AlignCenter);
516 if (!tips.isEmpty()) {
517 lbl->setToolTip(tips);
519 parent->setCellWidget(row, index, lbl);
521 // last = new BatSortingTableItem;
522 // parent->setItem(row, index, last);
523 // last->setIcon(pix);
526 void TableItemFormatter::setText(int col, const QString &fld)
528 last = new BatSortingTableItem;
529 parent->setItem(row, col, last);
533 void TableItemFormatter::setTextAlignment(int /*index*/, int align)
535 last->setTextAlignment(align);
538 void TableItemFormatter::setBackground(int /*index*/, const QBrush &qb)
540 last->setBackground(qb);
543 void TableItemFormatter::setSortValue(int /* index */, const QVariant &value )
545 last->setSortData(value);
548 QTableWidgetItem *TableItemFormatter::widget(int col)
550 return parent->item(row, col);
553 const QTableWidgetItem *TableItemFormatter::widget(int col) const
555 return parent->item(row, col);