Solid

upowerdevice.cpp
1/*
2 SPDX-FileCopyrightText: 2010 Michael Zanetti <mzanetti@kde.org>
3 SPDX-FileCopyrightText: 2010 Lukas Tinkl <ltinkl@redhat.com>
4
5 SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
6*/
7
8#include "upowerdevice.h"
9#include "upower.h"
10#include "upowerbattery.h"
11#include "upowerdeviceinterface.h"
12#include "upowergenericinterface.h"
13
14#include <solid/device.h>
15#include <solid/genericinterface.h>
16
17#include <QDBusConnection>
18#include <QDBusReply>
19#include <QStringList>
20
21using namespace Solid::Backends::UPower;
22
23UPowerDevice::UPowerDevice(const QString &udi)
24 : Solid::Ifaces::Device()
25 , m_udi(udi)
26{
27 QDBusConnection::systemBus().connect(QStringLiteral(UP_DBUS_SERVICE),
28 m_udi,
29 QStringLiteral("org.freedesktop.DBus.Properties"),
30 QStringLiteral("PropertiesChanged"),
31 this,
32 SLOT(onPropertiesChanged(QString, QVariantMap, QStringList)));
33
34 // TODO port this to Solid::Power, we can't link against kdelibs4support for this signal
35 // older upower versions not affected
36 QDBusConnection::systemBus().connect(QStringLiteral("org.freedesktop.login1"), //
37 QStringLiteral("/org/freedesktop/login1"),
38 QStringLiteral("org.freedesktop.login1.Manager"),
39 QStringLiteral("PrepareForSleep"),
40 this,
41 SLOT(login1Resuming(bool)));
42}
43
44UPowerDevice::~UPowerDevice()
45{
46}
47
48QObject *UPowerDevice::createDeviceInterface(const Solid::DeviceInterface::Type &type)
49{
50 if (!queryDeviceInterface(type)) {
51 return nullptr;
52 }
53
54 DeviceInterface *iface = nullptr;
55 switch (type) {
56 case Solid::DeviceInterface::GenericInterface:
57 iface = new GenericInterface(this);
58 break;
59 case Solid::DeviceInterface::Battery:
60 iface = new Battery(this);
61 break;
62 default:
63 break;
64 }
65 return iface;
66}
67
68bool UPowerDevice::queryDeviceInterface(const Solid::DeviceInterface::Type &type) const
69{
70 const UpDeviceKind uptype = static_cast<UpDeviceKind>(prop(QStringLiteral("Type")).toUInt());
71 switch (type) {
72 case Solid::DeviceInterface::GenericInterface:
73 return true;
74 case Solid::DeviceInterface::Battery:
75 switch (uptype) {
76 case UP_DEVICE_KIND_BATTERY:
77 case UP_DEVICE_KIND_UPS:
78 case UP_DEVICE_KIND_MOUSE:
79 case UP_DEVICE_KIND_KEYBOARD:
80 case UP_DEVICE_KIND_PDA:
81 case UP_DEVICE_KIND_PHONE:
82 case UP_DEVICE_KIND_TABLET:
83 case UP_DEVICE_KIND_GAMING_INPUT:
84 case UP_DEVICE_KIND_SPEAKERS:
85 case UP_DEVICE_KIND_HEADSET:
86 case UP_DEVICE_KIND_HEADPHONES:
87 case UP_DEVICE_KIND_BLUETOOTH_GENERIC:
88 case UP_DEVICE_KIND_TOUCHPAD:
89 return true;
90 case UP_DEVICE_KIND_UNKNOWN:
91 // There is currently no "Bluetooth battery" type, so check if it comes from Bluez
92 if (prop(QStringLiteral("NativePath")).toString().startsWith(QLatin1String("/org/bluez/"))) {
93 return true;
94 }
95 return false;
96 case UP_DEVICE_KIND_LINE_POWER:
97 case UP_DEVICE_KIND_MONITOR:
98 case UP_DEVICE_KIND_MEDIA_PLAYER:
99 case UP_DEVICE_KIND_COMPUTER:
100 case UP_DEVICE_KIND_LAST:
101 return false;
102 }
103 Q_FALLTHROUGH();
104 default:
105 return false;
106 }
107}
108
109QStringList UPowerDevice::emblems() const
110{
111 return QStringList();
112}
113
114QString UPowerDevice::description() const
115{
116 if (queryDeviceInterface(Solid::DeviceInterface::Battery)) {
117 if (!batteryTechnology().isEmpty()) {
118 return tr("%1 Battery", "%1 is battery technology").arg(batteryTechnology());
119 }
120 }
121 QString result = prop(QStringLiteral("Model")).toString();
122 if (result.isEmpty()) {
123 return vendor();
124 }
125 return result;
126}
127
128QString UPowerDevice::batteryTechnology() const
129{
130 const UpDeviceTechnology tech = static_cast<UpDeviceTechnology>(prop(QStringLiteral("Technology")).toUInt());
131 switch (tech) {
132 case UP_DEVICE_TECHNOLOGY_UNKNOWN:
133 return QString();
134 case UP_DEVICE_TECHNOLOGY_LITHIUM_ION:
135 return tr("Lithium Ion", "battery technology");
136 case UP_DEVICE_TECHNOLOGY_LITHIUM_POLYMER:
137 return tr("Lithium Polymer", "battery technology");
138 case UP_DEVICE_TECHNOLOGY_LITHIUM_IRON_PHOSPHATE:
139 return tr("Lithium Iron Phosphate", "battery technology");
140 case UP_DEVICE_TECHNOLOGY_LEAD_ACID:
141 return tr("Lead Acid", "battery technology");
142 case UP_DEVICE_TECHNOLOGY_NICKEL_CADMIUM:
143 return tr("Nickel Cadmium", "battery technology");
144 case UP_DEVICE_TECHNOLOGY_NICKEL_METAL_HYDRIDE:
145 return tr("Nickel Metal Hydride", "battery technology");
146 case UP_DEVICE_TECHNOLOGY_LAST:
147 return QString();
148 }
149 return QString();
150}
151
152QString UPowerDevice::icon() const
153{
154 if (queryDeviceInterface(Solid::DeviceInterface::Battery)) {
155 return QStringLiteral("battery");
156 } else {
157 return QString();
158 }
159}
160
161QString UPowerDevice::product() const
162{
163 QString result = prop(QStringLiteral("Model")).toString();
164
165 if (result.isEmpty()) {
166 result = description();
167 }
168
169 return result;
170}
171
172QString UPowerDevice::vendor() const
173{
174 return prop(QStringLiteral("Vendor")).toString();
175}
176
177QString UPowerDevice::udi() const
178{
179 return m_udi;
180}
181
182QString UPowerDevice::parentUdi() const
183{
184 return QStringLiteral(UP_UDI_PREFIX);
185}
186
187void UPowerDevice::checkCache(const QString &key) const
188{
189 if (m_cache.contains(key) || m_negativeCache.contains(key)) {
190 return;
191 }
192
193 loadCache();
194
195 if (m_cache.contains(key)) {
196 return;
197 }
198
199 QDBusMessage call =
200 QDBusMessage::createMethodCall(QStringLiteral(UP_DBUS_SERVICE), m_udi, QStringLiteral("org.freedesktop.DBus.Properties"), QStringLiteral("Get"));
201 call.setArguments({QStringLiteral(UP_DBUS_INTERFACE_DEVICE), key});
202 QDBusReply<QVariant> reply = QDBusConnection::systemBus().call(call);
203
204 if (reply.isValid()) {
205 m_cache[key] = reply.value();
206 } else {
207 m_negativeCache.append(key);
208 }
209}
210
211QVariant UPowerDevice::prop(const QString &key) const
212{
213 checkCache(key);
214 return m_cache.value(key);
215}
216
217bool UPowerDevice::propertyExists(const QString &key) const
218{
219 checkCache(key);
220 return m_cache.contains(key);
221}
222
223void UPowerDevice::loadCache() const
224{
225 QDBusMessage call =
226 QDBusMessage::createMethodCall(QStringLiteral(UP_DBUS_SERVICE), m_udi, QStringLiteral("org.freedesktop.DBus.Properties"), QStringLiteral("GetAll"));
227 call.setArguments({QStringLiteral(UP_DBUS_INTERFACE_DEVICE)});
228 QDBusReply<QVariantMap> reply = QDBusConnection::systemBus().call(call);
229
230 if (reply.isValid()) {
231 m_cache = reply.value();
232 m_cacheComplete = true;
233 } else {
234 m_cache.clear();
235 }
236}
237
238QMap<QString, QVariant> UPowerDevice::allProperties() const
239{
240 if (!m_cacheComplete) {
241 loadCache();
242 }
243
244 return m_cache;
245}
246
247void UPowerDevice::onPropertiesChanged(const QString &ifaceName, const QVariantMap &changedProps, const QStringList &invalidatedProps)
248{
249 if (ifaceName != QStringLiteral(UP_DBUS_INTERFACE_DEVICE))
250 return;
251
252 QMap<QString, int> changeMap;
253 for (auto it = changedProps.begin(); it != changedProps.end(); ++it) {
254 m_cache[it.key()] = it.value();
255 m_negativeCache.removeOne(it.key());
256 changeMap.insert(it.key(), Solid::GenericInterface::PropertyModified);
257 }
258 for (const auto &propName : invalidatedProps) {
259 m_cache.remove(propName);
260 m_negativeCache.removeOne(propName);
261 changeMap.insert(propName, Solid::GenericInterface::PropertyModified);
262 m_cacheComplete = false;
263 }
264 Q_EMIT propertyChanged(changeMap);
265}
266
267void UPowerDevice::login1Resuming(bool active)
268{
269 // Nothing to do when going into sleep
270 if (active)
271 return;
272
273 QMap<QString, int> changeMap;
274 for (auto it = m_cache.begin(); it != m_cache.end(); ++it) {
275 if (it.value().isValid()) {
276 changeMap.insert(it.key(), Solid::GenericInterface::PropertyModified);
277 }
278 }
279 m_cache.clear();
280 m_negativeCache.clear();
281 m_cacheComplete = false;
282 Q_EMIT propertyChanged(changeMap);
283}
284
285#include "moc_upowerdevice.cpp"
Type
This enum type defines the type of device interface that a Device can have.
This class allows applications to deal with devices available in the underlying system.
char * toString(const EngineQuery &query)
QDBusMessage call(const QDBusMessage &message, QDBus::CallMode mode, int timeout) const const
bool connect(const QString &service, const QString &path, const QString &interface, const QString &name, QObject *receiver, const char *slot)
QDBusConnection systemBus()
QDBusMessage createMethodCall(const QString &service, const QString &path, const QString &interface, const QString &method)
void setArguments(const QList< QVariant > &arguments)
bool isValid() const const
void clear()
iterator insert(const Key &key, const T &value)
Q_EMITQ_EMIT
QString tr(const char *sourceText, const char *disambiguation, int n)
QString arg(Args &&... args) const const
bool isEmpty() const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2025 The KDE developers.
Generated on Fri Apr 11 2025 11:57:29 by doxygen 1.13.2 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.