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 QApplication::setOverrideCursor(Qt::WaitCursor);
73 qw->setUpdatesEnabled(false);
79 qw->setUpdatesEnabled(true);
80 QApplication::restoreOverrideCursor();
85 /***********************************************
87 * ItemFormatterBase static members
89 ***********************************************/
91 ItemFormatterBase::BYTES_CONVERSION ItemFormatterBase::cnvFlag(BYTES_CONVERSION_IEC);
93 QString ItemFormatterBase::convertBytesIEC(qint64 qfld)
95 static const qint64 KB = Q_INT64_C(1024);
96 static const qint64 MB = (KB * KB);
97 static const qint64 GB = (MB * KB);
98 static const qint64 TB = (GB * KB);
99 static const qint64 PB = (TB * KB);
100 static const qint64 EB = (PB * KB);
102 /* note: division is integer, so to have some decimals we divide for a
103 smaller unit (e.g. GB for a TB number and so on) */
109 else if (qfld >= PB) {
113 else if (qfld >= TB) {
117 else if (qfld >= GB) {
121 else if (qfld >= MB) {
125 else if (qfld >= KB) {
129 /* plain bytes, no need to reformat */
130 return QString("%1 B").arg(qfld);
133 /* having divided for a smaller unit, now we can safely convert to double and
134 use the extra room for decimals */
135 return QString("%1 %2iB").arg(qfld / 1000.0, 0, 'f', 2).arg(suffix);
138 QString ItemFormatterBase::convertBytesSI(qint64 qfld)
140 static const qint64 KB = Q_INT64_C(1000);
141 static const qint64 MB = (KB * KB);
142 static const qint64 GB = (MB * KB);
143 static const qint64 TB = (GB * KB);
144 static const qint64 PB = (TB * KB);
145 static const qint64 EB = (PB * KB);
147 /* note: division is integer, so to have some decimals we divide for a
148 smaller unit (e.g. GB for a TB number and so on) */
154 else if (qfld >= PB) {
158 else if (qfld >= TB) {
162 else if (qfld >= GB) {
166 else if (qfld >= MB) {
170 else if (qfld >= KB) {
171 suffix = 'k'; /* SI uses lowercase k */
174 /* plain bytes, no need to reformat */
175 return QString("%1 B").arg(qfld);
178 /* having divided for a smaller unit, now we can safely convert to double and
179 use the extra room for decimals */
180 return QString("%1 %2B").arg(qfld / 1000.0, 0, 'f', 2).arg(suffix);
183 /***********************************************
185 * base formatting routines
187 ***********************************************/
189 ItemFormatterBase::ItemFormatterBase()
193 ItemFormatterBase::~ItemFormatterBase()
197 void ItemFormatterBase::setTextFld(int index, const QString &fld, bool center)
199 setText(index, fld.trimmed());
201 setTextAlignment(index, Qt::AlignCenter);
205 void ItemFormatterBase::setRightFld(int index, const QString &fld)
207 setText(index, fld.trimmed());
208 setTextAlignment(index, Qt::AlignRight | Qt::AlignVCenter);
211 void ItemFormatterBase::setBoolFld(int index, const QString &fld, bool center)
213 if (fld.trimmed().toInt())
214 setTextFld(index, QObject::tr("Yes"), center);
216 setTextFld(index, QObject::tr("No"), center);
219 void ItemFormatterBase::setBoolFld(int index, int fld, bool center)
222 setTextFld(index, QObject::tr("Yes"), center);
224 setTextFld(index, QObject::tr("No"), center);
227 void ItemFormatterBase::setNumericFld(int index, const QString &fld)
229 setRightFld(index, fld.trimmed());
230 setSortValue(index, fld.toDouble() );
233 void ItemFormatterBase::setNumericFld(int index, const QString &fld, const QVariant &sortval)
235 setRightFld(index, fld.trimmed());
236 setSortValue(index, sortval );
239 void ItemFormatterBase::setBytesFld(int index, const QString &fld)
241 qint64 qfld = fld.trimmed().toLongLong();
244 case BYTES_CONVERSION_NONE:
245 msg = QString::number(qfld);
247 case BYTES_CONVERSION_IEC:
248 msg = convertBytesIEC(qfld);
250 case BYTES_CONVERSION_SI:
251 msg = convertBytesSI(qfld);
255 setNumericFld(index, msg, qfld);
258 void ItemFormatterBase::setDurationFld(int index, const QString &fld)
260 static const qint64 HOUR = Q_INT64_C(3600);
261 static const qint64 DAY = HOUR * 24;
262 static const qint64 WEEK = DAY * 7;
263 static const qint64 MONTH = DAY * 30;
264 static const qint64 YEAR = DAY * 365;
265 static const qint64 divs[] = { YEAR, MONTH, WEEK, DAY, HOUR };
266 static const char sufs[] = { 'y', 'm', 'w', 'd', 'h', '\0' };
268 qint64 dfld = fld.trimmed().toLongLong();
272 for (int pos = 0 ; sufs[pos] ; ++pos) {
273 if (dfld % divs[pos] == 0) {
282 msg = QString("%1%2").arg(dfld).arg(suffix);
284 /* previous check returned a number too big. The original specification perhaps
285 was mixed, like 1d 2h, so we try to match with this routine */
286 dfld = fld.trimmed().toLongLong();
288 for (int pos = 0 ; sufs[pos] ; ++pos) {
289 if (dfld / divs[pos] != 0) {
290 msg += QString(" %1%2").arg(dfld / divs[pos]).arg(sufs[pos]);
295 msg += QString(" %1s").arg(dfld);
298 setNumericFld(index, msg, fld.trimmed().toLongLong());
301 void ItemFormatterBase::setVolStatusFld(int index, const QString &fld, bool center)
303 QString mp(fld.trimmed());
304 setTextFld(index, volume_status_to_str(mp.toUtf8()), center);
306 if (mp == "Append" ) {
307 setBackground(index, Qt::green);
308 } else if (mp == "Error") {
309 setBackground(index, Qt::red);
310 } else if (mp == "Used" || mp == "Full"){
311 setBackground(index, Qt::yellow);
312 } else if (mp == "Read-only" || mp == "Disabled"){
313 setBackground(index, Qt::lightGray);
317 void ItemFormatterBase::setJobStatusFld(int index, const QString &status, bool center)
319 /* C (created, not yet running) uses the default background */
320 static QString greenchars("TR");
321 static QString redchars("BEf");
322 static QString yellowchars("eDAFSMmsjdctp");
324 setTextFld(index, convertJobStatus(status), center);
326 QString st(status.trimmed());
327 if (greenchars.contains(st, Qt::CaseSensitive)) {
328 setBackground(index, Qt::green);
329 } else if (redchars.contains(st, Qt::CaseSensitive)) {
330 setBackground(index, Qt::red);
331 } else if (yellowchars.contains(st, Qt::CaseSensitive)){
332 setBackground(index, Qt::yellow);
336 void ItemFormatterBase::setJobTypeFld(int index, const QString &fld, bool center)
338 QByteArray jtype(fld.trimmed().toAscii());
340 setTextFld(index, job_type_to_str(jtype[0]), center);
342 setTextFld(index, "", center);
346 void ItemFormatterBase::setJobLevelFld(int index, const QString &fld, bool center)
348 QByteArray lvl(fld.trimmed().toAscii());
350 setTextFld(index, job_level_to_str(lvl[0]), center);
352 setTextFld(index, "", center);
358 /***********************************************
360 * treeitem formatting routines
362 ***********************************************/
363 TreeItemFormatter::TreeItemFormatter(QTreeWidgetItem &parent, int indent_level):
365 wdg(new QTreeWidgetItem(&parent)),
370 void TreeItemFormatter::setText(int index, const QString &fld)
372 wdg->setData(index, Qt::UserRole, level);
373 wdg->setText(index, fld);
376 void TreeItemFormatter::setTextAlignment(int index, int align)
378 wdg->setTextAlignment(index, align);
381 void TreeItemFormatter::setBackground(int index, const QBrush &qb)
383 wdg->setBackground(index, qb);
386 /* at this time we don't sort trees, so this method does nothing */
387 void TreeItemFormatter::setSortValue(int /* index */, const QVariant & /* value */)
391 /***********************************************
393 * Specialized table widget used for sorting
395 ***********************************************/
396 TableItemFormatter::BatSortingTableItem::BatSortingTableItem():
401 void TableItemFormatter::BatSortingTableItem::setSortData(const QVariant &d)
403 setData(SORTDATA_ROLE, d);
406 bool TableItemFormatter::BatSortingTableItem::operator< ( const QTableWidgetItem & o ) const
408 QVariant my = data(SORTDATA_ROLE);
409 QVariant other = o.data(SORTDATA_ROLE);
410 if (!my.isValid() || !other.isValid() || my.type() != other.type())
411 return QTableWidgetItem::operator< (o); /* invalid combination, revert to default sorting */
413 /* 64bit integers must be handled separately, others can be converted to double */
414 if (QVariant::ULongLong == my.type()) {
415 return my.toULongLong() < other.toULongLong();
416 } else if (QVariant::LongLong == my.type()) {
417 return my.toLongLong() < other.toLongLong();
418 } else if (my.canConvert(QVariant::Double)) {
419 return my.toDouble() < other.toDouble();
421 return QTableWidgetItem::operator< (o); /* invalid combination, revert to default sorting */
425 /***********************************************
427 * tableitem formatting routines
429 ***********************************************/
430 TableItemFormatter::TableItemFormatter(QTableWidget &tparent, int trow):
438 void TableItemFormatter::setText(int col, const QString &fld)
440 last = new BatSortingTableItem;
441 parent->setItem(row, col, last);
445 void TableItemFormatter::setTextAlignment(int /*index*/, int align)
447 last->setTextAlignment(align);
450 void TableItemFormatter::setBackground(int /*index*/, const QBrush &qb)
452 last->setBackground(qb);
455 void TableItemFormatter::setSortValue(int /* index */, const QVariant &value )
457 last->setSortData(value);
460 QTableWidgetItem *TableItemFormatter::widget(int col)
462 return parent->item(row, col);
465 const QTableWidgetItem *TableItemFormatter::widget(int col) const
467 return parent->item(row, col);