File indexing completed on 2024-04-21 03:51:46

0001 /*
0002     This file is part of the KDE Baloo project.
0003     SPDX-FileCopyrightText: 2011 Sebastian Trueg <trueg@kde.org>
0004     SPDX-FileCopyrightText: 2014 Vishesh Handa <vhanda@kde.org>
0005 
0006     SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
0007 */
0008 
0009 #include "storagedevices.h"
0010 #include "baloodebug.h"
0011 
0012 #include <Solid/DeviceNotifier>
0013 #include <Solid/DeviceInterface>
0014 #include <Solid/Block>
0015 #include <Solid/StorageDrive>
0016 #include <Solid/StorageVolume>
0017 #include <Solid/StorageAccess>
0018 #include <Solid/NetworkShare>
0019 #include <Solid/OpticalDisc>
0020 #include <Solid/Predicate>
0021 
0022 using namespace Baloo;
0023 
0024 StorageDevices::StorageDevices(QObject* parent)
0025     : QObject(parent)
0026 {
0027     connect(Solid::DeviceNotifier::instance(), &Solid::DeviceNotifier::deviceAdded,
0028             this, &StorageDevices::slotSolidDeviceAdded);
0029     connect(Solid::DeviceNotifier::instance(), &Solid::DeviceNotifier::deviceRemoved,
0030             this, &StorageDevices::slotSolidDeviceRemoved);
0031 
0032     initCacheEntries();
0033 }
0034 
0035 StorageDevices::~StorageDevices()
0036 {
0037 }
0038 
0039 void StorageDevices::initCacheEntries()
0040 {
0041     const QList<Solid::Device> devices
0042         = Solid::Device::listFromQuery(QStringLiteral("StorageVolume.usage=='FileSystem'"))
0043           + Solid::Device::listFromType(Solid::DeviceInterface::NetworkShare);
0044     for (const Solid::Device& dev : devices) {
0045         createCacheEntry(dev);
0046     }
0047 }
0048 
0049 QList<StorageDevices::Entry> StorageDevices::allMedia() const
0050 {
0051     return m_metadataCache.values();
0052 }
0053 
0054 StorageDevices::Entry* StorageDevices::createCacheEntry(const Solid::Device& dev)
0055 {
0056     if (dev.udi().isEmpty()) {
0057         return nullptr;
0058     }
0059 
0060     const Solid::StorageAccess* storage = dev.as<Solid::StorageAccess>();
0061     if (!storage) {
0062         return nullptr;
0063     }
0064 
0065     Entry entry(dev);
0066     auto it = m_metadataCache.insert(dev.udi(), entry);
0067 
0068     connect(storage, &Solid::StorageAccess::accessibilityChanged,
0069             this, &StorageDevices::slotAccessibilityChanged);
0070     //connect(storage, SIGNAL(teardownRequested(QString)),
0071     //        this, SLOT(slotTeardownRequested(QString)));
0072     return &it.value();
0073 }
0074 
0075 bool StorageDevices::isEmpty() const
0076 {
0077     return m_metadataCache.isEmpty();
0078 }
0079 
0080 void StorageDevices::slotSolidDeviceAdded(const QString& udi)
0081 {
0082     qCDebug(BALOO) << udi;
0083     Entry* e = createCacheEntry(Solid::Device(udi));
0084     if (e) {
0085         Q_EMIT deviceAdded(e);
0086     }
0087 }
0088 
0089 void StorageDevices::slotSolidDeviceRemoved(const QString& udi)
0090 {
0091     QHash< QString, Entry >::iterator it = m_metadataCache.find(udi);
0092     if (it != m_metadataCache.end()) {
0093         qCDebug(BALOO) << "Found removable storage volume for Baloo undocking:" << udi;
0094         Q_EMIT deviceRemoved(&it.value());
0095         m_metadataCache.erase(it);
0096     }
0097 }
0098 
0099 void StorageDevices::slotAccessibilityChanged(bool accessible, const QString& udi)
0100 {
0101     qCDebug(BALOO) << accessible << udi;
0102     Q_UNUSED(accessible);
0103 
0104     //
0105     // cache new mount path
0106     //
0107     Entry* entry = &m_metadataCache[udi];
0108     Q_ASSERT(entry != nullptr);
0109     Q_EMIT deviceAccessibilityChanged(entry);
0110 }
0111 
0112 StorageDevices::Entry::Entry()
0113 {
0114 }
0115 
0116 StorageDevices::Entry::Entry(const Solid::Device& device)
0117     : m_device(device)
0118 {
0119 }
0120 
0121 QString StorageDevices::Entry::mountPath() const
0122 {
0123     if (const Solid::StorageAccess* sa = m_device.as<Solid::StorageAccess>()) {
0124         return sa->filePath();
0125     } else {
0126         return QString();
0127     }
0128 }
0129 
0130 bool StorageDevices::Entry::isMounted() const
0131 {
0132     if (const Solid::StorageAccess* sa = m_device.as<Solid::StorageAccess>()) {
0133         return sa->isAccessible();
0134     } else {
0135         return false;
0136     }
0137 }
0138 
0139 bool StorageDevices::Entry::isUsable() const
0140 {
0141     if (mountPath().isEmpty()) {
0142         return false;
0143     }
0144 
0145     bool usable = true;
0146 
0147     const Solid::Device& dev = m_device;
0148     if (dev.is<Solid::StorageVolume>() && dev.parent().is<Solid::StorageDrive>()) {
0149         auto parent = dev.parent().as<Solid::StorageDrive>();
0150         if (parent->isRemovable() || parent->isHotpluggable()) {
0151             usable = false;
0152         }
0153 
0154         const Solid::StorageVolume* volume = dev.as<Solid::StorageVolume>();
0155         if (volume->isIgnored() || volume->usage() != Solid::StorageVolume::FileSystem) {
0156             usable = false;
0157         }
0158     }
0159 
0160     if (dev.is<Solid::NetworkShare>()) {
0161         usable = false;
0162     } else if (dev.is<Solid::OpticalDisc>()) {
0163         usable = false;
0164     }
0165 
0166     if (usable) {
0167         if (const Solid::StorageAccess* sa = dev.as<Solid::StorageAccess>()) {
0168             usable = sa->isAccessible();
0169         }
0170     }
0171 
0172     return usable;
0173 }
0174 
0175 #include "moc_storagedevices.cpp"