Refine Framework monitoring history and configurable tray telemetry
This commit is contained in:
@@ -0,0 +1,85 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
#include "tooltip.h"
|
||||
#include <cmath>
|
||||
#include <algorithm>
|
||||
|
||||
QVector<TooltipSensor> tooltipSensors(const QVector<Sensor> &sensors)
|
||||
{
|
||||
QVector<TooltipSensor> result{{"cpu", "CPU", {}}, {"memory", "RAM", {}}, {"nvme", "NVMe", {}},
|
||||
{"battery", "Battery", {}}, {"board", "Board", {}}};
|
||||
const QStringList prefixes{"cros_ec/peci-temp", "spd5118/", "nvme/Composite", "cros_ec/battery_temp@b", "cros_ec/local_f75397@4c"};
|
||||
for (int i = 0; i < result.size(); ++i) {
|
||||
for (const auto &sensor : sensors) if (sensor.id.startsWith(prefixes[i])) { result[i].id = sensor.id; break; }
|
||||
if (i == 0 && result[i].id.isEmpty())
|
||||
for (const auto &sensor : sensors) if (sensor.id.startsWith("coretemp/Package id")) { result[i].id = sensor.id; break; }
|
||||
}
|
||||
return result;
|
||||
}
|
||||
bool tooltipEnabled(const QVariantMap &settings, const QString &key)
|
||||
{
|
||||
return settings.value("tray/hover/" + key, true).toBool();
|
||||
}
|
||||
int tooltipAppCount(const QVariantMap &settings)
|
||||
{
|
||||
return std::clamp(settings.value("tray/hover/topApps", settings.value("tray/hover/topApp", false).toBool() ? 1 : 0).toInt(), 0, 3);
|
||||
}
|
||||
QString batteryTooltip(const QVariantMap &battery, int limit, const QVariantMap &upower)
|
||||
{
|
||||
if (battery.isEmpty()) return "Battery unavailable";
|
||||
QString text = "Battery " + (battery.contains("capacity") ? QString::number(battery["capacity"].toInt()) + "%" : "—");
|
||||
const auto energy = [&](const QString &key) {
|
||||
const double value = battery.value(key, NAN).toDouble();
|
||||
if (!std::isfinite(value) || value < 0) return QString("—");
|
||||
QString number = QString::number(qRound64(value));
|
||||
for (int i = number.size() - 3; i > 0; i -= 3) number.insert(i, ' ');
|
||||
return number;
|
||||
};
|
||||
text += " · " + energy("remainingMWh") + " mWh / " + energy("fullMWh") + " mWh";
|
||||
const auto watts = batteryRate(battery);
|
||||
text += "\n\u2003" + (watts ? (*watts > 0 ? "+" : "") + QString::number(*watts, 'f', 1) + " W" : "— W");
|
||||
const bool charging = battery["state"] == "Charging", discharging = battery["state"] == "Discharging";
|
||||
double seconds = 0;
|
||||
bool approximate = false;
|
||||
if (discharging) seconds = upower.value("TimeToEmpty").toDouble();
|
||||
else if (charging && limit == 100) seconds = upower.value("TimeToFull").toDouble();
|
||||
else if (charging && limit < 100) {
|
||||
approximate = true;
|
||||
if (battery["current_now"].toDouble() > 0 && battery.contains("charge_now") && battery["charge_full"].toDouble() > 0)
|
||||
seconds = (battery["charge_full"].toDouble() * limit / 100 - battery["charge_now"].toDouble()) / battery["current_now"].toDouble() * 3600;
|
||||
else if (watts && *watts > 0 && battery.contains("energy_now") && battery["energy_full"].toDouble() > 0)
|
||||
seconds = (battery["energy_full"].toDouble() * limit / 100 - battery["energy_now"].toDouble()) / (*watts * 1e6) * 3600;
|
||||
}
|
||||
if (std::isfinite(seconds) && seconds > 0) {
|
||||
const auto minutes = qint64(std::ceil(seconds / 60));
|
||||
text += QString(" · %1%2 h %3 min to %4%").arg(approximate ? "≈" : "")
|
||||
.arg(minutes / 60).arg(minutes % 60).arg(discharging ? 0 : limit);
|
||||
} else if (charging && battery.contains("capacity") && battery["capacity"].toInt() >= limit)
|
||||
text += QString(" · %1% limit reached").arg(limit);
|
||||
else if (charging || discharging) text += " · Time remaining unavailable";
|
||||
else text += " · " + battery["state"].toString();
|
||||
return text;
|
||||
}
|
||||
QString trayTooltip(const QVariantMap &settings, const QMap<QString, double> &values,
|
||||
const QVector<TooltipSensor> &temperatures, const QString &battery, const QStringList &topApps)
|
||||
{
|
||||
const auto reading = [&](const QString &id, int decimals) {
|
||||
const auto it = values.constFind(id);
|
||||
return it != values.cend() && std::isfinite(*it) ? QString::number(*it, 'f', decimals) : QString("—");
|
||||
};
|
||||
QStringList lines;
|
||||
if (tooltipEnabled(settings, "cpu")) {
|
||||
lines << "CPU usage: " + reading("cpu-usage", 1) + " %";
|
||||
const int count = tooltipAppCount(settings);
|
||||
if (count && topApps.isEmpty()) lines << "\u2003CPU app readings unavailable";
|
||||
for (int i = 0; i < std::min(count, int(topApps.size())); ++i) lines << "\u2003" + topApps[i];
|
||||
}
|
||||
if (tooltipEnabled(settings, "battery")) lines << battery;
|
||||
if (tooltipEnabled(settings, "fan")) lines << "Fan speed: " + reading("fan", 0) + " RPM (" + reading("fan-duty", 0) + " %)";
|
||||
QStringList temps;
|
||||
for (const auto &sensor : temperatures)
|
||||
if (!sensor.id.isEmpty() && tooltipEnabled(settings, "temperature/" + sensor.key))
|
||||
temps << sensor.name + " " + reading(sensor.id, 0) + "°C";
|
||||
if (temps.size() > 1) lines << "Temperatures:";
|
||||
for (const auto &temp : temps) lines << (temps.size() > 1 ? "\u2003" : "") + temp;
|
||||
return lines.join('\n');
|
||||
}
|
||||
Reference in New Issue
Block a user