diff --git a/model/placesitem.cpp b/model/placesitem.cpp index ef66cdf..262ec04 100644 --- a/model/placesitem.cpp +++ b/model/placesitem.cpp @@ -20,6 +20,7 @@ #include "placesitem.h" #include +#include #include PlacesItem::PlacesItem(const QString &displayName, @@ -29,6 +30,7 @@ PlacesItem::PlacesItem(const QString &displayName, , m_displayName(displayName) , m_url(url) , m_category("") + , m_isOpticalDisc(false) , m_isAccessible(false) { } @@ -124,6 +126,11 @@ void PlacesItem::updateDeviceInfo(const QString &udi) m_displayName = m_device.description(); #endif + if (m_device.is()) { + m_isOpticalDisc = true; + emit itemChanged(this); + } + if (m_access) { m_url = QUrl::fromLocalFile(m_access->filePath()); connect(m_access.data(), &Solid::StorageAccess::accessibilityChanged, this, &PlacesItem::onAccessibilityChanged); @@ -150,3 +157,8 @@ void PlacesItem::setCategory(const QString &category) { m_category = category; } + +bool PlacesItem::isOpticalDisc() const +{ + return m_isOpticalDisc; +} diff --git a/model/placesitem.h b/model/placesitem.h index be8f18c..cd4e515 100644 --- a/model/placesitem.h +++ b/model/placesitem.h @@ -59,6 +59,8 @@ public: QString category() const; void setCategory(const QString &category); + bool isOpticalDisc() const; + signals: void itemChanged(PlacesItem *); @@ -74,6 +76,7 @@ private: QUrl m_url; QString m_category; + bool m_isOpticalDisc; bool m_isAccessible; Solid::Device m_device; diff --git a/model/placesmodel.cpp b/model/placesmodel.cpp index 29058ec..852e379 100644 --- a/model/placesmodel.cpp +++ b/model/placesmodel.cpp @@ -117,6 +117,11 @@ PlacesModel::PlacesModel(QObject *parent) deviceItem->setCategory(tr("Drives")); m_items.append(deviceItem); } + + // Init Signals + for (PlacesItem *item : m_items) { + connect(item, &PlacesItem::itemChanged, this, &PlacesModel::onItemChanged); + } } PlacesModel::~PlacesModel() @@ -132,6 +137,7 @@ QHash PlacesModel::roleNames() const roleNames[PlacesModel::UrlRole] = "url"; roleNames[PlacesModel::PathRole] = "path"; roleNames[PlacesModel::IsDeviceRole] = "isDevice"; + roleNames[PlacesModel::IsOpticalDisc] = "isOpticalDisc"; roleNames[PlacesModel::setupNeededRole] = "setupNeeded"; roleNames[PlacesModel::CategoryRole] = "category"; return roleNames; @@ -177,6 +183,9 @@ QVariant PlacesModel::data(const QModelIndex &index, int role) const case PlacesModel::IsDeviceRole: return item->isDevice(); break; + case PlacesModel::IsOpticalDisc: + return item->isOpticalDisc(); + break; case PlacesModel::setupNeededRole: return item->setupNeeded(); break; @@ -256,6 +265,20 @@ void PlacesModel::requestEject(const int &index) } } +void PlacesModel::requestTeardown(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(); + + if (access != nullptr) { + access->teardown(); + } + } +} + void PlacesModel::onDeviceAdded(const QString &udi) { if (m_predicate.matches(Solid::Device(udi))) { @@ -265,6 +288,8 @@ void PlacesModel::onDeviceAdded(const QString &udi) deviceItem->setCategory(tr("Drives")); m_items.append(deviceItem); endInsertRows(); + + connect(deviceItem, &PlacesItem::itemChanged, this, &PlacesModel::onItemChanged); } } @@ -276,6 +301,20 @@ void PlacesModel::onDeviceRemoved(const QString &udi) PlacesItem *item = m_items.at(i); m_items.removeOne(item); endRemoveRows(); + + disconnect(item); } } } + +void PlacesModel::onItemChanged(PlacesItem *item) +{ + // 更新 item 数据 + int index = m_items.indexOf(item); + + if (index < 0 || index > m_items.size()) + return; + + QModelIndex idx = this->index(index, 0); + emit dataChanged(idx, idx); +} diff --git a/model/placesmodel.h b/model/placesmodel.h index 204739e..a407dee 100644 --- a/model/placesmodel.h +++ b/model/placesmodel.h @@ -36,6 +36,7 @@ public: UrlRole, PathRole, IsDeviceRole, + IsOpticalDisc, setupNeededRole, CategoryRole }; @@ -56,6 +57,7 @@ public: Q_INVOKABLE QVariantMap get(const int &index) const; Q_INVOKABLE void requestSetup(const int &index); Q_INVOKABLE void requestEject(const int &index); + Q_INVOKABLE void requestTeardown(const int &index); signals: void deviceSetupDone(const QString &filePath); @@ -63,6 +65,7 @@ signals: private slots: void onDeviceAdded(const QString &udi); void onDeviceRemoved(const QString &udi); + void onItemChanged(PlacesItem *); private: QList m_items; diff --git a/qml/SideBar.qml b/qml/SideBar.qml index 4d566ba..a93de27 100644 --- a/qml/SideBar.qml +++ b/qml/SideBar.qml @@ -127,6 +127,35 @@ ListView { sideBar.openInNewWindow(model.path ? model.path : model.url) } } + + MenuSeparator { + Layout.fillWidth: true + visible: _ejectMenuItem.visible || _umountMenuItem.visible + } + + MenuItem { + id: _ejectMenuItem + text: qsTr("Eject") + visible: model.isDevice && + !model.setupNeeded && + model.isOpticalDisc + + onTriggered: { + placesModel.requestEject(index) + } + } + + MenuItem { + id: _umountMenuItem + text: qsTr("Unmount") + visible: model.isDevice && + !model.setupNeeded && + !model.isOpticalDisc + + onTriggered: { + placesModel.requestTeardown(index) + } + } } Rectangle { diff --git a/translations/en_US.ts b/translations/en_US.ts index 9f29909..3b2c0e4 100644 --- a/translations/en_US.ts +++ b/translations/en_US.ts @@ -441,7 +441,7 @@ - + Drives Drives @@ -502,10 +502,20 @@ Open - + Open in new window + + + Eject + + + + + Unmount + + main diff --git a/translations/zh_CN.ts b/translations/zh_CN.ts index 2912b6e..ebddd27 100644 --- a/translations/zh_CN.ts +++ b/translations/zh_CN.ts @@ -441,7 +441,7 @@ - + Drives 设备 @@ -510,10 +510,20 @@ 打开 - + Open in new window 在新窗口中打开 + + + Eject + 弹出 + + + + Unmount + 卸载 + main