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.
237 lines
8.2 KiB
237 lines
8.2 KiB
/* |
|
* Copyright 2011 Viranch Mehta <viranch.mehta@gmail.com> |
|
* Copyright 2012 Jacopo De Simoi <wilderkde@gmail.com> |
|
* Copyright 2016 Kai Uwe Broulik <kde@privat.broulik.de> |
|
* Copyright 2020 Nate Graham <nate@kde.org> |
|
* |
|
* This program is free software; you can redistribute it and/or modify |
|
* it under the terms of the GNU Library General Public License as |
|
* published by the Free Software Foundation; either version 2 or |
|
* (at your option) any later version. |
|
* |
|
* This program is distributed in the hope that it will be useful, |
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
* GNU General Public License for more details |
|
* |
|
* You should have received a copy of the GNU Library General Public |
|
* License along with this program; if not, write to the |
|
* Free Software Foundation, Inc., |
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
|
*/ |
|
|
|
import QtQuick 2.0 |
|
import QtQuick.Controls 2.12 as QQC2 |
|
import QtQml.Models 2.14 |
|
|
|
import org.kde.plasma.core 2.0 as PlasmaCore |
|
import org.kde.plasma.extras 2.0 as PlasmaExtras |
|
|
|
import org.kde.kquickcontrolsaddons 2.0 |
|
|
|
PlasmaExtras.ExpandableListItem { |
|
id: deviceItem |
|
|
|
property string udi |
|
readonly property int state: sdSource.data[udi] ? sdSource.data[udi].State : 0 |
|
readonly property int operationResult: (model["Operation result"]) |
|
|
|
readonly property bool isMounted: devicenotifier.isMounted(udi) |
|
readonly property bool hasMessage: statusSource.lastUdi == udi && statusSource.data[statusSource.last] ? true : false |
|
readonly property var message: hasMessage ? statusSource.data[statusSource.last] || ({}) : ({}) |
|
|
|
readonly property double freeSpace: sdSource.data[udi] && sdSource.data[udi]["Free Space"] ? sdSource.data[udi]["Free Space"] : -1.0 |
|
readonly property double totalSpace: sdSource.data[udi] && sdSource.data[udi]["Size"] ? sdSource.data[udi]["Size"] : -1.0 |
|
property bool freeSpaceKnown: freeSpace > 0 && totalSpace > 0 |
|
|
|
onOperationResultChanged: { |
|
if (!popupIconTimer.running) { |
|
if (operationResult == 1) { |
|
devicenotifier.popupIcon = "dialog-ok" |
|
popupIconTimer.restart() |
|
} else if (operationResult == 2) { |
|
devicenotifier.popupIcon = "dialog-error" |
|
popupIconTimer.restart() |
|
} |
|
} |
|
} |
|
|
|
onHasMessageChanged: { |
|
if (deviceItem.hasMessage) { |
|
messageHighlight.highlight(this) |
|
} |
|
} |
|
|
|
Connections { |
|
target: unmountAll |
|
onClicked: { |
|
if (model["Removable"] && isMounted) { |
|
actionTriggered(); |
|
} |
|
} |
|
} |
|
|
|
// this keeps the delegate around for 5 seconds after the device has been |
|
// removed in case there was a message, such as "you can now safely remove this" |
|
ListView.onRemove: { |
|
deviceItem.isEnabled = false |
|
|
|
if (deviceItem.hasMessage) { |
|
ListView.delayRemove = true |
|
keepDelegateTimer.restart() |
|
|
|
++devicenotifier.pendingDelegateRemoval // QTBUG-50380 |
|
} |
|
// Otherwise there are briefly multiple highlight effects |
|
devicenotifier.currentIndex = -1 |
|
} |
|
|
|
Timer { |
|
id: keepDelegateTimer |
|
interval: 5000 // same interval as the auto hide / passive timer |
|
onTriggered: { |
|
deviceItem.ListView.delayRemove = false |
|
// otherwise the last message will show again when this device reappears |
|
statusSource.clearMessage() |
|
|
|
--devicenotifier.pendingDelegateRemoval // QTBUG-50380 |
|
} |
|
} |
|
|
|
Timer { |
|
id: updateStorageSpaceTimer |
|
interval: 5000 |
|
repeat: true |
|
running: isMounted && plasmoid.expanded |
|
triggeredOnStart: true // Update the storage space as soon as we open the plasmoid |
|
onTriggered: { |
|
var service = sdSource.serviceForSource(udi); |
|
var operation = service.operationDescription("updateFreespace"); |
|
service.startOperationCall(operation); |
|
} |
|
} |
|
|
|
Component { |
|
id: deviceActionComponent |
|
QQC2.Action { } |
|
} |
|
|
|
function actionTriggered() { |
|
var service |
|
var operationName |
|
var operation |
|
if (!sdSource.data[udi].Removable) { |
|
service = hpSource.serviceForSource(udi); |
|
operation = service.operationDescription('invokeAction'); |
|
operation.predicate = "test-predicate-openinwindow.desktop"; |
|
} else { |
|
var wasMounted = isMounted; |
|
service = sdSource.serviceForSource(udi); |
|
operation = service.operationDescription(wasMounted ? "unmount" : "mount"); |
|
} |
|
service.startOperationCall(operation); |
|
if (wasMounted) { |
|
deviceItem.collapse(); |
|
} |
|
} |
|
|
|
|
|
icon: sdSource.data[udi] == undefined ? "" : sdSource.data[udi].Icon |
|
|
|
iconEmblem: { |
|
if (sdSource.data[udi] != undefined) { |
|
if (deviceItem.hasMessage) { |
|
if (deviceItem.message.solidError === 0) { |
|
return "emblem-information" |
|
} else { |
|
return "emblem-error" |
|
} |
|
} else if (deviceItem.state == 0 && Emblems && Emblems[0]) { |
|
return Emblems[0] |
|
} else { |
|
return "" |
|
} |
|
} |
|
return "" |
|
} |
|
|
|
title: sdSource.data[udi] == undefined ? "" : sdSource.data[udi].Description |
|
|
|
subtitle: { |
|
if (deviceItem.hasMessage) { |
|
return deviceItem.message.error |
|
} |
|
if (deviceItem.state == 0) { |
|
if (!hpSource.data[udi]) { |
|
return "" |
|
} |
|
if (freeSpaceKnown) { |
|
var freeSpaceText = sdSource.data[udi]["Free Space Text"] |
|
var totalSpaceText = sdSource.data[udi]["Size Text"] |
|
return i18nc("@info:status Free disk space", "%1 free of %2", freeSpaceText, totalSpaceText) |
|
} |
|
return "" |
|
} else if (deviceItem.state == 1) { |
|
return i18nc("Accessing is a less technical word for Mounting; translation should be short and mean \'Currently mounting this device\'", "Accessing...") |
|
} else { |
|
return i18nc("Removing is a less technical word for Unmounting; translation should be short and mean \'Currently unmounting this device\'", "Removing...") |
|
} |
|
} |
|
|
|
subtitleCanWrap: true |
|
|
|
// Color the subtitle red for disks with less than 5% free space |
|
subtitleColor: { |
|
if (freeSpaceKnown) { |
|
if (freeSpace / totalSpace <= 0.05) { |
|
return theme.negativeTextColor |
|
} |
|
} |
|
return theme.textColor |
|
} |
|
|
|
defaultActionButtonAction: QQC2.Action { |
|
icon.name: { |
|
if (!sdSource.data[udi].Removable) { |
|
return "document-open-folder" |
|
} else { |
|
return isMounted ? "media-eject" : "media-mount" |
|
} |
|
} |
|
text: { |
|
if (!sdSource.data[udi].Removable) { |
|
return i18n("Open in File Manager") |
|
} else { |
|
var types = model["Device Types"]; |
|
if (!isMounted) { |
|
return i18n("Mount") |
|
} else if (types && types.indexOf("OpticalDisc") !== -1) { |
|
return i18n("Eject") |
|
} else { |
|
return i18n("Safely remove") |
|
} |
|
} |
|
} |
|
onTriggered: actionTriggered() |
|
} |
|
|
|
isBusy: deviceItem.state != 0 |
|
|
|
// We need a JS array full of QQC2 actions; this Instantiator creates them |
|
// from the actions list of the data source |
|
Instantiator { |
|
model: hpSource.data[udi] ? hpSource.data[udi].actions : [] |
|
delegate: QQC2.Action { |
|
text: modelData.text |
|
icon.name: modelData.icon |
|
onTriggered: { |
|
var service = hpSource.serviceForSource(udi); |
|
var operation = service.operationDescription('invokeAction'); |
|
operation.predicate = modelData.predicate; |
|
service.startOperationCall(operation); |
|
devicenotifier.currentIndex = -1; |
|
} |
|
} |
|
onObjectAdded: contextualActionsModel.push(object) |
|
} |
|
}
|
|
|