From: Dirk H Bartley Date: Thu, 15 May 2008 01:54:01 +0000 (+0000) Subject: Riccardo' patch for formatting text. X-Git-Tag: Release-3.0.0~1428 X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=5a40bf19dbefda97a4cd5f94d2b916aedc739020;p=bacula%2Fbacula Riccardo' patch for formatting text. git-svn-id: https://bacula.svn.sourceforge.net/svnroot/bacula/trunk@6977 91ce42f0-d328-0410-95d8-f526ca767f89 --- diff --git a/bacula/src/qt-console/joblist/joblist.cpp b/bacula/src/qt-console/joblist/joblist.cpp index bb3e49d9cf..2f7f5f5d6f 100644 --- a/bacula/src/qt-console/joblist/joblist.cpp +++ b/bacula/src/qt-console/joblist/joblist.cpp @@ -40,6 +40,7 @@ #ifdef HAVE_QWT #include "jobgraphs/jobplot.h" #endif +#include "util/fmtwidgetitem.h" /* * Constructor for the class @@ -106,14 +107,120 @@ JobList::~JobList() */ void JobList::populateTable() { - QStringList results; - QString resultline; - QBrush blackBrush(Qt::black); - if (!m_console->preventInUseConnect()) return; /* Can't do this in constructor because not neccesarily conected in constructor */ + prepareFilterWidgets(); + + /* Set up query */ + QString query; + fillQueryString(query); + + /* Set up the Header for the table */ + QStringList headerlist = (QStringList() + << tr("Job Id") << tr("Job Name") << tr("Client") << tr("Job Starttime") + << tr("Job Type") << tr("Job Level") << tr("Job Files") + << tr("Job Bytes") << tr("Job Status") << tr("Purged") << tr("File Set")); + + m_jobIdIndex = headerlist.indexOf(tr("Job Id")); + m_purgedIndex = headerlist.indexOf(tr("Purged")); + m_typeIndex = headerlist.indexOf(tr("Job Type")); + m_statusIndex = headerlist.indexOf(tr("Job Status")); + m_startIndex = headerlist.indexOf(tr("Job Starttime")); + m_filesIndex = headerlist.indexOf(tr("Job Files")); + m_bytesIndex = headerlist.indexOf(tr("Job Bytes")); + + /* Initialize the QTableWidget */ + m_checkCurrentWidget = false; + mp_tableWidget->clear(); + m_checkCurrentWidget = true; + mp_tableWidget->setColumnCount(headerlist.size()); + mp_tableWidget->setHorizontalHeaderLabels(headerlist); + mp_tableWidget->setSelectionBehavior(QAbstractItemView::SelectRows); + mp_tableWidget->setSelectionMode(QAbstractItemView::SingleSelection); + + if (mainWin->m_sqlDebug) { + Pmsg1(000, "Query cmd : %s\n",query.toUtf8().data()); + } + + QStringList results; + if (m_console->sql_cmd(query, results)) { + m_resultCount = results.count(); + + QStringList fieldlist; + mp_tableWidget->setRowCount(results.size()); + + int row = 0; + /* Iterate through the record returned from the query */ + QString resultline; + foreach (resultline, results) { + fieldlist = resultline.split("\t"); + if (fieldlist.size() < 12) + continue; // some fields missing, ignore row + + TableItemFormatter jobitem(*mp_tableWidget, row); + + /* Iterate through fields in the record */ + QStringListIterator fld(fieldlist); + int col = 0; + + /* job id */ + jobitem.setNumericFld(col++, fld.next()); + + /* job name */ + jobitem.setTextFld(col++, fld.next()); + + /* client */ + jobitem.setTextFld(col++, fld.next()); + + /* job starttime */ + jobitem.setTextFld(col++, fld.next(), true); + + /* job type */ + jobitem.setJobTypeFld(col++, fld.next()); + + /* job level */ + jobitem.setJobLevelFld(col++, fld.next()); + + /* job files */ + jobitem.setNumericFld(col++, fld.next()); + + /* job bytes */ + jobitem.setBytesFld(col++, fld.next()); + + /* job status */ + QString shortstatus(fld.next()); + QString longstatus(fld.next()); + jobitem.setJobStatusFld(col++, shortstatus, longstatus); + + /* purged */ + if (fld.next().toInt()) + jobitem.setTextFld(col++, tr("IS"), true); + else + jobitem.setTextFld(col++, tr("NOT"), true); + + /* fileset */ + jobitem.setTextFld(col++, fld.next()); + + row++; + } + } + /* Resize the columns */ + mp_tableWidget->resizeColumnsToContents(); + mp_tableWidget->resizeRowsToContents(); + mp_tableWidget->verticalHeader()->hide(); + if ((m_mediaName != tr("Any")) && (m_resultCount == 0)){ + /* for context sensitive searches, let the user know if there were no + * results */ + QMessageBox::warning(this, "Bat", + tr("The Jobs query returned no results.\n" + "Press OK to continue?"), QMessageBox::Ok ); + } +} + +void JobList::prepareFilterWidgets() +{ if (!m_populated) { clientComboBox->addItem(tr("Any")); clientComboBox->addItems(m_console->client_list); @@ -150,9 +257,11 @@ void JobList::populateTable() statusComboBox->addItem(tr("Any")); statusComboBox->addItems(statusLongList); } +} - /* Set up query */ - QString query(""); +void JobList::fillQueryString(QString &query) +{ + query = ""; int volumeIndex = volumeComboBox->currentIndex(); if (volumeIndex != -1) m_mediaName = volumeComboBox->itemText(volumeIndex); @@ -221,124 +330,13 @@ void JobList::populateTable() } } /* Descending */ - query += " ORDER BY Job.Starttime DESC, Job.JobId DESC"; + query += " ORDER BY Job.Starttime=0 DESC, Job.Starttime DESC, Job.JobId DESC"; /* If Limit check box for limit records returned is checked */ if (limitCheckBox->checkState() == Qt::Checked) { QString limit; limit.setNum(limitSpinBox->value()); query += " LIMIT " + limit; } - - /* Set up the Header for the table */ - QStringList headerlist = (QStringList() - << tr("Job Id") << tr("Job Name") << tr("Client") << tr("Job Starttime") - << tr("Job Type") << tr("Job Level") << tr("Job Files") - << tr("Job Bytes") << tr("Job Status") << tr("Purged") << tr("File Set")); - m_jobIdIndex = headerlist.indexOf(tr("Job Id")); - m_purgedIndex = headerlist.indexOf(tr("Purged")); - m_typeIndex = headerlist.indexOf(tr("Job Type")); - m_statusIndex = headerlist.indexOf(tr("Job Status")); - m_startIndex = headerlist.indexOf(tr("Job Starttime")); - m_filesIndex = headerlist.indexOf(tr("Job Files")); - m_bytesIndex = headerlist.indexOf(tr("Job Bytes")); - int jobLevelIndex = headerlist.indexOf(tr("Job Level")); - - /* Initialize the QTableWidget */ - m_checkCurrentWidget = false; - mp_tableWidget->clear(); - m_checkCurrentWidget = true; - mp_tableWidget->setColumnCount(headerlist.size()); - mp_tableWidget->setHorizontalHeaderLabels(headerlist); - - if (mainWin->m_sqlDebug) { - Pmsg1(000, "Query cmd : %s\n",query.toUtf8().data()); - } - if (m_console->sql_cmd(query, results)) { - m_resultCount = results.count(); - - QTableWidgetItem* p_tableitem; - QString field; - QStringList fieldlist; - mp_tableWidget->setRowCount(results.size()); - - int row = 0; - /* Iterate through the record returned from the query */ - foreach (resultline, results) { - fieldlist = resultline.split("\t"); - int column = 0; - bool m_statusIndexDone = false; - QString statusCode(""); - /* Iterate through fields in the record */ - foreach (field, fieldlist) { - field = field.trimmed(); /* strip leading & trailing spaces */ - if ((column == m_statusIndex) && (!m_statusIndexDone)){ - m_statusIndexDone = true; - statusCode = field; - } else { - p_tableitem = new QTableWidgetItem(field, 1); - p_tableitem->setFlags(Qt::ItemIsSelectable); - p_tableitem->setForeground(blackBrush); - mp_tableWidget->setItem(row, column, p_tableitem); - if (column == m_statusIndex) - setStatusColor(p_tableitem, statusCode); - if (column == m_bytesIndex) { - QString text; - bool okay; - qlonglong bytes = field.toULongLong(&okay); - if (okay){ - QString test = QString("%1").arg(bytes); - mainWin->hrConvert(text, bytes); - p_tableitem->setText(text); - } else { Pmsg1(000, "conversion error %s\n", field.toUtf8().data()); } - } else if (column == m_purgedIndex) { - bool okay; - int isPurged = field.toInt(&okay); - if (okay){ - if (isPurged) { p_tableitem->setText(tr("IS")); - } else { p_tableitem->setText(tr("NOT")); } - } - } else if (column == m_typeIndex) { - if (field == "B") { p_tableitem->setText(tr("Backup")); } - else if (field == "R") { p_tableitem->setText(tr("Restore")); } - } else if (column == jobLevelIndex) { - if (field == "F") { p_tableitem->setText("Full"); } - else if (field == "D") { p_tableitem->setText("Diff"); } - else if (field == "I") { p_tableitem->setText("Incr"); } - } - if ((column == m_bytesIndex) || (column == m_filesIndex)){ - p_tableitem->setTextAlignment(Qt::AlignRight); - } - column++; - } - } - row++; - } - } - /* Resize the columns */ - mp_tableWidget->resizeColumnsToContents(); - mp_tableWidget->resizeRowsToContents(); - mp_tableWidget->verticalHeader()->hide(); - if ((m_mediaName != tr("Any")) && (m_resultCount == 0)){ - /* for context sensitive searches, let the user know if there were no - * results */ - QMessageBox::warning(this, "Bat", - tr("The Jobs query returned no results.\n" - "Press OK to continue?"), QMessageBox::Ok ); - } -} - -void JobList::setStatusColor(QTableWidgetItem *item, QString &field) -{ - QString greenchars("TCR"); - QString redchars("BEf"); - QString yellowchars("eDAFSMmsjdctp"); - if (greenchars.contains(field, Qt::CaseSensitive)) { - item->setBackground(Qt::green); - } else if (redchars.contains(field, Qt::CaseSensitive)) { - item->setBackground(Qt::red); - } else if (yellowchars.contains(field, Qt::CaseSensitive)){ - item->setBackground(Qt::yellow); - } } /* diff --git a/bacula/src/qt-console/joblist/joblist.h b/bacula/src/qt-console/joblist/joblist.h index 19456bf687..18eaabeddf 100644 --- a/bacula/src/qt-console/joblist/joblist.h +++ b/bacula/src/qt-console/joblist/joblist.h @@ -73,9 +73,10 @@ private slots: private: void createConnections(); - void setStatusColor(QTableWidgetItem *item, QString &field); void writeSettings(); void readSettings(); + void prepareFilterWidgets(); + void fillQueryString(QString &query); void selectedJobsGet(); QSplitter *m_splitter; QString m_groupText; diff --git a/bacula/src/qt-console/mainwin.cpp b/bacula/src/qt-console/mainwin.cpp index 4a485b747e..e52342b1ab 100644 --- a/bacula/src/qt-console/mainwin.cpp +++ b/bacula/src/qt-console/mainwin.cpp @@ -54,6 +54,7 @@ #include "jobgraphs/jobplot.h" #endif #include "status/dirstat.h" +#include "util/fmtwidgetitem.h" /* * Daemon message callback @@ -674,13 +675,16 @@ void MainWin::setPreferences() prefs.rtRestore1CheckBox->setCheckState(m_rtRestore1Debug ? Qt::Checked : Qt::Unchecked); prefs.rtRestore2CheckBox->setCheckState(m_rtRestore2Debug ? Qt::Checked : Qt::Unchecked); prefs.rtRestore3CheckBox->setCheckState(m_rtRestore3Debug ? Qt::Checked : Qt::Unchecked); - if (m_radioConvert == 0) { + switch (ItemFormatterBase::getBytesConversion()) { + case ItemFormatterBase::BYTES_CONVERSION_NONE: prefs.radioConvertOff->setChecked(Qt::Checked); - } else if (m_radioConvert == 1){ + break; + case ItemFormatterBase::BYTES_CONVERSION_IEC: prefs.radioConvertIEC->setChecked(Qt::Checked); - } else { - m_radioConvert = 2; + break; + default: prefs.radioConvertStandard->setChecked(Qt::Checked); + break; } prefs.openPlotCheckBox->setCheckState(m_openPlot ? Qt::Checked : Qt::Unchecked); prefs.openBrowserCheckBox->setCheckState(m_openBrowser ? Qt::Checked : Qt::Unchecked); @@ -725,11 +729,11 @@ void prefsDialog::accept() mainWin->m_rtRestore2Debug = this->rtRestore2CheckBox->checkState() == Qt::Checked; mainWin->m_rtRestore3Debug = this->rtRestore3CheckBox->checkState() == Qt::Checked; if (this->radioConvertOff->isChecked()) { - mainWin->m_radioConvert = 0; + ItemFormatterBase::setBytesConversion(ItemFormatterBase::BYTES_CONVERSION_NONE); } else if (this->radioConvertIEC->isChecked()){ - mainWin->m_radioConvert = 1; + ItemFormatterBase::setBytesConversion(ItemFormatterBase::BYTES_CONVERSION_IEC); } else { - mainWin->m_radioConvert = 2; + ItemFormatterBase::setBytesConversion(ItemFormatterBase::BYTES_CONVERSION_SI); } mainWin->m_openPlot = this->openPlotCheckBox->checkState() == Qt::Checked; mainWin->m_openBrowser = this->openBrowserCheckBox->checkState() == Qt::Checked; @@ -757,7 +761,7 @@ void prefsDialog::accept() settings.endGroup(); settings.beginGroup("Misc"); settings.setValue("longList", mainWin->m_longList); - settings.setValue("byteConvert", mainWin->m_radioConvert); + settings.setValue("byteConvert", ItemFormatterBase::getBytesConversion()); settings.setValue("openplot", mainWin->m_openPlot); settings.setValue("openbrowser", mainWin->m_openBrowser); settings.setValue("opendirstat", mainWin->m_openDirStat); @@ -812,7 +816,9 @@ void MainWin::readPreferences() settings.endGroup(); settings.beginGroup("Misc"); m_longList = settings.value("longList", false).toBool(); - m_radioConvert = settings.value("byteConvert", false).toInt(); + ItemFormatterBase::setBytesConversion( + (ItemFormatterBase::BYTES_CONVERSION) settings.value("byteConvert", + ItemFormatterBase::BYTES_CONVERSION_IEC).toInt()); m_openPlot = settings.value("openplot", false).toBool(); m_openBrowser = settings.value("openbrowser", false).toBool(); m_openDirStat = settings.value("opendirstat", false).toBool(); @@ -833,70 +839,4 @@ void MainWin::readPreferences() settings.endGroup(); } -void MainWin::hrConvert(QString &ret, qlonglong &inval) -{ - double net = 0; - qlonglong base; - QStringList suflist; - if (m_radioConvert == 0) { - ret = QString("%1").arg(inval); - return; - } else if (m_radioConvert == 1){ - base = 1000; - suflist = (QStringList() << "B" << "KiB" << "MiB" << "GiB" << "TiB" << "PiB" << "EiB" << "ZiB"); - } else { - base = 1024; - suflist = (QStringList() << "B" << "KB" << "MB" << "GB" << "TB" << "PB" << "EB" << "ZB"); - } - qlonglong running = base; - bool done = false; - int count = 1; - while (done == false) { - QString test1 = QString("%1").arg(inval); - QString test2 = QString("%1").arg(running); - if (float(inval) < (float)(running)) { - done = true; - ret = suflist[count - 1]; - net = (float)inval / (float)(running/base); - } - count += 1; - if (count > suflist.count()) done = true; - running *= base; - } - char format = 'f'; - if (net != 0) - ret = QString("%1 %2") - .arg(net, 0, format, 2, QLatin1Char(' ')) - .arg(ret); - else ret = "0 B"; -} - -void MainWin::hrConvertSeconds(QString &ret, qlonglong &inval) -{ - double net = 0; - QList durations; - durations.append(1); - durations.append(60); - durations.append(3600); - durations.append(86400); - durations.append(2592000); - durations.append(31536000); - QStringList abbrlist = (QStringList() << "Sec" << "Min" << "Hrs" << "Days" << "Mnth" << "Yrs"); - bool done = false; - int count = 1; - while (done == false) { - QString test1 = QString("%1").arg(inval); - QString test2 = QString("%1").arg(durations[count]); - if ((inval < durations[count]) || (count >= abbrlist.count() - 1)) { - done = true; - net = (float)inval / (float)(durations[count - 1]); - if (net != 0) - ret = QString("%1 %2") - .arg(net, 0, 'f', 2, QLatin1Char(' ')) - .arg(abbrlist[count - 1]); - else ret = "0 S"; - } - count += 1; - } -} diff --git a/bacula/src/qt-console/mainwin.h b/bacula/src/qt-console/mainwin.h index 0316817d5a..81ae9758fe 100644 --- a/bacula/src/qt-console/mainwin.h +++ b/bacula/src/qt-console/mainwin.h @@ -59,8 +59,6 @@ public: void hashInsert(QTreeWidgetItem *, Pages *); void hashRemove(Pages *); void hashRemove(QTreeWidgetItem *, Pages *); - void hrConvert(QString &, qlonglong &); - void hrConvertSeconds(QString &, qlonglong &); Console *currentConsole(); QTreeWidgetItem *currentTopItem(); Pages* getFromHash(QTreeWidgetItem *); @@ -101,7 +99,6 @@ public: bool m_rtRestore1Debug; bool m_rtRestore2Debug; bool m_rtRestore3Debug; - int m_radioConvert; bool m_openBrowser; bool m_openPlot; bool m_openDirStat; diff --git a/bacula/src/qt-console/medialist/medialist.cpp b/bacula/src/qt-console/medialist/medialist.cpp index 10469ce83b..09e434c765 100644 --- a/bacula/src/qt-console/medialist/medialist.cpp +++ b/bacula/src/qt-console/medialist/medialist.cpp @@ -146,7 +146,7 @@ void MediaList::populateTree() continue; // some fields missing, ignore row int index = 0; - ItemFormatter mediaitem(*pooltreeitem, 2); + TreeItemFormatter mediaitem(*pooltreeitem, 2); /* Iterate through fields in the record */ QStringListIterator fld(fieldlist); diff --git a/bacula/src/qt-console/storage/storage.cpp b/bacula/src/qt-console/storage/storage.cpp index f6b45ccc9a..3a33e28a8e 100644 --- a/bacula/src/qt-console/storage/storage.cpp +++ b/bacula/src/qt-console/storage/storage.cpp @@ -95,7 +95,7 @@ void Storage::populateTree() mp_treeWidget->setHeaderLabels(headerlist); foreach(QString storageName, m_console->storage_list){ - ItemFormatter storageItem(*topItem, 1); + TreeItemFormatter storageItem(*topItem, 1); storageItem.setTextFld(0, storageName); storageItem.widget()->setExpanded(true); @@ -167,7 +167,7 @@ void Storage::mediaList(QTreeWidgetItem *parent, const QString &storageID) /* Iterate through fields in the record */ QStringListIterator fld(fieldlist); int index = 0; - ItemFormatter fmt(*parent, 2); + TreeItemFormatter fmt(*parent, 2); /* volname */ fmt.setTextFld(index++, fld.next()); diff --git a/bacula/src/qt-console/util/fmtwidgetitem.cpp b/bacula/src/qt-console/util/fmtwidgetitem.cpp index 99cba81535..f9314edf92 100644 --- a/bacula/src/qt-console/util/fmtwidgetitem.cpp +++ b/bacula/src/qt-console/util/fmtwidgetitem.cpp @@ -36,18 +36,127 @@ */ #include +#include +#include +#include #include #include #include #include "fmtwidgetitem.h" -ItemFormatter::ItemFormatter(QTreeWidgetItem &parent, int indent_level): -wdg(new QTreeWidgetItem(&parent)), -level(indent_level) +/*********************************************** + * + * ItemFormatterBase static members + * + ***********************************************/ + +ItemFormatterBase::BYTES_CONVERSION ItemFormatterBase::cnvFlag(BYTES_CONVERSION_IEC); + +QString ItemFormatterBase::convertBytesIEC(qint64 qfld) { + static const qint64 KB = Q_INT64_C(1024); + static const qint64 MB = (KB * KB); + static const qint64 GB = (MB * KB); + static const qint64 TB = (GB * KB); + static const qint64 PB = (TB * KB); + static const qint64 EB = (PB * KB); + + /* note: division is integer, so to have some decimals we divide for a + smaller unit (e.g. GB for a TB number and so on) */ + char suffix; + if (qfld >= EB) { + qfld /= PB; + suffix = 'E'; + } + else if (qfld >= PB) { + qfld /= TB; + suffix = 'P'; + } + else if (qfld >= TB) { + qfld /= GB; + suffix = 'T'; + } + else if (qfld >= GB) { + qfld /= MB; + suffix = 'G'; + } + else if (qfld >= MB) { + qfld /= KB; + suffix = 'M'; + } + else if (qfld >= KB) { + suffix = 'K'; + } + else { + /* plain bytes, no need to reformat */ + return QString("%1 B").arg(qfld); + } + + /* having divided for a smaller unit, now we can safely convert to double and + use the extra room for decimals */ + return QString("%1 %2iB").arg(qfld / 1000.0, 0, 'f', 2).arg(suffix); } -void ItemFormatter::setBoolFld(int index, const QString &fld, bool center) +QString ItemFormatterBase::convertBytesSI(qint64 qfld) +{ + static const qint64 KB = Q_INT64_C(1000); + static const qint64 MB = (KB * KB); + static const qint64 GB = (MB * KB); + static const qint64 TB = (GB * KB); + static const qint64 PB = (TB * KB); + static const qint64 EB = (PB * KB); + + /* note: division is integer, so to have some decimals we divide for a + smaller unit (e.g. GB for a TB number and so on) */ + char suffix; + if (qfld >= EB) { + qfld /= PB; + suffix = 'E'; + } + else if (qfld >= PB) { + qfld /= TB; + suffix = 'P'; + } + else if (qfld >= TB) { + qfld /= GB; + suffix = 'T'; + } + else if (qfld >= GB) { + qfld /= MB; + suffix = 'G'; + } + else if (qfld >= MB) { + qfld /= KB; + suffix = 'M'; + } + else if (qfld >= KB) { + suffix = 'k'; /* SI uses lowercase k */ + } + else { + /* plain bytes, no need to reformat */ + return QString("%1 B").arg(qfld); + } + + /* having divided for a smaller unit, now we can safely convert to double and + use the extra room for decimals */ + return QString("%1 %2B").arg(qfld / 1000.0, 0, 'f', 2).arg(suffix); +} + +/*********************************************** + * + * base formatting routines + * + ***********************************************/ + +ItemFormatterBase::ItemFormatterBase() +{ +} + +ItemFormatterBase::~ItemFormatterBase() +{ +} + +void ItemFormatterBase::setBoolFld(int index, const QString &fld, bool center) { if (fld.trimmed().toInt()) setTextFld(index, "Yes", center); @@ -55,7 +164,7 @@ void ItemFormatter::setBoolFld(int index, const QString &fld, bool center) setTextFld(index, "No", center); } -void ItemFormatter::setBoolFld(int index, int fld, bool center) +void ItemFormatterBase::setBoolFld(int index, int fld, bool center) { if (fld) setTextFld(index, "Yes", center); @@ -63,84 +172,234 @@ void ItemFormatter::setBoolFld(int index, int fld, bool center) setTextFld(index, "No", center); } -void ItemFormatter::setTextFld(int index, const QString &fld, bool center) +void ItemFormatterBase::setNumericFld(int index, const QString &fld) +{ + setTextFld(index, fld); + setTextAlignment(index, Qt::AlignRight | Qt::AlignVCenter); +} + +void ItemFormatterBase::setBytesFld(int index, const QString &fld) +{ + qint64 qfld = fld.trimmed().toLongLong(); + QString msg; + switch (cnvFlag) { + case BYTES_CONVERSION_NONE: + msg = QString::number(qfld); + break; + case BYTES_CONVERSION_IEC: + msg = convertBytesIEC(qfld); + break; + case BYTES_CONVERSION_SI: + msg = convertBytesSI(qfld); + break; + } + setNumericFld(index, msg); +} + +void ItemFormatterBase::setDurationFld(int index, const QString &fld) +{ + static const qint64 HOUR = Q_INT64_C(3600); + static const qint64 DAY = HOUR * 24; + static const qint64 WEEK = DAY * 7; + static const qint64 MONTH = DAY * 30; + static const qint64 YEAR = DAY * 365; + static const qint64 divs[] = { YEAR, MONTH, WEEK, DAY, HOUR }; + static const char sufs[] = { 'y', 'm', 'w', 'd', 'h', '\0' }; + + qint64 dfld = fld.trimmed().toLongLong(); + + char suffix = 's'; + if (dfld) { + for (int pos = 0 ; sufs[pos] ; ++pos) { + if (dfld % divs[pos] == 0) { + dfld /= divs[pos]; + suffix = sufs[pos]; + break; + } + } + } + QString msg; + if (dfld < 100) { + msg = QString("%1%2").arg(dfld).arg(suffix); + } else { + /* previous check returned a number too big. The original specification perhaps + was mixed, like 1d 2h, so we try to match with this routine */ + dfld = fld.trimmed().toLongLong(); + msg = ""; + for (int pos = 0 ; sufs[pos] ; ++pos) { + if (dfld / divs[pos] != 0) { + msg += QString(" %1%2").arg(dfld / divs[pos]).arg(sufs[pos]); + dfld %= divs[pos]; + } + } + if (dfld) + msg += QString(" %1s").arg(dfld); + +/* + double net = 0; + QList durations; + durations.append(1); + durations.append(60); + durations.append(HOUR); + durations.append(DAY); + durations.append(MONTH); + durations.append(YEAR); + QStringList abbrlist = (QStringList() << "s" << "min" << "h" << "d" << "m" << "y"); + bool done = false; + int count = 1; + while (done == false) { + if ((dfld < durations[count]) || (count >= abbrlist.count() - 1)) { + done = true; + net = (double)dfld / (double)(durations[count - 1]); + if (net != 0) { + msg = QString("%1%2") + .arg(net, 0, 'f', 2, QLatin1Char(' ')) + .arg(abbrlist[count - 1]); + } else { + msg = "0s"; + } + } + count += 1; + } +*/ } + + setNumericFld(index, msg); +} + +void ItemFormatterBase::setVolStatusFld(int index, const QString &fld, bool center) +{ + setTextFld(index, fld, center); + + if (fld == "Append" ) { + setBackground(index, Qt::green); + } else if (fld == "Error") { + setBackground(index, Qt::red); + } else if (fld == "Used" || fld == "Full"){ + setBackground(index, Qt::yellow); + } +} + +void ItemFormatterBase::setJobStatusFld(int index, const QString &shortstatus, + const QString &longstatus, bool center) +{ + /* C (created, not yet running) uses the default background */ + static QString greenchars("TR"); + static QString redchars("BEf"); + static QString yellowchars("eDAFSMmsjdctp"); + + setTextFld(index, longstatus, center); + + QString st(shortstatus.trimmed()); + if (greenchars.contains(st, Qt::CaseSensitive)) { + setBackground(index, Qt::green); + } else if (redchars.contains(st, Qt::CaseSensitive)) { + setBackground(index, Qt::red); + } else if (yellowchars.contains(st, Qt::CaseSensitive)){ + setBackground(index, Qt::yellow); + } +} + +void ItemFormatterBase::setJobTypeFld(int index, const QString &fld, bool center) +{ + static QHash jobt; + if (jobt.isEmpty()) { + jobt.insert("B", QObject::tr("Backup")); + jobt.insert("R", QObject::tr("Restore")); + jobt.insert("V", QObject::tr("Verify")); + jobt.insert("A", QObject::tr("Admin")); + } + + setTextFld(index, jobt.value(fld.trimmed(), fld.trimmed()), center); +} + +void ItemFormatterBase::setJobLevelFld(int index, const QString &fld, bool center) +{ + static QHash jobt; + if (jobt.isEmpty()) { + jobt.insert("F", QObject::tr("Full")); + jobt.insert("D", QObject::tr("Differential")); + jobt.insert("I", QObject::tr("Incremental")); + jobt.insert("C", QObject::tr("Catalog")); + jobt.insert("O", QObject::tr("VolToCatalog")); + } + + setTextFld(index, jobt.value(fld.trimmed(), fld.trimmed()), center); +} + + + +/*********************************************** + * + * treeitem formatting routines + * + ***********************************************/ +TreeItemFormatter::TreeItemFormatter(QTreeWidgetItem &parent, int indent_level): +ItemFormatterBase(), +wdg(new QTreeWidgetItem(&parent)), +level(indent_level) +{ +} + +void TreeItemFormatter::setTextFld(int index, const QString &fld, bool center) { wdg->setData(index, Qt::UserRole, level); if (center) { - wdg->setTextAlignment(index, Qt::AlignHCenter); + setTextAlignment(index, Qt::AlignCenter); } wdg->setText(index, fld.trimmed()); } -void ItemFormatter::setNumericFld(int index, const QString &fld) +void TreeItemFormatter::setTextAlignment(int index, int align) { - wdg->setData(index, Qt::UserRole, level); - wdg->setTextAlignment(index, Qt::AlignRight); - wdg->setText(index, fld.trimmed()); + wdg->setTextAlignment(index, align); } -void ItemFormatter::setBytesFld(int index, const QString &fld) +void TreeItemFormatter::setBackground(int index, const QBrush &qb) { - static const double KB = 1024.0; - static const double MB = KB * KB; - static const double GB = MB * KB; - static const double TB = GB * KB; + wdg->setBackground(index, qb); +} - double dfld = fld.trimmed().toDouble(); - QString msg; - if (dfld >= TB) - msg = QString("%1TB").arg(dfld / TB, 0, 'f', 2); - else if (dfld >= GB) - msg = QString("%1GB").arg(dfld / GB, 0, 'f', 2); - else if (dfld >= MB) - msg = QString("%1MB").arg(dfld / MB, 0, 'f', 2); - else if (dfld >= KB) - msg = QString("%1KB").arg(dfld / KB, 0, 'f', 2); - else - msg = QString::number(dfld, 'f', 0); - - wdg->setData(index, Qt::UserRole, level); - wdg->setTextAlignment(index, Qt::AlignRight); - wdg->setText(index, msg); + +/*********************************************** + * + * tableitem formatting routines + * + ***********************************************/ +TableItemFormatter::TableItemFormatter(QTableWidget &tparent, int trow): +ItemFormatterBase(), +parent(&tparent), +row(trow), +last(NULL) +{ +} + +void TableItemFormatter::setTextFld(int col, const QString &fld, bool center) +{ + last = new QTableWidgetItem(1); +/* last->setForeground(blackBrush); */ + parent->setItem(row, col, last); + if (center) { + setTextAlignment(col, Qt::AlignCenter); + } + last->setText(fld.trimmed()); } -void ItemFormatter::setDurationFld(int index, const QString &fld) +void TableItemFormatter::setTextAlignment(int /*index*/, int align) { - static const double HOUR = 3600; - static const double DAY = HOUR * 24; - static const double WEEK = DAY * 7; - static const double MONTH = DAY * 30; - static const double YEAR = DAY * 365; + last->setTextAlignment(align); +} - double dfld = fld.trimmed().toDouble(); - QString msg; - if (fmod(dfld, YEAR) == 0) - msg = QString("%1y").arg(dfld / YEAR, 0, 'f', 0); - else if (fmod(dfld, MONTH) == 0) - msg = QString("%1m").arg(dfld / MONTH, 0, 'f', 0); - else if (fmod(dfld, WEEK) == 0) - msg = QString("%1w").arg(dfld / WEEK, 0, 'f', 0); - else if (fmod(dfld, DAY) == 0) - msg = QString("%1d").arg(dfld / DAY, 0, 'f', 0); - else if (fmod(dfld, HOUR) == 0) - msg = QString("%1h").arg(dfld / HOUR, 0, 'f', 0); - else - msg = QString("%1s").arg(dfld, 0, 'f', 0); - - wdg->setData(index, Qt::UserRole, level); - wdg->setTextAlignment(index, Qt::AlignRight); - wdg->setText(index, msg); +void TableItemFormatter::setBackground(int /*index*/, const QBrush &qb) +{ + last->setBackground(qb); } -void ItemFormatter::setVolStatusFld(int index, const QString &fld, bool center) +QTableWidgetItem *TableItemFormatter::widget(int col) { - setTextFld(index, fld, center); + return parent->item(row, col); +} - if (fld == "Append" ) { - wdg->setBackground(index, Qt::green); - } else if (fld == "Error") { - wdg->setBackground(index, Qt::red); - } else if (fld == "Used" || fld == "Full"){ - wdg->setBackground(index, Qt::yellow); - } +const QTableWidgetItem *TableItemFormatter::widget(int col) const +{ + return parent->item(row, col); } diff --git a/bacula/src/qt-console/util/fmtwidgetitem.h b/bacula/src/qt-console/util/fmtwidgetitem.h index 2f6c35a736..f0761888d6 100644 --- a/bacula/src/qt-console/util/fmtwidgetitem.h +++ b/bacula/src/qt-console/util/fmtwidgetitem.h @@ -34,25 +34,33 @@ */ class QTreeWidgetItem; +class QTableWidget; +class QTableWidgetItem; class QString; +class QBrush; /* - * This class can be used instead of QTreeWidgetItem (it allocates one internally, - * to format data fields. - * All setXXXFld routines receive a column index and the unformatted string value. + * base class for formatters + * */ -class ItemFormatter +class ItemFormatterBase { public: + enum BYTES_CONVERSION { + BYTES_CONVERSION_NONE, + BYTES_CONVERSION_IEC, + BYTES_CONVERSION_SI, + }; - ItemFormatter(QTreeWidgetItem &parent, int indent_level); +public: + virtual ~ItemFormatterBase(); /* Prints Yes if fld is != 0, No otherwise. Centers field if center true*/ void setBoolFld(int index, const QString &fld, bool center = true); void setBoolFld(int index, int fld, bool center = true); /* Normal text field. Centers field if center true*/ - void setTextFld(int index, const QString &fld, bool center = false); + virtual void setTextFld(int index, const QString &fld, bool center = false) = 0; /* Right-aligned text field.*/ void setNumericFld(int index, const QString &fld); @@ -65,91 +73,93 @@ public: /* fld value interpreted as volume status. Colored accordingly */ void setVolStatusFld(int index, const QString &fld, bool center = true); + + /* fld value interpreted as job status. Colored accordingly */ + void setJobStatusFld(int index, const QString &shortStatus, const QString &longstatus, + bool center = true); + + /* fld value interpreted as job type. */ + void setJobTypeFld(int index, const QString &fld, bool center = false); + + /* fld value interpreted as job level. */ + void setJobLevelFld(int index, const QString &fld, bool center = false); + + static void setBytesConversion(BYTES_CONVERSION b) { + cnvFlag = b; + } + static BYTES_CONVERSION getBytesConversion() { + return cnvFlag; + } + +protected: + /* only derived classes can create one of these */ + ItemFormatterBase(); + + virtual void setTextAlignment(int index, int align) = 0; + virtual void setBackground(int index, const QBrush &) = 0; - /* access internal widget */ - QTreeWidgetItem *widget() { return wdg; } - const QTreeWidgetItem *widget() const { return wdg; } +private: + /* bytes formatted as power-of-two with IEC suffixes (KiB, MiB, and so on) */ + static QString convertBytesIEC(qint64 fld); + + /* bytes formatted as power-of-ten with SI suffixes (kB, MB, and so on) */ + static QString convertBytesSI(qint64 fld); private: - QTreeWidgetItem *wdg; - int level; + static BYTES_CONVERSION cnvFlag; }; -#endif /* _FMTWIDGETITEM_H_ */ -#ifndef _FMTWIDGETITEM_H_ -#define _FMTWIDGETITEM_H_ /* - Bacula® - The Network Backup Solution - - Copyright (C) 2007-2007 Free Software Foundation Europe e.V. + * This class can be used instead of QTreeWidgetItem (it allocates one internally, + * to format data fields. + * All setXXXFld routines receive a column index and the unformatted string value. + */ +class TreeItemFormatter : public ItemFormatterBase +{ +public: - The main author of Bacula is Kern Sibbald, with contributions from - many others, a complete list can be found in the file AUTHORS. - This program is Free Software; you can redistribute it and/or - modify it under the terms of version two of the GNU General Public - License as published by the Free Software Foundation and included - in the file LICENSE. + TreeItemFormatter(QTreeWidgetItem &parent, int indent_level); - This program is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + virtual void setTextFld(int index, const QString &fld, bool center = false); - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301, USA. + /* access internal widget */ + QTreeWidgetItem *widget() { return wdg; } + const QTreeWidgetItem *widget() const { return wdg; } - Bacula® is a registered trademark of John Walker. - The licensor of Bacula is the Free Software Foundation Europe - (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich, - Switzerland, email:ftf@fsfeurope.org. -*/ -/* - * Version $Id$ - * - * TreeView formatting helpers - Riccardo Ghetta, May 2008 - */ +protected: + virtual void setTextAlignment(int index, int align); + virtual void setBackground(int index, const QBrush &); -class QTreeWidgetItem; -class QString; +private: + QTreeWidgetItem *wdg; + int level; +}; /* - * This class can be used instead of QTreeWidgetItem (it allocates one internally, + * This class can be used instead of QTableWidgetItem (it allocates one internally, * to format data fields. - * All setXXXFld routines receive a column index and the unformatted string value. + * All setXXXFld routines receive the column and the unformatted string value. */ -class ItemFormatter +class TableItemFormatter : public ItemFormatterBase { public: - ItemFormatter(QTreeWidgetItem &parent, int indent_level); + TableItemFormatter(QTableWidget &parent, int row); - /* Prints Yes if fld is != 0, No otherwise. Centers field if center true*/ - void setBoolFld(int index, const QString &fld, bool center = true); - - /* Normal text field. Centers field if center true*/ - void setTextFld(int index, const QString &fld, bool center = false); - - /* Right-aligned text field.*/ - void setNumericFld(int index, const QString &fld); + virtual void setTextFld(int col, const QString &fld, bool center = false); - /* fld value interpreted as bytes and formatted with size suffixes */ - void setBytesFld(int index, const QString &fld); + /* access internal widget at column col*/ + QTableWidgetItem *widget(int col); + const QTableWidgetItem *widget(int col) const; - /* fld value interpreted as seconds and formatted with y,m,w,h suffixes */ - void setDurationFld(int index, const QString &fld); - - /* fld value interpreted as volume status. Colored accordingly */ - void setVolStatusFld(int index, const QString &fld, bool center = true); - - /* access internal widget */ - QTreeWidgetItem *widget() { return wdg; } - const QTreeWidgetItem *widget() const { return wdg; } +protected: + virtual void setTextAlignment(int index, int align); + virtual void setBackground(int index, const QBrush &); private: - QTreeWidgetItem *wdg; - int level; + QTableWidget *parent; + int row; + QTableWidgetItem *last; }; #endif /* _FMTWIDGETITEM_H_ */