Solid

frontend/devicemanager.cpp
1 /*
2  SPDX-FileCopyrightText: 2005-2007 Kevin Ottens <[email protected]>
3 
4  SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
5 */
6 
7 #include "devicenotifier.h"
8 #include "devicemanager_p.h" //krazy:exclude=includes (devicenotifier.h is the header file for this class)
9 
10 #include "device.h"
11 #include "device_p.h"
12 #include "predicate.h"
13 
14 #include "ifaces/devicemanager.h"
15 #include "ifaces/device.h"
16 
17 #include "soliddefs_p.h"
18 
19 Q_GLOBAL_STATIC(Solid::DeviceManagerStorage, globalDeviceStorage)
20 
21 Solid::DeviceManagerPrivate::DeviceManagerPrivate()
22  : m_nullDevice(new DevicePrivate(QString()))
23 {
24  loadBackends();
25 
26  const QList<QObject *> backends = managerBackends();
27  for (QObject *backend : backends) {
28  connect(backend, SIGNAL(deviceAdded(QString)),
29  this, SLOT(_k_deviceAdded(QString)));
30  connect(backend, SIGNAL(deviceRemoved(QString)),
31  this, SLOT(_k_deviceRemoved(QString)));
32  }
33 }
34 
35 Solid::DeviceManagerPrivate::~DeviceManagerPrivate()
36 {
37  const QList<QObject *> backends = managerBackends();
38  for (QObject *backend : backends) {
39  disconnect(backend, nullptr, this, nullptr);
40  }
41 
42  // take a copy as m_devicesMap is changed by Solid::DeviceManagerPrivate::_k_destroyed
43  const auto deviceMap = m_devicesMap;
44  for (QPointer<DevicePrivate> dev : deviceMap) {
45  if (!dev.data()->ref.deref()) {
46  delete dev.data();
47  }
48  }
49 
50  m_devicesMap.clear();
51 }
52 
54 {
55  QList<Device> list;
56  const QList<QObject *> backends = globalDeviceStorage->managerBackends();
57 
58  for (QObject *backendObj : backends) {
59  Ifaces::DeviceManager *backend = qobject_cast<Ifaces::DeviceManager *>(backendObj);
60 
61  if (backend == nullptr) {
62  continue;
63  }
64 
65  const QStringList udis = backend->allDevices();
66  for (const QString &udi : udis) {
67  list.append(Device(udi));
68  }
69  }
70 
71  return list;
72 }
73 
75  const QString &parentUdi)
76 {
77  Predicate p = Predicate::fromString(predicate);
78 
79  if (p.isValid()) {
80  return listFromQuery(p, parentUdi);
81  } else {
82  return QList<Device>();
83  }
84 }
85 
87  const QString &parentUdi)
88 {
89  QList<Device> list;
90  const QList<QObject *> backends = globalDeviceStorage->managerBackends();
91 
92  for (QObject *backendObj : backends) {
93  Ifaces::DeviceManager *backend = qobject_cast<Ifaces::DeviceManager *>(backendObj);
94 
95  if (backend == nullptr) {
96  continue;
97  }
98  if (!backend->supportedInterfaces().contains(type)) {
99  continue;
100  }
101 
102  const QStringList udis = backend->devicesFromQuery(parentUdi, type);
103  for (const QString &udi : udis) {
104  list.append(Device(udi));
105  }
106  }
107 
108  return list;
109 }
110 
112  const QString &parentUdi)
113 {
114  QList<Device> list;
115  const QSet<DeviceInterface::Type> usedTypes = predicate.usedTypes();
116  const QList<QObject *> backends = globalDeviceStorage->managerBackends();
117  for (QObject *backendObj : backends) {
118  Ifaces::DeviceManager *backend = qobject_cast<Ifaces::DeviceManager *>(backendObj);
119 
120  if (backend == nullptr) {
121  continue;
122  }
123 
124  QStringList udis;
125  if (predicate.isValid()) {
126  QSet<DeviceInterface::Type> supportedTypes = backend->supportedInterfaces();
127  if (supportedTypes.intersect(usedTypes).isEmpty()) {
128  continue;
129  }
130 
131  QList<DeviceInterface::Type> sortedTypes = supportedTypes.values();
132  std::sort(sortedTypes.begin(), sortedTypes.end());
133  for (DeviceInterface::Type type : qAsConst(sortedTypes)) {
134  udis += backend->devicesFromQuery(parentUdi, type);
135  }
136  } else {
137  udis += backend->allDevices();
138  }
139 
140  QSet<QString> seen;
141  for (const QString &udi : qAsConst(udis)) {
142  if (seen.contains(udi)) {
143  continue;
144  }
145  seen.insert(udi);
146  Device dev(udi);
147 
148  bool matches = false;
149 
150  if (!predicate.isValid()) {
151  matches = true;
152  } else {
153  matches = predicate.matches(dev);
154  }
155 
156  if (matches) {
157  list.append(dev);
158  }
159  }
160  }
161 
162  return list;
163 }
164 
165 Solid::DeviceNotifier *Solid::DeviceNotifier::instance()
166 {
167  return globalDeviceStorage->notifier();
168 }
169 
170 void Solid::DeviceManagerPrivate::_k_deviceAdded(const QString &udi)
171 {
172  if (m_devicesMap.contains(udi)) {
173  DevicePrivate *dev = m_devicesMap[udi].data();
174 
175  // Ok, this one was requested somewhere was invalid
176  // and now becomes magically valid!
177 
178  if (dev && dev->backendObject() == nullptr) {
179  dev->setBackendObject(createBackendObject(udi));
180  Q_ASSERT(dev->backendObject() != nullptr);
181  }
182  }
183 
184  emit deviceAdded(udi);
185 }
186 
187 void Solid::DeviceManagerPrivate::_k_deviceRemoved(const QString &udi)
188 {
189  if (m_devicesMap.contains(udi)) {
190  DevicePrivate *dev = m_devicesMap[udi].data();
191 
192  // Ok, this one was requested somewhere was valid
193  // and now becomes magically invalid!
194 
195  if (dev) {
196  Q_ASSERT(dev->backendObject() != nullptr);
197  dev->setBackendObject(nullptr);
198  Q_ASSERT(dev->backendObject() == nullptr);
199  }
200  }
201 
202  emit deviceRemoved(udi);
203 }
204 
205 void Solid::DeviceManagerPrivate::_k_destroyed(QObject *object)
206 {
207  QString udi = m_reverseMap.take(object);
208 
209  if (!udi.isEmpty()) {
210  m_devicesMap.remove(udi);
211  }
212 }
213 
214 Solid::DevicePrivate *Solid::DeviceManagerPrivate::findRegisteredDevice(const QString &udi)
215 {
216  if (udi.isEmpty()) {
217  return m_nullDevice.data();
218  } else if (m_devicesMap.contains(udi)) {
219  return m_devicesMap[udi].data();
220  } else {
221  Ifaces::Device *iface = createBackendObject(udi);
222 
223  DevicePrivate *devData = new DevicePrivate(udi);
224  devData->setBackendObject(iface);
225 
226  QPointer<DevicePrivate> ptr(devData);
227  m_devicesMap[udi] = ptr;
228  m_reverseMap[devData] = udi;
229 
230  connect(devData, SIGNAL(destroyed(QObject*)),
231  this, SLOT(_k_destroyed(QObject*)));
232 
233  return devData;
234  }
235 }
236 
237 Solid::Ifaces::Device *Solid::DeviceManagerPrivate::createBackendObject(const QString &udi)
238 {
239  const QList<QObject *> backends = globalDeviceStorage->managerBackends();
240 
241  for (QObject *backendObj : backends) {
242  Ifaces::DeviceManager *backend = qobject_cast<Ifaces::DeviceManager *>(backendObj);
243 
244  if (backend == nullptr) {
245  continue;
246  }
247  if (!udi.startsWith(backend->udiPrefix())) {
248  continue;
249  }
250 
251  Ifaces::Device *iface = nullptr;
252 
253  QObject *object = backend->createDevice(udi);
254  iface = qobject_cast<Ifaces::Device *>(object);
255 
256  if (iface == nullptr) {
257  delete object;
258  }
259 
260  return iface;
261  }
262 
263  return nullptr;
264 }
265 
266 Solid::DeviceManagerStorage::DeviceManagerStorage()
267 {
268 
269 }
270 
271 QList<QObject *> Solid::DeviceManagerStorage::managerBackends()
272 {
273  ensureManagerCreated();
274  return m_storage.localData()->managerBackends();
275 }
276 
277 Solid::DeviceNotifier *Solid::DeviceManagerStorage::notifier()
278 {
279  ensureManagerCreated();
280  return m_storage.localData();
281 }
282 
283 void Solid::DeviceManagerStorage::ensureManagerCreated()
284 {
285  if (!m_storage.hasLocalData()) {
286  m_storage.setLocalData(new DeviceManagerPrivate());
287  }
288 }
289 
290 #include "moc_devicemanager_p.cpp"
291 #include "moc_devicenotifier.cpp"
292 
This class allows applications to deal with devices available in the underlying system.
This class specifies the interface a backend will have to implement in order to be used in the system...
Definition: devicemanager.h:28
QSet< DeviceInterface::Type > usedTypes() const
Retrieves the device interface types used in this predicate.
Definition: predicate.cpp:221
bool matches(const Device &device) const
Checks if a device matches the predicate.
Definition: predicate.cpp:169
QSet::iterator insert(const T &value)
QString & remove(int position, int n)
Type
This enum type defines the type of device interface that a Device can have.
void append(const T &value)
QList< T > values() const const
static QList< Device > listFromQuery(const Predicate &predicate, const QString &parentUdi=QString())
Retrieves a list of devices of the system given matching the given constraints (parent and predicate)...
bool isEmpty() const const
bool startsWith(const QString &s, Qt::CaseSensitivity cs) const const
static Predicate fromString(const QString &predicate)
Converts a string to a predicate.
QString udi() const
Retrieves the Universal Device Identifier (UDI).
Device(const QString &udi=QString())
Constructs a device for a given Universal Device Identifier (UDI).
virtual QObject * createDevice(const QString &udi)=0
Instantiates a new Device object from this backend given its UDI.
QList::iterator end()
bool isValid() const
Indicates if the predicate is valid.
Definition: predicate.cpp:164
virtual QSet< Solid::DeviceInterface::Type > supportedInterfaces() const =0
Retrieves a set of interfaces the backend supports.
bool contains(const T &value) const const
static QList< Device > listFromType(const DeviceInterface::Type &type, const QString &parentUdi=QString())
Retrieves a list of devices of the system given matching the given constraints (parent and device int...
static QList< Device > allDevices()
Retrieves all the devices available in the underlying system.
virtual QStringList allDevices()=0
Retrieves the Universal Device Identifier (UDI) of all the devices available in the system...
QSet< T > & intersect(const QSet< T > &other)
This class allow to query the underlying system to obtain information about the hardware available...
This class implements predicates for devices.
Definition: predicate.h:31
virtual QStringList devicesFromQuery(const QString &parentUdi, Solid::DeviceInterface::Type type=Solid::DeviceInterface::Unknown)=0
Retrieves the Universal Device Identifier (UDI) of all the devices matching the given constraints (pa...
The single responsibility of this class is to create arguments valid for logind Inhibit call...
This class specifies the interface a device will have to comply to in order to be used in the system...
Definition: ifaces/device.h:32
virtual QString udiPrefix() const =0
Retrieves the prefix used for the UDIs off all the devices reported by the device manager...
QChar * data()
QList::iterator begin()
QString parentUdi() const
Retrieves the Universal Device Identifier (UDI) of the Device&#39;s parent.
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Fri Jul 10 2020 22:48:12 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.