File indexing completed on 2024-05-12 05:37:20
0001 /* 0002 SPDX-FileCopyrightText: 2007 Christopher Blauvelt <cblauvelt@gmail.com> 0003 0004 SPDX-License-Identifier: LGPL-2.0-only 0005 */ 0006 0007 #include "soliddeviceengine.h" 0008 #include "soliddeviceservice.h" 0009 0010 #include <KLazyLocalizedString> 0011 #include <QDateTime> 0012 #include <QMetaEnum> 0013 #include <Solid/GenericInterface> 0014 #include <klocalizedstring.h> 0015 0016 #include <KFormat> 0017 #include <KNotification> 0018 #include <QDebug> 0019 0020 #include <Plasma5Support/DataContainer> 0021 0022 // TODO: implement in libsolid2 0023 namespace 0024 { 0025 template<class DevIface> 0026 DevIface *getAncestorAs(const Solid::Device &device) 0027 { 0028 for (Solid::Device parent = device.parent(); parent.isValid(); parent = parent.parent()) { 0029 if (parent.is<DevIface>()) { 0030 return parent.as<DevIface>(); 0031 } 0032 } 0033 return nullptr; 0034 } 0035 } 0036 0037 SolidDeviceEngine::SolidDeviceEngine(QObject *parent) 0038 : Plasma5Support::DataEngine(parent) 0039 , m_temperature(nullptr) 0040 , m_notifier(nullptr) 0041 { 0042 m_signalmanager = new DeviceSignalMapManager(this); 0043 0044 listenForNewDevices(); 0045 setMinimumPollingInterval(1000); 0046 connect(this, &Plasma5Support::DataEngine::sourceRemoved, this, &SolidDeviceEngine::sourceWasRemoved); 0047 } 0048 0049 SolidDeviceEngine::~SolidDeviceEngine() 0050 { 0051 } 0052 0053 Plasma5Support::Service *SolidDeviceEngine::serviceForSource(const QString &source) 0054 { 0055 return new SolidDeviceService(this, source); 0056 } 0057 0058 void SolidDeviceEngine::listenForNewDevices() 0059 { 0060 if (m_notifier) { 0061 return; 0062 } 0063 0064 // detect when new devices are added 0065 m_notifier = Solid::DeviceNotifier::instance(); 0066 connect(m_notifier, &Solid::DeviceNotifier::deviceAdded, this, &SolidDeviceEngine::deviceAdded); 0067 connect(m_notifier, &Solid::DeviceNotifier::deviceRemoved, this, &SolidDeviceEngine::deviceRemoved); 0068 } 0069 0070 bool SolidDeviceEngine::sourceRequestEvent(const QString &name) 0071 { 0072 if (name.startsWith('/')) { 0073 Solid::Device device = Solid::Device(name); 0074 if (device.isValid()) { 0075 if (m_devicemap.contains(name)) { 0076 return true; 0077 } else { 0078 m_devicemap[name] = device; 0079 return populateDeviceData(name); 0080 } 0081 } 0082 } else { 0083 Solid::Predicate predicate = Solid::Predicate::fromString(name); 0084 if (predicate.isValid() && !m_predicatemap.contains(name)) { 0085 foreach (const Solid::Device &device, Solid::Device::listFromQuery(predicate)) { 0086 m_predicatemap[name] << device.udi(); 0087 } 0088 0089 setData(name, m_predicatemap[name]); 0090 return true; 0091 } 0092 } 0093 0094 qDebug() << "Source is not a predicate or a device."; 0095 return false; 0096 } 0097 0098 void SolidDeviceEngine::sourceWasRemoved(const QString &source) 0099 { 0100 m_devicemap.remove(source); 0101 m_predicatemap.remove(source); 0102 } 0103 0104 bool SolidDeviceEngine::populateDeviceData(const QString &name) 0105 { 0106 Solid::Device device = m_devicemap.value(name); 0107 if (!device.isValid()) { 0108 return false; 0109 } 0110 0111 QStringList devicetypes; 0112 setData(name, kli18n("Parent UDI").untranslatedText(), device.parentUdi()); 0113 setData(name, kli18n("Vendor").untranslatedText(), device.vendor()); 0114 setData(name, kli18n("Product").untranslatedText(), device.product()); 0115 setData(name, kli18n("Description").untranslatedText(), device.description()); 0116 setData(name, kli18n("Icon").untranslatedText(), device.icon()); 0117 setData(name, kli18n("Emblems").untranslatedText(), device.emblems()); 0118 setData(name, kli18n("State").untranslatedText(), Idle); 0119 setData(name, kli18n("Operation result").untranslatedText(), Working); 0120 setData(name, kli18n("Timestamp").untranslatedText(), QDateTime::currentDateTimeUtc()); 0121 0122 if (device.is<Solid::Processor>()) { 0123 Solid::Processor *processor = device.as<Solid::Processor>(); 0124 if (!processor) { 0125 return false; 0126 } 0127 0128 devicetypes << kli18n("Processor").untranslatedText(); 0129 setData(name, kli18n("Number").untranslatedText(), processor->number()); 0130 setData(name, kli18n("Max Speed").untranslatedText(), processor->maxSpeed()); 0131 setData(name, kli18n("Can Change Frequency").untranslatedText(), processor->canChangeFrequency()); 0132 } 0133 if (device.is<Solid::Block>()) { 0134 Solid::Block *block = device.as<Solid::Block>(); 0135 if (!block) { 0136 return false; 0137 } 0138 0139 devicetypes << kli18n("Block").untranslatedText(); 0140 setData(name, kli18n("Major").untranslatedText(), block->deviceMajor()); 0141 setData(name, kli18n("Minor").untranslatedText(), block->deviceMinor()); 0142 setData(name, kli18n("Device").untranslatedText(), block->device()); 0143 } 0144 if (device.is<Solid::StorageAccess>()) { 0145 Solid::StorageAccess *storageaccess = device.as<Solid::StorageAccess>(); 0146 if (!storageaccess) { 0147 return false; 0148 } 0149 0150 devicetypes << kli18n("Storage Access").untranslatedText(); 0151 setData(name, kli18n("Accessible").untranslatedText(), storageaccess->isAccessible()); 0152 setData(name, kli18n("File Path").untranslatedText(), storageaccess->filePath()); 0153 0154 if (storageaccess->isAccessible()) { 0155 updateStorageSpace(name); 0156 } 0157 0158 m_signalmanager->mapDevice(storageaccess, device.udi()); 0159 } 0160 0161 if (device.is<Solid::StorageDrive>()) { 0162 Solid::StorageDrive *storagedrive = device.as<Solid::StorageDrive>(); 0163 if (!storagedrive) { 0164 return false; 0165 } 0166 0167 devicetypes << kli18n("Storage Drive").untranslatedText(); 0168 0169 QStringList bus; 0170 bus << kli18n("Ide").untranslatedText() << kli18n("Usb").untranslatedText() << kli18n("Ieee1394").untranslatedText() 0171 << kli18n("Scsi").untranslatedText() << kli18n("Sata").untranslatedText() << kli18n("Platform").untranslatedText(); 0172 QStringList drivetype; 0173 drivetype << kli18n("Hard Disk").untranslatedText() << kli18n("Cdrom Drive").untranslatedText() << kli18n("Floppy").untranslatedText() 0174 << kli18n("Tape").untranslatedText() << kli18n("Compact Flash").untranslatedText() << kli18n("Memory Stick").untranslatedText() 0175 << kli18n("Smart Media").untranslatedText() << kli18n("SdMmc").untranslatedText() << kli18n("Xd").untranslatedText(); 0176 0177 setData(name, kli18n("Bus").untranslatedText(), bus.at((int)storagedrive->bus())); 0178 setData(name, kli18n("Drive Type").untranslatedText(), drivetype.at((int)storagedrive->driveType())); 0179 setData(name, kli18n("Removable").untranslatedText(), storagedrive->isRemovable()); 0180 setData(name, kli18n("Hotpluggable").untranslatedText(), storagedrive->isHotpluggable()); 0181 0182 updateHardDiskTemperature(name); 0183 } else { 0184 bool isRemovable = false; 0185 bool isHotpluggable = false; 0186 Solid::StorageDrive *drive = getAncestorAs<Solid::StorageDrive>(device); 0187 if (drive) { 0188 // remove check for isHotpluggable() when plasmoids are changed to check for both properties 0189 isRemovable = (drive->isRemovable() || drive->isHotpluggable()); 0190 isHotpluggable = drive->isHotpluggable(); 0191 } 0192 setData(name, kli18n("Removable").untranslatedText(), isRemovable); 0193 setData(name, kli18n("Hotpluggable").untranslatedText(), isHotpluggable); 0194 } 0195 0196 if (device.is<Solid::OpticalDrive>()) { 0197 Solid::OpticalDrive *opticaldrive = device.as<Solid::OpticalDrive>(); 0198 if (!opticaldrive) { 0199 return false; 0200 } 0201 0202 devicetypes << kli18n("Optical Drive").untranslatedText(); 0203 0204 QStringList supportedtypes; 0205 Solid::OpticalDrive::MediumTypes mediatypes = opticaldrive->supportedMedia(); 0206 if (mediatypes & Solid::OpticalDrive::Cdr) { 0207 supportedtypes << kli18n("CD-R").untranslatedText(); 0208 } 0209 if (mediatypes & Solid::OpticalDrive::Cdrw) { 0210 supportedtypes << kli18n("CD-RW").untranslatedText(); 0211 } 0212 if (mediatypes & Solid::OpticalDrive::Dvd) { 0213 supportedtypes << kli18n("DVD").untranslatedText(); 0214 } 0215 if (mediatypes & Solid::OpticalDrive::Dvdr) { 0216 supportedtypes << kli18n("DVD-R").untranslatedText(); 0217 } 0218 if (mediatypes & Solid::OpticalDrive::Dvdrw) { 0219 supportedtypes << kli18n("DVD-RW").untranslatedText(); 0220 } 0221 if (mediatypes & Solid::OpticalDrive::Dvdram) { 0222 supportedtypes << kli18n("DVD-RAM").untranslatedText(); 0223 } 0224 if (mediatypes & Solid::OpticalDrive::Dvdplusr) { 0225 supportedtypes << kli18n("DVD+R").untranslatedText(); 0226 } 0227 if (mediatypes & Solid::OpticalDrive::Dvdplusrw) { 0228 supportedtypes << kli18n("DVD+RW").untranslatedText(); 0229 } 0230 if (mediatypes & Solid::OpticalDrive::Dvdplusdl) { 0231 supportedtypes << kli18n("DVD+DL").untranslatedText(); 0232 } 0233 if (mediatypes & Solid::OpticalDrive::Dvdplusdlrw) { 0234 supportedtypes << kli18n("DVD+DLRW").untranslatedText(); 0235 } 0236 if (mediatypes & Solid::OpticalDrive::Bd) { 0237 supportedtypes << kli18n("BD").untranslatedText(); 0238 } 0239 if (mediatypes & Solid::OpticalDrive::Bdr) { 0240 supportedtypes << kli18n("BD-R").untranslatedText(); 0241 } 0242 if (mediatypes & Solid::OpticalDrive::Bdre) { 0243 supportedtypes << kli18n("BD-RE").untranslatedText(); 0244 } 0245 if (mediatypes & Solid::OpticalDrive::HdDvd) { 0246 supportedtypes << kli18n("HDDVD").untranslatedText(); 0247 } 0248 if (mediatypes & Solid::OpticalDrive::HdDvdr) { 0249 supportedtypes << kli18n("HDDVD-R").untranslatedText(); 0250 } 0251 if (mediatypes & Solid::OpticalDrive::HdDvdrw) { 0252 supportedtypes << kli18n("HDDVD-RW").untranslatedText(); 0253 } 0254 setData(name, kli18n("Supported Media").untranslatedText(), supportedtypes); 0255 0256 setData(name, kli18n("Read Speed").untranslatedText(), opticaldrive->readSpeed()); 0257 setData(name, kli18n("Write Speed").untranslatedText(), opticaldrive->writeSpeed()); 0258 0259 // the following method return QList<int> so we need to convert it to QList<QVariant> 0260 const QList<int> writespeeds = opticaldrive->writeSpeeds(); 0261 QList<QVariant> variantlist; 0262 foreach (int num, writespeeds) { 0263 variantlist << num; 0264 } 0265 setData(name, kli18n("Write Speeds").untranslatedText(), variantlist); 0266 } 0267 if (device.is<Solid::StorageVolume>()) { 0268 Solid::StorageVolume *storagevolume = device.as<Solid::StorageVolume>(); 0269 if (!storagevolume) { 0270 return false; 0271 } 0272 0273 devicetypes << kli18n("Storage Volume").untranslatedText(); 0274 0275 QStringList usagetypes; 0276 usagetypes << i18n("Other") << i18n("Unused") << i18n("File System") << i18n("Partition Table") << i18n("Raid") << i18n("Encrypted"); 0277 0278 if (usagetypes.count() > storagevolume->usage()) { 0279 setData(name, kli18n("Usage").untranslatedText(), usagetypes.at((int)storagevolume->usage())); 0280 } else { 0281 setData(name, kli18n("Usage").untranslatedText(), i18n("Unknown")); 0282 } 0283 0284 setData(name, kli18n("Ignored").untranslatedText(), storagevolume->isIgnored()); 0285 setData(name, kli18n("File System Type").untranslatedText(), storagevolume->fsType()); 0286 setData(name, kli18n("Label").untranslatedText(), storagevolume->label()); 0287 setData(name, kli18n("UUID").untranslatedText(), storagevolume->uuid()); 0288 updateInUse(name); 0289 0290 // Check if the volume is part of an encrypted container 0291 // This needs to trigger an update for the encrypted container volume since 0292 // libsolid cannot notify us when the accessibility of the container changes 0293 Solid::Device encryptedContainer = storagevolume->encryptedContainer(); 0294 if (encryptedContainer.isValid()) { 0295 const QString containerUdi = encryptedContainer.udi(); 0296 setData(name, kli18n("Encrypted Container").untranslatedText(), containerUdi); 0297 m_encryptedContainerMap[name] = containerUdi; 0298 // TODO: compress the calls? 0299 forceUpdateAccessibility(containerUdi); 0300 } 0301 } 0302 if (device.is<Solid::OpticalDisc>()) { 0303 Solid::OpticalDisc *opticaldisc = device.as<Solid::OpticalDisc>(); 0304 if (!opticaldisc) { 0305 return false; 0306 } 0307 0308 devicetypes << kli18n("OpticalDisc").untranslatedText(); 0309 0310 // get the content types 0311 QStringList contenttypelist; 0312 const Solid::OpticalDisc::ContentTypes contenttypes = opticaldisc->availableContent(); 0313 if (contenttypes.testFlag(Solid::OpticalDisc::Audio)) { 0314 contenttypelist << kli18n("Audio").untranslatedText(); 0315 } 0316 if (contenttypes.testFlag(Solid::OpticalDisc::Data)) { 0317 contenttypelist << kli18n("Data").untranslatedText(); 0318 } 0319 if (contenttypes.testFlag(Solid::OpticalDisc::VideoCd)) { 0320 contenttypelist << kli18n("Video CD").untranslatedText(); 0321 } 0322 if (contenttypes.testFlag(Solid::OpticalDisc::SuperVideoCd)) { 0323 contenttypelist << kli18n("Super Video CD").untranslatedText(); 0324 } 0325 if (contenttypes.testFlag(Solid::OpticalDisc::VideoDvd)) { 0326 contenttypelist << kli18n("Video DVD").untranslatedText(); 0327 } 0328 if (contenttypes.testFlag(Solid::OpticalDisc::VideoBluRay)) { 0329 contenttypelist << kli18n("Video Blu Ray").untranslatedText(); 0330 } 0331 setData(name, kli18n("Available Content").untranslatedText(), contenttypelist); 0332 0333 QStringList disctypes; 0334 disctypes << kli18n("Unknown Disc Type").untranslatedText() << kli18n("CD Rom").untranslatedText() << kli18n("CD Recordable").untranslatedText() 0335 << kli18n("CD Rewritable").untranslatedText() << kli18n("DVD Rom").untranslatedText() << kli18n("DVD Ram").untranslatedText() 0336 << kli18n("DVD Recordable").untranslatedText() << kli18n("DVD Rewritable").untranslatedText() 0337 << kli18n("DVD Plus Recordable").untranslatedText() << kli18n("DVD Plus Rewritable").untranslatedText() 0338 << kli18n("DVD Plus Recordable Duallayer").untranslatedText() << kli18n("DVD Plus Rewritable Duallayer").untranslatedText() 0339 << kli18n("Blu Ray Rom").untranslatedText() << kli18n("Blu Ray Recordable").untranslatedText() 0340 << kli18n("Blu Ray Rewritable").untranslatedText() << kli18n("HD DVD Rom").untranslatedText() 0341 << kli18n("HD DVD Recordable").untranslatedText() << kli18n("HD DVD Rewritable").untranslatedText(); 0342 //+1 because the enum starts at -1 0343 setData(name, kli18n("Disc Type").untranslatedText(), disctypes.at((int)opticaldisc->discType() + 1)); 0344 setData(name, kli18n("Appendable").untranslatedText(), opticaldisc->isAppendable()); 0345 setData(name, kli18n("Blank").untranslatedText(), opticaldisc->isBlank()); 0346 setData(name, kli18n("Rewritable").untranslatedText(), opticaldisc->isRewritable()); 0347 setData(name, kli18n("Capacity").untranslatedText(), opticaldisc->capacity()); 0348 } 0349 if (device.is<Solid::Camera>()) { 0350 Solid::Camera *camera = device.as<Solid::Camera>(); 0351 if (!camera) { 0352 return false; 0353 } 0354 0355 devicetypes << kli18n("Camera").untranslatedText(); 0356 0357 setData(name, kli18n("Supported Protocols").untranslatedText(), camera->supportedProtocols()); 0358 setData(name, kli18n("Supported Drivers").untranslatedText(), camera->supportedDrivers()); 0359 // Cameras are necessarily Removable and Hotpluggable 0360 setData(name, kli18n("Removable").untranslatedText(), true); 0361 setData(name, kli18n("Hotpluggable").untranslatedText(), true); 0362 } 0363 if (device.is<Solid::PortableMediaPlayer>()) { 0364 Solid::PortableMediaPlayer *mediaplayer = device.as<Solid::PortableMediaPlayer>(); 0365 if (!mediaplayer) { 0366 return false; 0367 } 0368 0369 devicetypes << kli18n("Portable Media Player").untranslatedText(); 0370 0371 setData(name, kli18n("Supported Protocols").untranslatedText(), mediaplayer->supportedProtocols()); 0372 setData(name, kli18n("Supported Drivers").untranslatedText(), mediaplayer->supportedDrivers()); 0373 // Portable Media Players are necessarily Removable and Hotpluggable 0374 setData(name, kli18n("Removable").untranslatedText(), true); 0375 setData(name, kli18n("Hotpluggable").untranslatedText(), true); 0376 } 0377 if (device.is<Solid::Battery>()) { 0378 Solid::Battery *battery = device.as<Solid::Battery>(); 0379 if (!battery) { 0380 return false; 0381 } 0382 0383 devicetypes << kli18n("Battery").untranslatedText(); 0384 0385 QStringList batterytype; 0386 batterytype << kli18n("Unknown Battery").untranslatedText() << kli18n("PDA Battery").untranslatedText() << kli18n("UPS Battery").untranslatedText() 0387 << kli18n("Primary Battery").untranslatedText() << kli18n("Mouse Battery").untranslatedText() 0388 << kli18n("Keyboard Battery").untranslatedText() << kli18n("Keyboard Mouse Battery").untranslatedText() 0389 << kli18n("Camera Battery").untranslatedText() << kli18n("Phone Battery").untranslatedText() << kli18n("Monitor Battery").untranslatedText() 0390 << kli18n("Gaming Input Battery").untranslatedText() << kli18n("Bluetooth Battery").untranslatedText(); 0391 0392 QStringList chargestate; 0393 chargestate << kli18n("Not Charging").untranslatedText() << kli18n("Charging").untranslatedText() << kli18n("Discharging").untranslatedText() 0394 << kli18n("Fully Charged").untranslatedText(); 0395 0396 setData(name, kli18n("Plugged In").untranslatedText(), battery->isPresent()); // FIXME Rename when interested parties are adjusted 0397 setData(name, kli18n("Type").untranslatedText(), batterytype.value((int)battery->type())); 0398 setData(name, kli18n("Charge Percent").untranslatedText(), battery->chargePercent()); 0399 setData(name, kli18n("Rechargeable").untranslatedText(), battery->isRechargeable()); 0400 setData(name, kli18n("Charge State").untranslatedText(), chargestate.at((int)battery->chargeState())); 0401 0402 m_signalmanager->mapDevice(battery, device.udi()); 0403 } 0404 0405 using namespace Solid; 0406 // we cannot just iterate the enum in reverse order since Battery comes second to last 0407 // and then our phone which also has a battery gets treated as battery :( 0408 static const Solid::DeviceInterface::Type typeOrder[] = { 0409 Solid::DeviceInterface::PortableMediaPlayer, 0410 Solid::DeviceInterface::Camera, 0411 Solid::DeviceInterface::OpticalDisc, 0412 Solid::DeviceInterface::StorageVolume, 0413 Solid::DeviceInterface::OpticalDrive, 0414 Solid::DeviceInterface::StorageDrive, 0415 Solid::DeviceInterface::NetworkShare, 0416 Solid::DeviceInterface::StorageAccess, 0417 Solid::DeviceInterface::Block, 0418 Solid::DeviceInterface::Battery, 0419 Solid::DeviceInterface::Processor, 0420 }; 0421 0422 for (int i = 0; i < 11; ++i) { 0423 const Solid::DeviceInterface *interface = device.asDeviceInterface(typeOrder[i]); 0424 if (interface) { 0425 setData(name, kli18n("Type Description").untranslatedText(), Solid::DeviceInterface::typeDescription(typeOrder[i])); 0426 break; 0427 } 0428 } 0429 0430 setData(name, kli18n("Device Types").untranslatedText(), devicetypes); 0431 return true; 0432 } 0433 0434 void SolidDeviceEngine::deviceAdded(const QString &udi) 0435 { 0436 Solid::Device device(udi); 0437 0438 foreach (const QString &query, m_predicatemap.keys()) { 0439 Solid::Predicate predicate = Solid::Predicate::fromString(query); 0440 if (predicate.matches(device)) { 0441 m_predicatemap[query] << udi; 0442 setData(query, m_predicatemap[query]); 0443 } 0444 } 0445 0446 if (device.is<Solid::OpticalDisc>()) { 0447 Solid::OpticalDrive *drive = getAncestorAs<Solid::OpticalDrive>(device); 0448 if (drive) { 0449 connect(drive, &Solid::OpticalDrive::ejectRequested, this, &SolidDeviceEngine::setUnmountingState); 0450 connect(drive, &Solid::OpticalDrive::ejectDone, this, &SolidDeviceEngine::setIdleState); 0451 } 0452 } else if (device.is<Solid::StorageVolume>()) { 0453 // update the volume in case of 2-stage devices 0454 if (m_devicemap.contains(udi) && containerForSource(udi)->data().value(kli18n("Size").untranslatedText()).toULongLong() == 0) { 0455 Solid::GenericInterface *iface = device.as<Solid::GenericInterface>(); 0456 if (iface) { 0457 iface->setProperty("udi", udi); 0458 connect(iface, SIGNAL(propertyChanged(QMap<QString, int>)), this, SLOT(deviceChanged(QMap<QString, int>))); 0459 } 0460 } 0461 0462 Solid::StorageAccess *access = device.as<Solid::StorageAccess>(); 0463 if (access) { 0464 connect(access, &Solid::StorageAccess::setupRequested, this, &SolidDeviceEngine::setMountingState); 0465 connect(access, &Solid::StorageAccess::setupDone, this, &SolidDeviceEngine::setIdleState); 0466 connect(access, &Solid::StorageAccess::teardownRequested, this, &SolidDeviceEngine::setUnmountingState); 0467 connect(access, &Solid::StorageAccess::teardownDone, this, &SolidDeviceEngine::setIdleState); 0468 } 0469 } 0470 } 0471 0472 void SolidDeviceEngine::setMountingState(const QString &udi) 0473 { 0474 setData(udi, kli18n("State").untranslatedText(), Mounting); 0475 setData(udi, kli18n("Operation result").untranslatedText(), Working); 0476 } 0477 0478 void SolidDeviceEngine::setUnmountingState(const QString &udi) 0479 { 0480 setData(udi, kli18n("State").untranslatedText(), Unmounting); 0481 setData(udi, kli18n("Operation result").untranslatedText(), Working); 0482 } 0483 0484 void SolidDeviceEngine::setIdleState(Solid::ErrorType error, QVariant errorData, const QString &udi) 0485 { 0486 Q_UNUSED(errorData) 0487 0488 if (error == Solid::NoError) { 0489 setData(udi, kli18n("Operation result").untranslatedText(), Successful); 0490 } else { 0491 setData(udi, kli18n("Operation result").untranslatedText(), Unsuccessful); 0492 } 0493 setData(udi, kli18n("State").untranslatedText(), Idle); 0494 0495 Solid::Device device = m_devicemap.value(udi); 0496 if (!device.isValid()) { 0497 return; 0498 } 0499 0500 Solid::StorageAccess *storageaccess = device.as<Solid::StorageAccess>(); 0501 if (!storageaccess) { 0502 return; 0503 } 0504 0505 setData(udi, kli18n("Accessible").untranslatedText(), storageaccess->isAccessible()); 0506 setData(udi, kli18n("File Path").untranslatedText(), storageaccess->filePath()); 0507 } 0508 0509 void SolidDeviceEngine::deviceChanged(const QMap<QString, int> &props) 0510 { 0511 Solid::GenericInterface *iface = qobject_cast<Solid::GenericInterface *>(sender()); 0512 if (iface && iface->isValid() && props.contains(QLatin1String("Size")) && iface->property(QStringLiteral("Size")).toInt() > 0) { 0513 const QString udi = qobject_cast<QObject *>(iface)->property("udi").toString(); 0514 if (populateDeviceData(udi)) 0515 forceImmediateUpdateOfAllVisualizations(); 0516 } 0517 } 0518 0519 bool SolidDeviceEngine::updateStorageSpace(const QString &udi) 0520 { 0521 Solid::Device device = m_devicemap.value(udi); 0522 0523 Solid::StorageAccess *storageaccess = device.as<Solid::StorageAccess>(); 0524 if (!storageaccess || !storageaccess->isAccessible()) { 0525 return false; 0526 } 0527 0528 QString path = storageaccess->filePath(); 0529 if (!m_paths.contains(path)) { 0530 QTimer *timer = new QTimer(this); 0531 timer->setSingleShot(true); 0532 connect(timer, &QTimer::timeout, [path]() { 0533 KNotification::event(KNotification::Error, i18n("Filesystem is not responding"), i18n("Filesystem mounted at '%1' is not responding", path)); 0534 }); 0535 0536 m_paths.insert(path); 0537 0538 // create job 0539 KIO::FileSystemFreeSpaceJob *job = KIO::fileSystemFreeSpace(QUrl::fromLocalFile(path)); 0540 0541 // delete later timer 0542 connect(job, &KJob::result, timer, &QTimer::deleteLater); 0543 0544 // collect and process info 0545 connect(job, &KJob::result, this, [this, timer, path, udi, job]() { 0546 timer->stop(); 0547 0548 if (!job->error()) { 0549 KIO::filesize_t size = job->size(); 0550 KIO::filesize_t available = job->availableSize(); 0551 setData(udi, kli18n("Free Space").untranslatedText(), QVariant(available).toDouble()); 0552 setData(udi, kli18n("Free Space Text").untranslatedText(), KFormat().formatByteSize(available)); 0553 setData(udi, kli18n("Size").untranslatedText(), QVariant(size).toDouble()); 0554 setData(udi, kli18n("Size Text").untranslatedText(), KFormat().formatByteSize(size)); 0555 } 0556 0557 m_paths.remove(path); 0558 }); 0559 0560 // start timer: after 15 seconds we will get an error 0561 timer->start(15000); 0562 } 0563 0564 return false; 0565 } 0566 0567 bool SolidDeviceEngine::updateHardDiskTemperature(const QString &udi) 0568 { 0569 Solid::Device device = m_devicemap.value(udi); 0570 Solid::Block *block = device.as<Solid::Block>(); 0571 if (!block) { 0572 return false; 0573 } 0574 0575 if (!m_temperature) { 0576 m_temperature = new HddTemp(this); 0577 } 0578 0579 if (m_temperature->sources().contains(block->device())) { 0580 setData(udi, kli18n("Temperature").untranslatedText(), m_temperature->data(block->device(), HddTemp::Temperature)); 0581 setData(udi, kli18n("Temperature Unit").untranslatedText(), m_temperature->data(block->device(), HddTemp::Unit)); 0582 return true; 0583 } 0584 0585 return false; 0586 } 0587 0588 bool SolidDeviceEngine::updateEmblems(const QString &udi) 0589 { 0590 Solid::Device device = m_devicemap.value(udi); 0591 0592 setData(udi, kli18n("Emblems").untranslatedText(), device.emblems()); 0593 return true; 0594 } 0595 0596 bool SolidDeviceEngine::forceUpdateAccessibility(const QString &udi) 0597 { 0598 Solid::Device device = m_devicemap.value(udi); 0599 if (!device.isValid()) { 0600 return false; 0601 } 0602 0603 updateEmblems(udi); 0604 Solid::StorageAccess *storageaccess = device.as<Solid::StorageAccess>(); 0605 if (storageaccess) { 0606 setData(udi, kli18n("Accessible").untranslatedText(), storageaccess->isAccessible()); 0607 } 0608 0609 return true; 0610 } 0611 0612 bool SolidDeviceEngine::updateInUse(const QString &udi) 0613 { 0614 Solid::Device device = m_devicemap.value(udi); 0615 if (!device.isValid()) { 0616 return false; 0617 } 0618 0619 Solid::StorageAccess *storageaccess = device.as<Solid::StorageAccess>(); 0620 if (!storageaccess) { 0621 return false; 0622 } 0623 0624 if (storageaccess->isAccessible()) { 0625 setData(udi, kli18n("In Use").untranslatedText(), true); 0626 } else { 0627 Solid::StorageDrive *drive = getAncestorAs<Solid::StorageDrive>(Solid::Device(udi)); 0628 if (drive) { 0629 setData(udi, kli18n("In Use").untranslatedText(), drive->isInUse()); 0630 } 0631 } 0632 0633 return true; 0634 } 0635 0636 bool SolidDeviceEngine::updateSourceEvent(const QString &source) 0637 { 0638 bool update1 = updateStorageSpace(source); 0639 bool update2 = updateHardDiskTemperature(source); 0640 bool update3 = updateEmblems(source); 0641 bool update4 = updateInUse(source); 0642 0643 return (update1 || update2 || update3 || update4); 0644 } 0645 0646 void SolidDeviceEngine::deviceRemoved(const QString &udi) 0647 { 0648 // libsolid cannot notify us when an encrypted container is closed, 0649 // hence we trigger an update when a device contained in an encrypted container device dies 0650 const QString containerUdi = m_encryptedContainerMap.value(udi, QString()); 0651 0652 if (!containerUdi.isEmpty()) { 0653 forceUpdateAccessibility(containerUdi); 0654 m_encryptedContainerMap.remove(udi); 0655 } 0656 0657 foreach (const QString &query, m_predicatemap.keys()) { 0658 m_predicatemap[query].removeAll(udi); 0659 setData(query, m_predicatemap[query]); 0660 } 0661 0662 Solid::Device device(udi); 0663 if (device.is<Solid::StorageVolume>()) { 0664 Solid::StorageAccess *access = device.as<Solid::StorageAccess>(); 0665 if (access) { 0666 disconnect(access, nullptr, this, nullptr); 0667 } 0668 } else if (device.is<Solid::OpticalDisc>()) { 0669 Solid::OpticalDrive *drive = getAncestorAs<Solid::OpticalDrive>(device); 0670 if (drive) { 0671 disconnect(drive, nullptr, this, nullptr); 0672 } 0673 } 0674 0675 m_devicemap.remove(udi); 0676 removeSource(udi); 0677 } 0678 0679 void SolidDeviceEngine::deviceChanged(const QString &udi, const QString &property, const QVariant &value) 0680 { 0681 setData(udi, property, value); 0682 updateSourceEvent(udi); 0683 } 0684 0685 K_PLUGIN_CLASS_WITH_JSON(SolidDeviceEngine, "plasma-dataengine-soliddevice.json") 0686 0687 #include "soliddeviceengine.moc"