2 Bacula® - The Network Backup Solution
4 Copyright (C) 2007-2007 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 two of the GNU 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 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.
32 * Helper functions for tree widget formatting
34 * Riccardo Ghetta, May 2008
39 #include <QTreeWidgetItem>
40 #include <QTableWidget>
41 #include <QTableWidgetItem>
44 #include <QStringList>
46 #include "fmtwidgetitem.h"
48 /***********************************************
52 ***********************************************/
54 QString convertJobStatus(const QString &sts)
56 QString code( sts.trimmed() );
57 if ( code.size() != 1) {
58 return QObject::tr("Invalid job status %1").arg(sts);
62 jobstatus_to_ascii_gui( code[0].toAscii(), buf, sizeof(buf));
67 * disable widget updating
69 Freeze::Freeze(QWidget &q):
72 qw->setUpdatesEnabled(false);
78 qw->setUpdatesEnabled(true);
83 /***********************************************
85 * ItemFormatterBase static members
87 ***********************************************/
89 ItemFormatterBase::BYTES_CONVERSION ItemFormatterBase::cnvFlag(BYTES_CONVERSION_IEC);
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 QString convertBytesSI(qint64 qfld)
138 static const qint64 KB = Q_INT64_C(1000);
139 static const qint64 MB = (KB * KB);
140 static const qint64 GB = (MB * KB);
141 static const qint64 TB = (GB * KB);
142 static const qint64 PB = (TB * KB);
143 static const qint64 EB = (PB * KB);
145 /* note: division is integer, so to have some decimals we divide for a
146 smaller unit (e.g. GB for a TB number and so on) */
152 else if (qfld >= PB) {
156 else if (qfld >= TB) {
160 else if (qfld >= GB) {
164 else if (qfld >= MB) {
168 else if (qfld >= KB) {
169 suffix = 'k'; /* SI uses lowercase k */
172 /* plain bytes, no need to reformat */
173 return QString("%1 B").arg(qfld);
176 /* having divided for a smaller unit, now we can safely convert to double and
177 use the extra room for decimals */
178 return QString("%1 %2B").arg(qfld / 1000.0, 0, 'f', 2).arg(suffix);
181 /***********************************************
183 * base formatting routines
185 ***********************************************/
187 ItemFormatterBase::ItemFormatterBase()
191 ItemFormatterBase::~ItemFormatterBase()
195 void ItemFormatterBase::setPercent(int index, float value)
198 bsnprintf(buf, sizeof(buf), "%.2f%%", value);
202 pix = ":images/0p.png";
203 } else if (value < 24) {
204 pix = ":images/16p.png";
205 } else if (value < 40) {
206 pix = ":images/32p.png";
207 } else if (value < 56) {
208 pix = ":images/48p.png";
209 } else if (value < 72) {
210 pix = ":images/64p.png";
211 } else if (value < 88) {
212 pix = ":images/80p.png";
214 pix = ":images/96p.png";
216 setPixmap(index, QPixmap(pix), val);
217 setSortValue(index, (int) value);
220 /* By default, the setPixmap implementation with tooltip don't implement
223 void ItemFormatterBase::setPixmap(int index, const QPixmap &pix,
226 setPixmap(index, pix);
229 void ItemFormatterBase::setInChanger(int index, const QString &InChanger)
232 QPixmap(":images/inflag"+InChanger+".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::setRightFld(int index, const QString &fld)
246 setText(index, fld.trimmed());
247 setTextAlignment(index, Qt::AlignRight | Qt::AlignVCenter);
250 void ItemFormatterBase::setBoolFld(int index, const QString &fld, bool center)
252 if (fld.trimmed().toInt())
253 setTextFld(index, QObject::tr("Yes"), center);
255 setTextFld(index, QObject::tr("No"), center);
258 void ItemFormatterBase::setBoolFld(int index, int fld, bool center)
261 setTextFld(index, QObject::tr("Yes"), center);
263 setTextFld(index, QObject::tr("No"), center);
266 void ItemFormatterBase::setNumericFld(int index, const QString &fld)
268 setRightFld(index, fld.trimmed());
269 setSortValue(index, fld.toDouble() );
272 void ItemFormatterBase::setNumericFld(int index, const QString &fld, const QVariant &sortval)
274 setRightFld(index, fld.trimmed());
275 setSortValue(index, sortval );
278 void ItemFormatterBase::setBytesFld(int index, const QString &fld)
280 qint64 qfld = fld.trimmed().toLongLong();
283 case BYTES_CONVERSION_NONE:
284 msg = QString::number(qfld);
286 case BYTES_CONVERSION_IEC:
287 msg = convertBytesIEC(qfld);
289 case BYTES_CONVERSION_SI:
290 msg = convertBytesSI(qfld);
294 setNumericFld(index, msg, qfld);
297 void ItemFormatterBase::setDurationFld(int index, const QString &fld)
299 static const qint64 HOUR = Q_INT64_C(3600);
300 static const qint64 DAY = HOUR * 24;
301 static const qint64 WEEK = DAY * 7;
302 static const qint64 MONTH = DAY * 30;
303 static const qint64 YEAR = DAY * 365;
304 static const qint64 divs[] = { YEAR, MONTH, WEEK, DAY, HOUR };
305 static const char sufs[] = { 'y', 'm', 'w', 'd', 'h', '\0' };
307 qint64 dfld = fld.trimmed().toLongLong();
311 for (int pos = 0 ; sufs[pos] ; ++pos) {
312 if (dfld % divs[pos] == 0) {
321 msg = QString("%1%2").arg(dfld).arg(suffix);
323 /* previous check returned a number too big. The original specification perhaps
324 was mixed, like 1d 2h, so we try to match with this routine */
325 dfld = fld.trimmed().toLongLong();
327 for (int pos = 0 ; sufs[pos] ; ++pos) {
328 if (dfld / divs[pos] != 0) {
329 msg += QString(" %1%2").arg(dfld / divs[pos]).arg(sufs[pos]);
334 msg += QString(" %1s").arg(dfld);
337 setNumericFld(index, msg, fld.trimmed().toLongLong());
340 void ItemFormatterBase::setVolStatusFld(int index, const QString &fld, bool center)
342 QString mp(fld.trimmed());
343 setTextFld(index, volume_status_to_str(mp.toUtf8()), center);
345 if (mp == "Append" ) {
346 setBackground(index, Qt::green);
347 } else if (mp == "Error") {
348 setBackground(index, Qt::red);
349 } else if (mp == "Used" || mp == "Full"){
350 setBackground(index, Qt::yellow);
351 } else if (mp == "Read-only" || mp == "Disabled"){
352 setBackground(index, Qt::lightGray);
356 void ItemFormatterBase::setJobStatusFld(int index, const QString &status, bool center)
358 /* C (created, not yet running) uses the default background */
359 static QString greenchars("TR");
360 static QString redchars("BEf");
361 static QString yellowchars("eDAFSMmsjdctp");
363 setTextFld(index, convertJobStatus(status), center);
365 QString st(status.trimmed());
366 if (greenchars.contains(st, Qt::CaseSensitive)) {
367 setBackground(index, Qt::green);
368 } else if (redchars.contains(st, Qt::CaseSensitive)) {
369 setBackground(index, Qt::red);
370 } else if (yellowchars.contains(st, Qt::CaseSensitive)){
371 setBackground(index, Qt::yellow);
375 void ItemFormatterBase::setJobTypeFld(int index, const QString &fld, bool center)
377 QByteArray jtype(fld.trimmed().toAscii());
379 setTextFld(index, job_type_to_str(jtype[0]), center);
381 setTextFld(index, "", center);
385 void ItemFormatterBase::setJobLevelFld(int index, const QString &fld, bool center)
387 QByteArray lvl(fld.trimmed().toAscii());
389 setTextFld(index, job_level_to_str(lvl[0]), center);
391 setTextFld(index, "", center);
397 /***********************************************
399 * treeitem formatting routines
401 ***********************************************/
402 TreeItemFormatter::TreeItemFormatter(QTreeWidgetItem &parent, int indent_level):
404 wdg(new QTreeWidgetItem(&parent)),
409 void TreeItemFormatter::setText(int index, const QString &fld)
411 wdg->setData(index, Qt::UserRole, level);
412 wdg->setText(index, fld);
415 void TreeItemFormatter::setTextAlignment(int index, int align)
417 wdg->setTextAlignment(index, align);
420 void TreeItemFormatter::setBackground(int index, const QBrush &qb)
422 wdg->setBackground(index, qb);
425 /* at this time we don't sort trees, so this method does nothing */
426 void TreeItemFormatter::setSortValue(int /* index */, const QVariant & /* value */)
430 void TreeItemFormatter::setPixmap(int index, const QPixmap &pix)
432 wdg->setIcon(index, QIcon(pix));
435 /***********************************************
437 * Specialized table widget used for sorting
439 ***********************************************/
440 TableItemFormatter::BatSortingTableItem::BatSortingTableItem():
445 void TableItemFormatter::BatSortingTableItem::setSortData(const QVariant &d)
447 setData(SORTDATA_ROLE, d);
450 bool TableItemFormatter::BatSortingTableItem::operator< ( const QTableWidgetItem & o ) const
452 QVariant my = data(SORTDATA_ROLE);
453 QVariant other = o.data(SORTDATA_ROLE);
454 if (!my.isValid() || !other.isValid() || my.type() != other.type())
455 return QTableWidgetItem::operator< (o); /* invalid combination, revert to default sorting */
457 /* 64bit integers must be handled separately, others can be converted to double */
458 if (QVariant::ULongLong == my.type()) {
459 return my.toULongLong() < other.toULongLong();
460 } else if (QVariant::LongLong == my.type()) {
461 return my.toLongLong() < other.toLongLong();
462 } else if (my.canConvert(QVariant::Double)) {
463 return my.toDouble() < other.toDouble();
465 return QTableWidgetItem::operator< (o); /* invalid combination, revert to default sorting */
469 /***********************************************
471 * tableitem formatting routines
473 ***********************************************/
474 TableItemFormatter::TableItemFormatter(QTableWidget &tparent, int trow):
482 void TableItemFormatter::setPixmap(int index, const QPixmap &pix)
484 // Centered, but not sortable !
485 QLabel *lbl = new QLabel();
486 lbl->setAlignment(Qt::AlignCenter);
488 parent->setCellWidget(row, index, lbl);
491 void TableItemFormatter::setPixmap(int index, const QPixmap &pix,
494 // Centered, but not sortable !
495 QLabel *lbl = new QLabel();
496 lbl->setAlignment(Qt::AlignCenter);
498 if (!tips.isEmpty()) {
499 lbl->setToolTip(tips);
501 parent->setCellWidget(row, index, lbl);
503 // last = new BatSortingTableItem;
504 // parent->setItem(row, index, last);
505 // last->setIcon(pix);
508 void TableItemFormatter::setText(int col, const QString &fld)
510 last = new BatSortingTableItem;
511 parent->setItem(row, col, last);
515 void TableItemFormatter::setTextAlignment(int /*index*/, int align)
517 last->setTextAlignment(align);
520 void TableItemFormatter::setBackground(int /*index*/, const QBrush &qb)
522 last->setBackground(qb);
525 void TableItemFormatter::setSortValue(int /* index */, const QVariant &value )
527 last->setSortData(value);
530 QTableWidgetItem *TableItemFormatter::widget(int col)
532 return parent->item(row, col);
535 const QTableWidgetItem *TableItemFormatter::widget(int col) const
537 return parent->item(row, col);