]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/qt-console/util/fmtwidgetitem.cpp
This is the application of a patch from Ricardo. Includes a great qty of translation...
[bacula/bacula] / bacula / src / qt-console / util / fmtwidgetitem.cpp
1 /*
2    Bacula® - The Network Backup Solution
3
4    Copyright (C) 2007-2007 Free Software Foundation Europe e.V.
5
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
11    in the file LICENSE.
12
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.
17
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
21    02110-1301, USA.
22
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.
27 */
28  
29 /*
30  *   Version $Id$
31  *
32  *  Helper functions for tree widget formatting
33  *
34  *   Riccardo Ghetta, May 2008
35  *
36  */ 
37
38 #include <QTreeWidgetItem>
39 #include <QTableWidget>
40 #include <QTableWidgetItem>
41 #include <QBrush>
42 #include <QString>
43 #include <QStringList>
44 #include <math.h>
45 #include "bacula.h"
46 #include "fmtwidgetitem.h"
47
48 /***********************************************
49  *
50  * ItemFormatterBase static members
51  *
52  ***********************************************/
53
54 ItemFormatterBase::BYTES_CONVERSION ItemFormatterBase::cnvFlag(BYTES_CONVERSION_IEC);
55
56 QString ItemFormatterBase::convertBytesIEC(qint64 qfld)
57 {
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);
64
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) */
67    char suffix;
68    if (qfld >= EB) {
69       qfld /= PB; 
70       suffix = 'E';
71    }
72    else if (qfld >= PB) {
73       qfld /= TB; 
74       suffix = 'P';
75    }
76    else if (qfld >= TB) {
77       qfld /= GB; 
78       suffix = 'T';
79    }
80    else if (qfld >= GB) {
81       qfld /= MB;
82       suffix = 'G';
83    }
84    else if (qfld >= MB) {
85       qfld /= KB;
86       suffix = 'M';
87    }
88    else if (qfld >= KB) {
89       suffix = 'K';
90    }
91    else  {
92       /* plain bytes, no need to reformat */
93       return QString("%1 B").arg(qfld); 
94    }
95
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);
99 }
100
101 QString ItemFormatterBase::convertBytesSI(qint64 qfld)
102 {
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);
109
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) */
112    char suffix;
113    if (qfld >= EB) {
114       qfld /= PB; 
115       suffix = 'E';
116    }
117    else if (qfld >= PB) {
118       qfld /= TB; 
119       suffix = 'P';
120    }
121    else if (qfld >= TB) {
122       qfld /= GB; 
123       suffix = 'T';
124    }
125    else if (qfld >= GB) {
126       qfld /= MB;
127       suffix = 'G';
128    }
129    else if (qfld >= MB) {
130       qfld /= KB;
131       suffix = 'M';
132    }
133    else if (qfld >= KB) {
134       suffix = 'k'; /* SI uses lowercase k */
135    }
136    else  {
137       /* plain bytes, no need to reformat */
138       return QString("%1 B").arg(qfld); 
139    }
140
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);
144 }
145
146 /***********************************************
147  *
148  * base formatting routines
149  *
150  ***********************************************/
151
152 ItemFormatterBase::ItemFormatterBase()
153 {
154 }
155
156 ItemFormatterBase::~ItemFormatterBase()
157 {
158 }
159
160 void ItemFormatterBase::setTextFld(int index, const QString &fld, bool center)
161 {
162    setText(index, fld.trimmed());
163    if (center) {
164       setTextAlignment(index, Qt::AlignCenter);
165    }
166 }
167
168 void ItemFormatterBase::setRightFld(int index, const QString &fld)
169 {
170    setText(index, fld.trimmed());
171    setTextAlignment(index, Qt::AlignRight | Qt::AlignVCenter);
172 }
173
174 void ItemFormatterBase::setBoolFld(int index, const QString &fld, bool center)
175 {
176    if (fld.trimmed().toInt())
177      setTextFld(index, QObject::tr("Yes"), center);
178    else
179      setTextFld(index, QObject::tr("No"), center);
180 }
181
182 void ItemFormatterBase::setBoolFld(int index, int fld, bool center)
183 {
184    if (fld)
185      setTextFld(index, QObject::tr("Yes"), center);
186    else
187      setTextFld(index, QObject::tr("No"), center);
188 }
189
190 void ItemFormatterBase::setNumericFld(int index, const QString &fld)
191 {
192    setRightFld(index, fld.trimmed());
193    setSortValue(index, fld.toDouble() );
194 }
195
196 void ItemFormatterBase::setNumericFld(int index, const QString &fld, const QVariant &sortval)
197 {
198    setRightFld(index, fld.trimmed());
199    setSortValue(index, sortval );
200 }
201
202 void ItemFormatterBase::setBytesFld(int index, const QString &fld)
203 {
204    qint64 qfld = fld.trimmed().toLongLong();
205    QString msg;
206    switch (cnvFlag) {
207    case BYTES_CONVERSION_NONE:
208       msg = QString::number(qfld);
209       break;
210    case BYTES_CONVERSION_IEC:
211       msg = convertBytesIEC(qfld);
212       break;
213    case BYTES_CONVERSION_SI:
214       msg = convertBytesSI(qfld);
215       break;
216    }
217
218    setNumericFld(index, msg, qfld);
219 }
220
221 void ItemFormatterBase::setDurationFld(int index, const QString &fld)
222 {
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' };
230
231    qint64 dfld = fld.trimmed().toLongLong();
232
233    char suffix = 's';
234    if (dfld) {
235       for (int pos = 0 ; sufs[pos] ; ++pos) {
236           if (dfld % divs[pos] == 0) {
237              dfld /= divs[pos];
238              suffix = sufs[pos];
239              break;
240           }
241       }
242    }
243    QString msg;
244    if (dfld < 100) {
245       msg = QString("%1%2").arg(dfld).arg(suffix);
246    } else {
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();
250       msg = "";
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]);
254              dfld %= divs[pos];
255           }
256       }
257       if (dfld)
258          msg += QString(" %1s").arg(dfld);
259    }
260
261    setNumericFld(index, msg, fld.trimmed().toLongLong());
262 }
263
264 void ItemFormatterBase::setVolStatusFld(int index, const QString &fld, bool center)
265 {
266    setTextFld(index, fld, center);
267
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);
274    }
275 }
276
277 void ItemFormatterBase::setJobStatusFld(int index, const QString &shortstatus, 
278                                         const QString &longstatus, bool center)
279 {
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");
284
285    setTextFld(index, longstatus, center);
286
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);
294    }
295 }
296
297 void ItemFormatterBase::setJobTypeFld(int index, const QString &fld, bool center)
298 {
299    QByteArray jtype(fld.trimmed().toAscii());
300    if (jtype.size()) {
301       setTextFld(index, job_type_to_str(jtype[0]), center);
302    } else {
303       setTextFld(index, "", center);
304    }
305 }
306
307 void ItemFormatterBase::setJobLevelFld(int index, const QString &fld, bool center)
308 {
309    QByteArray lvl(fld.trimmed().toAscii());
310    if (lvl.size()) {
311       setTextFld(index, job_level_to_str(lvl[0]), center);
312    } else {
313       setTextFld(index, "", center);
314    }
315 }
316
317
318
319 /***********************************************
320  *
321  * treeitem formatting routines
322  *
323  ***********************************************/
324 TreeItemFormatter::TreeItemFormatter(QTreeWidgetItem &parent, int indent_level):
325 ItemFormatterBase(),
326 wdg(new QTreeWidgetItem(&parent)),
327 level(indent_level)
328 {
329 }
330
331 void TreeItemFormatter::setText(int index, const QString &fld)
332 {
333    wdg->setData(index, Qt::UserRole, level);
334    wdg->setText(index, fld);
335 }
336
337 void TreeItemFormatter::setTextAlignment(int index, int align)
338 {
339    wdg->setTextAlignment(index, align);
340 }
341
342 void TreeItemFormatter::setBackground(int index, const QBrush &qb)
343 {
344    wdg->setBackground(index, qb);
345 }
346
347 /* at this time we don't sort trees, so this method does nothing */
348 void TreeItemFormatter::setSortValue(int /* index */, const QVariant & /* value */)
349 {
350 }
351
352 /***********************************************
353  *
354  * Specialized table widget used for sorting
355  *
356  ***********************************************/
357 TableItemFormatter::BatSortingTableItem::BatSortingTableItem():
358 QTableWidgetItem(1)
359 {
360 }
361
362 void TableItemFormatter::BatSortingTableItem::setSortData(const QVariant &d)
363 {
364    setData(SORTDATA_ROLE, d);
365 }
366
367 bool TableItemFormatter::BatSortingTableItem::operator< ( const QTableWidgetItem & o ) const 
368 {
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 */
373
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(); 
381    } else {
382       return QTableWidgetItem::operator< (o); /* invalid combination, revert to default sorting */
383    }
384 }
385
386 /***********************************************
387  *
388  * tableitem formatting routines
389  *
390  ***********************************************/
391 TableItemFormatter::TableItemFormatter(QTableWidget &tparent, int trow):
392 ItemFormatterBase(),
393 parent(&tparent),
394 row(trow),
395 last(NULL)
396 {
397 }
398
399 void TableItemFormatter::setText(int col, const QString &fld)
400 {
401    last = new BatSortingTableItem;
402    parent->setItem(row, col, last);
403    last->setText(fld);
404 }
405
406 void TableItemFormatter::setTextAlignment(int /*index*/, int align)
407 {
408    last->setTextAlignment(align);
409 }
410
411 void TableItemFormatter::setBackground(int /*index*/, const QBrush &qb)
412 {
413    last->setBackground(qb);
414 }
415
416 void TableItemFormatter::setSortValue(int /* index */, const QVariant &value )
417 {
418    last->setSortData(value);
419 }
420
421 QTableWidgetItem *TableItemFormatter::widget(int col)
422 {
423    return parent->item(row, col);
424 }
425
426 const QTableWidgetItem *TableItemFormatter::widget(int col) const
427 {
428    return parent->item(row, col);
429 }
430