diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 5e0e93d7a..80fe32852 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -1139,20 +1139,16 @@ void MainWindow::updateGUI() { html += "qBittorrent"; html += ""; html += "
"; - /* HACK because QString rounds up. Eg QString::number(0.999*100.0, 'f' ,1) == 99.9 - ** but QString::number(0.9999*100.0, 'f' ,1) == 100.0 */ - html += " "+tr("DL speed: %1 KiB/s", "e.g: Download speed: 10 KiB/s").arg(QString::number((int)((QBtSession::instance()->getPayloadDownloadRate()/1024.)*10)/10.0, 'f', 1)); + html += " "+tr("DL speed: %1 KiB/s", "e.g: Download speed: 10 KiB/s").arg(misc::accurateDoubleToString(QBtSession::instance()->getPayloadDownloadRate()/1024., 1)); html += "
"; html += "
"; - html += " "+tr("UP speed: %1 KiB/s", "e.g: Upload speed: 10 KiB/s").arg(QString::number((int)((QBtSession::instance()->getPayloadUploadRate()/1024.)*10)/10.0, 'f', 1)); + html += " "+tr("UP speed: %1 KiB/s", "e.g: Upload speed: 10 KiB/s").arg(misc::accurateDoubleToString(QBtSession::instance()->getPayloadUploadRate()/1024., 1)); html += "
"; #else // OSes such as Windows do not support html here - /* HACK because QString rounds up. Eg QString::number(0.999*100.0, 'f' ,1) == 99.9 - ** but QString::number(0.9999*100.0, 'f' ,1) == 100.0 */ - QString html =tr("DL speed: %1 KiB/s", "e.g: Download speed: 10 KiB/s").arg(QString::number((int)((QBtSession::instance()->getPayloadDownloadRate()/1024.)*10)/10.0, 'f', 1)); + QString html =tr("DL speed: %1 KiB/s", "e.g: Download speed: 10 KiB/s").arg(misc::accurateDoubleToString(QBtSession::instance()->getPayloadDownloadRate()/1024., 1)); html += "\n"; - html += tr("UP speed: %1 KiB/s", "e.g: Upload speed: 10 KiB/s").arg(QString::number((int)((QBtSession::instance()->getPayloadUploadRate()/1024.)*10)/10.0, 'f', 1)); + html += tr("UP speed: %1 KiB/s", "e.g: Upload speed: 10 KiB/s").arg(misc::accurateDoubleToString(QBtSession::instance()->getPayloadUploadRate()/1024., 1)); #endif systrayIcon->setToolTip(html); // tray icon } diff --git a/src/misc.cpp b/src/misc.cpp index 2cc473e4e..b236d1cde 100644 --- a/src/misc.cpp +++ b/src/misc.cpp @@ -30,6 +30,8 @@ #include "misc.h" +#include + #include #include #include @@ -38,6 +40,7 @@ #include #include #include +#include #ifdef DISABLE_GUI #include @@ -255,9 +258,7 @@ QString misc::friendlyUnit(qreal val, bool is_speed) { if (i == 0) ret = QString::number((long)val) + " " + QCoreApplication::translate("misc", units[0].source, units[0].comment); else - /* HACK because QString rounds up. Eg QString::number(0.999*100.0, 'f' ,1) == 99.9 - ** but QString::number(0.9999*100.0, 'f' ,1) == 100.0 */ - ret = QString::number((int)(val*10)/10.0, 'f', 1) + " " + QCoreApplication::translate("misc", units[i].source, units[i].comment); + ret = accurateDoubleToString(val, 1) + " " + QCoreApplication::translate("misc", units[i].source, units[i].comment); if (is_speed) ret += QCoreApplication::translate("misc", "/s", "per second"); return ret; @@ -572,3 +573,18 @@ bool misc::naturalSort(QString left, QString right, bool &result) { // uses less return false; } #endif + +QString misc::accurateDoubleToString(double n, int precision) { + /* HACK because QString rounds up. Eg QString::number(0.999*100.0, 'f' ,1) == 99.9 + ** but QString::number(0.9999*100.0, 'f' ,1) == 100.0 The problem manifests when + ** the number has more digits after the decimal than we want AND the digit after + ** our 'wanted' is >= 5. In this case our last digit gets rounded up. So for each + ** precision we add an extra 0 behind 1 in the below algorithm. + ** However this, approach has a drawback. eg (99,99, 2) returns 99.98 and (99.99, 3) + ** returns 99.989. This is a minor issue because mostly we want to use precision 1 or 2 + ** and the double fed into this function will have more decimal places than required + ** precision anyway.*/ + + double prec = std::pow(10.0, precision); + return QLocale::system().toString((int)(n*(int)prec)/prec, 'f', precision); +} diff --git a/src/misc.h b/src/misc.h index 16a52a721..ed4d498c0 100644 --- a/src/misc.h +++ b/src/misc.h @@ -108,6 +108,7 @@ namespace misc QList boolListfromStringList(const QStringList &l); QString toQString(time_t t); + QString accurateDoubleToString(double n, int precision); #ifndef DISABLE_GUI bool naturalSort(QString left, QString right, bool& result); diff --git a/src/previewlistdelegate.h b/src/previewlistdelegate.h index 65db98865..f6ba96e1b 100644 --- a/src/previewlistdelegate.h +++ b/src/previewlistdelegate.h @@ -65,9 +65,7 @@ class PreviewListDelegate: public QItemDelegate { QStyleOptionProgressBarV2 newopt; qreal progress = index.data().toDouble()*100.; newopt.rect = opt.rect; - /* HACK because QString rounds up. Eg QString::number(0.999*100.0, 'f' ,1) == 99.9 - ** but QString::number(0.9999*100.0, 'f' ,1) == 100.0 */ - newopt.text = QString::number((int)(progress*10)/10.0, 'f', 1)+"%"; + newopt.text = misc::accurateDoubleToString(progress, 1); newopt.progress = (int)progress; newopt.maximum = 100; newopt.minimum = 0; diff --git a/src/properties/peerlistdelegate.h b/src/properties/peerlistdelegate.h index 30e8345be..c819c544b 100644 --- a/src/properties/peerlistdelegate.h +++ b/src/properties/peerlistdelegate.h @@ -67,9 +67,7 @@ public: case PROGRESS:{ QItemDelegate::drawBackground(painter, opt, index); qreal progress = index.data().toDouble(); - /* HACK because QString rounds up. Eg QString::number(0.999*100.0, 'f' ,1) == 99.9 - ** but QString::number(0.9999*100.0, 'f' ,1) == 100.0 */ - QItemDelegate::drawDisplay(painter, opt, opt.rect, QString::number((int)((progress*100.0)*10)/10.0, 'f', 1)+"%"); + QItemDelegate::drawDisplay(painter, opt, opt.rect, misc::accurateDoubleToString(progress*100.0, 1)+"%"); break; } default: diff --git a/src/properties/propertieswidget.cpp b/src/properties/propertieswidget.cpp index 49a581373..91ebdf91d 100644 --- a/src/properties/propertieswidget.cpp +++ b/src/properties/propertieswidget.cpp @@ -336,9 +336,7 @@ void PropertiesWidget::loadDynamicData() { reannounce_lbl->setText(h.next_announce()); // Update ratio info const qreal ratio = QBtSession::instance()->getRealRatio(h.hash()); - /* HACK because QString rounds up. Eg QString::number(0.999*100.0, 'f' ,1) == 99.9 - ** but QString::number(0.9999*100.0, 'f' ,1) == 100.0 */ - shareRatio->setText(ratio > QBtSession::MAX_RATIO ? QString::fromUtf8("∞") : QString::number((int)(ratio*100)/100.0, 'f', 2)); + shareRatio->setText(ratio > QBtSession::MAX_RATIO ? QString::fromUtf8("∞") : misc::accurateDoubleToString(ratio*100, 2)); if (!h.is_seed()) { showPiecesDownloaded(true); // Downloaded pieces @@ -355,17 +353,13 @@ void PropertiesWidget::loadDynamicData() { std::vector avail; h.piece_availability(avail); pieces_availability->setAvailability(avail); - /* HACK because QString rounds up. Eg QString::number(0.999*100.0, 'f' ,1) == 99.9 - ** but QString::number(0.9999*100.0, 'f' ,1) == 100.0 */ - avail_average_lbl->setText(QString::number((int)(h.distributed_copies()*1000)/1000.0, 'f', 3)); + avail_average_lbl->setText(misc::accurateDoubleToString(h.distributed_copies(), 3)); } else { showPiecesAvailability(false); } // Progress qreal progress = h.progress()*100.; - /* HACK because QString rounds up. Eg QString::number(0.999*100.0, 'f' ,1) == 99.9 - ** but QString::number(0.9999*100.0, 'f' ,1) == 100.0 */ - progress_lbl->setText(QString::number((int)(progress*10)/10.0, 'f', 1)+"%"); + progress_lbl->setText(misc::accurateDoubleToString(progress, 1)+"%"); } else { showPiecesAvailability(false); showPiecesDownloaded(false); diff --git a/src/properties/proplistdelegate.h b/src/properties/proplistdelegate.h index 3b03b41fb..8ee055e3f 100644 --- a/src/properties/proplistdelegate.h +++ b/src/properties/proplistdelegate.h @@ -78,9 +78,7 @@ public: QStyleOptionProgressBarV2 newopt; qreal progress = index.data().toDouble()*100.; newopt.rect = opt.rect; - /* HACK because QString rounds up. Eg QString::number(0.999*100.0, 'f' ,1) == 99.9 - ** but QString::number(0.9999*100.0, 'f' ,1) == 100.0 */ - newopt.text = QString::number((int)(progress*10)/10.0, 'f', 1)+"%"; + newopt.text = misc::accurateDoubleToString(progress, 1); newopt.progress = (int)progress; newopt.maximum = 100; newopt.minimum = 0; diff --git a/src/statsdialog.cpp b/src/statsdialog.cpp index e514e9fa7..7f6d27640 100644 --- a/src/statsdialog.cpp +++ b/src/statsdialog.cpp @@ -67,13 +67,13 @@ void StatsDialog::updateUI() { // Global ratio ui->labelGlobalRatio->setText( ( atd > 0 && atu > 0 ) ? - QString::number( (qreal)atu / (qreal)atd, 'f', 2) : + misc::accurateDoubleToString((qreal)atu / (qreal)atd, 2) : "-" ); // Cache hits ui->labelCacheHits->setText( ( cache.blocks_read > 0 && cache.blocks_read_hit > 0 ) ? - QString("%L1\%").arg(100. * (qreal)cache.blocks_read_hit / (qreal)cache.blocks_read, 0, 'f', 2) : + misc::accurateDoubleToString(100. * (qreal)cache.blocks_read_hit / (qreal)cache.blocks_read, 2) : "-" ); // Buffers size @@ -91,12 +91,12 @@ void StatsDialog::updateUI() { peers += (*iBegin).status().num_peers; ui->labelWriteStarve->setText( ( ss.disk_write_queue > 0 && peers > 0 ) ? - QString("%L1\%").arg(100. * (qreal)ss.disk_write_queue / (qreal)peers, 0, 'f', 2) : + misc::accurateDoubleToString(100. * (qreal)ss.disk_write_queue / (qreal)peers, 2) : QString("0\%") ); ui->labelReadStarve->setText( ( ss.disk_read_queue > 0 && peers > 0 ) ? - QString("%L1\%").arg(100. * (qreal)ss.disk_read_queue / (qreal)peers, 0, 'f', 2) : + misc::accurateDoubleToString(100. * (qreal)ss.disk_read_queue / (qreal)peers, 2) : QString("0\%") ); // Disk queues diff --git a/src/transferlistdelegate.h b/src/transferlistdelegate.h index 96b892d3b..4158ac5c6 100644 --- a/src/transferlistdelegate.h +++ b/src/transferlistdelegate.h @@ -138,9 +138,7 @@ public: case TorrentModelItem::TR_DLLIMIT:{ QItemDelegate::drawBackground(painter, opt, index); const qlonglong limit = index.data().toLongLong(); - /* HACK because QString rounds up. Eg QString::number(0.999*100.0, 'f' ,1) == 99.9 - ** but QString::number(0.9999*100.0, 'f' ,1) == 100.0 */ - QItemDelegate::drawDisplay(painter, opt, opt.rect, limit > 0 ? QString::number((int)((limit/1024.)*10)/10.0, 'f', 1) + " " + tr("KiB/s", "KiB/second (.i.e per second)") : QString::fromUtf8("∞")); + QItemDelegate::drawDisplay(painter, opt, opt.rect, limit > 0 ? misc::accurateDoubleToString(limit/1024., 1) + " " + tr("KiB/s", "KiB/second (.i.e per second)") : QString::fromUtf8("∞")); break; } case TorrentModelItem::TR_TIME_ELAPSED: { @@ -160,9 +158,7 @@ public: case TorrentModelItem::TR_RATIO:{ QItemDelegate::drawBackground(painter, opt, index); const qreal ratio = index.data().toDouble(); - /* HACK because QString rounds up. Eg QString::number(0.999*100.0, 'f' ,1) == 99.9 - ** but QString::number(0.9999*100.0, 'f' ,1) == 100.0 */ - QItemDelegate::drawDisplay(painter, opt, opt.rect, ratio > QBtSession::MAX_RATIO ? QString::fromUtf8("∞") : QString::number((int)(ratio*100)/100.0, 'f', 2)); + QItemDelegate::drawDisplay(painter, opt, opt.rect, ratio > QBtSession::MAX_RATIO ? QString::fromUtf8("∞") : misc::accurateDoubleToString(ratio, 2)); break; } case TorrentModelItem::TR_PRIORITY: { @@ -179,9 +175,7 @@ public: QStyleOptionProgressBarV2 newopt; qreal progress = index.data().toDouble()*100.; newopt.rect = opt.rect; - /* HACK because QString rounds up. Eg QString::number(0.999*100.0, 'f' ,1) == 99.9 - ** but QString::number(0.9999*100.0, 'f' ,1) == 100.0 */ - newopt.text = QString::number((int)(progress*10)/10.0, 'f', 1)+"%"; + newopt.text = misc::accurateDoubleToString(progress, 1); newopt.progress = (int)progress; newopt.maximum = 100; newopt.minimum = 0; diff --git a/src/webui/btjson.cpp b/src/webui/btjson.cpp index 52da45303..b68bb2f69 100644 --- a/src/webui/btjson.cpp +++ b/src/webui/btjson.cpp @@ -143,9 +143,7 @@ static JsonDict toJson(const QTorrentHandle& h) leechs += " ("+QString::number(h.num_incomplete())+")"; ret.add(KEY_TORRENT_LEECHS, leechs); const qreal ratio = QBtSession::instance()->getRealRatio(h.hash()); - /* HACK because QString rounds up. Eg QString::number(0.999*100.0, 'f' ,1) == 99.9 - ** but QString::number(0.9999*100.0, 'f' ,1) == 100.0 */ - ret.add(KEY_TORRENT_RATIO, (ratio > 100.) ? QString::fromUtf8("∞") : QString::number((int)(ratio*10)/10.0, 'f', 1)); + ret.add(KEY_TORRENT_RATIO, (ratio > 100.) ? QString::fromUtf8("∞") : misc::accurateDoubleToString(ratio, 1)); QString eta; QString state; if (h.is_paused()) { @@ -307,9 +305,7 @@ QString btjson::getPropertiesForTorrent(const QString& hash) data.add(KEY_PROP_TIME_ELAPSED, elapsed_txt); data.add(KEY_PROP_CONNECT_COUNT, QString(QString::number(h.num_connections()) + " (" + tr("%1 max", "e.g. 10 max").arg(QString::number(h.connections_limit())) + ")")); const qreal ratio = QBtSession::instance()->getRealRatio(h.hash()); - /* HACK because QString rounds up. Eg QString::number(0.999*100.0, 'f' ,1) == 99.9 - ** but QString::number(0.9999*100.0, 'f' ,1) == 100.0 */ - data.add(KEY_PROP_RATIO, ratio > 100. ? QString::fromUtf8("∞") : QString::number((int)(ratio*10)/10.0, 'f', 1)); + data.add(KEY_PROP_RATIO, ratio > 100. ? QString::fromUtf8("∞") : misc::accurateDoubleToString(ratio, 1)); } catch(const std::exception& e) { qWarning() << Q_FUNC_INFO << "Invalid torrent: " << e.what(); return QString();