From 702b9c8415097bdf299fea07b565665c68302dd3 Mon Sep 17 00:00:00 2001 From: Johnny Silverman Date: Mon, 3 Nov 2025 21:54:40 +0200 Subject: [PATCH] Use megabytes instead of gigabytes for size calculations internally. Change variable types to "int64_t" for megabyte calc. Add function "getSizeTextFromMegabytes" for generating size strings where it was repeated code. Optimize code to do less reading of reusable locale strings and read "logicalBlockSize" before reading other size parameters. --- include/mainwindow.h | 7 +++ src/mainwindow.cpp | 142 +++++++++++++++++++------------------------ 2 files changed, 71 insertions(+), 78 deletions(-) diff --git a/include/mainwindow.h b/include/mainwindow.h index e79c5ff..bc27452 100644 --- a/include/mainwindow.h +++ b/include/mainwindow.h @@ -95,4 +95,11 @@ private: void addSmartAttributesTable(const QJsonArray &attributes); void transformWindow(); void mousePressEvent(QMouseEvent*); + +private: + QString mbSymbol; + QString gbSymbol; + QString tbSymbol; + QString pbSymbol; + QString getMbToPrettyString(const int64_t &sizeInMbI64, const int &precisionInt, const bool &useGbBool); }; diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index d090a15..5e0e280 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -18,6 +18,7 @@ MainWindow::MainWindow(QWidget *parent) , ui(new Ui::MainWindow) , settings("qdiskinfo", "qdiskinfo") , initializing(true) + , mbSymbol("MB"), gbSymbol("GB"), tbSymbol("TB"), pbSymbol("PB") { ui->setupUi(this); @@ -145,6 +146,11 @@ MainWindow::MainWindow(QWidget *parent) delete temperatureValueHorizontal; delete healthStatusValueHorizontal; } + + mbSymbol = locale.formattedDataSize(1 << 20, 1, QLocale::DataSizeTraditionalFormat).split(' ')[1]; + gbSymbol = locale.formattedDataSize(1 << 30, 1, QLocale::DataSizeTraditionalFormat).split(' ')[1]; + tbSymbol = locale.formattedDataSize(qint64(1) << 40, 1, QLocale::DataSizeTraditionalFormat).split(' ')[1]; + pbSymbol = locale.formattedDataSize(qint64(1) << 50, 1, QLocale::DataSizeTraditionalFormat).split(' ')[1]; } MainWindow::~MainWindow() @@ -184,6 +190,11 @@ void MainWindow::updateNavigationButtons(qsizetype currentIndex) void MainWindow::updateUI(const QString ¤tDeviceName) { + mbSymbol = locale.formattedDataSize(1 << 20, 1, QLocale::DataSizeTraditionalFormat).split(' ')[1]; + gbSymbol = locale.formattedDataSize(1 << 30, 1, QLocale::DataSizeTraditionalFormat).split(' ')[1]; + tbSymbol = locale.formattedDataSize(qint64(1) << 40, 1, QLocale::DataSizeTraditionalFormat).split(' ')[1]; + pbSymbol = locale.formattedDataSize(qint64(1) << 50, 1, QLocale::DataSizeTraditionalFormat).split(' ')[1]; + QVector diskItems; bool firstTime = true; @@ -238,17 +249,10 @@ void MainWindow::updateUI(const QString ¤tDeviceName) QString health; QColor healthColor; - double diskCapacityGB = localObj.value("user_capacity").toObject().value("bytes").toDouble() / 1e9; - QString gbSymbol = locale.formattedDataSize(1 << 30, 1, QLocale::DataSizeTraditionalFormat).split(' ')[1]; - QString tbSymbol = locale.formattedDataSize(qint64(1) << 40, 1, QLocale::DataSizeTraditionalFormat).split(' ')[1]; - QString diskCapacityString; - int diskCapacityGbInt = static_cast(diskCapacityGB); + double diskCapacityMB = localObj.value("user_capacity").toObject().value("bytes").toDouble() / 1e6; + int64_t diskCapacityMbI64 = static_cast(diskCapacityMB); bool useGB = ui->actionUse_GB_instead_of_TB->isChecked(); - if (diskCapacityGbInt < 1000 || useGB) { - diskCapacityString = locale.toString(diskCapacityGB, 'f', 1) + " " + gbSymbol; - } else { - diskCapacityString = QString::number(diskCapacityGbInt/1000) + " " + tbSymbol; - } + QString diskCapacityString = getMbToPrettyString(diskCapacityMbI64, 0, useGB); QJsonObject temperatureObj = localObj["temperature"].toObject(); int temperatureInt = temperatureObj["current"].toInt(); @@ -433,23 +437,16 @@ void MainWindow::populateWindow(const QJsonObject &localObj, const QString &heal QJsonObject nvmeLog = localObj["nvme_smart_health_information_log"].toObject(); QString modelName = localObj["model_name"].toString(); QString firmwareVersion = localObj["firmware_version"].toString("----"); - double diskCapacityGB = localObj.value("user_capacity").toObject().value("bytes").toDouble() / 1e9; - int diskCapacityGbInt = static_cast(diskCapacityGB); + double diskCapacityMB = localObj.value("user_capacity").toObject().value("bytes").toDouble() / 1e6; + int64_t diskCapacityMbI64 = static_cast(diskCapacityMB); int powerCycleCountInt = localObj["power_cycle_count"].toInt(-1); QJsonObject temperatureObj = localObj["temperature"].toObject(); int temperatureInt = temperatureObj["current"].toInt(); - int totalWritesInt = 0; - int totalReadsInt = 0; + int64_t totalMbWritesI64 = 0; + int64_t totalMbReadsI64 = 0; bool useGB = ui->actionUse_GB_instead_of_TB->isChecked(); - QString gbSymbol = locale.formattedDataSize(1 << 30, 1, QLocale::DataSizeTraditionalFormat).split(' ')[1]; - QString tbSymbol = locale.formattedDataSize(qint64(1) << 40, 1, QLocale::DataSizeTraditionalFormat).split(' ')[1]; - QString diskCapacityString; - if (diskCapacityGbInt < 1000 || useGB) { - diskCapacityString = locale.toString(diskCapacityGB, 'f', 1) + " " + gbSymbol; - } else { - diskCapacityString = QString::number(diskCapacityGbInt/1000) + " " + tbSymbol; - } + QString diskCapacityString = getMbToPrettyString(diskCapacityMbI64, 0, useGB); QString totalReads; QString totalWrites; @@ -474,8 +471,8 @@ void MainWindow::populateWindow(const QJsonObject &localObj, const QString &heal modelName = localObj["scsi_model_name"].toString(); powerCycleCountInt = localObj["scsi_start_stop_cycle_counter"].toObject().value("accumulated_load_unload_cycles").toInt(); firmwareVersion = localObj["scsi_revision"].toString("----"); - totalReadsInt = scsiErrorCounterLog.value("read").toObject().value("gigabytes_processed").toString().split(",").first().toInt(); - totalWritesInt = scsiErrorCounterLog.value("write").toObject().value("gigabytes_processed").toString().split(",").first().toInt(); + totalMbReadsI64 = scsiErrorCounterLog.value("read").toObject().value("gigabytes_processed").toString().split(",").first().toInt() * 1000; + totalMbWritesI64 = scsiErrorCounterLog.value("write").toObject().value("gigabytes_processed").toString().split(",").first().toInt() * 1000; } bool nvmeHasSelfTest = false; @@ -591,6 +588,7 @@ void MainWindow::populateWindow(const QJsonObject &localObj, const QString &heal powerOnHoursLineEdit->setText(powerOnTime); powerOnHoursLineEdit->setAlignment(Qt::AlignRight); + int logicalBlockSize = localObj["logical_block_size"].toInt(); if (!isNvme) { for (const QJsonValue &attr : std::as_const(attributes)) { QJsonObject attrObj = attr.toObject(); @@ -602,57 +600,46 @@ void MainWindow::populateWindow(const QJsonObject &localObj, const QString &heal } else if (attrObj["id"] == 241) { if (attrObj["name"] == "Total_Writes_GB") { int gigabytes = attrObj["raw"].toObject()["value"].toInt(); - totalWritesInt = gigabytes; + totalMbWritesI64 = gigabytes * 1000; } else if (attrObj["name"] == "Host_Writes_32MiB") { - double gigabytes = (attrObj["raw"].toObject()["value"].toInt() * 32 * 1024.0 * 1024.0) / 1e9; - totalWritesInt = static_cast(gigabytes); + double megabytes = (attrObj["raw"].toObject()["value"].toInt() * 32 * 1024.0 * 1024.0) / 1e6; + totalMbWritesI64 = static_cast(megabytes); } else if (attrObj["name"] == "Total_LBAs_Written") { - int logicalBlockSize = localObj["logical_block_size"].toInt(); qlonglong lbaWritten = attrObj["raw"].toObject()["value"].toVariant().toLongLong(); - qlonglong gigabytes = (lbaWritten * logicalBlockSize) / 1e9; - int gigabytesInt = static_cast(gigabytes); - if (!gigabytesInt) { - gigabytesInt = static_cast(lbaWritten); - } - totalWritesInt = gigabytesInt; + double megabytes = double(lbaWritten * logicalBlockSize) / 1e6; + totalMbWritesI64 = static_cast(megabytes); } else if (attrObj["name"] == "Host_Writes_GiB" || attrObj["name"] == "Lifetime_Writes_GiB") { double gibibytes = attrObj["raw"].toObject()["value"].toDouble(); double bytesPerGiB = static_cast(1ULL << 30); - double bytesPerGB = 1e9; - double conversionFactor = bytesPerGiB / bytesPerGB; - double gigabytes = gibibytes * conversionFactor; - totalWritesInt = static_cast(gigabytes); + double bytesPerMB = 1e6; + double conversionFactor = bytesPerGiB / bytesPerMB; + double megabytes = gibibytes * conversionFactor; + totalMbWritesI64 = static_cast(megabytes); } } else if (attrObj["id"] == 242) { if (attrObj["name"] == "Total_Reads_GB") { int gigabytes = attrObj["raw"].toObject()["value"].toInt(); - totalReadsInt = gigabytes; + totalMbReadsI64 = gigabytes * 1000; } else if (attrObj["name"] == "Host_Reads_32MiB") { - double gigabytes = (attrObj["raw"].toObject()["value"].toInt() * 32 * 1024.0 * 1024.0) / 1e9; - totalReadsInt = static_cast(gigabytes); + double megabytes = (attrObj["raw"].toObject()["value"].toInt() * 32 * 1024 * 1024) / 1e6; + totalMbReadsI64 = static_cast(megabytes); } else if (attrObj["name"] == "Total_LBAs_Read") { - int logicalBlockSize = localObj["logical_block_size"].toInt(); qlonglong lbaRead = attrObj["raw"].toObject()["value"].toVariant().toLongLong(); - qlonglong gigabytes = (lbaRead * logicalBlockSize) / 1e9; - int gigabytesInt = static_cast(gigabytes); - if (!gigabytesInt) { - gigabytesInt = static_cast(lbaRead); - } - totalReadsInt = gigabytesInt; + double megabytes = double(lbaRead * logicalBlockSize) / 1e6; + totalMbReadsI64 = static_cast(megabytes); } else if (attrObj["name"] == "Host_Reads_GiB" || attrObj["name"] == "Lifetime_Reads_GiB") { double gibibytes = attrObj["raw"].toObject()["value"].toDouble(); double bytesPerGiB = static_cast(1ULL << 30); - double bytesPerGB = 1e9; - double conversionFactor = bytesPerGiB / bytesPerGB; - double gigabytes = gibibytes * conversionFactor; - totalReadsInt = static_cast(gigabytes); + double bytesPerMB = 1e6; + double conversionFactor = bytesPerGiB / bytesPerMB; + double megabytes = gibibytes * conversionFactor; + totalMbReadsI64 = static_cast(megabytes); } } else if (attrObj["id"] == 246) { // MX500 if (attrObj["name"] == "Total_LBAs_Written") { - int logicalBlockSize = localObj["logical_block_size"].toInt(); qlonglong lbaWritten = attrObj["raw"].toObject()["value"].toVariant().toLongLong(); - qlonglong gigabytes = (lbaWritten * logicalBlockSize) / 1e9; - totalWritesInt = static_cast(gigabytes); + double megabytes = double(lbaWritten * logicalBlockSize) / 1e6; + totalMbWritesI64 = static_cast(megabytes); } } else if (attrObj["name"] == "Remaining_Lifetime_Perc") { int percentageUsed = attrObj["raw"].toObject()["value"].toInt(); @@ -682,14 +669,15 @@ void MainWindow::populateWindow(const QJsonObject &localObj, const QString &heal for (auto smartItem = nvmeLog.begin(); smartItem != nvmeLog.end(); ++smartItem) { QString key = smartItem.key(); QJsonValue value = smartItem.value(); + // it appears that NVME drives report data_units as logical_block_size*1000 bytes if (key == "data_units_written") { double dataUnitsWritten = value.toDouble(); - double gigabytes = (dataUnitsWritten * 512) / 1'000'000; - totalWritesInt = static_cast(gigabytes); + double megabytes = (dataUnitsWritten * logicalBlockSize) / 1000; + totalMbWritesI64 = static_cast(megabytes); } else if (key == "data_units_read") { double dataUnitsRead = value.toDouble(); - double gigabytes = (dataUnitsRead * 512) / 1'000'000; - totalReadsInt = static_cast(gigabytes); + double megabytes = (dataUnitsRead * logicalBlockSize) / 1000; + totalMbReadsI64 = static_cast(megabytes); } else if (key == "percentage_used") { int percentageUsed = 100 - value.toInt(); percentage = QString::number(percentageUsed) + " %"; @@ -697,25 +685,8 @@ void MainWindow::populateWindow(const QJsonObject &localObj, const QString &heal } } - if (totalReadsInt) { - if (totalReadsInt < 1000 || useGB) { - totalReads = QString::number(totalReadsInt) + " " + gbSymbol; - } else { - totalReads = QString::number(totalReadsInt/1000.0, 'f', 1) + " " + tbSymbol; - } - } else { - totalReads = "----"; - } - - if (totalWritesInt) { - if (totalWritesInt < 1000 || useGB) { - totalWrites = QString::number(totalWritesInt) + " " + gbSymbol; - } else { - totalWrites = QString::number(totalWritesInt/1000.0, 'f', 1) + " " + tbSymbol; - } - } else { - totalWrites = "----"; - } + totalReads = getMbToPrettyString(totalMbReadsI64, 1, useGB); + totalWrites = getMbToPrettyString(totalMbWritesI64, 1, useGB); totalReadsLineEdit->setText(totalReads); totalReadsLineEdit->setAlignment(Qt::AlignRight); @@ -1480,3 +1451,18 @@ void MainWindow::on_actionSave_Image_triggered() screenshot.save(QFileDialog::getSaveFileName(this, tr("Save Image"), "QDiskInfo_" + deviceNodeLineEdit->text().section('/', -1) + ".png", tr("PNG Files (*.png)"))); } +QString MainWindow::getMbToPrettyString(const int64_t &sizeInMbI64, const int &precisionInt, const bool &useGbBool) +{ + if (!sizeInMbI64) + return "----"; + + int precision = precisionInt ? (useGbBool ? 1 : precisionInt) : 0; + double sizeInMB = double(sizeInMbI64); + if (sizeInMbI64 < 1000) + return QString::number(sizeInMbI64) + " " + mbSymbol; + else if (sizeInMbI64 < 1000000 || useGbBool) + return QString::number(sizeInMB/1e3, 'f', precision) + " " + gbSymbol; + else if (sizeInMbI64 < 1000000000) + return QString::number(sizeInMB/1e6, 'f', precision) + " " + tbSymbol; + return QString::number(sizeInMB/1e9, 'f', precision) + " " + pbSymbol; +}