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 }