File indexing completed on 2024-04-21 05:31:42

0001 /*
0002  * SPDX-FileCopyrightText: 2021 Arjen Hiemstra <ahiemstra@heimr.nl>
0003  *
0004  * SPDX-License-Identifier: LGPL-2.0-or-later
0005  */
0006 
0007 #include "SensorUnitModel.h"
0008 
0009 #include <optional>
0010 #include <array>
0011 
0012 #include <QScopeGuard>
0013 
0014 #include "formatter/Formatter.h"
0015 #include "formatter/Unit.h"
0016 #include "systemstats/SensorInfo.h"
0017     
0018 #include "SensorDaemonInterface_p.h"
0019 
0020 using namespace KSysGuard;
0021 
0022 struct UnitInfo {
0023     Unit unit = UnitNone;
0024     QString symbol;
0025     qreal multiplier;
0026 };
0027 
0028 class Q_DECL_HIDDEN SensorUnitModel::Private
0029 {
0030 public:
0031     bool insertUnits(const std::array<Unit, 6> &from, Unit start);
0032 
0033     QStringList requestedSensors;
0034     QSet<QString> processedSensors;
0035     QMap<Unit, UnitInfo> units;
0036 };
0037 
0038 SensorUnitModel::SensorUnitModel(QObject *parent)
0039     : QAbstractListModel(parent)
0040     , d(new Private)
0041 {
0042     connect(SensorDaemonInterface::instance(), &SensorDaemonInterface::metaDataChanged, this, &SensorUnitModel::metaDataChanged);
0043 }
0044 
0045 SensorUnitModel::~SensorUnitModel() = default;
0046 
0047 QStringList SensorUnitModel::sensors() const
0048 {
0049     return d->requestedSensors;
0050 }
0051 
0052 void SensorUnitModel::setSensors(const QStringList &newSensors)
0053 {
0054     if (newSensors == d->requestedSensors) {
0055         return;
0056     }
0057 
0058     beginResetModel();
0059 
0060     d->requestedSensors = newSensors;
0061     d->processedSensors.clear();
0062     d->units.clear();
0063 
0064     endResetModel();
0065 
0066     if (d->requestedSensors.size() > 0) {
0067         SensorDaemonInterface::instance()->requestMetaData(d->requestedSensors);
0068     }
0069 
0070     Q_EMIT sensorsChanged();
0071     Q_EMIT readyChanged();
0072 }
0073 
0074 bool SensorUnitModel::ready() const
0075 {
0076     return d->requestedSensors.size() == d->processedSensors.size();
0077 }
0078 
0079 QHash<int, QByteArray> SensorUnitModel::roleNames() const
0080 {
0081     static const QHash<int, QByteArray> roleNames = {
0082         {UnitRole, "unit"},
0083         {SymbolRole, "symbol"},
0084         {MultiplierRole, "multiplier"},
0085     };
0086     return roleNames;
0087 }
0088 
0089 int SensorUnitModel::rowCount(const QModelIndex &parent) const
0090 {
0091     if (parent.isValid()) {
0092         return 0;
0093     }
0094 
0095     return d->units.size();
0096 }
0097 
0098 QVariant SensorUnitModel::data(const QModelIndex &index, int role) const
0099 {
0100     if (!checkIndex(index, CheckIndexOption::IndexIsValid | CheckIndexOption::DoNotUseParent)) {
0101         return QVariant{};
0102     }
0103 
0104     auto itr = d->units.begin() + index.row();
0105     auto entry = itr.value();
0106 
0107     switch (role) {
0108     case UnitRole:
0109         return entry.unit;
0110     case SymbolRole:
0111         return entry.symbol;
0112     case MultiplierRole:
0113         return entry.multiplier;
0114     }
0115 
0116     return QVariant{};
0117 }
0118 
0119 void SensorUnitModel::metaDataChanged(const QString &id, const SensorInfo &info)
0120 {
0121     if (!d->requestedSensors.contains(id) || d->processedSensors.contains(id)) {
0122         return;
0123     }
0124 
0125     d->processedSensors.insert(id);
0126 
0127     auto unit = info.unit;
0128     if (unit == UnitInvalid || unit == UnitNone) {
0129         return;
0130     }
0131 
0132     beginResetModel();
0133 
0134     auto guard = qScopeGuard([this, &id]() {
0135         endResetModel();
0136         d->processedSensors.insert(id);
0137         Q_EMIT readyChanged();
0138     });
0139 
0140     static const std::array<Unit, 6> bytes = {
0141         UnitByte,
0142         UnitKiloByte,
0143         UnitMegaByte,
0144         UnitGigaByte,
0145         UnitTeraByte,
0146         UnitPetaByte,
0147     };
0148     if (d->insertUnits(bytes, unit)) {
0149         return;
0150     }
0151 
0152     static const std::array<Unit, 6> rates = {
0153         UnitByteRate,
0154         UnitKiloByteRate,
0155         UnitMegaByteRate,
0156         UnitGigaByteRate,
0157         UnitTeraByteRate,
0158         UnitPetaByteRate,
0159     };
0160     if (d->insertUnits(rates, unit)) {
0161         return;
0162     }
0163 
0164     static const std::array<Unit, 6> frequencies = {
0165         UnitHertz,
0166         UnitKiloHertz,
0167         UnitMegaHertz,
0168         UnitGigaHertz,
0169         UnitTeraHertz,
0170         UnitPetaHertz,
0171     };
0172     if (d->insertUnits(frequencies, unit)) {
0173         return;
0174     }
0175 
0176     UnitInfo unitInfo;
0177     unitInfo.unit = unit;
0178     unitInfo.symbol = Formatter::symbol(unit);
0179     unitInfo.multiplier = 1.0;
0180 
0181     d->units.insert(unit, unitInfo);
0182 }
0183 
0184 bool SensorUnitModel::Private::insertUnits(const std::array<Unit, 6> &from, Unit start)
0185 {
0186     auto itr = std::find(from.begin(), from.end(), start);
0187     if (itr == from.end()) {
0188         return false;
0189     }
0190 
0191     auto baseUnit = from.at(0);
0192 
0193     for (; itr != from.end(); ++itr) {
0194         UnitInfo info;
0195         info.unit = *itr;
0196         info.symbol = Formatter::symbol(*itr);
0197         info.multiplier = Formatter::scaleDownFactor(1.0, start, static_cast<MetricPrefix>((*itr) - baseUnit));
0198         units.insert(*itr, info);
0199     }
0200 
0201     return true;
0202 }