1 /*
2 SPDX-FileCopyrightText: 2020 Harald Sitter <sitter@kde.org>
3 SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
4 */
5
6 #include "smbmountmodel.h"
7
8 #include <QDebug>
9 #include <QIcon>
10 #include <QMetaEnum>
11 #include <Solid/DeviceInterface>
12 #include <Solid/DeviceNotifier>
13 #include <Solid/NetworkShare>
14 #include <Solid/StorageAccess>
15
SmbMountModel(QObject * parent)16 SmbMountModel::SmbMountModel(QObject *parent)
17 : QAbstractListModel(parent)
18 {
19 connect(Solid::DeviceNotifier::instance(), &Solid::DeviceNotifier::deviceAdded, this, &SmbMountModel::addDevice);
20 connect(Solid::DeviceNotifier::instance(), &Solid::DeviceNotifier::deviceRemoved, this, &SmbMountModel::removeDevice);
21 metaObject()->invokeMethod(this, &SmbMountModel::reloadData);
22 }
23
24 SmbMountModel::~SmbMountModel() = default;
25
rowCount(const QModelIndex & parent) const26 int SmbMountModel::rowCount(const QModelIndex &parent) const
27 {
28 Q_UNUSED(parent)
29 return m_devices.size();
30 }
31
data(const QModelIndex & index,int intRole) const32 QVariant SmbMountModel::data(const QModelIndex &index, int intRole) const
33 {
34 if (!index.isValid()) {
35 return {};
36 }
37
38 Q_ASSERT(index.row() < m_devices.count());
39
40 static QMetaEnum roleEnum = QMetaEnum::fromType<Role>();
41 if (roleEnum.valueToKey(intRole) == nullptr) {
42 return {};
43 }
44 const auto role = static_cast<Role>(intRole);
45
46 const Solid::Device &device = m_devices.at(index.row());
47 switch (role) {
48 case Role::Share:
49 return device.as<Solid::NetworkShare>()->url();
50 case Role::Path:
51 return device.as<Solid::StorageAccess>()->filePath();
52 case Role::Accessible:
53 return device.as<Solid::StorageAccess>()->isAccessible();
54 }
55
56 return {};
57 }
58
addDevice(const QString & udi)59 void SmbMountModel::addDevice(const QString &udi)
60 {
61 auto it = deviceForUdi(udi);
62 if (it != m_devices.constEnd()) {
63 return; // already in the list
64 }
65
66 Solid::Device device(udi);
67 if (!device.is<Solid::NetworkShare>()) {
68 return;
69 }
70
71 beginInsertRows(QModelIndex(), m_devices.count(), m_devices.count());
72 m_devices.append(device);
73 endInsertRows();
74 }
75
removeDevice(const QString & udi)76 void SmbMountModel::removeDevice(const QString &udi)
77 {
78 auto it = deviceForUdi(udi);
79 if (it == m_devices.constEnd()) {
80 return; // untracked udi
81 }
82
83 const int index = static_cast<int>(std::distance(m_devices.constBegin(), it));
84 beginRemoveRows(QModelIndex(), index, index);
85 m_devices.removeAt(index);
86 endRemoveRows();
87 }
88
reloadData()89 void SmbMountModel::reloadData()
90 {
91 beginResetModel();
92 m_devices.clear();
93 const auto devices = Solid::Device::listFromType(Solid::DeviceInterface::NetworkShare);
94 for (auto it = devices.begin(); it != devices.end(); ++it) {
95 if (!it->is<Solid::NetworkShare>()) {
96 // Workaround in case listFromType still gives incorrect types.
97 // https://bugs.kde.org/show_bug.cgi?id=419220
98 continue;
99 }
100 switch (it->as<Solid::NetworkShare>()->type()) {
101 case Solid::NetworkShare::Cifs:
102 m_devices.append(*it);
103 continue;
104 case Solid::NetworkShare::Nfs:
105 case Solid::NetworkShare::Unknown:
106 continue;
107 }
108 }
109 endResetModel();
110 }
111
hasChildren(const QModelIndex & parent) const112 bool SmbMountModel::hasChildren(const QModelIndex &parent) const
113 {
114 return !parent.isValid() ? false : (rowCount(parent) > 0);
115 }
116
roleNames() const117 QHash<int, QByteArray> SmbMountModel::roleNames() const
118 {
119 static QHash<int, QByteArray> roles;
120 if (!roles.isEmpty()) {
121 return roles;
122 }
123
124 const QMetaEnum roleEnum = QMetaEnum::fromType<Role>();
125 for (int i = 0; i < roleEnum.keyCount(); ++i) {
126 const int value = roleEnum.value(i);
127 Q_ASSERT(value != -1);
128 roles[static_cast<int>(value)] = QByteArray("ROLE_") + roleEnum.valueToKey(value);
129 }
130 return roles;
131 }
132