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
38 #include <QTreeWidgetItem>
39 #include <QTableWidget>
40 #include <QTableWidgetItem>
43 #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 QApplication::setOverrideCursor(Qt::WaitCursor);
73 qw->setUpdatesEnabled(false);
79 qw->setUpdatesEnabled(true);
80 QApplication::restoreOverrideCursor();
84 /***********************************************
86 * ItemFormatterBase static members
88 ***********************************************/
90 ItemFormatterBase::BYTES_CONVERSION ItemFormatterBase::cnvFlag(BYTES_CONVERSION_IEC);
92 QString ItemFormatterBase::convertBytesIEC(qint64 qfld)
94 static const qint64 KB = Q_INT64_C(1024);
95 static const qint64 MB = (KB * KB);
96 static const qint64 GB = (MB * KB);
97 static const qint64 TB = (GB * KB);
98 static const qint64 PB = (TB * KB);
99 static const qint64 EB = (PB * KB);
101 /* note: division is integer, so to have some decimals we divide for a
102 smaller unit (e.g. GB for a TB number and so on) */
108 else if (qfld >= PB) {
112 else if (qfld >= TB) {
116 else if (qfld >= GB) {
120 else if (qfld >= MB) {
124 else if (qfld >= KB) {
128 /* plain bytes, no need to reformat */
129 return QString("%1 B").arg(qfld);
132 /* having divided for a smaller unit, now we can safely convert to double and
133 use the extra room for decimals */
134 return QString("%1 %2iB").arg(qfld / 1000.0, 0, 'f', 2).arg(suffix);
137 QString ItemFormatterBase::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::setTextFld(int index, const QString &fld, bool center)
198 setText(index, fld.trimmed());
200 setTextAlignment(index, Qt::AlignCenter);
204 void ItemFormatterBase::setRightFld(int index, const QString &fld)
206 setText(index, fld.trimmed());
207 setTextAlignment(index, Qt::AlignRight | Qt::AlignVCenter);
210 void ItemFormatterBase::setBoolFld(int index, const QString &fld, bool center)
212 if (fld.trimmed().toInt())
213 setTextFld(index, QObject::tr("Yes"), center);
215 setTextFld(index, QObject::tr("No"), center);
218 void ItemFormatterBase::setBoolFld(int index, int fld, bool center)
221 setTextFld(index, QObject::tr("Yes"), center);
223 setTextFld(index, QObject::tr("No"), center);
226 void ItemFormatterBase::setNumericFld(int index, const QString &fld)
228 setRightFld(index, fld.trimmed());
229 setSortValue(index, fld.toDouble() );
232 void ItemFormatterBase::setNumericFld(int index, const QString &fld, const QVariant &sortval)
234 setRightFld(index, fld.trimmed());
235 setSortValue(index, sortval );
238 void ItemFormatterBase::setBytesFld(int index, const QString &fld)
240 qint64 qfld = fld.trimmed().toLongLong();
243 case BYTES_CONVERSION_NONE:
244 msg = QString::number(qfld);
246 case BYTES_CONVERSION_IEC:
247 msg = convertBytesIEC(qfld);
249 case BYTES_CONVERSION_SI:
250 msg = convertBytesSI(qfld);
254 setNumericFld(index, msg, qfld);
257 void ItemFormatterBase::setDurationFld(int index, const QString &fld)
259 static const qint64 HOUR = Q_INT64_C(3600);
260 static const qint64 DAY = HOUR * 24;
261 static const qint64 WEEK = DAY * 7;
262 static const qint64 MONTH = DAY * 30;
263 static const qint64 YEAR = DAY * 365;
264 static const qint64 divs[] = { YEAR, MONTH, WEEK, DAY, HOUR };
265 static const char sufs[] = { 'y', 'm', 'w', 'd', 'h', '\0' };
267 qint64 dfld = fld.trimmed().toLongLong();
271 for (int pos = 0 ; sufs[pos] ; ++pos) {
272 if (dfld % divs[pos] == 0) {
281 msg = QString("%1%2").arg(dfld).arg(suffix);
283 /* previous check returned a number too big. The original specification perhaps
284 was mixed, like 1d 2h, so we try to match with this routine */
285 dfld = fld.trimmed().toLongLong();
287 for (int pos = 0 ; sufs[pos] ; ++pos) {
288 if (dfld / divs[pos] != 0) {
289 msg += QString(" %1%2").arg(dfld / divs[pos]).arg(sufs[pos]);
294 msg += QString(" %1s").arg(dfld);
297 setNumericFld(index, msg, fld.trimmed().toLongLong());
300 void ItemFormatterBase::setVolStatusFld(int index, const QString &fld, bool center)
302 QString mp(fld.trimmed());
303 setTextFld(index, volume_status_to_str(mp.toUtf8()), center);
305 if (mp == "Append" ) {
306 setBackground(index, Qt::green);
307 } else if (mp == "Error") {
308 setBackground(index, Qt::red);
309 } else if (mp == "Used" || mp == "Full"){
310 setBackground(index, Qt::yellow);
311 } else if (mp == "Read-only" || mp == "Disabled"){
312 setBackground(index, Qt::lightGray);
316 void ItemFormatterBase::setJobStatusFld(int index, const QString &status, bool center)
318 /* C (created, not yet running) uses the default background */
319 static QString greenchars("TR");
320 static QString redchars("BEf");
321 static QString yellowchars("eDAFSMmsjdctp");
323 setTextFld(index, convertJobStatus(status), center);
325 QString st(status.trimmed());
326 if (greenchars.contains(st, Qt::CaseSensitive)) {
327 setBackground(index, Qt::green);
328 } else if (redchars.contains(st, Qt::CaseSensitive)) {
329 setBackground(index, Qt::red);
330 } else if (yellowchars.contains(st, Qt::CaseSensitive)){
331 setBackground(index, Qt::yellow);
335 void ItemFormatterBase::setJobTypeFld(int index, const QString &fld, bool center)
337 QByteArray jtype(fld.trimmed().toAscii());
339 setTextFld(index, job_type_to_str(jtype[0]), center);
341 setTextFld(index, "", center);
345 void ItemFormatterBase::setJobLevelFld(int index, const QString &fld, bool center)
347 QByteArray lvl(fld.trimmed().toAscii());
349 setTextFld(index, job_level_to_str(lvl[0]), center);
351 setTextFld(index, "", center);
357 /***********************************************
359 * treeitem formatting routines
361 ***********************************************/
362 TreeItemFormatter::TreeItemFormatter(QTreeWidgetItem &parent, int indent_level):
364 wdg(new QTreeWidgetItem(&parent)),
369 void TreeItemFormatter::setText(int index, const QString &fld)
371 wdg->setData(index, Qt::UserRole, level);
372 wdg->setText(index, fld);
375 void TreeItemFormatter::setTextAlignment(int index, int align)
377 wdg->setTextAlignment(index, align);
380 void TreeItemFormatter::setBackground(int index, const QBrush &qb)
382 wdg->setBackground(index, qb);
385 /* at this time we don't sort trees, so this method does nothing */
386 void TreeItemFormatter::setSortValue(int /* index */, const QVariant & /* value */)
390 /***********************************************
392 * Specialized table widget used for sorting
394 ***********************************************/
395 TableItemFormatter::BatSortingTableItem::BatSortingTableItem():
400 void TableItemFormatter::BatSortingTableItem::setSortData(const QVariant &d)
402 setData(SORTDATA_ROLE, d);
405 bool TableItemFormatter::BatSortingTableItem::operator< ( const QTableWidgetItem & o ) const
407 QVariant my = data(SORTDATA_ROLE);
408 QVariant other = o.data(SORTDATA_ROLE);
409 if (!my.isValid() || !other.isValid() || my.type() != other.type())
410 return QTableWidgetItem::operator< (o); /* invalid combination, revert to default sorting */
412 /* 64bit integers must be handled separately, others can be converted to double */
413 if (QVariant::ULongLong == my.type()) {
414 return my.toULongLong() < other.toULongLong();
415 } else if (QVariant::LongLong == my.type()) {
416 return my.toLongLong() < other.toLongLong();
417 } else if (my.canConvert(QVariant::Double)) {
418 return my.toDouble() < other.toDouble();
420 return QTableWidgetItem::operator< (o); /* invalid combination, revert to default sorting */
424 /***********************************************
426 * tableitem formatting routines
428 ***********************************************/
429 TableItemFormatter::TableItemFormatter(QTableWidget &tparent, int trow):
437 void TableItemFormatter::setText(int col, const QString &fld)
439 last = new BatSortingTableItem;
440 parent->setItem(row, col, last);
444 void TableItemFormatter::setTextAlignment(int /*index*/, int align)
446 last->setTextAlignment(align);
449 void TableItemFormatter::setBackground(int /*index*/, const QBrush &qb)
451 last->setBackground(qb);
454 void TableItemFormatter::setSortValue(int /* index */, const QVariant &value )
456 last->setSortData(value);
459 QTableWidgetItem *TableItemFormatter::widget(int col)
461 return parent->item(row, col);
464 const QTableWidgetItem *TableItemFormatter::widget(int col) const
466 return parent->item(row, col);