Plasma5Support

soliddeviceengine.cpp
1/*
2 SPDX-FileCopyrightText: 2007 Christopher Blauvelt <cblauvelt@gmail.com>
3
4 SPDX-License-Identifier: LGPL-2.0-only
5*/
6
7#include "soliddeviceengine.h"
8#include "soliddeviceservice.h"
9
10#include <KLazyLocalizedString>
11#include <QDateTime>
12#include <QMetaEnum>
13#include <Solid/GenericInterface>
14#include <klocalizedstring.h>
15
16#include <KFormat>
17#include <KNotification>
18#include <QDebug>
19
20#include <Plasma5Support/DataContainer>
21
22// TODO: implement in libsolid2
23namespace
24{
25template<class DevIface>
26DevIface *getAncestorAs(const Solid::Device &device)
27{
28 for (Solid::Device parent = device.parent(); parent.isValid(); parent = parent.parent()) {
29 if (parent.is<DevIface>()) {
30 return parent.as<DevIface>();
31 }
32 }
33 return nullptr;
34}
35}
36
37SolidDeviceEngine::SolidDeviceEngine(QObject *parent)
38 : Plasma5Support::DataEngine(parent)
39 , m_temperature(nullptr)
40 , m_notifier(nullptr)
41{
42 m_signalmanager = new DeviceSignalMapManager(this);
43
44 listenForNewDevices();
45 setMinimumPollingInterval(1000);
46 connect(this, &Plasma5Support::DataEngine::sourceRemoved, this, &SolidDeviceEngine::sourceWasRemoved);
47}
48
49SolidDeviceEngine::~SolidDeviceEngine()
50{
51}
52
54{
55 return new SolidDeviceService(this, source);
56}
57
58void SolidDeviceEngine::listenForNewDevices()
59{
60 if (m_notifier) {
61 return;
62 }
63
64 // detect when new devices are added
65 m_notifier = Solid::DeviceNotifier::instance();
66 connect(m_notifier, &Solid::DeviceNotifier::deviceAdded, this, &SolidDeviceEngine::deviceAdded);
67 connect(m_notifier, &Solid::DeviceNotifier::deviceRemoved, this, &SolidDeviceEngine::deviceRemoved);
68}
69
71{
72 if (name.startsWith('/')) {
73 Solid::Device device = Solid::Device(name);
74 if (device.isValid()) {
75 if (m_devicemap.contains(name)) {
76 return true;
77 } else {
78 m_devicemap[name] = device;
79 return populateDeviceData(name);
80 }
81 }
82 } else {
84 if (predicate.isValid() && !m_predicatemap.contains(name)) {
85 for (const auto devices = Solid::Device::listFromQuery(predicate); const Solid::Device &device : devices) {
86 m_predicatemap[name] << device.udi();
87 }
88
89 setData(name, m_predicatemap[name]);
90 return true;
91 }
92 }
93
94 qDebug() << "Source is not a predicate or a device.";
95 return false;
96}
97
98void SolidDeviceEngine::sourceWasRemoved(const QString &source)
99{
100 m_devicemap.remove(source);
101 m_predicatemap.remove(source);
102}
103
104bool SolidDeviceEngine::populateDeviceData(const QString &name)
105{
106 Solid::Device device = m_devicemap.value(name);
107 if (!device.isValid()) {
108 return false;
109 }
110
111 QStringList devicetypes;
112 setData(name, kli18n("Parent UDI").untranslatedText(), device.parentUdi());
113 setData(name, kli18n("Vendor").untranslatedText(), device.vendor());
114 setData(name, kli18n("Product").untranslatedText(), device.product());
115 setData(name, kli18n("Description").untranslatedText(), device.description());
116 setData(name, kli18n("Icon").untranslatedText(), device.icon());
117 setData(name, kli18n("Emblems").untranslatedText(), device.emblems());
118 setData(name, kli18n("State").untranslatedText(), Idle);
119 setData(name, kli18n("Operation result").untranslatedText(), Working);
120 setData(name, kli18n("Timestamp").untranslatedText(), QDateTime::currentDateTimeUtc());
121
122 if (device.is<Solid::Processor>()) {
123 Solid::Processor *processor = device.as<Solid::Processor>();
124 if (!processor) {
125 return false;
126 }
127
128 devicetypes << kli18n("Processor").untranslatedText();
129 setData(name, kli18n("Number").untranslatedText(), processor->number());
130 setData(name, kli18n("Max Speed").untranslatedText(), processor->maxSpeed());
131 setData(name, kli18n("Can Change Frequency").untranslatedText(), processor->canChangeFrequency());
132 }
133 if (device.is<Solid::Block>()) {
134 Solid::Block *block = device.as<Solid::Block>();
135 if (!block) {
136 return false;
137 }
138
139 devicetypes << kli18n("Block").untranslatedText();
140 setData(name, kli18n("Major").untranslatedText(), block->deviceMajor());
141 setData(name, kli18n("Minor").untranslatedText(), block->deviceMinor());
142 setData(name, kli18n("Device").untranslatedText(), block->device());
143 }
144 if (device.is<Solid::StorageAccess>()) {
145 Solid::StorageAccess *storageaccess = device.as<Solid::StorageAccess>();
146 if (!storageaccess) {
147 return false;
148 }
149
150 devicetypes << kli18n("Storage Access").untranslatedText();
151 setData(name, kli18n("Accessible").untranslatedText(), storageaccess->isAccessible());
152 setData(name, kli18n("File Path").untranslatedText(), storageaccess->filePath());
153
154 if (storageaccess->isAccessible()) {
155 updateStorageSpace(name);
156 }
157
158 m_signalmanager->mapDevice(storageaccess, device.udi());
159 }
160
161 if (device.is<Solid::StorageDrive>()) {
162 Solid::StorageDrive *storagedrive = device.as<Solid::StorageDrive>();
163 if (!storagedrive) {
164 return false;
165 }
166
167 devicetypes << kli18n("Storage Drive").untranslatedText();
168
169 QStringList bus;
170 bus << kli18n("Ide").untranslatedText() << kli18n("Usb").untranslatedText() << kli18n("Ieee1394").untranslatedText()
171 << kli18n("Scsi").untranslatedText() << kli18n("Sata").untranslatedText() << kli18n("Platform").untranslatedText();
172 QStringList drivetype;
173 drivetype << kli18n("Hard Disk").untranslatedText() << kli18n("Cdrom Drive").untranslatedText() << kli18n("Floppy").untranslatedText()
174 << kli18n("Tape").untranslatedText() << kli18n("Compact Flash").untranslatedText() << kli18n("Memory Stick").untranslatedText()
175 << kli18n("Smart Media").untranslatedText() << kli18n("SdMmc").untranslatedText() << kli18n("Xd").untranslatedText();
176
177 setData(name, kli18n("Bus").untranslatedText(), bus.at((int)storagedrive->bus()));
178 setData(name, kli18n("Drive Type").untranslatedText(), drivetype.at((int)storagedrive->driveType()));
179 setData(name, kli18n("Removable").untranslatedText(), storagedrive->isRemovable());
180 setData(name, kli18n("Hotpluggable").untranslatedText(), storagedrive->isHotpluggable());
181
182 updateHardDiskTemperature(name);
183 } else {
184 bool isRemovable = false;
185 bool isHotpluggable = false;
186 Solid::StorageDrive *drive = getAncestorAs<Solid::StorageDrive>(device);
187 if (drive) {
188 // remove check for isHotpluggable() when plasmoids are changed to check for both properties
189 isRemovable = (drive->isRemovable() || drive->isHotpluggable());
190 isHotpluggable = drive->isHotpluggable();
191 }
192 setData(name, kli18n("Removable").untranslatedText(), isRemovable);
193 setData(name, kli18n("Hotpluggable").untranslatedText(), isHotpluggable);
194 }
195
196 if (device.is<Solid::OpticalDrive>()) {
197 Solid::OpticalDrive *opticaldrive = device.as<Solid::OpticalDrive>();
198 if (!opticaldrive) {
199 return false;
200 }
201
202 devicetypes << kli18n("Optical Drive").untranslatedText();
203
204 QStringList supportedtypes;
205 Solid::OpticalDrive::MediumTypes mediatypes = opticaldrive->supportedMedia();
206 if (mediatypes & Solid::OpticalDrive::Cdr) {
207 supportedtypes << kli18n("CD-R").untranslatedText();
208 }
209 if (mediatypes & Solid::OpticalDrive::Cdrw) {
210 supportedtypes << kli18n("CD-RW").untranslatedText();
211 }
212 if (mediatypes & Solid::OpticalDrive::Dvd) {
213 supportedtypes << kli18n("DVD").untranslatedText();
214 }
215 if (mediatypes & Solid::OpticalDrive::Dvdr) {
216 supportedtypes << kli18n("DVD-R").untranslatedText();
217 }
218 if (mediatypes & Solid::OpticalDrive::Dvdrw) {
219 supportedtypes << kli18n("DVD-RW").untranslatedText();
220 }
221 if (mediatypes & Solid::OpticalDrive::Dvdram) {
222 supportedtypes << kli18n("DVD-RAM").untranslatedText();
223 }
224 if (mediatypes & Solid::OpticalDrive::Dvdplusr) {
225 supportedtypes << kli18n("DVD+R").untranslatedText();
226 }
227 if (mediatypes & Solid::OpticalDrive::Dvdplusrw) {
228 supportedtypes << kli18n("DVD+RW").untranslatedText();
229 }
230 if (mediatypes & Solid::OpticalDrive::Dvdplusdl) {
231 supportedtypes << kli18n("DVD+DL").untranslatedText();
232 }
233 if (mediatypes & Solid::OpticalDrive::Dvdplusdlrw) {
234 supportedtypes << kli18n("DVD+DLRW").untranslatedText();
235 }
236 if (mediatypes & Solid::OpticalDrive::Bd) {
237 supportedtypes << kli18n("BD").untranslatedText();
238 }
239 if (mediatypes & Solid::OpticalDrive::Bdr) {
240 supportedtypes << kli18n("BD-R").untranslatedText();
241 }
242 if (mediatypes & Solid::OpticalDrive::Bdre) {
243 supportedtypes << kli18n("BD-RE").untranslatedText();
244 }
245 if (mediatypes & Solid::OpticalDrive::HdDvd) {
246 supportedtypes << kli18n("HDDVD").untranslatedText();
247 }
248 if (mediatypes & Solid::OpticalDrive::HdDvdr) {
249 supportedtypes << kli18n("HDDVD-R").untranslatedText();
250 }
251 if (mediatypes & Solid::OpticalDrive::HdDvdrw) {
252 supportedtypes << kli18n("HDDVD-RW").untranslatedText();
253 }
254 setData(name, kli18n("Supported Media").untranslatedText(), supportedtypes);
255
256 setData(name, kli18n("Read Speed").untranslatedText(), opticaldrive->readSpeed());
257 setData(name, kli18n("Write Speed").untranslatedText(), opticaldrive->writeSpeed());
258
259 // the following method return QList<int> so we need to convert it to QList<QVariant>
260 const QList<int> writespeeds = opticaldrive->writeSpeeds();
261 QList<QVariant> variantlist;
262 for (int num : writespeeds) {
263 variantlist << num;
264 }
265 setData(name, kli18n("Write Speeds").untranslatedText(), variantlist);
266 }
267 if (device.is<Solid::StorageVolume>()) {
268 Solid::StorageVolume *storagevolume = device.as<Solid::StorageVolume>();
269 if (!storagevolume) {
270 return false;
271 }
272
273 devicetypes << kli18n("Storage Volume").untranslatedText();
274
275 QStringList usagetypes;
276 usagetypes << i18n("Other") << i18n("Unused") << i18n("File System") << i18n("Partition Table") << i18n("Raid") << i18n("Encrypted");
277
278 if (usagetypes.count() > storagevolume->usage()) {
279 setData(name, kli18n("Usage").untranslatedText(), usagetypes.at((int)storagevolume->usage()));
280 } else {
281 setData(name, kli18n("Usage").untranslatedText(), i18n("Unknown"));
282 }
283
284 setData(name, kli18n("Ignored").untranslatedText(), storagevolume->isIgnored());
285 setData(name, kli18n("File System Type").untranslatedText(), storagevolume->fsType());
286 setData(name, kli18n("Label").untranslatedText(), storagevolume->label());
287 setData(name, kli18n("UUID").untranslatedText(), storagevolume->uuid());
288 updateInUse(name);
289
290 // Check if the volume is part of an encrypted container
291 // This needs to trigger an update for the encrypted container volume since
292 // libsolid cannot notify us when the accessibility of the container changes
293 Solid::Device encryptedContainer = storagevolume->encryptedContainer();
294 if (encryptedContainer.isValid()) {
295 const QString containerUdi = encryptedContainer.udi();
296 setData(name, kli18n("Encrypted Container").untranslatedText(), containerUdi);
297 m_encryptedContainerMap[name] = containerUdi;
298 // TODO: compress the calls?
299 forceUpdateAccessibility(containerUdi);
300 }
301 }
302 if (device.is<Solid::OpticalDisc>()) {
303 Solid::OpticalDisc *opticaldisc = device.as<Solid::OpticalDisc>();
304 if (!opticaldisc) {
305 return false;
306 }
307
308 devicetypes << kli18n("OpticalDisc").untranslatedText();
309
310 // get the content types
311 QStringList contenttypelist;
312 const Solid::OpticalDisc::ContentTypes contenttypes = opticaldisc->availableContent();
313 if (contenttypes.testFlag(Solid::OpticalDisc::Audio)) {
314 contenttypelist << kli18n("Audio").untranslatedText();
315 }
316 if (contenttypes.testFlag(Solid::OpticalDisc::Data)) {
317 contenttypelist << kli18n("Data").untranslatedText();
318 }
319 if (contenttypes.testFlag(Solid::OpticalDisc::VideoCd)) {
320 contenttypelist << kli18n("Video CD").untranslatedText();
321 }
322 if (contenttypes.testFlag(Solid::OpticalDisc::SuperVideoCd)) {
323 contenttypelist << kli18n("Super Video CD").untranslatedText();
324 }
325 if (contenttypes.testFlag(Solid::OpticalDisc::VideoDvd)) {
326 contenttypelist << kli18n("Video DVD").untranslatedText();
327 }
328 if (contenttypes.testFlag(Solid::OpticalDisc::VideoBluRay)) {
329 contenttypelist << kli18n("Video Blu Ray").untranslatedText();
330 }
331 setData(name, kli18n("Available Content").untranslatedText(), contenttypelist);
332
333 QStringList disctypes;
334 disctypes << kli18n("Unknown Disc Type").untranslatedText() << kli18n("CD Rom").untranslatedText() << kli18n("CD Recordable").untranslatedText()
335 << kli18n("CD Rewritable").untranslatedText() << kli18n("DVD Rom").untranslatedText() << kli18n("DVD Ram").untranslatedText()
336 << kli18n("DVD Recordable").untranslatedText() << kli18n("DVD Rewritable").untranslatedText()
337 << kli18n("DVD Plus Recordable").untranslatedText() << kli18n("DVD Plus Rewritable").untranslatedText()
338 << kli18n("DVD Plus Recordable Duallayer").untranslatedText() << kli18n("DVD Plus Rewritable Duallayer").untranslatedText()
339 << kli18n("Blu Ray Rom").untranslatedText() << kli18n("Blu Ray Recordable").untranslatedText()
340 << kli18n("Blu Ray Rewritable").untranslatedText() << kli18n("HD DVD Rom").untranslatedText()
341 << kli18n("HD DVD Recordable").untranslatedText() << kli18n("HD DVD Rewritable").untranslatedText();
342 //+1 because the enum starts at -1
343 setData(name, kli18n("Disc Type").untranslatedText(), disctypes.at((int)opticaldisc->discType() + 1));
344 setData(name, kli18n("Appendable").untranslatedText(), opticaldisc->isAppendable());
345 setData(name, kli18n("Blank").untranslatedText(), opticaldisc->isBlank());
346 setData(name, kli18n("Rewritable").untranslatedText(), opticaldisc->isRewritable());
347 setData(name, kli18n("Capacity").untranslatedText(), opticaldisc->capacity());
348 }
349 if (device.is<Solid::Camera>()) {
351 if (!camera) {
352 return false;
353 }
354
355 devicetypes << kli18n("Camera").untranslatedText();
356
357 setData(name, kli18n("Supported Protocols").untranslatedText(), camera->supportedProtocols());
358 setData(name, kli18n("Supported Drivers").untranslatedText(), camera->supportedDrivers());
359 // Cameras are necessarily Removable and Hotpluggable
360 setData(name, kli18n("Removable").untranslatedText(), true);
361 setData(name, kli18n("Hotpluggable").untranslatedText(), true);
362 }
363 if (device.is<Solid::PortableMediaPlayer>()) {
365 if (!mediaplayer) {
366 return false;
367 }
368
369 devicetypes << kli18n("Portable Media Player").untranslatedText();
370
371 setData(name, kli18n("Supported Protocols").untranslatedText(), mediaplayer->supportedProtocols());
372 setData(name, kli18n("Supported Drivers").untranslatedText(), mediaplayer->supportedDrivers());
373 // Portable Media Players are necessarily Removable and Hotpluggable
374 setData(name, kli18n("Removable").untranslatedText(), true);
375 setData(name, kli18n("Hotpluggable").untranslatedText(), true);
376 }
377 if (device.is<Solid::Battery>()) {
378 Solid::Battery *battery = device.as<Solid::Battery>();
379 if (!battery) {
380 return false;
381 }
382
383 devicetypes << kli18n("Battery").untranslatedText();
384
385 QStringList batterytype;
386 batterytype << kli18n("Unknown Battery").untranslatedText() << kli18n("PDA Battery").untranslatedText() << kli18n("UPS Battery").untranslatedText()
387 << kli18n("Primary Battery").untranslatedText() << kli18n("Mouse Battery").untranslatedText()
388 << kli18n("Keyboard Battery").untranslatedText() << kli18n("Keyboard Mouse Battery").untranslatedText()
389 << kli18n("Camera Battery").untranslatedText() << kli18n("Phone Battery").untranslatedText() << kli18n("Monitor Battery").untranslatedText()
390 << kli18n("Gaming Input Battery").untranslatedText() << kli18n("Bluetooth Battery").untranslatedText()
391 << kli18n("Tablet Battery").untranslatedText() << kli18n("Headphone Battery").untranslatedText()
392 << kli18n("Headset Battery").untranslatedText() << kli18n("Touchpad Battery").untranslatedText();
393
394 QStringList chargestate;
395 chargestate << kli18n("Not Charging").untranslatedText() << kli18n("Charging").untranslatedText() << kli18n("Discharging").untranslatedText()
396 << kli18n("Fully Charged").untranslatedText();
397
398 setData(name, kli18n("Plugged In").untranslatedText(), battery->isPresent()); // FIXME Rename when interested parties are adjusted
399 setData(name, kli18n("Type").untranslatedText(), batterytype.value((int)battery->type()));
400 setData(name, kli18n("Charge Percent").untranslatedText(), battery->chargePercent());
401 setData(name, kli18n("Rechargeable").untranslatedText(), battery->isRechargeable());
402 setData(name, kli18n("Charge State").untranslatedText(), chargestate.at((int)battery->chargeState()));
403
404 m_signalmanager->mapDevice(battery, device.udi());
405 }
406
407 using namespace Solid;
408 // we cannot just iterate the enum in reverse order since Battery comes second to last
409 // and then our phone which also has a battery gets treated as battery :(
410 static const Solid::DeviceInterface::Type typeOrder[] = {
411 Solid::DeviceInterface::PortableMediaPlayer,
412 Solid::DeviceInterface::Camera,
413 Solid::DeviceInterface::OpticalDisc,
414 Solid::DeviceInterface::StorageVolume,
415 Solid::DeviceInterface::OpticalDrive,
416 Solid::DeviceInterface::StorageDrive,
417 Solid::DeviceInterface::NetworkShare,
418 Solid::DeviceInterface::StorageAccess,
419 Solid::DeviceInterface::Block,
420 Solid::DeviceInterface::Battery,
421 Solid::DeviceInterface::Processor,
422 };
423
424 for (int i = 0; i < 11; ++i) {
425 const Solid::DeviceInterface *interface = device.asDeviceInterface(typeOrder[i]);
426 if (interface) {
427 setData(name, kli18n("Type Description").untranslatedText(), Solid::DeviceInterface::typeDescription(typeOrder[i]));
428 break;
429 }
430 }
431
432 setData(name, kli18n("Device Types").untranslatedText(), devicetypes);
433 return true;
434}
435
436void SolidDeviceEngine::deviceAdded(const QString &udi)
437{
438 Solid::Device device(udi);
439
440 for (auto it = m_predicatemap.cbegin(); it != m_predicatemap.cend(); it = std::next(it)) {
442 if (predicate.matches(device)) {
443 m_predicatemap[it.key()] << udi;
444 setData(it.key(), m_predicatemap[it.key()]);
445 }
446 }
447
448 if (device.is<Solid::OpticalDisc>()) {
449 Solid::OpticalDrive *drive = getAncestorAs<Solid::OpticalDrive>(device);
450 if (drive) {
451 connect(drive, &Solid::OpticalDrive::ejectRequested, this, &SolidDeviceEngine::setUnmountingState);
452 connect(drive, &Solid::OpticalDrive::ejectDone, this, &SolidDeviceEngine::setIdleState);
453 }
454 } else if (device.is<Solid::StorageVolume>()) {
455 // update the volume in case of 2-stage devices
456 if (m_devicemap.contains(udi) && containerForSource(udi)->data().value(kli18n("Size").untranslatedText()).toULongLong() == 0) {
458 if (iface) {
459 iface->setProperty("udi", udi);
460 connect(iface, SIGNAL(propertyChanged(QMap<QString, int>)), this, SLOT(deviceChanged(QMap<QString, int>)));
461 }
462 }
463
464 Solid::StorageAccess *access = device.as<Solid::StorageAccess>();
465 if (access) {
466 connect(access, &Solid::StorageAccess::setupRequested, this, &SolidDeviceEngine::setMountingState);
467 connect(access, &Solid::StorageAccess::setupDone, this, &SolidDeviceEngine::setIdleState);
468 connect(access, &Solid::StorageAccess::teardownRequested, this, &SolidDeviceEngine::setUnmountingState);
469 connect(access, &Solid::StorageAccess::teardownDone, this, &SolidDeviceEngine::setIdleState);
470 }
471 }
472}
473
474void SolidDeviceEngine::setMountingState(const QString &udi)
475{
476 setData(udi, kli18n("State").untranslatedText(), Mounting);
477 setData(udi, kli18n("Operation result").untranslatedText(), Working);
478}
479
480void SolidDeviceEngine::setUnmountingState(const QString &udi)
481{
482 setData(udi, kli18n("State").untranslatedText(), Unmounting);
483 setData(udi, kli18n("Operation result").untranslatedText(), Working);
484}
485
486void SolidDeviceEngine::setIdleState(Solid::ErrorType error, QVariant errorData, const QString &udi)
487{
488 Q_UNUSED(errorData)
489
490 if (error == Solid::NoError) {
491 setData(udi, kli18n("Operation result").untranslatedText(), Successful);
492 } else {
493 setData(udi, kli18n("Operation result").untranslatedText(), Unsuccessful);
494 }
495 setData(udi, kli18n("State").untranslatedText(), Idle);
496
497 Solid::Device device = m_devicemap.value(udi);
498 if (!device.isValid()) {
499 return;
500 }
501
502 Solid::StorageAccess *storageaccess = device.as<Solid::StorageAccess>();
503 if (!storageaccess) {
504 return;
505 }
506
507 setData(udi, kli18n("Accessible").untranslatedText(), storageaccess->isAccessible());
508 setData(udi, kli18n("File Path").untranslatedText(), storageaccess->filePath());
509}
510
511void SolidDeviceEngine::deviceChanged(const QMap<QString, int> &props)
512{
514 if (iface && iface->isValid() && props.contains(QLatin1String("Size")) && iface->property(QStringLiteral("Size")).toInt() > 0) {
515 const QString udi = qobject_cast<QObject *>(iface)->property("udi").toString();
516 if (populateDeviceData(udi))
518 }
519}
520
521bool SolidDeviceEngine::updateStorageSpace(const QString &udi)
522{
523 Solid::Device device = m_devicemap.value(udi);
524
525 Solid::StorageAccess *storageaccess = device.as<Solid::StorageAccess>();
526 if (!storageaccess || !storageaccess->isAccessible()) {
527 return false;
528 }
529
530 QString path = storageaccess->filePath();
531 if (!m_paths.contains(path)) {
532 QTimer *timer = new QTimer(this);
533 timer->setSingleShot(true);
534 connect(timer, &QTimer::timeout, [path]() {
535 KNotification::event(KNotification::Error, i18n("Filesystem is not responding"), i18n("Filesystem mounted at '%1' is not responding", path));
536 });
537
538 m_paths.insert(path);
539
540 // create job
542
543 // delete later timer
545
546 // collect and process info
547 connect(job, &KJob::result, this, [this, timer, path, udi, job]() {
548 timer->stop();
549
550 if (!job->error()) {
551 KIO::filesize_t size = job->size();
552 KIO::filesize_t available = job->availableSize();
553 setData(udi, kli18n("Free Space").untranslatedText(), QVariant(available).toDouble());
554 setData(udi, kli18n("Free Space Text").untranslatedText(), KFormat().formatByteSize(available));
555 setData(udi, kli18n("Size").untranslatedText(), QVariant(size).toDouble());
556 setData(udi, kli18n("Size Text").untranslatedText(), KFormat().formatByteSize(size));
557 }
558
559 m_paths.remove(path);
560 });
561
562 // start timer: after 15 seconds we will get an error
563 timer->start(15000);
564 }
565
566 return false;
567}
568
569bool SolidDeviceEngine::updateHardDiskTemperature(const QString &udi)
570{
571 Solid::Device device = m_devicemap.value(udi);
572 Solid::Block *block = device.as<Solid::Block>();
573 if (!block) {
574 return false;
575 }
576
577 if (!m_temperature) {
578 m_temperature = new HddTemp(this);
579 }
580
581 if (m_temperature->sources().contains(block->device())) {
582 setData(udi, kli18n("Temperature").untranslatedText(), m_temperature->data(block->device(), HddTemp::Temperature));
583 setData(udi, kli18n("Temperature Unit").untranslatedText(), m_temperature->data(block->device(), HddTemp::Unit));
584 return true;
585 }
586
587 return false;
588}
589
590bool SolidDeviceEngine::updateEmblems(const QString &udi)
591{
592 Solid::Device device = m_devicemap.value(udi);
593
594 setData(udi, kli18n("Emblems").untranslatedText(), device.emblems());
595 return true;
596}
597
598bool SolidDeviceEngine::forceUpdateAccessibility(const QString &udi)
599{
600 Solid::Device device = m_devicemap.value(udi);
601 if (!device.isValid()) {
602 return false;
603 }
604
605 updateEmblems(udi);
606 Solid::StorageAccess *storageaccess = device.as<Solid::StorageAccess>();
607 if (storageaccess) {
608 setData(udi, kli18n("Accessible").untranslatedText(), storageaccess->isAccessible());
609 }
610
611 return true;
612}
613
614bool SolidDeviceEngine::updateInUse(const QString &udi)
615{
616 Solid::Device device = m_devicemap.value(udi);
617 if (!device.isValid()) {
618 return false;
619 }
620
621 Solid::StorageAccess *storageaccess = device.as<Solid::StorageAccess>();
622 if (!storageaccess) {
623 return false;
624 }
625
626 if (storageaccess->isAccessible()) {
627 setData(udi, kli18n("In Use").untranslatedText(), true);
628 } else {
629 Solid::StorageDrive *drive = getAncestorAs<Solid::StorageDrive>(Solid::Device(udi));
630 if (drive) {
631 setData(udi, kli18n("In Use").untranslatedText(), drive->isInUse());
632 }
633 }
634
635 return true;
636}
637
639{
640 bool update1 = updateStorageSpace(source);
641 bool update2 = updateHardDiskTemperature(source);
642 bool update3 = updateEmblems(source);
643 bool update4 = updateInUse(source);
644
645 return (update1 || update2 || update3 || update4);
646}
647
648void SolidDeviceEngine::deviceRemoved(const QString &udi)
649{
650 // libsolid cannot notify us when an encrypted container is closed,
651 // hence we trigger an update when a device contained in an encrypted container device dies
652 const QString containerUdi = m_encryptedContainerMap.value(udi, QString());
653
654 if (!containerUdi.isEmpty()) {
655 forceUpdateAccessibility(containerUdi);
656 m_encryptedContainerMap.remove(udi);
657 }
658
659 for (const QString &query : m_predicatemap.keys()) {
660 m_predicatemap[query].removeAll(udi);
661 setData(query, m_predicatemap[query]);
662 }
663
664 Solid::Device device(udi);
665 if (device.is<Solid::StorageVolume>()) {
666 Solid::StorageAccess *access = device.as<Solid::StorageAccess>();
667 if (access) {
668 disconnect(access, nullptr, this, nullptr);
669 }
670 } else if (device.is<Solid::OpticalDisc>()) {
671 Solid::OpticalDrive *drive = getAncestorAs<Solid::OpticalDrive>(device);
672 if (drive) {
673 disconnect(drive, nullptr, this, nullptr);
674 }
675 }
676
677 m_devicemap.remove(udi);
678 removeSource(udi);
679}
680
681void SolidDeviceEngine::deviceChanged(const QString &udi, const QString &property, const QVariant &value)
682{
683 setData(udi, property, value);
685}
686
687K_PLUGIN_CLASS_WITH_JSON(SolidDeviceEngine, "plasma-dataengine-soliddevice.json")
688
689#include "soliddeviceengine.moc"
KIO::filesize_t availableSize() const
KIO::filesize_t size() const
int error() const
void result(KJob *job)
static KNotification * event(const QString &eventId, const QString &text=QString(), const QPixmap &pixmap=QPixmap(), const NotificationFlags &flags=CloseOnTimeout, const QString &componentName=QString())
#define K_PLUGIN_CLASS_WITH_JSON(classname, jsonFile)
void removeSource(const QString &source)
Removes a data source.
void forceImmediateUpdateOfAllVisualizations()
Forces an immediate update to all connected sources, even those with timeouts that haven't yet expire...
void setData(const QString &source, const QVariant &value)
Sets a value for a data source.
Q_INVOKABLE DataContainer * containerForSource(const QString &source)
Retrieves a pointer to the DataContainer for a given source.
void sourceRemoved(const QString &source)
Emitted when a data source is removed.
This class provides a generic API for write access to settings or services.
Definition service.h:78
This class evaluates the basic expressions given in the interface.
bool updateSourceEvent(const QString &source) override
Called by internal updating mechanisms to trigger the engine to refresh the data contained in a given...
bool sourceRequestEvent(const QString &name) override
When a source that does not currently exist is requested by the consumer, this method is called to gi...
Plasma5Support::Service * serviceForSource(const QString &source) override
Solid::Battery::BatteryType type() const
int chargePercent() const
Solid::Battery::ChargeState chargeState() const
bool isPresent() const
bool isRechargeable() const
int deviceMinor() const
QString device() const
int deviceMajor() const
static QString typeDescription(Type type)
void deviceRemoved(const QString &udi)
void deviceAdded(const QString &udi)
QString description() const
QStringList emblems() const
QString udi() const
QString parentUdi() const
QString icon() const
Device parent() const
QString vendor() const
bool is() const
static QList< Device > listFromQuery(const Predicate &predicate, const QString &parentUdi=QString())
bool isValid() const
QString product() const
DevIface * as()
QVariant property(const QString &key) const
bool isAppendable() const
qulonglong capacity() const
DiscType discType() const
bool isBlank() const
bool isRewritable() const
ContentTypes availableContent() const
MediumTypes supportedMedia() const
QList< int > writeSpeeds() const
void ejectDone(Solid::ErrorType error, QVariant errorData, const QString &udi)
int readSpeed() const
int writeSpeed() const
void ejectRequested(const QString &udi)
QStringList supportedProtocols() const
QStringList supportedDrivers(QString protocol=QString()) const
bool matches(const Device &device) const
bool isValid() const
static Predicate fromString(const QString &predicate)
int number() const
int maxSpeed() const
bool canChangeFrequency() const
void setupRequested(const QString &udi)
QString filePath() const
void teardownRequested(const QString &udi)
bool isAccessible() const
void teardownDone(Solid::ErrorType error, QVariant errorData, const QString &udi)
void setupDone(Solid::ErrorType error, QVariant errorData, const QString &udi)
bool isInUse() const
DriveType driveType() const
bool isHotpluggable() const
bool isRemovable() const
QString label() const
UsageType usage() const
QString fsType() const
Device encryptedContainer() const
QString uuid() const
bool isIgnored() const
Q_SCRIPTABLE QString camera()
QString i18n(const char *text, const TYPE &arg...)
KSERVICE_EXPORT KService::List query(FilterFunc filterFunc)
KIOCORE_EXPORT FileSystemFreeSpaceJob * fileSystemFreeSpace(const QUrl &url)
qulonglong filesize_t
QString path(const QString &relativePath)
QString name(StandardAction id)
Namespace for everything in libplasma.
Definition datamodel.cpp:15
QDateTime currentDateTimeUtc()
bool testFlag(Enum flag) const const
const_reference at(qsizetype i) const const
qsizetype count() const const
T value(qsizetype i) const const
const_iterator cbegin() const const
const_iterator cend() const const
bool contains(const Key &key) const const
QList< Key > keys() const const
size_type remove(const Key &key)
T value(const Key &key, const T &defaultValue) const const
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
void deleteLater()
bool disconnect(const QMetaObject::Connection &connection)
QVariant property(const char *name) const const
T qobject_cast(QObject *object)
QObject * sender() const const
bool setProperty(const char *name, QVariant &&value)
bool contains(const QSet< T > &other) const const
iterator insert(const T &value)
bool remove(const T &value)
bool isEmpty() const const
bool startsWith(QChar c, Qt::CaseSensitivity cs) const const
bool contains(QLatin1StringView str, Qt::CaseSensitivity cs) const const
QFuture< ArgsType< Signal > > connect(Sender *sender, Signal signal)
void setSingleShot(bool singleShot)
void start()
void stop()
void timeout()
QUrl fromLocalFile(const QString &localFile)
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Mon Nov 18 2024 12:08:57 by doxygen 1.12.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.