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::setBoolFld(int index, const QString &fld, bool center)
161 if (fld.trimmed().toInt())
162 setTextFld(index, "Yes", center);
164 setTextFld(index, "No", center);
167 void ItemFormatterBase::setBoolFld(int index, int fld, bool center)
170 setTextFld(index, "Yes", center);
172 setTextFld(index, "No", center);
175 void ItemFormatterBase::setNumericFld(int index, const QString &fld)
177 setTextFld(index, fld);
178 setTextAlignment(index, Qt::AlignRight | Qt::AlignVCenter);
181 void ItemFormatterBase::setBytesFld(int index, const QString &fld)
183 qint64 qfld = fld.trimmed().toLongLong();
186 case BYTES_CONVERSION_NONE:
187 msg = QString::number(qfld);
189 case BYTES_CONVERSION_IEC:
190 msg = convertBytesIEC(qfld);
192 case BYTES_CONVERSION_SI:
193 msg = convertBytesSI(qfld);
196 setNumericFld(index, msg);
199 void ItemFormatterBase::setDurationFld(int index, const QString &fld)
201 static const qint64 HOUR = Q_INT64_C(3600);
202 static const qint64 DAY = HOUR * 24;
203 static const qint64 WEEK = DAY * 7;
204 static const qint64 MONTH = DAY * 30;
205 static const qint64 YEAR = DAY * 365;
206 static const qint64 divs[] = { YEAR, MONTH, WEEK, DAY, HOUR };
207 static const char sufs[] = { 'y', 'm', 'w', 'd', 'h', '\0' };
209 qint64 dfld = fld.trimmed().toLongLong();
213 for (int pos = 0 ; sufs[pos] ; ++pos) {
214 if (dfld % divs[pos] == 0) {
223 msg = QString("%1%2").arg(dfld).arg(suffix);
225 /* previous check returned a number too big. The original specification perhaps
226 was mixed, like 1d 2h, so we try to match with this routine */
227 dfld = fld.trimmed().toLongLong();
229 for (int pos = 0 ; sufs[pos] ; ++pos) {
230 if (dfld / divs[pos] != 0) {
231 msg += QString(" %1%2").arg(dfld / divs[pos]).arg(sufs[pos]);
236 msg += QString(" %1s").arg(dfld);
240 QList<qlonglong> durations;
242 durations.append(60);
243 durations.append(HOUR);
244 durations.append(DAY);
245 durations.append(MONTH);
246 durations.append(YEAR);
247 QStringList abbrlist = (QStringList() << "s" << "min" << "h" << "d" << "m" << "y");
250 while (done == false) {
251 if ((dfld < durations[count]) || (count >= abbrlist.count() - 1)) {
253 net = (double)dfld / (double)(durations[count - 1]);
255 msg = QString("%1%2")
256 .arg(net, 0, 'f', 2, QLatin1Char(' '))
257 .arg(abbrlist[count - 1]);
266 setNumericFld(index, msg);
269 void ItemFormatterBase::setVolStatusFld(int index, const QString &fld, bool center)
271 setTextFld(index, fld, center);
273 if (fld == "Append" ) {
274 setBackground(index, Qt::green);
275 } else if (fld == "Error") {
276 setBackground(index, Qt::red);
277 } else if (fld == "Used" || fld == "Full"){
278 setBackground(index, Qt::yellow);
282 void ItemFormatterBase::setJobStatusFld(int index, const QString &shortstatus,
283 const QString &longstatus, bool center)
285 /* C (created, not yet running) uses the default background */
286 static QString greenchars("TR");
287 static QString redchars("BEf");
288 static QString yellowchars("eDAFSMmsjdctp");
290 setTextFld(index, longstatus, center);
292 QString st(shortstatus.trimmed());
293 if (greenchars.contains(st, Qt::CaseSensitive)) {
294 setBackground(index, Qt::green);
295 } else if (redchars.contains(st, Qt::CaseSensitive)) {
296 setBackground(index, Qt::red);
297 } else if (yellowchars.contains(st, Qt::CaseSensitive)){
298 setBackground(index, Qt::yellow);
302 void ItemFormatterBase::setJobTypeFld(int index, const QString &fld, bool center)
304 static QHash<QString, QString> jobt;
305 if (jobt.isEmpty()) {
306 jobt.insert("B", QObject::tr("Backup"));
307 jobt.insert("R", QObject::tr("Restore"));
308 jobt.insert("V", QObject::tr("Verify"));
309 jobt.insert("A", QObject::tr("Admin"));
312 setTextFld(index, jobt.value(fld.trimmed(), fld.trimmed()), center);
315 void ItemFormatterBase::setJobLevelFld(int index, const QString &fld, bool center)
317 static QHash<QString, QString> jobt;
318 if (jobt.isEmpty()) {
319 jobt.insert("F", QObject::tr("Full"));
320 jobt.insert("D", QObject::tr("Differential"));
321 jobt.insert("I", QObject::tr("Incremental"));
322 jobt.insert("C", QObject::tr("Catalog"));
323 jobt.insert("O", QObject::tr("VolToCatalog"));
326 setTextFld(index, jobt.value(fld.trimmed(), fld.trimmed()), center);
331 /***********************************************
333 * treeitem formatting routines
335 ***********************************************/
336 TreeItemFormatter::TreeItemFormatter(QTreeWidgetItem &parent, int indent_level):
338 wdg(new QTreeWidgetItem(&parent)),
343 void TreeItemFormatter::setTextFld(int index, const QString &fld, bool center)
345 wdg->setData(index, Qt::UserRole, level);
347 setTextAlignment(index, Qt::AlignCenter);
349 wdg->setText(index, fld.trimmed());
352 void TreeItemFormatter::setTextAlignment(int index, int align)
354 wdg->setTextAlignment(index, align);
357 void TreeItemFormatter::setBackground(int index, const QBrush &qb)
359 wdg->setBackground(index, qb);
363 /***********************************************
365 * tableitem formatting routines
367 ***********************************************/
368 TableItemFormatter::TableItemFormatter(QTableWidget &tparent, int trow):
376 void TableItemFormatter::setTextFld(int col, const QString &fld, bool center)
378 last = new QTableWidgetItem(1);
379 /* last->setForeground(blackBrush); */
380 parent->setItem(row, col, last);
382 setTextAlignment(col, Qt::AlignCenter);
384 last->setText(fld.trimmed());
387 void TableItemFormatter::setTextAlignment(int /*index*/, int align)
389 last->setTextAlignment(align);
392 void TableItemFormatter::setBackground(int /*index*/, const QBrush &qb)
394 last->setBackground(qb);
397 QTableWidgetItem *TableItemFormatter::widget(int col)
399 return parent->item(row, col);
402 const QTableWidgetItem *TableItemFormatter::widget(int col) const
404 return parent->item(row, col);