You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
338 lines
12 KiB
338 lines
12 KiB
/* |
|
SPDX-FileCopyrightText: 2011 Viranch Mehta <viranch.mehta@gmail.com> |
|
SPDX-FileCopyrightText: 2012 Jacopo De Simoi <wilderkde@gmail.com> |
|
SPDX-FileCopyrightText: 2014 David Edmundson <davidedmundson@kde.org> |
|
SPDX-FileCopyrightText: 2016 Kai Uwe Broulik <kde@privat.broulik.de> |
|
|
|
SPDX-License-Identifier: LGPL-2.0-or-later |
|
*/ |
|
|
|
import QtQuick 2.0 |
|
import QtQuick.Layouts 1.1 |
|
import org.kde.plasma.plasmoid 2.0 |
|
import org.kde.plasma.core 2.0 as PlasmaCore |
|
import org.kde.plasma.extras 2.0 as PlasmaExtras |
|
|
|
import org.kde.kquickcontrolsaddons 2.0 // For KCMShell |
|
|
|
Item { |
|
id: devicenotifier |
|
|
|
readonly property bool openAutomounterKcmAuthorized: KCMShell.authorize("device_automounter_kcm.desktop").length > 0 |
|
|
|
property string devicesType: { |
|
if (plasmoid.configuration.allDevices) { |
|
return "all" |
|
} else if (plasmoid.configuration.removableDevices) { |
|
return "removable" |
|
} else { |
|
return "nonRemovable" |
|
} |
|
} |
|
property string popupIcon: "device-notifier" |
|
|
|
property bool itemClicked: false |
|
property int currentIndex: -1 |
|
property var connectedRemovables: [] |
|
property int mountedRemovables: 0 |
|
|
|
// QTBUG-50380: As soon as the item gets removed from the model, all of ListView's |
|
// properties (count, contentHeight) pretend the delegate doesn't exist anymore |
|
// causing our "No devices" heading to overlap with the remaining device |
|
property int pendingDelegateRemoval: 0 |
|
|
|
Plasmoid.switchWidth: PlasmaCore.Units.gridUnit * 10 |
|
Plasmoid.switchHeight: PlasmaCore.Units.gridUnit * 10 |
|
|
|
Plasmoid.toolTipMainText: filterModel.count > 0 && filterModel.get(0) ? i18n("Most Recent Device") : i18n("No Devices Available") |
|
Plasmoid.toolTipSubText: { |
|
if (filterModel.count > 0) { |
|
var data = filterModel.get(0) |
|
if (data && data.Description) { |
|
return data.Description |
|
} |
|
} |
|
return "" |
|
} |
|
Plasmoid.icon: { |
|
if (filterModel.count > 0) { |
|
var data = filterModel.get(0) |
|
if (data && data.Icon) { |
|
return data.Icon |
|
} |
|
} |
|
return "device-notifier" |
|
} |
|
|
|
Plasmoid.status: (filterModel.count > 0 || pendingDelegateRemoval > 0) ? PlasmaCore.Types.ActiveStatus : PlasmaCore.Types.PassiveStatus |
|
|
|
PlasmaCore.DataSource { |
|
id: hpSource |
|
engine: "hotplug" |
|
connectedSources: sources |
|
interval: 0 |
|
|
|
onSourceAdded: { |
|
disconnectSource(source); |
|
connectSource(source); |
|
sdSource.connectedSources = sources |
|
} |
|
onSourceRemoved: { |
|
disconnectSource(source); |
|
} |
|
} |
|
|
|
Plasmoid.compactRepresentation: PlasmaCore.IconItem { |
|
source: devicenotifier.popupIcon |
|
width: PlasmaCore.Units.iconSizes.medium; |
|
height: PlasmaCore.Units.iconSizes.medium; |
|
active: compactMouse.containsMouse |
|
MouseArea { |
|
id: compactMouse |
|
anchors.fill: parent |
|
hoverEnabled: true |
|
onClicked: plasmoid.expanded = !plasmoid.expanded |
|
} |
|
} |
|
Plasmoid.fullRepresentation: FullRepresentation {} |
|
|
|
PlasmaCore.DataSource { |
|
id: sdSource |
|
engine: "soliddevice" |
|
interval: 0 |
|
property string last |
|
onSourceAdded: { |
|
disconnectSource(source); |
|
connectSource(source); |
|
last = source; |
|
processLastDevice(true); |
|
if (data[source].Removable) { |
|
devicenotifier.connectedRemovables.push(source); |
|
devicenotifier.connectedRemovables = devicenotifier.connectedRemovables; |
|
} |
|
} |
|
|
|
onSourceRemoved: { |
|
disconnectSource(source); |
|
var index = devicenotifier.connectedRemovables.indexOf(source); |
|
if (index >= 0) { |
|
devicenotifier.connectedRemovables.splice(index, 1); |
|
devicenotifier.connectedRemovables = devicenotifier.connectedRemovables; |
|
} |
|
} |
|
|
|
onDataChanged: { |
|
processLastDevice(true); |
|
var counter = 0; |
|
for (var i = 0; i < devicenotifier.connectedRemovables.length; i++) { |
|
if (isMounted(devicenotifier.connectedRemovables[i])) { |
|
counter++; |
|
} |
|
} |
|
if (counter !== devicenotifier.mountedRemovables) { |
|
devicenotifier.mountedRemovables = counter; |
|
} |
|
} |
|
|
|
onNewData: { |
|
last = sourceName; |
|
processLastDevice(false); |
|
} |
|
|
|
function isViableDevice(udi) { |
|
if (devicesType === "all") { |
|
return true; |
|
} |
|
|
|
var device = data[udi]; |
|
if (!device) { |
|
return false; |
|
} |
|
|
|
return (devicesType === "removable" && device.Removable) |
|
|| (devicesType === "nonRemovable" && !device.Removable); |
|
} |
|
|
|
function processLastDevice(expand) { |
|
if (last && isViableDevice(last)) { |
|
if (expand && hpSource.data[last] && hpSource.data[last].added) { |
|
devicenotifier.popupIcon = "preferences-desktop-notification"; |
|
expandTimer.restart(); |
|
popupIconTimer.restart(); |
|
} |
|
last = ""; |
|
} |
|
} |
|
} |
|
|
|
PlasmaCore.SortFilterModel { |
|
id: filterModel |
|
sourceModel: PlasmaCore.DataModel { |
|
dataSource: sdSource |
|
} |
|
filterRole: "Removable" |
|
filterRegExp: { |
|
if (devicesType === "removable") { |
|
return "true" |
|
} else if (devicesType === "nonRemovable") { |
|
return "false" |
|
} else { |
|
return "" |
|
} |
|
} |
|
sortRole: "Timestamp" |
|
sortOrder: Qt.DescendingOrder |
|
} |
|
|
|
PlasmaCore.DataSource { |
|
id: statusSource |
|
engine: "devicenotifications" |
|
property string last |
|
property string lastUdi |
|
onSourceAdded: { |
|
last = source; |
|
disconnectSource(source); |
|
connectSource(source); |
|
} |
|
onSourceRemoved: disconnectSource(source) |
|
onDataChanged: { |
|
if (last) { |
|
lastUdi = data[last].udi |
|
|
|
if (sdSource.isViableDevice(lastUdi)) { |
|
plasmoid.expanded = true |
|
plasmoid.fullRepresentationItem.spontaneousOpen = true; |
|
} |
|
} |
|
} |
|
|
|
function clearMessage() { |
|
last = "" |
|
lastUdi = "" |
|
} |
|
} |
|
|
|
property var showRemovableDevicesAction |
|
property var showNonRemovableDevicesAction |
|
property var showAllDevicesAction |
|
property var openAutomaticallyAction |
|
|
|
Component.onCompleted: { |
|
if (sdSource.connectedSources.count === 0) { |
|
Plasmoid.status = PlasmaCore.Types.PassiveStatus; |
|
} |
|
|
|
plasmoid.setAction("unmountAllDevices", i18n("Remove All"), "media-eject"); |
|
plasmoid.action("unmountAllDevices").visible = Qt.binding(() => { |
|
return devicenotifier.mountedRemovables > 1; |
|
}); |
|
|
|
plasmoid.setActionSeparator("sep0"); |
|
|
|
plasmoid.setAction("showRemovableDevices", i18n("Removable Devices"), "drive-removable-media"); |
|
devicenotifier.showRemovableDevicesAction = plasmoid.action("showRemovableDevices"); |
|
devicenotifier.showRemovableDevicesAction.checkable = true; |
|
devicenotifier.showRemovableDevicesAction.checked = Qt.binding(() => {return plasmoid.configuration.removableDevices;}); |
|
plasmoid.setActionGroup("showRemovableDevices", "devicesShown"); |
|
|
|
plasmoid.setAction("showNonRemovableDevices", i18n("Non Removable Devices"), "drive-harddisk"); |
|
devicenotifier.showNonRemovableDevicesAction = plasmoid.action("showNonRemovableDevices"); |
|
devicenotifier.showNonRemovableDevicesAction.checkable = true; |
|
devicenotifier.showNonRemovableDevicesAction.checked = Qt.binding(() => {return plasmoid.configuration.nonRemovableDevices;}); |
|
plasmoid.setActionGroup("showNonRemovableDevices", "devicesShown"); |
|
|
|
plasmoid.setAction("showAllDevices", i18n("All Devices")); |
|
devicenotifier.showAllDevicesAction = plasmoid.action("showAllDevices"); |
|
devicenotifier.showAllDevicesAction.checkable = true; |
|
devicenotifier.showAllDevicesAction.checked = Qt.binding(() => {return plasmoid.configuration.allDevices;}); |
|
plasmoid.setActionGroup("showAllDevices", "devicesShown"); |
|
|
|
plasmoid.setActionSeparator("sep"); |
|
|
|
plasmoid.setAction("openAutomatically", i18n("Show popup when new device is plugged in")); |
|
devicenotifier.openAutomaticallyAction = plasmoid.action("openAutomatically"); |
|
devicenotifier.openAutomaticallyAction.checkable = true; |
|
devicenotifier.openAutomaticallyAction.checked = Qt.binding(() => {return plasmoid.configuration.popupOnNewDevice;}); |
|
|
|
plasmoid.setActionSeparator("sep2"); |
|
|
|
if (devicenotifier.openAutomounterKcmAuthorized) { |
|
plasmoid.removeAction("configure"); |
|
plasmoid.setAction("configure", i18nc("Open auto mounter kcm", "Configure Removable Devices…"), "configure") |
|
} |
|
} |
|
|
|
function action_configure() { |
|
KCMShell.openSystemSettings("kcm_device_automounter") |
|
} |
|
|
|
function action_showRemovableDevices() { |
|
plasmoid.configuration.removableDevices = true; |
|
plasmoid.configuration.nonRemovableDevices = false; |
|
plasmoid.configuration.allDevices = false; |
|
} |
|
|
|
function action_showNonRemovableDevices() { |
|
plasmoid.configuration.removableDevices = false; |
|
plasmoid.configuration.nonRemovableDevices = true; |
|
plasmoid.configuration.allDevices = false; |
|
} |
|
|
|
function action_showAllDevices() { |
|
plasmoid.configuration.removableDevices = false; |
|
plasmoid.configuration.nonRemovableDevices = false; |
|
plasmoid.configuration.allDevices = true; |
|
} |
|
|
|
function action_openAutomatically() { |
|
plasmoid.configuration.popupOnNewDevice = !plasmoid.configuration.popupOnNewDevice; |
|
} |
|
|
|
Plasmoid.onExpandedChanged: { |
|
popupEventSlot(plasmoid.expanded); |
|
} |
|
|
|
function popupEventSlot(popped) { |
|
if (!popped) { |
|
// reset the property that lets us remember if an item was clicked |
|
// (versus only hovered) for autohide purposes |
|
devicenotifier.itemClicked = true; |
|
devicenotifier.currentIndex = -1; |
|
} |
|
} |
|
|
|
function isMounted(udi) { |
|
if (!sdSource.data[udi]) { |
|
return false; |
|
} |
|
|
|
var types = sdSource.data[udi]["Device Types"]; |
|
if (types.indexOf("Storage Access") >= 0) { |
|
return sdSource.data[udi]["Accessible"]; |
|
} |
|
|
|
return (types.indexOf("Storage Volume") >= 0 && types.indexOf("OpticalDisc") >= 0) |
|
} |
|
|
|
Timer { |
|
id: popupIconTimer |
|
interval: 3000 |
|
onTriggered: devicenotifier.popupIcon = "device-notifier"; |
|
} |
|
|
|
Timer { |
|
id: expandTimer |
|
interval: 250 |
|
onTriggered: { |
|
// We don't show a UI for it, but there is a hidden option to not |
|
// show the popup on new device attachment if the user has added |
|
// the text "popupOnNewDevice=false" to their |
|
// plasma-org.kde.plasma.desktop-appletsrc file. |
|
if (plasmoid.configuration.popupOnNewDevice) { // Bug 351592 |
|
plasmoid.expanded = true; |
|
plasmoid.fullRepresentationItem.spontaneousOpen = true; |
|
} |
|
} |
|
} |
|
|
|
}
|
|
|