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(UP_DBUS_SERVICE,
28 m_udi,
29 "org.freedesktop.DBus.Properties",
30 "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("org.freedesktop.login1", //
37 "/org/freedesktop/login1",
38 "org.freedesktop.login1.Manager",
39 "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("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("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 return tr("%1 Battery", "%1 is battery technology").arg(batteryTechnology());
118 } else {
119 QString result = prop("Model").toString();
120 if (result.isEmpty()) {
121 return vendor();
122 }
123 return result;
124 }
125}
126
127QString UPowerDevice::batteryTechnology() const
128{
129 const UpDeviceTechnology tech = static_cast<UpDeviceTechnology>(prop("Technology").toUInt());
130 switch (tech) {
131 case UP_DEVICE_TECHNOLOGY_UNKNOWN:
132 return tr("Unknown", "battery technology");
133 case UP_DEVICE_TECHNOLOGY_LITHIUM_ION:
134 return tr("Lithium Ion", "battery technology");
135 case UP_DEVICE_TECHNOLOGY_LITHIUM_POLYMER:
136 return tr("Lithium Polymer", "battery technology");
137 case UP_DEVICE_TECHNOLOGY_LITHIUM_IRON_PHOSPHATE:
138 return tr("Lithium Iron Phosphate", "battery technology");
139 case UP_DEVICE_TECHNOLOGY_LEAD_ACID:
140 return tr("Lead Acid", "battery technology");
141 case UP_DEVICE_TECHNOLOGY_NICKEL_CADMIUM:
142 return tr("Nickel Cadmium", "battery technology");
143 case UP_DEVICE_TECHNOLOGY_NICKEL_METAL_HYDRIDE:
144 return tr("Nickel Metal Hydride", "battery technology");
145 case UP_DEVICE_TECHNOLOGY_LAST:
146 return tr("Unknown", "battery technology");
147 }
148 return tr("Unknown", "battery technology");
149}
150
151QString UPowerDevice::icon() const
152{
153 if (queryDeviceInterface(Solid::DeviceInterface::Battery)) {
154 return "battery";
155 } else {
156 return QString();
157 }
158}
159
160QString UPowerDevice::product() const
161{
162 QString result = prop("Model").toString();
163
164 if (result.isEmpty()) {
165 result = description();
166 }
167
168 return result;
169}
170
171QString UPowerDevice::vendor() const
172{
173 return prop("Vendor").toString();
174}
175
176QString UPowerDevice::udi() const
177{
178 return m_udi;
179}
180
181QString UPowerDevice::parentUdi() const
182{
183 return UP_UDI_PREFIX;
184}
185
186void UPowerDevice::checkCache(const QString &key) const
187{
188 if (m_cache.contains(key) || m_negativeCache.contains(key)) {
189 return;
190 }
191
192 loadCache();
193
194 if (m_cache.contains(key)) {
195 return;
196 }
197
198 QDBusMessage call = QDBusMessage::createMethodCall(UP_DBUS_SERVICE, m_udi, "org.freedesktop.DBus.Properties", "Get");
199 call.setArguments({UP_DBUS_INTERFACE_DEVICE, key});
201
202 if (reply.isValid()) {
203 m_cache[key] = reply.value();
204 } else {
205 m_negativeCache.append(key);
206 }
207}
208
209QVariant UPowerDevice::prop(const QString &key) const
210{
211 checkCache(key);
212 return m_cache.value(key);
213}
214
215bool UPowerDevice::propertyExists(const QString &key) const
216{
217 checkCache(key);
218 return m_cache.contains(key);
219}
220
221void UPowerDevice::loadCache() const
222{
223 QDBusMessage call = QDBusMessage::createMethodCall(UP_DBUS_SERVICE, m_udi, "org.freedesktop.DBus.Properties", "GetAll");
224 call.setArguments({UP_DBUS_INTERFACE_DEVICE});
226
227 if (reply.isValid()) {
228 m_cache = reply.value();
229 m_cacheComplete = true;
230 } else {
231 m_cache.clear();
232 }
233}
234
235QMap<QString, QVariant> UPowerDevice::allProperties() const
236{
237 if (!m_cacheComplete) {
238 loadCache();
239 }
240
241 return m_cache;
242}
243
244void UPowerDevice::onPropertiesChanged(const QString &ifaceName, const QVariantMap &changedProps, const QStringList &invalidatedProps)
245{
246 if (ifaceName != UP_DBUS_INTERFACE_DEVICE)
247 return;
248
249 QMap<QString, int> changeMap;
250 for (auto it = changedProps.begin(); it != changedProps.end(); ++it) {
251 m_cache[it.key()] = it.value();
252 m_negativeCache.removeOne(it.key());
253 changeMap.insert(it.key(), Solid::GenericInterface::PropertyModified);
254 }
255 for (const auto &propName : invalidatedProps) {
256 m_cache.remove(propName);
257 m_negativeCache.removeOne(propName);
258 changeMap.insert(propName, Solid::GenericInterface::PropertyModified);
259 m_cacheComplete = false;
260 }
261 Q_EMIT propertyChanged(changeMap);
262}
263
264void UPowerDevice::login1Resuming(bool active)
265{
266 // Nothing to do when going into sleep
267 if (active)
268 return;
269
270 QMap<QString, int> changeMap;
271 for (auto it = m_cache.begin(); it != m_cache.end(); ++it) {
272 if (it.value().isValid()) {
273 changeMap.insert(it.key(), Solid::GenericInterface::PropertyModified);
274 }
275 }
276 m_cache.clear();
277 m_negativeCache.clear();
278 m_cacheComplete = false;
279 Q_EMIT propertyChanged(changeMap);
280}
281
282#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.
The single responsibility of this class is to create arguments valid for logind Inhibit call.
Definition fakebattery.h:16
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 append(QList< T > &&value)
void clear()
bool removeOne(const AT &t)
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
bool startsWith(QChar c, Qt::CaseSensitivity cs) const const
bool contains(QLatin1StringView str, Qt::CaseSensitivity cs) const const
QString toString() const const
uint toUInt(bool *ok) const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Tue Mar 26 2024 11:17:12 by doxygen 1.10.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.