File indexing completed on 2024-05-05 05:34:25

0001 /*
0002     SPDX-FileCopyrightText: 2019 Vlad Zahorodnii <vlad.zahorodnii@kde.org>
0003 
0004     formatBootTimestamp is based on TimeUtil class:
0005     SPDX-FileCopyrightText: 2014 Gregor Mi <codestruct@posteo.org>
0006 
0007     SPDX-License-Identifier: LGPL-2.0-or-later
0008 */
0009 
0010 #include "Formatter.h"
0011 
0012 #include <KFormat>
0013 #include <KLocalizedString>
0014 
0015 #include <QFontMetrics>
0016 #include <QLocale>
0017 #include <QTime>
0018 
0019 #include <cmath>
0020 #include <ctime>
0021 
0022 #include <time.h>
0023 #include <unistd.h>
0024 
0025 #include "formatter_debug.h"
0026 
0027 namespace KSysGuard
0028 {
0029 // TODO: Is there a bit nicer way to handle formatting?
0030 
0031 static KLocalizedString unitFormat(Unit unit)
0032 {
0033     const static KLocalizedString B = ki18nc("Bytes unit symbol", "%1 B");
0034     const static KLocalizedString KiB = ki18nc("Kilobytes unit symbol", "%1 KiB");
0035     const static KLocalizedString MiB = ki18nc("Megabytes unit symbol", "%1 MiB");
0036     const static KLocalizedString GiB = ki18nc("Gigabytes unit symbol", "%1 GiB");
0037     const static KLocalizedString TiB = ki18nc("Terabytes unit symbol", "%1 TiB");
0038     const static KLocalizedString PiB = ki18nc("Petabytes unit symbol", "%1 PiB");
0039 
0040     const static KLocalizedString bps = ki18nc("Bytes per second unit symbol", "%1 B/s");
0041     const static KLocalizedString Kbps = ki18nc("Kilobytes per second unit symbol", "%1 KiB/s");
0042     const static KLocalizedString Mbps = ki18nc("Megabytes per second unit symbol", "%1 MiB/s");
0043     const static KLocalizedString Gbps = ki18nc("Gigabytes per second unit symbol", "%1 GiB/s");
0044     const static KLocalizedString Tbps = ki18nc("Terabytes per second unit symbol", "%1 TiB/s");
0045     const static KLocalizedString Pbps = ki18nc("Petabytes per second unit symbol", "%1 PiB/s");
0046 
0047     const static KLocalizedString bitsps = ki18nc("Bits per second unit symbol", "%1 bps");
0048     const static KLocalizedString Kbitsps = ki18nc("Kilobits per second unit symbol", "%1 Kbps");
0049     const static KLocalizedString Mbitsps = ki18nc("Megabits per second unit symbol", "%1 Mbps");
0050     const static KLocalizedString Gbitsps = ki18nc("Gigabits per second unit symbol", "%1 Gbps");
0051     const static KLocalizedString Tbitsps = ki18nc("Terabits per second unit symbol", "%1 Tbps");
0052     const static KLocalizedString Pbitsps = ki18nc("Petabits per second unit symbol", "%1 Pbps");
0053 
0054     const static KLocalizedString Hz = ki18nc("Hertz unit symbol", "%1 Hz");
0055     const static KLocalizedString kHz = ki18nc("Kilohertz unit symbol", "%1 kHz");
0056     const static KLocalizedString MHz = ki18nc("Megahertz unit symbol", "%1 MHz");
0057     const static KLocalizedString GHz = ki18nc("Gigahertz unit symbol", "%1 GHz");
0058     const static KLocalizedString THz = ki18nc("Terahertz unit symbol", "%1 THz");
0059     const static KLocalizedString PHz = ki18nc("Petahertz unit symbol", "%1 PHz");
0060 
0061     const static KLocalizedString V = ki18nc("Volts unit symbol", "%1 V");
0062     const static KLocalizedString kV = ki18nc("Kilovolts unit symbol", "%1 kV");
0063     const static KLocalizedString MV = ki18nc("Megavolts unit symbol", "%1 MV");
0064     const static KLocalizedString GV = ki18nc("Gigavolts unit symbol", "%1 GV");
0065     const static KLocalizedString TV = ki18nc("Teravolts unit symbol", "%1 TV");
0066     const static KLocalizedString PV = ki18nc("Petavolts unit symbol", "%1 PV");
0067 
0068     const static KLocalizedString W = ki18nc("Watts unit symbol", "%1 W");
0069     const static KLocalizedString kW = ki18nc("Kilowatts unit symbol", "%1 kW");
0070     const static KLocalizedString MW = ki18nc("Megawatts unit symbol", "%1 MW");
0071     const static KLocalizedString GW = ki18nc("Gigawatts unit symbol", "%1 GW");
0072     const static KLocalizedString TW = ki18nc("Terawatts unit symbol", "%1 TW");
0073     const static KLocalizedString PW = ki18nc("Petawatts unit symbol", "%1 PW");
0074 
0075     const static KLocalizedString Wh = ki18nc("Watt-hours unit symbol", "%1 Wh");
0076     const static KLocalizedString kWh = ki18nc("Kilowatt-hours unit symbol", "%1 kWh");
0077     const static KLocalizedString MWh = ki18nc("Megawatt-hours unit symbol", "%1 MWh");
0078     const static KLocalizedString GWh = ki18nc("Gigawatt-hours unit symbol", "%1 GWh");
0079     const static KLocalizedString TWh = ki18nc("Terawatt-hours unit symbol", "%1 TWh");
0080     const static KLocalizedString PWh = ki18nc("Petawatt-hours unit symbol", "%1 PWh");
0081 
0082     const static KLocalizedString A = ki18nc("Ampere unit symbol", "%1 A");
0083     const static KLocalizedString kA = ki18nc("Kiloamperes unit symbol", "%1 kA");
0084     const static KLocalizedString MA = ki18nc("Megaamperes unit symbol", "%1 MA");
0085     const static KLocalizedString GA = ki18nc("Gigaamperes unit symbol", "%1 GA");
0086     const static KLocalizedString TA = ki18nc("Teraamperes unit symbol", "%1 TA");
0087     const static KLocalizedString PA = ki18nc("Petaamperes unit symbol", "%1 PA");
0088 
0089     const static KLocalizedString percent = ki18nc("Percent unit", "%1%");
0090     const static KLocalizedString RPM = ki18nc("Revolutions per minute unit symbol", "%1 RPM");
0091     const static KLocalizedString C = ki18nc("Celsius unit symbol", "%1°C");
0092     const static KLocalizedString dBm = ki18nc("Decibels unit symbol", "%1 dBm");
0093     const static KLocalizedString s = ki18nc("Seconds unit symbol", "%1s");
0094     const static KLocalizedString rate = ki18nc("Rate unit symbol", "%1 s⁻¹");
0095     const static KLocalizedString unitless = ki18nc("Unitless", "%1");
0096 
0097     switch (unit) {
0098     case UnitByte:
0099         return B;
0100     case UnitKiloByte:
0101         return KiB;
0102     case UnitMegaByte:
0103         return MiB;
0104     case UnitGigaByte:
0105         return GiB;
0106     case UnitTeraByte:
0107         return TiB;
0108     case UnitPetaByte:
0109         return PiB;
0110 
0111     case UnitByteRate:
0112         return bps;
0113     case UnitKiloByteRate:
0114         return Kbps;
0115     case UnitMegaByteRate:
0116         return Mbps;
0117     case UnitGigaByteRate:
0118         return Gbps;
0119     case UnitTeraByteRate:
0120         return Tbps;
0121     case UnitPetaByteRate:
0122         return Pbps;
0123 
0124     case UnitBitRate:
0125         return bitsps;
0126     case UnitKiloBitRate:
0127         return Kbitsps;
0128     case UnitMegaBitRate:
0129         return Mbitsps;
0130     case UnitGigaBitRate:
0131         return Gbitsps;
0132     case UnitTeraBitRate:
0133         return Tbitsps;
0134     case UnitPetaBitRate:
0135         return Pbitsps;
0136 
0137     case UnitHertz:
0138         return Hz;
0139     case UnitKiloHertz:
0140         return kHz;
0141     case UnitMegaHertz:
0142         return MHz;
0143     case UnitGigaHertz:
0144         return GHz;
0145     case UnitTeraHertz:
0146         return THz;
0147     case UnitPetaHertz:
0148         return PHz;
0149 
0150     case UnitVolt:
0151         return V;
0152     case UnitKiloVolt:
0153         return kV;
0154     case UnitMegaVolt:
0155         return MV;
0156     case UnitGigaVolt:
0157         return GV;
0158     case UnitTeraVolt:
0159         return TV;
0160     case UnitPetaVolt:
0161         return PV;
0162 
0163     case UnitWatt:
0164         return W;
0165     case UnitKiloWatt:
0166         return kW;
0167     case UnitMegaWatt:
0168         return MW;
0169     case UnitGigaWatt:
0170         return GW;
0171     case UnitTeraWatt:
0172         return TW;
0173     case UnitPetaWatt:
0174         return PV;
0175 
0176     case UnitWattHour:
0177         return Wh;
0178     case UnitKiloWattHour:
0179         return kWh;
0180     case UnitMegaWattHour:
0181         return MWh;
0182     case UnitGigaWattHour:
0183         return GWh;
0184     case UnitTeraWattHour:
0185         return TWh;
0186     case UnitPetaWattHour:
0187         return PWh;
0188 
0189     case UnitAmpere:
0190         return A;
0191     case UnitKiloAmpere:
0192         return kA;
0193     case UnitMegaAmpere:
0194         return MA;
0195     case UnitGigaAmpere:
0196         return GA;
0197     case UnitTeraAmpere:
0198         return TA;
0199     case UnitPetaAmpere:
0200         return PA;
0201 
0202     case UnitCelsius:
0203         return C;
0204     case UnitDecibelMilliWatts:
0205         return dBm;
0206     case UnitPercent:
0207         return percent;
0208     case UnitRate:
0209         return rate;
0210     case UnitRpm:
0211         return RPM;
0212     case UnitSecond:
0213         return s;
0214 
0215     default:
0216         return unitless;
0217     }
0218 }
0219 
0220 static int unitOrder(Unit unit)
0221 {
0222     switch (unit) {
0223     case UnitByte:
0224     case UnitKiloByte:
0225     case UnitMegaByte:
0226     case UnitGigaByte:
0227     case UnitTeraByte:
0228     case UnitPetaByte:
0229     case UnitByteRate:
0230     case UnitKiloByteRate:
0231     case UnitMegaByteRate:
0232     case UnitGigaByteRate:
0233     case UnitTeraByteRate:
0234     case UnitPetaByteRate:
0235     case UnitBitRate:
0236     case UnitKiloBitRate:
0237     case UnitMegaBitRate:
0238     case UnitGigaBitRate:
0239     case UnitTeraBitRate:
0240     case UnitPetaBitRate:
0241         return 1024;
0242 
0243     case UnitHertz:
0244     case UnitKiloHertz:
0245     case UnitMegaHertz:
0246     case UnitGigaHertz:
0247     case UnitTeraHertz:
0248     case UnitPetaHertz:
0249 
0250     case UnitWatt:
0251     case UnitKiloWatt:
0252     case UnitMegaWatt:
0253     case UnitGigaWatt:
0254     case UnitTeraWatt:
0255     case UnitPetaWatt:
0256 
0257     case UnitWattHour:
0258     case UnitKiloWattHour:
0259     case UnitMegaWattHour:
0260     case UnitGigaWattHour:
0261     case UnitTeraWattHour:
0262     case UnitPetaWattHour:
0263 
0264     case UnitAmpere:
0265     case UnitKiloAmpere:
0266     case UnitMegaAmpere:
0267     case UnitGigaAmpere:
0268     case UnitTeraAmpere:
0269     case UnitPetaAmpere:
0270 
0271     case UnitVolt:
0272     case UnitKiloVolt:
0273     case UnitMegaVolt:
0274     case UnitGigaVolt:
0275     case UnitTeraVolt:
0276     case UnitPetaVolt:
0277         return 1000;
0278 
0279     default:
0280         return 0;
0281     }
0282 }
0283 
0284 static Unit unitBase(Unit unit)
0285 {
0286     switch (unit) {
0287     case UnitByte:
0288     case UnitKiloByte:
0289     case UnitMegaByte:
0290     case UnitGigaByte:
0291     case UnitTeraByte:
0292     case UnitPetaByte:
0293         return UnitByte;
0294 
0295     case UnitByteRate:
0296     case UnitKiloByteRate:
0297     case UnitMegaByteRate:
0298     case UnitGigaByteRate:
0299     case UnitTeraByteRate:
0300     case UnitPetaByteRate:
0301         return UnitByteRate;
0302 
0303     case UnitBitRate:
0304     case UnitKiloBitRate:
0305     case UnitMegaBitRate:
0306     case UnitGigaBitRate:
0307     case UnitTeraBitRate:
0308     case UnitPetaBitRate:
0309         return UnitBitRate;
0310 
0311     case UnitHertz:
0312     case UnitKiloHertz:
0313     case UnitMegaHertz:
0314     case UnitGigaHertz:
0315     case UnitTeraHertz:
0316     case UnitPetaHertz:
0317         return UnitHertz;
0318 
0319     case UnitVolt:
0320     case UnitKiloVolt:
0321     case UnitMegaVolt:
0322     case UnitGigaVolt:
0323     case UnitTeraVolt:
0324     case UnitPetaVolt:
0325         return UnitVolt;
0326 
0327     case UnitWatt:
0328     case UnitKiloWatt:
0329     case UnitMegaWatt:
0330     case UnitGigaWatt:
0331     case UnitTeraWatt:
0332     case UnitPetaWatt:
0333         return UnitWatt;
0334 
0335     case UnitWattHour:
0336     case UnitKiloWattHour:
0337     case UnitMegaWattHour:
0338     case UnitGigaWattHour:
0339     case UnitTeraWattHour:
0340     case UnitPetaWattHour:
0341         return UnitWattHour;
0342 
0343     case UnitAmpere:
0344     case UnitKiloAmpere:
0345     case UnitMegaAmpere:
0346     case UnitGigaAmpere:
0347     case UnitTeraAmpere:
0348     case UnitPetaAmpere:
0349         return UnitAmpere;
0350 
0351     default:
0352         return unit;
0353     }
0354 }
0355 
0356 static Unit adjustedUnit(qreal value, Unit unit, MetricPrefix prefix)
0357 {
0358     const int order = unitOrder(unit);
0359     if (!order) {
0360         return unit;
0361     }
0362 
0363     const Unit baseUnit = unitBase(unit);
0364     const MetricPrefix basePrefix = MetricPrefix(unit - baseUnit);
0365 
0366     if (prefix == MetricPrefixAutoAdjust) {
0367         const qreal absoluteValue = value * std::pow(order, int(basePrefix));
0368         if (absoluteValue > 0) {
0369             const int targetPrefix = std::log2(absoluteValue) / std::log2(order);
0370             if (targetPrefix <= MetricPrefixLast) {
0371                 prefix = MetricPrefix(targetPrefix);
0372             }
0373         }
0374         if (prefix == MetricPrefixAutoAdjust) {
0375             prefix = basePrefix;
0376         }
0377     }
0378 
0379     const Unit newUnit = Unit(prefix + baseUnit);
0380     // If there is no prefixed unit,
0381     // don't overflow into the following unrelated units.
0382     if (unitBase(newUnit) != baseUnit) {
0383         return unit;
0384     }
0385 
0386     return newUnit;
0387 }
0388 
0389 static QString formatNumber(const QVariant &value, Unit unit, MetricPrefix prefix, FormatOptions options)
0390 {
0391     qreal amount = value.toDouble();
0392 
0393     if (!options.testFlag(FormatOptionShowNull) && (qFuzzyIsNull(amount) || qIsNaN(amount))) {
0394         return QString();
0395     }
0396 
0397     const Unit adjusted = adjustedUnit(amount, unit, prefix);
0398     if (adjusted != unit) {
0399         amount /= std::pow(unitOrder(unit), adjusted - unit);
0400     }
0401 
0402     const int precision = (value.type() != QVariant::Double && adjusted <= unit) ? 0 : 1;
0403     const QString text = QLocale().toString(amount, 'f', precision);
0404 
0405     return unitFormat(adjusted).subs(text).toString();
0406 }
0407 
0408 static QString formatTime(const QVariant &value)
0409 {
0410     return KFormat().formatDuration(value.toLongLong() * 1000);
0411 }
0412 
0413 static QString formatTicks(const QVariant &value)
0414 {
0415     auto seconds = value.toLongLong() / sysconf(_SC_CLK_TCK);
0416     return KFormat().formatDuration(seconds * 1000);
0417 }
0418 
0419 static QString formatBootTimestamp(const QVariant &value)
0420 {
0421     timespec tp;
0422 #ifdef Q_OS_LINUX
0423     clock_gettime(CLOCK_BOOTTIME, &tp);
0424 #else
0425     clock_gettime(CLOCK_MONOTONIC, &tp);
0426 #endif
0427 
0428     const QDateTime systemBootTime = QDateTime::currentDateTime().addSecs(-tp.tv_sec);
0429 
0430     const qreal secondsSinceSystemBoot = value.toReal() / sysconf(_SC_CLK_TCK);
0431     const QDateTime absoluteTimeSinceBoot = systemBootTime.addSecs(secondsSinceSystemBoot);
0432 
0433     return KFormat().formatRelativeDateTime(absoluteTimeSinceBoot, QLocale::ShortFormat);
0434 }
0435 
0436 qreal Formatter::scaleDownFactor(const QVariant &value, Unit unit, MetricPrefix targetPrefix)
0437 {
0438     const Unit adjusted = adjustedUnit(value.toDouble(), unit, targetPrefix);
0439     if (adjusted == unit) {
0440         return 1;
0441     }
0442 
0443     return std::pow(unitOrder(unit), adjusted - unit);
0444 }
0445 
0446 KLocalizedString Formatter::localizedString(const QVariant &value, Unit unit, MetricPrefix targetPrefix)
0447 {
0448     const Unit adjusted = adjustedUnit(value.toDouble(), unit, targetPrefix);
0449     return unitFormat(adjusted);
0450 }
0451 
0452 QString Formatter::formatValue(const QVariant &value, Unit unit, MetricPrefix targetPrefix, FormatOptions options)
0453 {
0454     switch (unit) {
0455     case UnitByte:
0456     case UnitKiloByte:
0457     case UnitMegaByte:
0458     case UnitGigaByte:
0459     case UnitTeraByte:
0460     case UnitPetaByte:
0461     case UnitByteRate:
0462     case UnitKiloByteRate:
0463     case UnitMegaByteRate:
0464     case UnitGigaByteRate:
0465     case UnitTeraByteRate:
0466     case UnitPetaByteRate:
0467     case UnitBitRate:
0468     case UnitKiloBitRate:
0469     case UnitMegaBitRate:
0470     case UnitGigaBitRate:
0471     case UnitTeraBitRate:
0472     case UnitPetaBitRate:
0473     case UnitHertz:
0474     case UnitKiloHertz:
0475     case UnitMegaHertz:
0476     case UnitGigaHertz:
0477     case UnitTeraHertz:
0478     case UnitPetaHertz:
0479     case UnitVolt:
0480     case UnitKiloVolt:
0481     case UnitMegaVolt:
0482     case UnitGigaVolt:
0483     case UnitTeraVolt:
0484     case UnitPetaVolt:
0485     case UnitWatt:
0486     case UnitKiloWatt:
0487     case UnitMegaWatt:
0488     case UnitGigaWatt:
0489     case UnitTeraWatt:
0490     case UnitPetaWatt:
0491     case UnitWattHour:
0492     case UnitKiloWattHour:
0493     case UnitMegaWattHour:
0494     case UnitGigaWattHour:
0495     case UnitTeraWattHour:
0496     case UnitPetaWattHour:
0497     case UnitAmpere:
0498     case UnitKiloAmpere:
0499     case UnitMegaAmpere:
0500     case UnitGigaAmpere:
0501     case UnitTeraAmpere:
0502     case UnitPetaAmpere:
0503     case UnitSecond:
0504     case UnitPercent:
0505     case UnitRate:
0506     case UnitRpm:
0507     case UnitCelsius:
0508     case UnitDecibelMilliWatts:
0509         return formatNumber(value, unit, targetPrefix, options);
0510 
0511     case UnitBootTimestamp:
0512         return formatBootTimestamp(value);
0513     case UnitTime:
0514         return formatTime(value);
0515     case UnitNone:
0516         return formatNumber(value, unit, MetricPrefix::MetricPrefixUnity, options);
0517     case UnitTicks:
0518         return formatTicks(value);
0519 
0520     default:
0521         return value.toString();
0522     }
0523 }
0524 
0525 QString Formatter::symbol(Unit unit)
0526 {
0527     // TODO: Is it possible to avoid duplication of these symbols?
0528     switch (unit) {
0529     case UnitByte:
0530         return i18nc("Bytes unit symbol", "B");
0531     case UnitKiloByte:
0532         return i18nc("Kilobytes unit symbol", "KiB");
0533     case UnitMegaByte:
0534         return i18nc("Megabytes unit symbol", "MiB");
0535     case UnitGigaByte:
0536         return i18nc("Gigabytes unit symbol", "GiB");
0537     case UnitTeraByte:
0538         return i18nc("Terabytes unit symbol", "TiB");
0539     case UnitPetaByte:
0540         return i18nc("Petabytes unit symbol", "PiB");
0541 
0542     case UnitByteRate:
0543         return i18nc("Bytes per second unit symbol", "B/s");
0544     case UnitKiloByteRate:
0545         return i18nc("Kilobytes per second unit symbol", "KiB/s");
0546     case UnitMegaByteRate:
0547         return i18nc("Megabytes per second unit symbol", "MiB/s");
0548     case UnitGigaByteRate:
0549         return i18nc("Gigabytes per second unit symbol", "GiB/s");
0550     case UnitTeraByteRate:
0551         return i18nc("Terabytes per second unit symbol", "TiB/s");
0552     case UnitPetaByteRate:
0553         return i18nc("Petabytes per second unit symbol", "PiB/s");
0554 
0555     case UnitBitRate:
0556         return i18nc("Bits per second unit symbol", "bps");
0557     case UnitKiloBitRate:
0558         return i18nc("Kilobits per second unit symbol", "Kbps");
0559     case UnitMegaBitRate:
0560         return i18nc("Megabits per second unit symbol", "Mbps");
0561     case UnitGigaBitRate:
0562         return i18nc("Gigabits per second unit symbol", "Gbps");
0563     case UnitTeraBitRate:
0564         return i18nc("Terabits per second unit symbol", "Tbps");
0565     case UnitPetaBitRate:
0566         return i18nc("Petabits per second unit symbol", "Pbps");
0567 
0568     case UnitHertz:
0569         return i18nc("Hertz unit symbol", "Hz");
0570     case UnitKiloHertz:
0571         return i18nc("Kilohertz unit symbol", "kHz");
0572     case UnitMegaHertz:
0573         return i18nc("Megahertz unit symbol", "MHz");
0574     case UnitGigaHertz:
0575         return i18nc("Gigahertz unit symbol", "GHz");
0576     case UnitTeraHertz:
0577         return i18nc("Terahertz unit symbol", "THz");
0578     case UnitPetaHertz:
0579         return i18nc("Petahertz unit symbol", "PHz");
0580 
0581     case UnitVolt:
0582         return i18nc("Volts unit symbol", "V");
0583     case UnitKiloVolt:
0584         return i18nc("Kilovolts unit symbol", "kV");
0585     case UnitMegaVolt:
0586         return i18nc("Megavolts unit symbol", "MV");
0587     case UnitGigaVolt:
0588         return i18nc("Gigavolts unit symbol", "GV");
0589     case UnitTeraVolt:
0590         return i18nc("Teravolts unit symbol", "TV");
0591     case UnitPetaVolt:
0592         return i18nc("Petavolts unit symbol", "PV");
0593 
0594     case UnitWatt:
0595         return i18nc("Watts unit symbol", "W");
0596     case UnitKiloWatt:
0597         return i18nc("Kilowatts unit symbol", "kW");
0598     case UnitMegaWatt:
0599         return i18nc("Megawatts unit symbol", "MW");
0600     case UnitGigaWatt:
0601         return i18nc("Gigawatts unit symbol", "GW");
0602     case UnitTeraWatt:
0603         return i18nc("Terawatts unit symbol", "TW");
0604     case UnitPetaWatt:
0605         return i18nc("Petawatts unit symbol", "PW");
0606 
0607     case UnitWattHour:
0608         return i18nc("Watt-hours unit symbol", "Wh");
0609     case UnitKiloWattHour:
0610         return i18nc("Kilo-watthours unit symbol", "kWh");
0611     case UnitMegaWattHour:
0612         return i18nc("Mega-watthours unit symbol", "MWh");
0613     case UnitGigaWattHour:
0614         return i18nc("Giga-watthours unit symbol", "GWh");
0615     case UnitTeraWattHour:
0616         return i18nc("Tera-watthours unit symbol", "TWh");
0617     case UnitPetaWattHour:
0618         return i18nc("Peta-watthours unit symbol", "PWh");
0619 
0620     case UnitAmpere:
0621         return i18nc("Ampere unit symbol", "A");
0622     case UnitKiloAmpere:
0623         return i18nc("Kiloamperes unit symbol", "kA");
0624     case UnitMegaAmpere:
0625         return i18nc("Megaamperes unit symbol", "MA");
0626     case UnitGigaAmpere:
0627         return i18nc("Gigaamperes unit symbol", "GA");
0628     case UnitTeraAmpere:
0629         return i18nc("Teraamperes unit symbol", "TA");
0630     case UnitPetaAmpere:
0631         return i18nc("Petaamperes unit symbol", "PA");
0632 
0633     case UnitPercent:
0634         return i18nc("Percent unit", "%");
0635     case UnitRpm:
0636         return i18nc("Revolutions per minute unit symbol", "RPM");
0637     case UnitCelsius:
0638         return i18nc("Celsius unit symbol", "°C");
0639     case UnitDecibelMilliWatts:
0640         return i18nc("Decibels unit symbol", "dBm");
0641     case UnitSecond:
0642         return i18nc("Seconds unit symbol", "s");
0643 
0644     case UnitRate:
0645         return i18nc("Rate unit symbol", "s⁻¹");
0646 
0647     default:
0648         return QString();
0649     }
0650 }
0651 
0652 qreal Formatter::maximumLength(Unit unit, const QFont &font)
0653 {
0654     auto order = unitOrder(unit);
0655 
0656     QString maximum;
0657     switch (unitBase(unit)) {
0658     case UnitByte:
0659         maximum = formatValue(order - 0.5, UnitMegaByte, MetricPrefixMega);
0660         break;
0661     case UnitByteRate:
0662         maximum = formatValue(order - 0.5, UnitMegaByteRate, MetricPrefixMega);
0663         break;
0664     case UnitBitRate:
0665         maximum = formatValue(order - 0.5, UnitMegaBitRate, MetricPrefixMega);
0666         break;
0667     case UnitHertz:
0668         maximum = formatValue(order - 0.5, UnitMegaHertz, MetricPrefixMega);
0669         break;
0670     case UnitPercent:
0671         maximum = formatValue(9999.9, UnitPercent);
0672         break;
0673     default:
0674         return -1.0;
0675     }
0676 
0677     auto metrics = QFontMetrics{font};
0678     return metrics.horizontalAdvance(maximum);
0679 }
0680 
0681 } // namespace KSysGuard