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 John Walker.
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>
45 #include "fmtwidgetitem.h"
47 /***********************************************
49 * ItemFormatterBase static members
51 ***********************************************/
53 ItemFormatterBase::BYTES_CONVERSION ItemFormatterBase::cnvFlag(BYTES_CONVERSION_IEC);
55 QString ItemFormatterBase::convertBytesIEC(qint64 qfld)
57 static const qint64 KB = Q_INT64_C(1024);
58 static const qint64 MB = (KB * KB);
59 static const qint64 GB = (MB * KB);
60 static const qint64 TB = (GB * KB);
61 static const qint64 PB = (TB * KB);
62 static const qint64 EB = (PB * KB);
64 /* note: division is integer, so to have some decimals we divide for a
65 smaller unit (e.g. GB for a TB number and so on) */
71 else if (qfld >= PB) {
75 else if (qfld >= TB) {
79 else if (qfld >= GB) {
83 else if (qfld >= MB) {
87 else if (qfld >= KB) {
91 /* plain bytes, no need to reformat */
92 return QString("%1 B").arg(qfld);
95 /* having divided for a smaller unit, now we can safely convert to double and
96 use the extra room for decimals */
97 return QString("%1 %2iB").arg(qfld / 1000.0, 0, 'f', 2).arg(suffix);
100 QString ItemFormatterBase::convertBytesSI(qint64 qfld)
102 static const qint64 KB = Q_INT64_C(1000);
103 static const qint64 MB = (KB * KB);
104 static const qint64 GB = (MB * KB);
105 static const qint64 TB = (GB * KB);
106 static const qint64 PB = (TB * KB);
107 static const qint64 EB = (PB * KB);
109 /* note: division is integer, so to have some decimals we divide for a
110 smaller unit (e.g. GB for a TB number and so on) */
116 else if (qfld >= PB) {
120 else if (qfld >= TB) {
124 else if (qfld >= GB) {
128 else if (qfld >= MB) {
132 else if (qfld >= KB) {
133 suffix = 'k'; /* SI uses lowercase k */
136 /* plain bytes, no need to reformat */
137 return QString("%1 B").arg(qfld);
140 /* having divided for a smaller unit, now we can safely convert to double and
141 use the extra room for decimals */
142 return QString("%1 %2B").arg(qfld / 1000.0, 0, 'f', 2).arg(suffix);
145 /***********************************************
147 * base formatting routines
149 ***********************************************/
151 ItemFormatterBase::ItemFormatterBase()
155 ItemFormatterBase::~ItemFormatterBase()
159 void ItemFormatterBase::setTextFld(int index, const QString &fld, bool center)
161 setText(index, fld.trimmed());
163 setTextAlignment(index, Qt::AlignCenter);
167 void ItemFormatterBase::setRightFld(int index, const QString &fld)
169 setText(index, fld.trimmed());
170 setTextAlignment(index, Qt::AlignRight | Qt::AlignVCenter);
173 void ItemFormatterBase::setBoolFld(int index, const QString &fld, bool center)
175 if (fld.trimmed().toInt())
176 setTextFld(index, QObject::tr("Yes"), center);
178 setTextFld(index, QObject::tr("No"), center);
181 void ItemFormatterBase::setBoolFld(int index, int fld, bool center)
184 setTextFld(index, QObject::tr("Yes"), center);
186 setTextFld(index, QObject::tr("No"), center);
189 void ItemFormatterBase::setNumericFld(int index, const QString &fld)
191 setRightFld(index, fld.trimmed());
192 setSortValue(index, fld.toDouble() );
195 void ItemFormatterBase::setNumericFld(int index, const QString &fld, const QVariant &sortval)
197 setRightFld(index, fld.trimmed());
198 setSortValue(index, sortval );
201 void ItemFormatterBase::setBytesFld(int index, const QString &fld)
203 qint64 qfld = fld.trimmed().toLongLong();
206 case BYTES_CONVERSION_NONE:
207 msg = QString::number(qfld);
209 case BYTES_CONVERSION_IEC:
210 msg = convertBytesIEC(qfld);
212 case BYTES_CONVERSION_SI:
213 msg = convertBytesSI(qfld);
217 setNumericFld(index, msg, qfld);
220 void ItemFormatterBase::setDurationFld(int index, const QString &fld)
222 static const qint64 HOUR = Q_INT64_C(3600);
223 static const qint64 DAY = HOUR * 24;
224 static const qint64 WEEK = DAY * 7;
225 static const qint64 MONTH = DAY * 30;
226 static const qint64 YEAR = DAY * 365;
227 static const qint64 divs[] = { YEAR, MONTH, WEEK, DAY, HOUR };
228 static const char sufs[] = { 'y', 'm', 'w', 'd', 'h', '\0' };
230 qint64 dfld = fld.trimmed().toLongLong();
234 for (int pos = 0 ; sufs[pos] ; ++pos) {
235 if (dfld % divs[pos] == 0) {
244 msg = QString("%1%2").arg(dfld).arg(suffix);
246 /* previous check returned a number too big. The original specification perhaps
247 was mixed, like 1d 2h, so we try to match with this routine */
248 dfld = fld.trimmed().toLongLong();
250 for (int pos = 0 ; sufs[pos] ; ++pos) {
251 if (dfld / divs[pos] != 0) {
252 msg += QString(" %1%2").arg(dfld / divs[pos]).arg(sufs[pos]);
257 msg += QString(" %1s").arg(dfld);
260 setNumericFld(index, msg, fld.trimmed().toLongLong());
263 void ItemFormatterBase::setVolStatusFld(int index, const QString &fld, bool center)
265 setTextFld(index, fld, center);
267 if (fld == "Append" ) {
268 setBackground(index, Qt::green);
269 } else if (fld == "Error") {
270 setBackground(index, Qt::red);
271 } else if (fld == "Used" || fld == "Full"){
272 setBackground(index, Qt::yellow);
276 void ItemFormatterBase::setJobStatusFld(int index, const QString &shortstatus,
277 const QString &longstatus, bool center)
279 /* C (created, not yet running) uses the default background */
280 static QString greenchars("TR");
281 static QString redchars("BEf");
282 static QString yellowchars("eDAFSMmsjdctp");
284 setTextFld(index, longstatus, center);
286 QString st(shortstatus.trimmed());
287 if (greenchars.contains(st, Qt::CaseSensitive)) {
288 setBackground(index, Qt::green);
289 } else if (redchars.contains(st, Qt::CaseSensitive)) {
290 setBackground(index, Qt::red);
291 } else if (yellowchars.contains(st, Qt::CaseSensitive)){
292 setBackground(index, Qt::yellow);
296 void ItemFormatterBase::setJobTypeFld(int index, const QString &fld, bool center)
298 static QHash<QString, QString> jobt;
299 if (jobt.isEmpty()) {
300 jobt.insert("B", QObject::tr("Backup"));
301 jobt.insert("R", QObject::tr("Restore"));
302 jobt.insert("V", QObject::tr("Verify"));
303 jobt.insert("A", QObject::tr("Admin"));
306 setTextFld(index, jobt.value(fld.trimmed(), fld.trimmed()), center);
309 void ItemFormatterBase::setJobLevelFld(int index, const QString &fld, bool center)
311 static QHash<QString, QString> jobt;
312 if (jobt.isEmpty()) {
313 jobt.insert("F", QObject::tr("Full"));
314 jobt.insert("D", QObject::tr("Differential"));
315 jobt.insert("I", QObject::tr("Incremental"));
316 jobt.insert("C", QObject::tr("Catalog"));
317 jobt.insert("O", QObject::tr("VolToCatalog"));
320 setTextFld(index, jobt.value(fld.trimmed(), fld.trimmed()), center);
325 /***********************************************
327 * treeitem formatting routines
329 ***********************************************/
330 TreeItemFormatter::TreeItemFormatter(QTreeWidgetItem &parent, int indent_level):
332 wdg(new QTreeWidgetItem(&parent)),
337 void TreeItemFormatter::setText(int index, const QString &fld)
339 wdg->setData(index, Qt::UserRole, level);
340 wdg->setText(index, fld);
343 void TreeItemFormatter::setTextAlignment(int index, int align)
345 wdg->setTextAlignment(index, align);
348 void TreeItemFormatter::setBackground(int index, const QBrush &qb)
350 wdg->setBackground(index, qb);
353 /* at this time we don't sort trees, so this method does nothing */
354 void TreeItemFormatter::setSortValue(int /* index */, const QVariant & /* value */)
358 /***********************************************
360 * Specialized table widget used for sorting
362 ***********************************************/
363 TableItemFormatter::BatSortingTableItem::BatSortingTableItem():
368 void TableItemFormatter::BatSortingTableItem::setSortData(const QVariant &d)
370 setData(SORTDATA_ROLE, d);
373 bool TableItemFormatter::BatSortingTableItem::operator< ( const QTableWidgetItem & o ) const
375 QVariant my = data(SORTDATA_ROLE);
376 QVariant other = o.data(SORTDATA_ROLE);
377 if (!my.isValid() || !other.isValid() || my.type() != other.type())
378 return QTableWidgetItem::operator< (o); /* invalid combination, revert to default sorting */
380 /* 64bit integers must be handled separately, others can be converted to double */
381 if (QVariant::ULongLong == my.type()) {
382 return my.toULongLong() < other.toULongLong();
383 } else if (QVariant::LongLong == my.type()) {
384 return my.toLongLong() < other.toLongLong();
385 } else if (my.canConvert(QVariant::Double)) {
386 return my.toDouble() < other.toDouble();
388 return QTableWidgetItem::operator< (o); /* invalid combination, revert to default sorting */
392 /***********************************************
394 * tableitem formatting routines
396 ***********************************************/
397 TableItemFormatter::TableItemFormatter(QTableWidget &tparent, int trow):
405 void TableItemFormatter::setText(int col, const QString &fld)
407 last = new BatSortingTableItem;
408 parent->setItem(row, col, last);
412 void TableItemFormatter::setTextAlignment(int /*index*/, int align)
414 last->setTextAlignment(align);
417 void TableItemFormatter::setBackground(int /*index*/, const QBrush &qb)
419 last->setBackground(qb);
422 void TableItemFormatter::setSortValue(int /* index */, const QVariant &value )
424 last->setSortData(value);
427 QTableWidgetItem *TableItemFormatter::widget(int col)
429 return parent->item(row, col);
432 const QTableWidgetItem *TableItemFormatter::widget(int col) const
434 return parent->item(row, col);