1 | /* |
2 | This file is part of the KDE project |
3 | SPDX-FileCopyrightText: 2007 Kevin Ottens <ervin@kde.org> |
4 | |
5 | SPDX-License-Identifier: LGPL-2.0-only |
6 | */ |
7 | |
8 | #include "kfileplacesitem_p.h" |
9 | |
10 | #include <QDateTime> |
11 | #include <QDir> |
12 | #include <QIcon> |
13 | |
14 | #include <KBookmarkManager> |
15 | #include <KConfig> |
16 | #include <KConfigGroup> |
17 | #include <KIconUtils> |
18 | #include <KLocalizedString> |
19 | #include <KMountPoint> |
20 | #include <kprotocolinfo.h> |
21 | #include <solid/block.h> |
22 | #include <solid/genericinterface.h> |
23 | #include <solid/networkshare.h> |
24 | #include <solid/opticaldisc.h> |
25 | #include <solid/opticaldrive.h> |
26 | #include <solid/portablemediaplayer.h> |
27 | #include <solid/storageaccess.h> |
28 | #include <solid/storagedrive.h> |
29 | #include <solid/storagevolume.h> |
30 | |
31 | static bool isTrash(const KBookmark &bk) |
32 | { |
33 | return bk.url().toString() == QLatin1String("trash:/" ); |
34 | } |
35 | |
36 | KFilePlacesItem::KFilePlacesItem(KBookmarkManager *manager, const QString &address, const QString &udi, KFilePlacesModel *parent) |
37 | : QObject(static_cast<QObject *>(parent)) |
38 | , m_manager(manager) |
39 | , m_folderIsEmpty(true) |
40 | , m_isCdrom(false) |
41 | , m_isAccessible(false) |
42 | , m_isTeardownAllowed(false) |
43 | , m_isTeardownOverlayRecommended(false) |
44 | , m_isTeardownInProgress(false) |
45 | , m_isSetupInProgress(false) |
46 | , m_isEjectInProgress(false) |
47 | , m_isReadOnly(false) |
48 | { |
49 | updateDeviceInfo(udi); |
50 | |
51 | setBookmark(m_manager->findByAddress(address)); |
52 | |
53 | if (udi.isEmpty() && m_bookmark.metaDataItem(QStringLiteral("ID" )).isEmpty()) { |
54 | m_bookmark.setMetaDataItem(QStringLiteral("ID" ), value: generateNewId()); |
55 | } else if (udi.isEmpty()) { |
56 | if (isTrash(bk: m_bookmark)) { |
57 | KConfig cfg(QStringLiteral("trashrc" ), KConfig::SimpleConfig); |
58 | const KConfigGroup group = cfg.group(QStringLiteral("Status" )); |
59 | m_folderIsEmpty = group.readEntry(key: "Empty" , defaultValue: true); |
60 | } |
61 | } |
62 | |
63 | // Hide SSHFS network device mounted by kdeconnect, since we already have the kdeconnect:// place. |
64 | if (isDevice() && m_access && device().vendor() == QLatin1String("fuse.sshfs" )) { |
65 | const QString storageFilePath = m_access->filePath(); |
66 | // Not using findByPath() as it resolves symlinks, potentially blocking, |
67 | // but here we know we query for an existing actual mount point. |
68 | const auto mountPoints = KMountPoint::currentMountPoints(); |
69 | auto it = std::find_if(first: mountPoints.cbegin(), last: mountPoints.cend(), pred: [&storageFilePath](const KMountPoint::Ptr &mountPoint) { |
70 | return mountPoint->mountPoint() == storageFilePath; |
71 | }); |
72 | if (it != mountPoints.cend()) { |
73 | if ((*it)->mountedFrom().startsWith(s: QLatin1String("kdeconnect@" ))) { |
74 | // Hide only if the user never set the "Hide" checkbox on the device. |
75 | if (m_bookmark.metaDataItem(QStringLiteral("IsHidden" )).isEmpty()) { |
76 | setHidden(true); |
77 | } |
78 | } |
79 | } |
80 | } |
81 | } |
82 | |
83 | KFilePlacesItem::~KFilePlacesItem() |
84 | { |
85 | } |
86 | |
87 | QString KFilePlacesItem::id() const |
88 | { |
89 | if (isDevice()) { |
90 | return bookmark().metaDataItem(QStringLiteral("UDI" )); |
91 | } else { |
92 | return bookmark().metaDataItem(QStringLiteral("ID" )); |
93 | } |
94 | } |
95 | |
96 | bool KFilePlacesItem::hasSupportedScheme(const QStringList &schemes) const |
97 | { |
98 | if (schemes.isEmpty()) { |
99 | return true; |
100 | } |
101 | |
102 | // StorageAccess is always local, doesn't need to be accessible to know this |
103 | if (m_access && schemes.contains(str: QLatin1String("file" ))) { |
104 | return true; |
105 | } |
106 | |
107 | if (m_networkShare && schemes.contains(str: m_networkShare->url().scheme())) { |
108 | return true; |
109 | } |
110 | |
111 | if (m_player) { |
112 | const QStringList protocols = m_player->supportedProtocols(); |
113 | for (const QString &protocol : protocols) { |
114 | if (schemes.contains(str: protocol)) { |
115 | return true; |
116 | } |
117 | } |
118 | } |
119 | |
120 | return false; |
121 | } |
122 | |
123 | bool KFilePlacesItem::isDevice() const |
124 | { |
125 | return !bookmark().metaDataItem(QStringLiteral("UDI" )).isEmpty(); |
126 | } |
127 | |
128 | KFilePlacesModel::DeviceAccessibility KFilePlacesItem::deviceAccessibility() const |
129 | { |
130 | if (m_isTeardownInProgress || m_isEjectInProgress) { |
131 | return KFilePlacesModel::TeardownInProgress; |
132 | } else if (m_isSetupInProgress) { |
133 | return KFilePlacesModel::SetupInProgress; |
134 | } else if (m_isAccessible) { |
135 | return KFilePlacesModel::Accessible; |
136 | } else { |
137 | return KFilePlacesModel::SetupNeeded; |
138 | } |
139 | } |
140 | |
141 | bool KFilePlacesItem::isTeardownAllowed() const |
142 | { |
143 | return m_isTeardownAllowed; |
144 | } |
145 | |
146 | bool KFilePlacesItem::isTeardownOverlayRecommended() const |
147 | { |
148 | return m_isTeardownOverlayRecommended; |
149 | } |
150 | |
151 | bool KFilePlacesItem::isEjectAllowed() const |
152 | { |
153 | return m_isCdrom; |
154 | } |
155 | |
156 | KBookmark KFilePlacesItem::bookmark() const |
157 | { |
158 | return m_bookmark; |
159 | } |
160 | |
161 | void KFilePlacesItem::setBookmark(const KBookmark &bookmark) |
162 | { |
163 | m_bookmark = bookmark; |
164 | |
165 | if (m_device.isValid()) { |
166 | m_bookmark.setMetaDataItem(QStringLiteral("UDI" ), value: m_device.udi()); |
167 | if (m_volume && !m_volume->uuid().isEmpty()) { |
168 | m_bookmark.setMetaDataItem(QStringLiteral("uuid" ), value: m_volume->uuid()); |
169 | } |
170 | } |
171 | |
172 | if (bookmark.metaDataItem(QStringLiteral("isSystemItem" )) == QLatin1String("true" )) { |
173 | // This context must stay as it is - the translated system bookmark names |
174 | // are created with 'KFile System Bookmarks' as their context, so this |
175 | // ensures the right string is picked from the catalog. |
176 | // (coles, 13th May 2009) |
177 | |
178 | m_text = i18nc("KFile System Bookmarks" , bookmark.text().toUtf8().data()); |
179 | } else { |
180 | m_text = bookmark.text(); |
181 | } |
182 | |
183 | const KFilePlacesModel::GroupType type = groupType(); |
184 | switch (type) { |
185 | case KFilePlacesModel::PlacesType: |
186 | m_groupName = i18nc("@item" , "Places" ); |
187 | break; |
188 | case KFilePlacesModel::RemoteType: |
189 | m_groupName = i18nc("@item" , "Remote" ); |
190 | break; |
191 | case KFilePlacesModel::RecentlySavedType: |
192 | m_groupName = i18nc("@item The place group section name for recent dynamic lists" , "Recent" ); |
193 | break; |
194 | case KFilePlacesModel::SearchForType: |
195 | m_groupName = i18nc("@item" , "Search For" ); |
196 | break; |
197 | case KFilePlacesModel::DevicesType: |
198 | m_groupName = i18nc("@item" , "Devices" ); |
199 | break; |
200 | case KFilePlacesModel::RemovableDevicesType: |
201 | m_groupName = i18nc("@item" , "Removable Devices" ); |
202 | break; |
203 | case KFilePlacesModel::TagsType: |
204 | m_groupName = i18nc("@item" , "Tags" ); |
205 | break; |
206 | default: |
207 | Q_UNREACHABLE(); |
208 | break; |
209 | } |
210 | } |
211 | |
212 | Solid::Device KFilePlacesItem::device() const |
213 | { |
214 | return m_device; |
215 | } |
216 | |
217 | QVariant KFilePlacesItem::data(int role) const |
218 | { |
219 | if (role == KFilePlacesModel::GroupRole) { |
220 | return QVariant(m_groupName); |
221 | } else if (role != KFilePlacesModel::HiddenRole && role != Qt::BackgroundRole && isDevice()) { |
222 | return deviceData(role); |
223 | } else { |
224 | return bookmarkData(role); |
225 | } |
226 | } |
227 | |
228 | KFilePlacesModel::GroupType KFilePlacesItem::groupType() const |
229 | { |
230 | if (!isDevice()) { |
231 | const QString protocol = bookmark().url().scheme(); |
232 | if (protocol == QLatin1String("timeline" ) || protocol == QLatin1String("recentlyused" )) { |
233 | return KFilePlacesModel::RecentlySavedType; |
234 | } |
235 | |
236 | if (protocol.contains(s: QLatin1String("search" ))) { |
237 | return KFilePlacesModel::SearchForType; |
238 | } |
239 | |
240 | if (protocol == QLatin1String("bluetooth" ) || protocol == QLatin1String("obexftp" ) || protocol == QLatin1String("kdeconnect" )) { |
241 | return KFilePlacesModel::DevicesType; |
242 | } |
243 | |
244 | if (protocol == QLatin1String("tags" )) { |
245 | return KFilePlacesModel::TagsType; |
246 | } |
247 | |
248 | if (protocol == QLatin1String("remote" ) || KProtocolInfo::protocolClass(protocol) != QLatin1String(":local" )) { |
249 | return KFilePlacesModel::RemoteType; |
250 | } else { |
251 | return KFilePlacesModel::PlacesType; |
252 | } |
253 | } |
254 | |
255 | if (m_drive && (m_drive->isHotpluggable() || m_drive->isRemovable())) { |
256 | return KFilePlacesModel::RemovableDevicesType; |
257 | } else if (m_networkShare) { |
258 | return KFilePlacesModel::RemoteType; |
259 | } else { |
260 | return KFilePlacesModel::DevicesType; |
261 | } |
262 | } |
263 | |
264 | bool KFilePlacesItem::isHidden() const |
265 | { |
266 | return m_bookmark.metaDataItem(QStringLiteral("IsHidden" )) == QLatin1String("true" ); |
267 | } |
268 | |
269 | void KFilePlacesItem::setHidden(bool hide) |
270 | { |
271 | if (m_bookmark.isNull() || isHidden() == hide) { |
272 | return; |
273 | } |
274 | m_bookmark.setMetaDataItem(QStringLiteral("IsHidden" ), value: hide ? QStringLiteral("true" ) : QStringLiteral("false" )); |
275 | } |
276 | |
277 | QVariant KFilePlacesItem::bookmarkData(int role) const |
278 | { |
279 | KBookmark b = bookmark(); |
280 | |
281 | if (b.isNull()) { |
282 | return QVariant(); |
283 | } |
284 | |
285 | switch (role) { |
286 | case Qt::DisplayRole: |
287 | return m_text; |
288 | case Qt::DecorationRole: |
289 | return QIcon::fromTheme(name: iconNameForBookmark(bookmark: b)); |
290 | case Qt::BackgroundRole: |
291 | if (isHidden()) { |
292 | return QColor(Qt::lightGray); |
293 | } else { |
294 | return QVariant(); |
295 | } |
296 | case KFilePlacesModel::UrlRole: |
297 | return b.url(); |
298 | case KFilePlacesModel::SetupNeededRole: |
299 | return false; |
300 | case KFilePlacesModel::HiddenRole: |
301 | return isHidden(); |
302 | case KFilePlacesModel::IconNameRole: |
303 | return iconNameForBookmark(bookmark: b); |
304 | default: |
305 | return QVariant(); |
306 | } |
307 | } |
308 | |
309 | QVariant KFilePlacesItem::deviceData(int role) const |
310 | { |
311 | Solid::Device d = device(); |
312 | |
313 | if (d.isValid()) { |
314 | switch (role) { |
315 | case Qt::DisplayRole: |
316 | if (m_deviceDisplayName.isEmpty()) { |
317 | m_deviceDisplayName = d.displayName(); |
318 | } |
319 | return m_deviceDisplayName; |
320 | case Qt::DecorationRole: |
321 | // qDebug() << "adding emblems" << m_emblems << "to device icon" << m_deviceIconName; |
322 | return KIconUtils::addOverlays(iconName: m_deviceIconName, overlays: m_emblems); |
323 | case KFilePlacesModel::UrlRole: |
324 | if (m_access) { |
325 | const QString path = m_access->filePath(); |
326 | return path.isEmpty() ? QUrl() : QUrl::fromLocalFile(localfile: path); |
327 | } else if (m_disc && (m_disc->availableContent() & Solid::OpticalDisc::Audio) != 0) { |
328 | Solid::Block *block = d.as<Solid::Block>(); |
329 | if (block) { |
330 | QString device = block->device(); |
331 | return QUrl(QStringLiteral("audiocd:/?device=%1" ).arg(a: device)); |
332 | } |
333 | // We failed to get the block device. Assume audiocd:/ can |
334 | // figure it out, but cannot handle multiple disc drives. |
335 | // See https://bugs.kde.org/show_bug.cgi?id=314544#c40 |
336 | return QUrl(QStringLiteral("audiocd:/" )); |
337 | } else if (m_player) { |
338 | const QStringList protocols = m_player->supportedProtocols(); |
339 | if (!protocols.isEmpty()) { |
340 | const QString protocol = protocols.first(); |
341 | if (protocol == QLatin1String("mtp" )) { |
342 | return QUrl(QStringLiteral("%1:udi=%2" ).arg(args: protocol, args: d.udi())); |
343 | } else { |
344 | QUrl url; |
345 | url.setScheme(protocol); |
346 | url.setHost(host: d.udi().section(asep: QLatin1Char('/'), astart: -1)); |
347 | url.setPath(QStringLiteral("/" )); |
348 | return url; |
349 | } |
350 | } |
351 | return QVariant(); |
352 | } else { |
353 | return QVariant(); |
354 | } |
355 | case KFilePlacesModel::SetupNeededRole: |
356 | if (m_access) { |
357 | return !m_isAccessible; |
358 | } else { |
359 | return QVariant(); |
360 | } |
361 | |
362 | case KFilePlacesModel::TeardownAllowedRole: |
363 | if (m_access) { |
364 | return m_isTeardownAllowed; |
365 | } else { |
366 | return QVariant(); |
367 | } |
368 | |
369 | case KFilePlacesModel::EjectAllowedRole: |
370 | return m_isAccessible && m_isCdrom; |
371 | |
372 | case KFilePlacesModel::TeardownOverlayRecommendedRole: |
373 | return m_isTeardownOverlayRecommended; |
374 | |
375 | case KFilePlacesModel::DeviceAccessibilityRole: |
376 | return deviceAccessibility(); |
377 | |
378 | case KFilePlacesModel::FixedDeviceRole: { |
379 | if (m_drive != nullptr) { |
380 | return !m_drive->isHotpluggable() && !m_drive->isRemovable(); |
381 | } |
382 | return true; |
383 | } |
384 | |
385 | case KFilePlacesModel::CapacityBarRecommendedRole: |
386 | return m_isAccessible && !m_isCdrom && !m_networkShare && !m_isReadOnly; |
387 | |
388 | case KFilePlacesModel::IconNameRole: |
389 | return m_deviceIconName; |
390 | |
391 | default: |
392 | return QVariant(); |
393 | } |
394 | } else { |
395 | return QVariant(); |
396 | } |
397 | } |
398 | |
399 | KBookmark KFilePlacesItem::createBookmark(KBookmarkManager *manager, const QString &label, const QUrl &url, const QString &iconName, KFilePlacesItem *after) |
400 | { |
401 | KBookmarkGroup root = manager->root(); |
402 | if (root.isNull()) { |
403 | return KBookmark(); |
404 | } |
405 | QString empty_icon = iconName; |
406 | if (url.toString() == QLatin1String("trash:/" )) { |
407 | if (empty_icon.endsWith(s: QLatin1String("-full" ))) { |
408 | empty_icon.chop(n: 5); |
409 | } else if (empty_icon.isEmpty()) { |
410 | empty_icon = QStringLiteral("user-trash" ); |
411 | } |
412 | } |
413 | KBookmark bookmark = root.addBookmark(text: label, url, icon: empty_icon); |
414 | bookmark.setMetaDataItem(QStringLiteral("ID" ), value: generateNewId()); |
415 | |
416 | if (after) { |
417 | root.moveBookmark(bookmark, after: after->bookmark()); |
418 | } |
419 | |
420 | return bookmark; |
421 | } |
422 | |
423 | KBookmark KFilePlacesItem::createSystemBookmark(KBookmarkManager *manager, |
424 | const char *untranslatedLabel, |
425 | const QUrl &url, |
426 | const QString &iconName, |
427 | const KBookmark &after) |
428 | { |
429 | KBookmark bookmark = createBookmark(manager, label: QString::fromUtf8(utf8: untranslatedLabel), url, iconName); |
430 | if (!bookmark.isNull()) { |
431 | bookmark.setMetaDataItem(QStringLiteral("isSystemItem" ), QStringLiteral("true" )); |
432 | } |
433 | if (!after.isNull()) { |
434 | manager->root().moveBookmark(bookmark, after); |
435 | } |
436 | return bookmark; |
437 | } |
438 | |
439 | KBookmark KFilePlacesItem::createDeviceBookmark(KBookmarkManager *manager, const Solid::Device &device) |
440 | { |
441 | KBookmarkGroup root = manager->root(); |
442 | if (root.isNull()) { |
443 | return KBookmark(); |
444 | } |
445 | KBookmark bookmark = root.createNewSeparator(); |
446 | bookmark.setMetaDataItem(QStringLiteral("UDI" ), value: device.udi()); |
447 | bookmark.setMetaDataItem(QStringLiteral("isSystemItem" ), QStringLiteral("true" )); |
448 | |
449 | const auto storage = device.as<Solid::StorageVolume>(); |
450 | if (storage) { |
451 | bookmark.setMetaDataItem(QStringLiteral("uuid" ), value: storage->uuid()); |
452 | } |
453 | return bookmark; |
454 | } |
455 | |
456 | KBookmark KFilePlacesItem::createTagBookmark(KBookmarkManager *manager, const QString &tag) |
457 | { |
458 | // TODO: Currently KFilePlacesItem::setBookmark() only decides by the "isSystemItem" property |
459 | // if the label text should be looked up for translation. So there is a small risk that |
460 | // labelTexts which match existing untranslated system labels accidentally get translated. |
461 | KBookmark bookmark = createBookmark(manager, label: tag, url: QUrl(QLatin1String("tags:/" ) + tag), QStringLiteral("tag" )); |
462 | if (!bookmark.isNull()) { |
463 | bookmark.setMetaDataItem(QStringLiteral("tag" ), value: tag); |
464 | bookmark.setMetaDataItem(QStringLiteral("isSystemItem" ), QStringLiteral("true" )); |
465 | } |
466 | |
467 | return bookmark; |
468 | } |
469 | |
470 | QString KFilePlacesItem::generateNewId() |
471 | { |
472 | static int count = 0; |
473 | |
474 | // return QString::number(count++); |
475 | |
476 | return QString::number(QDateTime::currentSecsSinceEpoch()) + QLatin1Char('/') + QString::number(count++); |
477 | |
478 | // return QString::number(QDateTime::currentSecsSinceEpoch()) |
479 | // + '/' + QString::number(qrand()); |
480 | } |
481 | |
482 | bool KFilePlacesItem::updateDeviceInfo(const QString &udi) |
483 | { |
484 | if (m_device.udi() == udi) { |
485 | return false; |
486 | } |
487 | |
488 | if (m_access) { |
489 | m_access->disconnect(receiver: this); |
490 | } |
491 | |
492 | if (m_opticalDrive) { |
493 | m_opticalDrive->disconnect(receiver: this); |
494 | } |
495 | |
496 | m_device = Solid::Device(udi); |
497 | if (m_device.isValid()) { |
498 | m_access = m_device.as<Solid::StorageAccess>(); |
499 | m_volume = m_device.as<Solid::StorageVolume>(); |
500 | m_disc = m_device.as<Solid::OpticalDisc>(); |
501 | m_player = m_device.as<Solid::PortableMediaPlayer>(); |
502 | m_networkShare = m_device.as<Solid::NetworkShare>(); |
503 | m_deviceIconName = m_device.icon(); |
504 | m_emblems = m_device.emblems(); |
505 | |
506 | m_drive = nullptr; |
507 | m_opticalDrive = nullptr; |
508 | |
509 | Solid::Device parentDevice = m_device; |
510 | while (parentDevice.isValid() && !m_drive) { |
511 | m_drive = parentDevice.as<Solid::StorageDrive>(); |
512 | m_opticalDrive = parentDevice.as<Solid::OpticalDrive>(); |
513 | parentDevice = parentDevice.parent(); |
514 | } |
515 | |
516 | if (m_access) { |
517 | connect(sender: m_access.data(), signal: &Solid::StorageAccess::setupRequested, context: this, slot: [this] { |
518 | m_isSetupInProgress = true; |
519 | Q_EMIT itemChanged(id: id(), roles: {KFilePlacesModel::DeviceAccessibilityRole}); |
520 | }); |
521 | connect(sender: m_access.data(), signal: &Solid::StorageAccess::setupDone, context: this, slot: [this] { |
522 | m_isSetupInProgress = false; |
523 | Q_EMIT itemChanged(id: id(), roles: {KFilePlacesModel::DeviceAccessibilityRole}); |
524 | }); |
525 | |
526 | connect(sender: m_access.data(), signal: &Solid::StorageAccess::teardownRequested, context: this, slot: [this] { |
527 | m_isTeardownInProgress = true; |
528 | Q_EMIT itemChanged(id: id(), roles: {KFilePlacesModel::DeviceAccessibilityRole}); |
529 | }); |
530 | connect(sender: m_access.data(), signal: &Solid::StorageAccess::teardownDone, context: this, slot: [this] { |
531 | m_isTeardownInProgress = false; |
532 | Q_EMIT itemChanged(id: id(), roles: {KFilePlacesModel::DeviceAccessibilityRole}); |
533 | }); |
534 | |
535 | connect(sender: m_access.data(), signal: &Solid::StorageAccess::accessibilityChanged, context: this, slot: &KFilePlacesItem::onAccessibilityChanged); |
536 | onAccessibilityChanged(m_access->isAccessible()); |
537 | } |
538 | |
539 | if (m_opticalDrive) { |
540 | connect(sender: m_opticalDrive.data(), signal: &Solid::OpticalDrive::ejectRequested, context: this, slot: [this] { |
541 | m_isEjectInProgress = true; |
542 | Q_EMIT itemChanged(id: id(), roles: {KFilePlacesModel::DeviceAccessibilityRole}); |
543 | }); |
544 | connect(sender: m_opticalDrive.data(), signal: &Solid::OpticalDrive::ejectDone, context: this, slot: [this] { |
545 | m_isEjectInProgress = false; |
546 | Q_EMIT itemChanged(id: id(), roles: {KFilePlacesModel::DeviceAccessibilityRole}); |
547 | }); |
548 | } |
549 | } else { |
550 | m_access = nullptr; |
551 | m_volume = nullptr; |
552 | m_disc = nullptr; |
553 | m_player = nullptr; |
554 | m_drive = nullptr; |
555 | m_opticalDrive = nullptr; |
556 | m_networkShare = nullptr; |
557 | m_deviceIconName.clear(); |
558 | m_emblems.clear(); |
559 | } |
560 | |
561 | return true; |
562 | } |
563 | |
564 | void KFilePlacesItem::onAccessibilityChanged(bool isAccessible) |
565 | { |
566 | m_isAccessible = isAccessible; |
567 | m_isCdrom = m_device.is<Solid::OpticalDrive>() || m_opticalDrive || (m_volume && m_volume->fsType() == QLatin1String("iso9660" )); |
568 | m_emblems = m_device.emblems(); |
569 | |
570 | if (auto generic = m_device.as<Solid::GenericInterface>()) { |
571 | // TODO add Solid API for this. |
572 | m_isReadOnly = generic->property(QStringLiteral("ReadOnly" )).toBool(); |
573 | } |
574 | |
575 | m_isTeardownAllowed = isAccessible; |
576 | if (m_isTeardownAllowed) { |
577 | if (m_access->filePath() == QDir::rootPath()) { |
578 | m_isTeardownAllowed = false; |
579 | } else { |
580 | KMountPoint::Ptr mountPoint = KMountPoint::currentMountPoints().findByPath(path: QDir::homePath()); |
581 | if (mountPoint && m_access->filePath() == mountPoint->mountPoint()) { |
582 | m_isTeardownAllowed = false; |
583 | } |
584 | } |
585 | } |
586 | |
587 | m_isTeardownOverlayRecommended = m_isTeardownAllowed && !m_networkShare; |
588 | if (m_isTeardownOverlayRecommended) { |
589 | if (m_drive && !m_drive->isHotpluggable() && !m_drive->isRemovable()) { |
590 | m_isTeardownOverlayRecommended = false; |
591 | } |
592 | } |
593 | |
594 | Q_EMIT itemChanged(id: id()); |
595 | } |
596 | |
597 | QString KFilePlacesItem::iconNameForBookmark(const KBookmark &bookmark) const |
598 | { |
599 | if (!m_folderIsEmpty && isTrash(bk: bookmark)) { |
600 | return bookmark.icon() + QLatin1String("-full" ); |
601 | } else { |
602 | return bookmark.icon(); |
603 | } |
604 | } |
605 | |
606 | #include "moc_kfileplacesitem_p.cpp" |
607 | |