File indexing completed on 2024-05-19 05:29:58
0001 /* 0002 * SPDX-FileCopyrightText: 2015 David Edmundson <david@davidedmundson.co.uk> 0003 * 0004 * SPDX-License-Identifier: LGPL-2.1-or-later 0005 * 0006 */ 0007 0008 #include "statisticsprovider.h" 0009 0010 #include <QDBusArgument> 0011 #include <QDBusConnection> 0012 #include <QDBusInterface> 0013 #include <QDBusMessage> 0014 #include <QDBusMetaType> // qDBusRegisterMetaType 0015 #include <QDBusPendingReply> 0016 #include <QDebug> 0017 0018 const QDBusArgument &operator<<(QDBusArgument &argument, const HistoryReply &data) 0019 { 0020 argument.beginStructure(); 0021 argument << data.time << data.value << data.charging; 0022 argument.endStructure(); 0023 return argument; 0024 } 0025 0026 const QDBusArgument &operator>>(const QDBusArgument &arg, HistoryReply &attrs) 0027 { 0028 arg.beginStructure(); 0029 arg >> attrs.time >> attrs.value >> attrs.charging; 0030 arg.endStructure(); 0031 return arg; 0032 } 0033 0034 StatisticsProvider::StatisticsProvider(QObject *parent) 0035 : QObject(parent) 0036 { 0037 m_type = StatisticsProvider::ChargeType; 0038 m_duration = 120; 0039 0040 qDBusRegisterMetaType<HistoryReply>(); 0041 qDBusRegisterMetaType<QList<HistoryReply>>(); 0042 } 0043 0044 void StatisticsProvider::setDevice(const QString &device) 0045 { 0046 if (device == m_device) { 0047 return; 0048 } 0049 0050 m_device = device; 0051 Q_EMIT deviceChanged(); 0052 0053 load(); 0054 } 0055 0056 void StatisticsProvider::setDuration(uint duration) 0057 { 0058 if (duration == m_duration) { 0059 return; 0060 } 0061 0062 m_duration = duration; 0063 Q_EMIT durationChanged(); 0064 0065 load(); 0066 } 0067 0068 void StatisticsProvider::setType(StatisticsProvider::HistoryType type) 0069 { 0070 if (m_type == type) { 0071 return; 0072 } 0073 0074 m_type = type; 0075 Q_EMIT typeChanged(); 0076 0077 load(); 0078 } 0079 0080 void StatisticsProvider::classBegin() 0081 { 0082 } 0083 0084 void StatisticsProvider::componentComplete() 0085 { 0086 m_isComplete = true; 0087 load(); 0088 } 0089 0090 QVariantList StatisticsProvider::asPoints() const 0091 { 0092 QVariantList points; 0093 points.reserve(m_values.count()); 0094 for (const HistoryReply &h : std::as_const(m_values)) { 0095 points.append(QPointF(h.time, h.value)); 0096 } 0097 0098 if (!points.isEmpty()) { 0099 points.takeLast(); 0100 } 0101 0102 return points; 0103 } 0104 0105 int StatisticsProvider::count() const 0106 { 0107 return m_values.count(); 0108 } 0109 0110 int StatisticsProvider::firstDataPointTime() const 0111 { 0112 if (m_values.isEmpty()) { 0113 return 0; 0114 } 0115 0116 return m_values.first().time; 0117 } 0118 0119 int StatisticsProvider::lastDataPointTime() const 0120 { 0121 if (m_values.isEmpty()) { 0122 return 0; 0123 } 0124 0125 return m_values.last().time; 0126 } 0127 0128 int StatisticsProvider::largestValue() const 0129 { 0130 if (m_values.isEmpty()) { 0131 return 0; 0132 } 0133 0134 int max = 0; // TODO std::max or something? 0135 for (auto it = m_values.constBegin(), end = m_values.constEnd(); it != end; ++it) { 0136 if ((*it).value > max) { 0137 max = (*it).value; 0138 } 0139 } 0140 return max; 0141 } 0142 0143 void StatisticsProvider::refresh() 0144 { 0145 load(); 0146 } 0147 0148 void StatisticsProvider::load() 0149 { 0150 if (!m_isComplete || m_device.isEmpty()) { 0151 return; 0152 } 0153 0154 auto msg = QDBusMessage::createMethodCall(QStringLiteral("org.freedesktop.UPower"), 0155 m_device, 0156 QStringLiteral("org.freedesktop.UPower.Device"), 0157 QStringLiteral("GetHistory")); 0158 if (m_type == RateType) { 0159 msg << QLatin1String("rate"); 0160 } else { // m_type must = ChargeType 0161 msg << QLatin1String("charge"); 0162 } 0163 0164 uint resolution = 100; 0165 msg << m_duration << resolution; 0166 0167 QDBusPendingReply<QList<HistoryReply>> reply = QDBusConnection::systemBus().asyncCall(msg); 0168 0169 auto *watcher = new QDBusPendingCallWatcher(reply, this); 0170 QObject::connect(watcher, &QDBusPendingCallWatcher::finished, this, [this](QDBusPendingCallWatcher *watcher) { 0171 QDBusPendingReply<QList<HistoryReply>> reply = *watcher; 0172 watcher->deleteLater(); 0173 m_values.clear(); 0174 0175 if (reply.isError()) { 0176 qWarning() << "Failed to get device history from UPower" << reply.error().message(); 0177 return; 0178 } 0179 0180 const auto replyValue = reply.value(); 0181 for (const HistoryReply &r : replyValue) { 0182 if (r.value > 0) { // we get back some values which contain no value, possibly to indicate if charging changes, ignore them 0183 m_values.prepend(r); 0184 } 0185 } 0186 0187 Q_EMIT dataChanged(); 0188 }); 0189 } 0190 0191 #include "moc_statisticsprovider.cpp"