1 | /* |
2 | This file is part of the KDE Baloo project. |
3 | SPDX-FileCopyrightText: 2011 Sebastian Trueg <trueg@kde.org> |
4 | SPDX-FileCopyrightText: 2014 Vishesh Handa <vhanda@kde.org> |
5 | |
6 | SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL |
7 | */ |
8 | |
9 | #include "storagedevices.h" |
10 | #include "baloodebug.h" |
11 | |
12 | #include <Solid/DeviceNotifier> |
13 | #include <Solid/DeviceInterface> |
14 | #include <Solid/Block> |
15 | #include <Solid/StorageDrive> |
16 | #include <Solid/StorageVolume> |
17 | #include <Solid/StorageAccess> |
18 | #include <Solid/NetworkShare> |
19 | #include <Solid/OpticalDisc> |
20 | #include <Solid/Predicate> |
21 | |
22 | using namespace Baloo; |
23 | |
24 | StorageDevices::StorageDevices(QObject* parent) |
25 | : QObject(parent) |
26 | { |
27 | connect(sender: Solid::DeviceNotifier::instance(), signal: &Solid::DeviceNotifier::deviceAdded, |
28 | context: this, slot: &StorageDevices::slotSolidDeviceAdded); |
29 | connect(sender: Solid::DeviceNotifier::instance(), signal: &Solid::DeviceNotifier::deviceRemoved, |
30 | context: this, slot: &StorageDevices::slotSolidDeviceRemoved); |
31 | |
32 | initCacheEntries(); |
33 | } |
34 | |
35 | StorageDevices::~StorageDevices() |
36 | { |
37 | } |
38 | |
39 | void StorageDevices::initCacheEntries() |
40 | { |
41 | const QList<Solid::Device> devices = Solid::Device::allDevices(); |
42 | for (const Solid::Device& dev : devices) { |
43 | createCacheEntry(dev); |
44 | } |
45 | } |
46 | |
47 | QList<StorageDevices::Entry> StorageDevices::allMedia() const |
48 | { |
49 | return m_metadataCache.values(); |
50 | } |
51 | |
52 | StorageDevices::Entry* StorageDevices::createCacheEntry(const Solid::Device& dev) |
53 | { |
54 | if (dev.udi().isEmpty()) { |
55 | return nullptr; |
56 | } |
57 | |
58 | const Solid::StorageAccess* storage = dev.as<Solid::StorageAccess>(); |
59 | if (!storage) { |
60 | return nullptr; |
61 | } |
62 | |
63 | Entry entry(dev); |
64 | auto it = m_metadataCache.insert(key: dev.udi(), value: entry); |
65 | |
66 | connect(sender: storage, signal: &Solid::StorageAccess::accessibilityChanged, |
67 | context: this, slot: &StorageDevices::slotAccessibilityChanged); |
68 | //connect(storage, SIGNAL(teardownRequested(QString)), |
69 | // this, SLOT(slotTeardownRequested(QString))); |
70 | return &it.value(); |
71 | } |
72 | |
73 | bool StorageDevices::isEmpty() const |
74 | { |
75 | return m_metadataCache.isEmpty(); |
76 | } |
77 | |
78 | void StorageDevices::slotSolidDeviceAdded(const QString& udi) |
79 | { |
80 | qCDebug(BALOO) << udi; |
81 | Entry* e = createCacheEntry(dev: Solid::Device(udi)); |
82 | if (e) { |
83 | Q_EMIT deviceAdded(entry: e); |
84 | } |
85 | } |
86 | |
87 | void StorageDevices::slotSolidDeviceRemoved(const QString& udi) |
88 | { |
89 | QHash< QString, Entry >::iterator it = m_metadataCache.find(key: udi); |
90 | if (it != m_metadataCache.end()) { |
91 | qCDebug(BALOO) << "Found removable storage volume for Baloo undocking:" << udi; |
92 | Q_EMIT deviceRemoved(entry: &it.value()); |
93 | m_metadataCache.erase(it); |
94 | } |
95 | } |
96 | |
97 | void StorageDevices::slotAccessibilityChanged(bool accessible, const QString& udi) |
98 | { |
99 | qCDebug(BALOO) << accessible << udi; |
100 | Q_UNUSED(accessible); |
101 | |
102 | // |
103 | // cache new mount path |
104 | // |
105 | Entry* entry = &m_metadataCache[udi]; |
106 | Q_ASSERT(entry != nullptr); |
107 | Q_EMIT deviceAccessibilityChanged(entry); |
108 | } |
109 | |
110 | StorageDevices::Entry::Entry() |
111 | { |
112 | } |
113 | |
114 | StorageDevices::Entry::Entry(const Solid::Device& device) |
115 | : m_device(device) |
116 | { |
117 | } |
118 | |
119 | QString StorageDevices::Entry::mountPath() const |
120 | { |
121 | if (const Solid::StorageAccess* sa = m_device.as<Solid::StorageAccess>()) { |
122 | return sa->filePath(); |
123 | } else { |
124 | return QString(); |
125 | } |
126 | } |
127 | |
128 | bool StorageDevices::Entry::isMounted() const |
129 | { |
130 | if (const Solid::StorageAccess* sa = m_device.as<Solid::StorageAccess>()) { |
131 | return sa->isAccessible(); |
132 | } else { |
133 | return false; |
134 | } |
135 | } |
136 | |
137 | bool StorageDevices::Entry::isUsable() const |
138 | { |
139 | if (mountPath().isEmpty()) { |
140 | return false; |
141 | } |
142 | |
143 | bool usable = true; |
144 | |
145 | const Solid::Device& dev = m_device; |
146 | if (dev.is<Solid::StorageVolume>() && dev.parent().is<Solid::StorageDrive>()) { |
147 | auto parent = dev.parent().as<Solid::StorageDrive>(); |
148 | if (parent->isRemovable() || parent->isHotpluggable()) { |
149 | usable = false; |
150 | } |
151 | |
152 | const Solid::StorageVolume* volume = dev.as<Solid::StorageVolume>(); |
153 | if (volume->isIgnored() || volume->usage() != Solid::StorageVolume::FileSystem) { |
154 | usable = false; |
155 | } |
156 | } |
157 | |
158 | if (dev.is<Solid::NetworkShare>()) { |
159 | usable = false; |
160 | } else if (dev.is<Solid::OpticalDisc>()) { |
161 | usable = false; |
162 | } else if (dev.is<Solid::StorageAccess>() && dev.parentUdi() == QStringLiteral("/org/kde/fstab" )) { |
163 | usable = false; |
164 | } |
165 | |
166 | if (usable) { |
167 | if (const Solid::StorageAccess* sa = dev.as<Solid::StorageAccess>()) { |
168 | usable = sa->isAccessible(); |
169 | } |
170 | } |
171 | |
172 | return usable; |
173 | } |
174 | |
175 | #include "moc_storagedevices.cpp" |
176 | |