Libksysguard

Formatter.cpp
1 /*
2  Copyright (C) 2019 Vlad Zahorodnii <[email protected]>
3 
4  formatBootTimestamp is based on TimeUtil class:
5  Copyright (C) 2014 Gregor Mi <[email protected]>
6 
7  This library is free software; you can redistribute it and/or
8  modify it under the terms of the GNU Library General Public
9  License as published by the Free Software Foundation; either
10  version 2 of the License, or (at your option) any later version.
11 
12  This library is distributed in the hope that it will be useful,
13  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  Library General Public License for more details.
16 
17  You should have received a copy of the GNU Library General Public License
18  along with this library; see the file COPYING.LIB. If not, write to
19  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20  Boston, MA 02110-1301, USA.
21 */
22 
23 #include "Formatter.h"
24 
25 #include <KLocalizedString>
26 
27 #include <QLocale>
28 #include <QTime>
29 
30 #include <cmath>
31 
32 #ifdef Q_OS_OSX
33 #include <mach/clock.h>
34 #include <mach/mach.h>
35 #else
36 #include <ctime>
37 #endif
38 
39 #include <unistd.h>
40 
41 #include "formatter_debug.h"
42 
43 namespace KSysGuard
44 {
45 
46 // TODO: Is there a bit nicer way to handle formatting?
47 
48 static KLocalizedString unitFormat(Unit unit)
49 {
50  const static KLocalizedString B = ki18nc("Bytes unit symbol", "%1 B");
51  const static KLocalizedString KiB = ki18nc("Kilobytes unit symbol", "%1 KiB");
52  const static KLocalizedString MiB = ki18nc("Megabytes unit symbol", "%1 MiB");
53  const static KLocalizedString GiB = ki18nc("Gigabytes unit symbol", "%1 GiB");
54  const static KLocalizedString TiB = ki18nc("Terabytes unit symbol", "%1 TiB");
55  const static KLocalizedString PiB = ki18nc("Petabytes unit symbol", "%1 PiB");
56 
57  const static KLocalizedString bps = ki18nc("Bytes per second unit symbol", "%1 B/s");
58  const static KLocalizedString Kbps = ki18nc("Kilobytes per second unit symbol", "%1 KiB/s");
59  const static KLocalizedString Mbps = ki18nc("Megabytes per second unit symbol", "%1 MiB/s");
60  const static KLocalizedString Gbps = ki18nc("Gigabytes per second unit symbol", "%1 GiB/s");
61  const static KLocalizedString Tbps = ki18nc("Gigabytes per second unit symbol", "%1 TiB/s");
62  const static KLocalizedString Pbps = ki18nc("Gigabytes per second unit symbol", "%1 PiB/s");
63 
64  const static KLocalizedString Hz = ki18nc("Hertz unit symbol", "%1 Hz");
65  const static KLocalizedString kHz = ki18nc("Kilohertz unit symbol", "%1 kHz");
66  const static KLocalizedString MHz = ki18nc("Megahertz unit symbol", "%1 MHz");
67  const static KLocalizedString GHz = ki18nc("Gigahertz unit symbol", "%1 GHz");
68  const static KLocalizedString THz = ki18nc("Terahertz unit symbol", "%1 THz");
69  const static KLocalizedString PHz = ki18nc("Petahertz unit symbol", "%1 PHz");
70 
71  const static KLocalizedString percent = ki18nc("Percent unit", "%1%");
72  const static KLocalizedString RPM = ki18nc("Revolutions per minute unit symbol", "%1 RPM");
73  const static KLocalizedString C = ki18nc("Celsius unit symbol", "%1°C");
74  const static KLocalizedString dBm = ki18nc("Decibels unit symbol", "%1 dBm");
75  const static KLocalizedString s = ki18nc("Seconds unit symbol", "%1s");
76  const static KLocalizedString V = ki18nc("Volts unit symbol", "%1 V");
77  const static KLocalizedString W = ki18nc("Watts unit symbol", "%1 W");
78  const static KLocalizedString Wh = ki18nc("Watt-hours unit symbol", "%1 Wh");
79  const static KLocalizedString rate = ki18nc("Rate unit symbol", "%1 s⁻¹");
80  const static KLocalizedString A = ki18nc("Ampere unit symbol", "%1 A");
81  const static KLocalizedString unitless = ki18nc("Unitless", "%1");
82 
83  switch (unit) {
84  case UnitByte:
85  return B;
86  case UnitKiloByte:
87  return KiB;
88  case UnitMegaByte:
89  return MiB;
90  case UnitGigaByte:
91  return GiB;
92  case UnitTeraByte:
93  return TiB;
94  case UnitPetaByte:
95  return PiB;
96 
97  case UnitByteRate:
98  return bps;
99  case UnitKiloByteRate:
100  return Kbps;
101  case UnitMegaByteRate:
102  return Mbps;
103  case UnitGigaByteRate:
104  return Gbps;
105  case UnitTeraByteRate:
106  return Tbps;
107  case UnitPetaByteRate:
108  return Pbps;
109 
110  case UnitHertz:
111  return Hz;
112  case UnitKiloHertz:
113  return kHz;
114  case UnitMegaHertz:
115  return MHz;
116  case UnitGigaHertz:
117  return GHz;
118  case UnitTeraHertz:
119  return THz;
120  case UnitPetaHertz:
121  return PHz;
122 
123  case UnitCelsius:
124  return C;
125  case UnitDecibelMilliWatts:
126  return dBm;
127  case UnitPercent:
128  return percent;
129  case UnitRate:
130  return rate;
131  case UnitRpm:
132  return RPM;
133  case UnitSecond:
134  return s;
135  case UnitVolt:
136  return V;
137  case UnitWatt:
138  return W;
139  case UnitWattHour:
140  return Wh;
141  case UnitAmpere:
142  return A;
143 
144  default:
145  return unitless;
146  }
147 }
148 
149 static int unitOrder(Unit unit)
150 {
151  switch (unit) {
152  case UnitByte:
153  case UnitKiloByte:
154  case UnitMegaByte:
155  case UnitGigaByte:
156  case UnitTeraByte:
157  case UnitPetaByte:
158  case UnitByteRate:
159  case UnitKiloByteRate:
160  case UnitMegaByteRate:
161  case UnitGigaByteRate:
162  case UnitTeraByteRate:
163  case UnitPetaByteRate:
164  return 1024;
165 
166  case UnitHertz:
167  case UnitKiloHertz:
168  case UnitMegaHertz:
169  case UnitGigaHertz:
170  case UnitTeraHertz:
171  case UnitPetaHertz:
172  case UnitWatt:
173  case UnitWattHour:
174  case UnitAmpere:
175  return 1000;
176 
177  default:
178  return 0;
179  }
180 }
181 
182 static Unit unitBase(Unit unit)
183 {
184  switch (unit) {
185  case UnitByte:
186  case UnitKiloByte:
187  case UnitMegaByte:
188  case UnitGigaByte:
189  case UnitTeraByte:
190  case UnitPetaByte:
191  return UnitByte;
192 
193  case UnitByteRate:
194  case UnitKiloByteRate:
195  case UnitMegaByteRate:
196  case UnitGigaByteRate:
197  case UnitTeraByteRate:
198  case UnitPetaByteRate:
199  return UnitByteRate;
200 
201  case UnitHertz:
202  case UnitKiloHertz:
203  case UnitMegaHertz:
204  case UnitGigaHertz:
205  case UnitTeraHertz:
206  case UnitPetaHertz:
207  return UnitHertz;
208 
209  default:
210  return unit;
211  }
212 }
213 
214 static Unit adjustedUnit(qreal value, Unit unit, MetricPrefix prefix)
215 {
216  const int order = unitOrder(unit);
217  if (!order) {
218  return unit;
219  }
220 
221  const Unit baseUnit = unitBase(unit);
222  const MetricPrefix basePrefix = MetricPrefix(unit - baseUnit);
223 
224  if (prefix == MetricPrefixAutoAdjust) {
225  const qreal absoluteValue = value * std::pow(order, int(basePrefix));
226  if (absoluteValue > 0) {
227  const int targetPrefix = std::log2(absoluteValue) / std::log2(order);
228  if (targetPrefix <= MetricPrefixLast) {
229  prefix = MetricPrefix(targetPrefix);
230  }
231  }
232  if (prefix == MetricPrefixAutoAdjust) {
233  prefix = basePrefix;
234  }
235  }
236 
237  return Unit(prefix + baseUnit);
238 }
239 
240 static QString formatNumber(const QVariant &value, Unit unit, MetricPrefix prefix, FormatOptions options)
241 {
242  qreal amount = value.toDouble();
243 
244  if (!options.testFlag(FormatOptionShowNull) && (qFuzzyIsNull(amount) || qIsNaN(amount))) {
245  return QString();
246  }
247 
248  const Unit adjusted = adjustedUnit(amount, unit, prefix);
249  if (adjusted != unit) {
250  amount /= std::pow(unitOrder(unit), adjusted - unit);
251  }
252 
253  const int precision = (value.type() != QVariant::Double && adjusted <= unit) ? 0 : 1;
254  const QString text = QLocale().toString(amount, 'f', precision);
255 
256  return unitFormat(adjusted).subs(text).toString();
257 }
258 
259 static QString formatTime(const QVariant &value)
260 {
261  const qlonglong seconds = value.toLongLong();
262 
263  const QString minutesString = QString::number(seconds / 60);
264  const QString secondsScring = QStringLiteral("%1").arg(seconds % 60, 2, 10, QLatin1Char('0'));
265 
266  return minutesString + QLatin1Char(':') + secondsScring;
267 }
268 
269 qreal Formatter::scaleDownFactor(const QVariant &value, Unit unit, MetricPrefix targetPrefix)
270 {
271  const Unit adjusted = adjustedUnit(value.toDouble(), unit, targetPrefix);
272  if (adjusted == unit) {
273  return 1;
274  }
275 
276  return std::pow(unitOrder(unit), adjusted - unit);
277 }
278 
279 KLocalizedString Formatter::localizedString(const QVariant &value, Unit unit, MetricPrefix targetPrefix)
280 {
281  const Unit adjusted = adjustedUnit(value.toDouble(), unit, targetPrefix);
282  return unitFormat(adjusted);
283 }
284 
285 QString Formatter::formatValue(const QVariant &value, Unit unit, MetricPrefix targetPrefix, FormatOptions options)
286 {
287  switch (unit) {
288  case UnitByte:
289  case UnitKiloByte:
290  case UnitMegaByte:
291  case UnitGigaByte:
292  case UnitTeraByte:
293  case UnitPetaByte:
294  case UnitByteRate:
295  case UnitKiloByteRate:
296  case UnitMegaByteRate:
297  case UnitGigaByteRate:
298  case UnitTeraByteRate:
299  case UnitPetaByteRate:
300  case UnitHertz:
301  case UnitKiloHertz:
302  case UnitMegaHertz:
303  case UnitGigaHertz:
304  case UnitTeraHertz:
305  case UnitPetaHertz:
306  case UnitPercent:
307  case UnitRate:
308  case UnitRpm:
309  case UnitCelsius:
310  case UnitDecibelMilliWatts:
311  case UnitVolt:
312  case UnitWatt:
313  case UnitSecond:
314  case UnitAmpere:
315  return formatNumber(value, unit, targetPrefix, options);
316 
317  case UnitBootTimestamp:
318  qCWarning(FORMATTER) << "UnitBootTimestamp is deprecated and is not formatted anymore";
319  return value.toString();
320  case UnitTime:
321  return formatTime(value);
322 
323  default:
324  return value.toString();
325  }
326 }
327 
329 {
330  // TODO: Is it possible to avoid duplication of these symbols?
331  switch (unit) {
332  case UnitByte:
333  return i18nc("Bytes unit symbol", "B");
334  case UnitKiloByte:
335  return i18nc("Kilobytes unit symbol", "KiB");
336  case UnitMegaByte:
337  return i18nc("Megabytes unit symbol", "MiB");
338  case UnitGigaByte:
339  return i18nc("Gigabytes unit symbol", "GiB");
340  case UnitTeraByte:
341  return i18nc("Terabytes unit symbol", "TiB");
342  case UnitPetaByte:
343  return i18nc("Petabytes unit symbol", "PiB");
344 
345  case UnitByteRate:
346  return i18nc("Bytes per second unit symbol", "B/s");
347  case UnitKiloByteRate:
348  return i18nc("Kilobytes per second unit symbol", "KiB/s");
349  case UnitMegaByteRate:
350  return i18nc("Megabytes per second unit symbol", "MiB/s");
351  case UnitGigaByteRate:
352  return i18nc("Gigabytes per second unit symbol", "GiB/s");
353  case UnitTeraByteRate:
354  return i18nc("Gigabytes per second unit symbol", "TiB/s");
355  case UnitPetaByteRate:
356  return i18nc("Gigabytes per second unit symbol", "PiB/s");
357 
358  case UnitHertz:
359  return i18nc("Hertz unit symbol", "Hz");
360  case UnitKiloHertz:
361  return i18nc("Kilohertz unit symbol", "kHz");
362  case UnitMegaHertz:
363  return i18nc("Megahertz unit symbol", "MHz");
364  case UnitGigaHertz:
365  return i18nc("Gigahertz unit symbol", "GHz");
366  case UnitTeraHertz:
367  return i18nc("Terahertz unit symbol", "THz");
368  case UnitPetaHertz:
369  return i18nc("Petahertz unit symbol", "PHz");
370 
371  case UnitPercent:
372  return i18nc("Percent unit", "%");
373  case UnitRpm:
374  return i18nc("Revolutions per minute unit symbol", "RPM");
375  case UnitCelsius:
376  return i18nc("Celsius unit symbol", "°C");
377  case UnitDecibelMilliWatts:
378  return i18nc("Decibels unit symbol", "dBm");
379  case UnitSecond:
380  return i18nc("Seconds unit symbol", "s");
381  case UnitVolt:
382  return i18nc("Volts unit symbol", "V");
383  case UnitWatt:
384  return i18nc("Watts unit symbol", "W");
385  case UnitWattHour:
386  return i18nc("Watt-hours unit symbol", "Wh");
387  case UnitRate:
388  return i18nc("Rate unit symbol", "s⁻¹");
389  case UnitAmpere:
390  return i18nc("Ampere unit symbol", "A");
391 
392  default:
393  return QString();
394  }
395 }
396 
397 } // namespace KSysGuard
qlonglong toLongLong(bool *ok) const const
QString toString() const
QString toString(qlonglong i) const const
static KLocalizedString localizedString(const QVariant &value, Unit unit, MetricPrefix targetPrefix=MetricPrefixAutoAdjust)
Returns localized string that is suitable for display.
Definition: Formatter.cpp:279
static QString symbol(Unit unit)
Returns a symbol that corresponds to the given unit.
Definition: Formatter.cpp:328
static QString formatValue(const QVariant &value, Unit unit, MetricPrefix targetPrefix=MetricPrefixAutoAdjust, FormatOptions options=FormatOptionNone)
Converts value to the appropriate displayable string.
Definition: Formatter.cpp:285
KLocalizedString subs(int a, int fieldWidth=0, int base=10, QChar fillChar=QLatin1Char(' ')) const
QString number(int n, int base)
QString i18nc(const char *context, const char *text, const TYPE &arg...)
KLocalizedString KI18N_EXPORT ki18nc(const char *context, const char *text)
static qreal scaleDownFactor(const QVariant &value, Unit unit, MetricPrefix targetPrefix=MetricPrefixAutoAdjust)
Returns the scale factor suitable for display.
Definition: Formatter.cpp:269
QString arg(qlonglong a, int fieldWidth, int base, QChar fillChar) const const
double toDouble(bool *ok) const const
QVariant::Type type() const const
QString toString() const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2021 The KDE developers.
Generated on Thu Mar 4 2021 23:09:25 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.