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>
46 #include "fmtwidgetitem.h"
48 /***********************************************
50 * ItemFormatterBase static members
52 ***********************************************/
54 ItemFormatterBase::BYTES_CONVERSION ItemFormatterBase::cnvFlag(BYTES_CONVERSION_IEC);
56 QString ItemFormatterBase::convertBytesIEC(qint64 qfld)
58 static const qint64 KB = Q_INT64_C(1024);
59 static const qint64 MB = (KB * KB);
60 static const qint64 GB = (MB * KB);
61 static const qint64 TB = (GB * KB);
62 static const qint64 PB = (TB * KB);
63 static const qint64 EB = (PB * KB);
65 /* note: division is integer, so to have some decimals we divide for a
66 smaller unit (e.g. GB for a TB number and so on) */
72 else if (qfld >= PB) {
76 else if (qfld >= TB) {
80 else if (qfld >= GB) {
84 else if (qfld >= MB) {
88 else if (qfld >= KB) {
92 /* plain bytes, no need to reformat */
93 return QString("%1 B").arg(qfld);
96 /* having divided for a smaller unit, now we can safely convert to double and
97 use the extra room for decimals */
98 return QString("%1 %2iB").arg(qfld / 1000.0, 0, 'f', 2).arg(suffix);
101 QString ItemFormatterBase::convertBytesSI(qint64 qfld)
103 static const qint64 KB = Q_INT64_C(1000);
104 static const qint64 MB = (KB * KB);
105 static const qint64 GB = (MB * KB);
106 static const qint64 TB = (GB * KB);
107 static const qint64 PB = (TB * KB);
108 static const qint64 EB = (PB * KB);
110 /* note: division is integer, so to have some decimals we divide for a
111 smaller unit (e.g. GB for a TB number and so on) */
117 else if (qfld >= PB) {
121 else if (qfld >= TB) {
125 else if (qfld >= GB) {
129 else if (qfld >= MB) {
133 else if (qfld >= KB) {
134 suffix = 'k'; /* SI uses lowercase k */
137 /* plain bytes, no need to reformat */
138 return QString("%1 B").arg(qfld);
141 /* having divided for a smaller unit, now we can safely convert to double and
142 use the extra room for decimals */
143 return QString("%1 %2B").arg(qfld / 1000.0, 0, 'f', 2).arg(suffix);
146 /***********************************************
148 * base formatting routines
150 ***********************************************/
152 ItemFormatterBase::ItemFormatterBase()
156 ItemFormatterBase::~ItemFormatterBase()
160 void ItemFormatterBase::setTextFld(int index, const QString &fld, bool center)
162 setText(index, fld.trimmed());
164 setTextAlignment(index, Qt::AlignCenter);
168 void ItemFormatterBase::setRightFld(int index, const QString &fld)
170 setText(index, fld.trimmed());
171 setTextAlignment(index, Qt::AlignRight | Qt::AlignVCenter);
174 void ItemFormatterBase::setBoolFld(int index, const QString &fld, bool center)
176 if (fld.trimmed().toInt())
177 setTextFld(index, QObject::tr("Yes"), center);
179 setTextFld(index, QObject::tr("No"), center);
182 void ItemFormatterBase::setBoolFld(int index, int fld, bool center)
185 setTextFld(index, QObject::tr("Yes"), center);
187 setTextFld(index, QObject::tr("No"), center);
190 void ItemFormatterBase::setNumericFld(int index, const QString &fld)
192 setRightFld(index, fld.trimmed());
193 setSortValue(index, fld.toDouble() );
196 void ItemFormatterBase::setNumericFld(int index, const QString &fld, const QVariant &sortval)
198 setRightFld(index, fld.trimmed());
199 setSortValue(index, sortval );
202 void ItemFormatterBase::setBytesFld(int index, const QString &fld)
204 qint64 qfld = fld.trimmed().toLongLong();
207 case BYTES_CONVERSION_NONE:
208 msg = QString::number(qfld);
210 case BYTES_CONVERSION_IEC:
211 msg = convertBytesIEC(qfld);
213 case BYTES_CONVERSION_SI:
214 msg = convertBytesSI(qfld);
218 setNumericFld(index, msg, qfld);
221 void ItemFormatterBase::setDurationFld(int index, const QString &fld)
223 static const qint64 HOUR = Q_INT64_C(3600);
224 static const qint64 DAY = HOUR * 24;
225 static const qint64 WEEK = DAY * 7;
226 static const qint64 MONTH = DAY * 30;
227 static const qint64 YEAR = DAY * 365;
228 static const qint64 divs[] = { YEAR, MONTH, WEEK, DAY, HOUR };
229 static const char sufs[] = { 'y', 'm', 'w', 'd', 'h', '\0' };
231 qint64 dfld = fld.trimmed().toLongLong();
235 for (int pos = 0 ; sufs[pos] ; ++pos) {
236 if (dfld % divs[pos] == 0) {
245 msg = QString("%1%2").arg(dfld).arg(suffix);
247 /* previous check returned a number too big. The original specification perhaps
248 was mixed, like 1d 2h, so we try to match with this routine */
249 dfld = fld.trimmed().toLongLong();
251 for (int pos = 0 ; sufs[pos] ; ++pos) {
252 if (dfld / divs[pos] != 0) {
253 msg += QString(" %1%2").arg(dfld / divs[pos]).arg(sufs[pos]);
258 msg += QString(" %1s").arg(dfld);
261 setNumericFld(index, msg, fld.trimmed().toLongLong());
264 void ItemFormatterBase::setVolStatusFld(int index, const QString &fld, bool center)
266 setTextFld(index, fld, center);
268 if (fld == "Append" ) {
269 setBackground(index, Qt::green);
270 } else if (fld == "Error") {
271 setBackground(index, Qt::red);
272 } else if (fld == "Used" || fld == "Full"){
273 setBackground(index, Qt::yellow);
277 void ItemFormatterBase::setJobStatusFld(int index, const QString &shortstatus,
278 const QString &longstatus, bool center)
280 /* C (created, not yet running) uses the default background */
281 static QString greenchars("TR");
282 static QString redchars("BEf");
283 static QString yellowchars("eDAFSMmsjdctp");
285 setTextFld(index, longstatus, center);
287 QString st(shortstatus.trimmed());
288 if (greenchars.contains(st, Qt::CaseSensitive)) {
289 setBackground(index, Qt::green);
290 } else if (redchars.contains(st, Qt::CaseSensitive)) {
291 setBackground(index, Qt::red);
292 } else if (yellowchars.contains(st, Qt::CaseSensitive)){
293 setBackground(index, Qt::yellow);
297 void ItemFormatterBase::setJobTypeFld(int index, const QString &fld, bool center)
299 QByteArray jtype(fld.trimmed().toAscii());
301 setTextFld(index, job_type_to_str(jtype[0]), center);
303 setTextFld(index, "", center);
307 void ItemFormatterBase::setJobLevelFld(int index, const QString &fld, bool center)
309 QByteArray lvl(fld.trimmed().toAscii());
311 setTextFld(index, job_level_to_str(lvl[0]), center);
313 setTextFld(index, "", center);
319 /***********************************************
321 * treeitem formatting routines
323 ***********************************************/
324 TreeItemFormatter::TreeItemFormatter(QTreeWidgetItem &parent, int indent_level):
326 wdg(new QTreeWidgetItem(&parent)),
331 void TreeItemFormatter::setText(int index, const QString &fld)
333 wdg->setData(index, Qt::UserRole, level);
334 wdg->setText(index, fld);
337 void TreeItemFormatter::setTextAlignment(int index, int align)
339 wdg->setTextAlignment(index, align);
342 void TreeItemFormatter::setBackground(int index, const QBrush &qb)
344 wdg->setBackground(index, qb);
347 /* at this time we don't sort trees, so this method does nothing */
348 void TreeItemFormatter::setSortValue(int /* index */, const QVariant & /* value */)
352 /***********************************************
354 * Specialized table widget used for sorting
356 ***********************************************/
357 TableItemFormatter::BatSortingTableItem::BatSortingTableItem():
362 void TableItemFormatter::BatSortingTableItem::setSortData(const QVariant &d)
364 setData(SORTDATA_ROLE, d);
367 bool TableItemFormatter::BatSortingTableItem::operator< ( const QTableWidgetItem & o ) const
369 QVariant my = data(SORTDATA_ROLE);
370 QVariant other = o.data(SORTDATA_ROLE);
371 if (!my.isValid() || !other.isValid() || my.type() != other.type())
372 return QTableWidgetItem::operator< (o); /* invalid combination, revert to default sorting */
374 /* 64bit integers must be handled separately, others can be converted to double */
375 if (QVariant::ULongLong == my.type()) {
376 return my.toULongLong() < other.toULongLong();
377 } else if (QVariant::LongLong == my.type()) {
378 return my.toLongLong() < other.toLongLong();
379 } else if (my.canConvert(QVariant::Double)) {
380 return my.toDouble() < other.toDouble();
382 return QTableWidgetItem::operator< (o); /* invalid combination, revert to default sorting */
386 /***********************************************
388 * tableitem formatting routines
390 ***********************************************/
391 TableItemFormatter::TableItemFormatter(QTableWidget &tparent, int trow):
399 void TableItemFormatter::setText(int col, const QString &fld)
401 last = new BatSortingTableItem;
402 parent->setItem(row, col, last);
406 void TableItemFormatter::setTextAlignment(int /*index*/, int align)
408 last->setTextAlignment(align);
411 void TableItemFormatter::setBackground(int /*index*/, const QBrush &qb)
413 last->setBackground(qb);
416 void TableItemFormatter::setSortValue(int /* index */, const QVariant &value )
418 last->setSortData(value);
421 QTableWidgetItem *TableItemFormatter::widget(int col)
423 return parent->item(row, col);
426 const QTableWidgetItem *TableItemFormatter::widget(int col) const
428 return parent->item(row, col);