From 358926370b363dfd3de157b83501f8dade97fcdd Mon Sep 17 00:00:00 2001 From: cutefishd Date: Tue, 30 Mar 2021 09:48:59 +0800 Subject: [PATCH] Support mount devices --- model/foldermodel.cpp | 3 ++ model/pathbarmodel.cpp | 3 +- model/placesitem.cpp | 48 ++++++++++++++++++++++++++++++++ model/placesitem.h | 19 +++++++++++++ model/placesmodel.cpp | 63 +++++++++++++++++++++++++++++++++++++++--- model/placesmodel.h | 10 ++++++- qml/SideBar.qml | 10 +++++-- 7 files changed, 147 insertions(+), 9 deletions(-) diff --git a/model/foldermodel.cpp b/model/foldermodel.cpp index 2e3f551..edf8f68 100644 --- a/model/foldermodel.cpp +++ b/model/foldermodel.cpp @@ -174,6 +174,9 @@ QString FolderModel::url() const void FolderModel::setUrl(const QString &url) { + if (url.isEmpty()) + return; + const QUrl &resolvedNewUrl = resolve(url); // Refresh this directory. diff --git a/model/pathbarmodel.cpp b/model/pathbarmodel.cpp index d76b2b4..cff9921 100644 --- a/model/pathbarmodel.cpp +++ b/model/pathbarmodel.cpp @@ -18,6 +18,7 @@ */ #include "pathbarmodel.h" +#include PathBarModel::PathBarModel(QObject *parent) : QAbstractItemModel(parent) @@ -33,7 +34,7 @@ QString PathBarModel::url() const { return m_url; } -#include + void PathBarModel::setUrl(const QString &url) { if (m_url != url) { diff --git a/model/placesitem.cpp b/model/placesitem.cpp index cc6c5eb..6ae0d1c 100644 --- a/model/placesitem.cpp +++ b/model/placesitem.cpp @@ -26,6 +26,7 @@ PlacesItem::PlacesItem(const QString &displayName, : QObject(parent) , m_displayName(displayName) , m_url(url) + , m_isAccessible(false) { } @@ -61,6 +62,9 @@ void PlacesItem::setIconPath(const QString &path) QUrl PlacesItem::url() const { + if (m_access) + return QUrl::fromLocalFile(m_access->filePath()); + return m_url; } @@ -82,4 +86,48 @@ QString PlacesItem::udi() const void PlacesItem::setUdi(const QString &udi) { m_udi = udi; + updateDeviceInfo(m_udi); +} + +bool PlacesItem::isDevice() +{ + return !m_udi.isEmpty() && m_device.isValid(); +} + +bool PlacesItem::setupNeeded() +{ + if (m_access) { + return !m_isAccessible; + } + + return false; +} + +void PlacesItem::updateDeviceInfo(const QString &udi) +{ + m_device = Solid::Device(udi); + + if (m_access) + m_access->disconnect(this); + + if (m_device.isValid()) { + m_access = m_device.as(); + m_iconName = m_device.icon(); + m_displayName = m_device.displayName(); + + if (m_access) { + // m_url = m_access->filePath(); + connect(m_access.data(), &Solid::StorageAccess::accessibilityChanged, this, &PlacesItem::onAccessibilityChanged); + onAccessibilityChanged(m_access->isAccessible()); + } + } else { + m_access = nullptr; + } +} + +void PlacesItem::onAccessibilityChanged(bool isAccessible) +{ + m_isAccessible = isAccessible; + + emit itemChanged(this); } diff --git a/model/placesitem.h b/model/placesitem.h index ecb17fc..e19ec00 100644 --- a/model/placesitem.h +++ b/model/placesitem.h @@ -21,8 +21,12 @@ #define PLACESITEM_H #include +#include #include +#include +#include + class PlacesItem : public QObject { Q_OBJECT @@ -49,12 +53,27 @@ public: QString udi() const; void setUdi(const QString &udi); + bool isDevice(); + bool setupNeeded(); + +signals: + void itemChanged(PlacesItem *); + +private slots: + void updateDeviceInfo(const QString &udi); + void onAccessibilityChanged(bool isAccessible); + private: QString m_displayName; QString m_iconName; QString m_iconPath; QString m_udi; QUrl m_url; + + bool m_isAccessible; + + Solid::Device m_device; + QPointer m_access; }; #endif // PLACESITEM_H diff --git a/model/placesmodel.cpp b/model/placesmodel.cpp index 3c1eaf2..50555b7 100644 --- a/model/placesmodel.cpp +++ b/model/placesmodel.cpp @@ -28,6 +28,7 @@ #include #include #include +#include PlacesModel::PlacesModel(QObject *parent) : QAbstractItemModel(parent) @@ -98,12 +99,14 @@ PlacesModel::PlacesModel(QObject *parent) predicate = Solid::Predicate::fromString(predicateStr); Solid::DeviceNotifier *notifier = Solid::DeviceNotifier::instance(); + connect(notifier, &Solid::DeviceNotifier::deviceAdded, this, &PlacesModel::onDeviceAdded); + connect(notifier, &Solid::DeviceNotifier::deviceRemoved, this, &PlacesModel::onDeviceRemoved); + + // Init devices const QList &deviceList = Solid::Device::listFromQuery(predicate); - for (const Solid::Device &device : deviceList) { - qDebug() << device.udi(); - - PlacesItem *deviceItem = new PlacesItem(device.udi()); + PlacesItem *deviceItem = new PlacesItem; + deviceItem->setUdi(device.udi()); m_items.append(deviceItem); } } @@ -120,6 +123,8 @@ QHash PlacesModel::roleNames() const roleNames[PlacesModel::IconPathRole] = "iconPath"; roleNames[PlacesModel::UrlRole] = "url"; roleNames[PlacesModel::PathRole] = "path"; + roleNames[PlacesModel::IsDeviceRole] = "isDevice"; + roleNames[PlacesModel::setupNeededRole] = "setupNeeded"; return roleNames; } @@ -160,6 +165,12 @@ QVariant PlacesModel::data(const QModelIndex &index, int role) const case PlacesModel::PathRole: return item->path(); break; + case PlacesModel::IsDeviceRole: + return item->isDevice(); + break; + case PlacesModel::setupNeededRole: + return item->setupNeeded(); + break; default: break; } @@ -202,3 +213,47 @@ QVariantMap PlacesModel::get(const int &index) const return res; } + +void PlacesModel::requestSetup(const int &index) +{ + PlacesItem *item = m_items.at(index); + if (!item->udi().isEmpty()) { + Solid::Device device = Solid::Device(item->udi()); + Solid::StorageAccess *access = device.as(); + access->setup(); + } +} + +void PlacesModel::requestEject(const int &index) +{ + PlacesItem *item = m_items.at(index); + if (!item->udi().isEmpty()) { + Solid::Device device = Solid::Device(item->udi()); + Solid::OpticalDrive *drive = device.parent().as(); + + if (drive) { + drive->eject(); + } + } +} + +void PlacesModel::onDeviceAdded(const QString &udi) +{ + beginInsertRows(QModelIndex(), rowCount(), rowCount()); + PlacesItem *deviceItem = new PlacesItem; + deviceItem->setUdi(udi); + m_items.append(deviceItem); + endInsertRows(); +} + +void PlacesModel::onDeviceRemoved(const QString &udi) +{ + for (int i = 0; i < m_items.size(); ++i) { + if (m_items.at(i)->udi() == udi) { + beginRemoveRows(QModelIndex(), i, i); + PlacesItem *item = m_items.at(i); + m_items.removeOne(item); + endRemoveRows(); + } + } +} diff --git a/model/placesmodel.h b/model/placesmodel.h index a830466..b833ee2 100644 --- a/model/placesmodel.h +++ b/model/placesmodel.h @@ -33,7 +33,9 @@ public: IconNameRole, IconPathRole, UrlRole, - PathRole + PathRole, + IsDeviceRole, + setupNeededRole }; Q_ENUMS(DataRole); @@ -50,6 +52,12 @@ public: QModelIndex parent(const QModelIndex &child) const override; Q_INVOKABLE QVariantMap get(const int &index) const; + Q_INVOKABLE void requestSetup(const int &index); + Q_INVOKABLE void requestEject(const int &index); + +private slots: + void onDeviceAdded(const QString &udi); + void onDeviceRemoved(const QString &udi); private: QList m_items; diff --git a/qml/SideBar.qml b/qml/SideBar.qml index b9b1640..8d18346 100644 --- a/qml/SideBar.qml +++ b/qml/SideBar.qml @@ -47,8 +47,11 @@ ListView { hoverEnabled: true acceptedButtons: Qt.LeftButton onClicked: { - sideBar.currentIndex = index - sideBar.clicked(model.path) + if (model.isDevice && model.setupNeeded) + placesModel.requestSetup(index) + + // sideBar.currentIndex = index + sideBar.clicked(model.path ? model.path : model.url) } } @@ -94,7 +97,8 @@ ListView { sideBar.currentIndex = -1 for (var i = 0; i < sideBar.count; ++i) { - if (path === sideBar.model.get(i).path) { + if (path === sideBar.model.get(i).path || + path === sideBar.model.get(i).url) { sideBar.currentIndex = i break }