Warning, /plasma/plasma-workspace/applets/batterymonitor/package/contents/ui/BatteryItem.qml is written in an unsupported language. File is not indexed.

0001 /*
0002     SPDX-FileCopyrightText: 2012-2013 Daniel Nicoletti <dantti12@gmail.com>
0003     SPDX-FileCopyrightText: 2013-2015 Kai Uwe Broulik <kde@privat.broulik.de>
0004 
0005     SPDX-License-Identifier: LGPL-2.0-or-later
0006 */
0007 
0008 import QtQuick
0009 import QtQuick.Layouts
0010 
0011 import org.kde.coreaddons as KCoreAddons
0012 import org.kde.plasma.components as PlasmaComponents3
0013 import org.kde.plasma.workspace.components
0014 import org.kde.kirigami as Kirigami
0015 
0016 import "logic.js" as Logic
0017 
0018 PlasmaComponents3.ItemDelegate {
0019     id: root
0020 
0021     // We'd love to use `required` properties, especially since the model provides role names for them;
0022     // but unfortunately some of those roles have whitespaces in their name, which QML doesn't have any
0023     // workaround for (raw identifiers like r#try in Rust would've helped here).
0024     //
0025     // type: {
0026     //  Capacity:           int,
0027     //  Energy:             real,
0028     //  "Is Power Supply":  bool,
0029     //  Percent:            int,
0030     //  "Plugged In":       bool,
0031     //  "Pretty Name":      string,
0032     //  Product:            string,
0033     //  State:              "Discharging"|"Charging"|"FullyCharged"|etc.,
0034     //  Type:               string,
0035     //  Vendor:             string,
0036     // }?
0037     property var battery
0038 
0039     // NOTE: According to the UPower spec this property is only valid for primary batteries, however
0040     // UPower seems to set the Present property false when a device is added but not probed yet
0041     readonly property bool isPresent: root.battery["Plugged in"]
0042 
0043     readonly property bool isPowerSupply: root.battery["Is Power Supply"]
0044 
0045     readonly property bool isBroken: root.battery.Capacity > 0 && root.battery.Capacity < 50
0046 
0047     property int remainingTime: 0
0048 
0049     // Existing instance of a slider to use as a reference to calculate extra
0050     // margins for a progress bar, so that the row of labels on top of it
0051     // could visually look as if it were on the same distance from the bar as
0052     // they are from the slider.
0053     property PlasmaComponents3.Slider matchHeightOfSlider: PlasmaComponents3.Slider {}
0054     readonly property real extraMargin: Math.max(0, Math.floor((matchHeightOfSlider.height - chargeBar.height) / 2))
0055 
0056     background.visible: highlighted
0057     highlighted: activeFocus
0058     hoverEnabled: false
0059     text: battery["Pretty Name"]
0060 
0061     Accessible.description: `${isPowerSupplyLabel.text} ${percentLabel.text}; ${details.Accessible.description}`
0062 
0063     contentItem: RowLayout {
0064         spacing: Kirigami.Units.gridUnit
0065 
0066         BatteryIcon {
0067             id: batteryIcon
0068 
0069             Layout.alignment: Qt.AlignTop
0070             Layout.preferredWidth: Kirigami.Units.iconSizes.medium
0071             Layout.preferredHeight: Kirigami.Units.iconSizes.medium
0072 
0073             batteryType: root.battery.Type
0074             percent: root.battery.Percent
0075             hasBattery: root.isPresent
0076             pluggedIn: root.battery.State === "Charging" && root.battery["Is Power Supply"]
0077         }
0078 
0079         ColumnLayout {
0080             Layout.fillWidth: true
0081             Layout.alignment: root.isPresent ? Qt.AlignTop : Qt.AlignVCenter
0082             spacing: 0
0083 
0084             RowLayout {
0085                 spacing: Kirigami.Units.smallSpacing
0086 
0087                 PlasmaComponents3.Label {
0088                     Layout.fillWidth: true
0089                     elide: Text.ElideRight
0090                     text: root.text
0091                     textFormat: Text.PlainText
0092                 }
0093 
0094                 PlasmaComponents3.Label {
0095                     id: isPowerSupplyLabel
0096                     text: Logic.stringForBatteryState(root.battery, pmSource)
0097                     textFormat: Text.PlainText
0098                     // For non-power supply batteries only show label for known-good states
0099                     visible: root.isPowerSupply || ["Discharging", "FullyCharged", "Charging"].includes(root.battery.State)
0100                     enabled: false
0101                 }
0102 
0103                 PlasmaComponents3.Label {
0104                     id: percentLabel
0105                     horizontalAlignment: Text.AlignRight
0106                     visible: root.isPresent
0107                     text: i18nc("Placeholder is battery percentage", "%1%", root.battery.Percent)
0108                     textFormat: Text.PlainText
0109                 }
0110             }
0111 
0112             PlasmaComponents3.ProgressBar {
0113                 id: chargeBar
0114 
0115                 Layout.fillWidth: true
0116                 Layout.topMargin: root.extraMargin
0117                 Layout.bottomMargin: root.extraMargin
0118 
0119                 from: 0
0120                 to: 100
0121                 visible: root.isPresent
0122                 value: Number(root.battery.Percent)
0123             }
0124 
0125             // This gridLayout basically emulates an at-most-two-rows table with a
0126             // single wide fillWidth/columnSpan header. Not really worth it trying
0127             // to refactor it into some more clever fancy model-delegate stuff.
0128             GridLayout {
0129                 id: details
0130 
0131                 Layout.fillWidth: true
0132                 Layout.topMargin: Kirigami.Units.smallSpacing
0133 
0134                 columns: 2
0135                 columnSpacing: Kirigami.Units.smallSpacing
0136                 rowSpacing: 0
0137 
0138                 Accessible.description: {
0139                     let description = [];
0140                     for (let i = 0; i < children.length; i++) {
0141                         if (children[i].visible && children[i].hasOwnProperty("text")) {
0142                             description.push(children[i].text);
0143                         }
0144                     }
0145                     return description.join(" ");
0146                 }
0147 
0148                 component LeftLabel : PlasmaComponents3.Label {
0149                     // fillWidth is true, so using internal alignment
0150                     horizontalAlignment: Text.AlignLeft
0151                     Layout.fillWidth: true
0152                     font: Kirigami.Theme.smallFont
0153                     textFormat: Text.PlainText
0154                     wrapMode: Text.WordWrap
0155                     enabled: false
0156                 }
0157                 component RightLabel : PlasmaComponents3.Label {
0158                     // fillWidth is false, so using external (grid-cell-internal) alignment
0159                     Layout.alignment: Qt.AlignRight
0160                     Layout.fillWidth: false
0161                     font: Kirigami.Theme.smallFont
0162                     enabled: false
0163                     textFormat: Text.PlainText
0164                 }
0165 
0166                 PlasmaComponents3.Label {
0167                     Layout.fillWidth: true
0168                     Layout.columnSpan: 2
0169 
0170                     text: root.isBroken && typeof root.battery.Capacity !== "undefined"
0171                         ? i18n("This battery's health is at only %1% and it should be replaced. Contact the manufacturer.", root.battery.Capacity)
0172                         : ""
0173                     textFormat: Text.PlainText
0174                     font: Kirigami.Theme.smallFont
0175                     color: Kirigami.Theme.neutralTextColor
0176                     visible: root.isBroken
0177                     wrapMode: Text.WordWrap
0178                 }
0179 
0180                 readonly property bool remainingTimeRowVisible: root.battery !== null
0181                     && root.remainingTime > 0
0182                     && root.battery["Is Power Supply"]
0183                     && ["Discharging", "Charging"].includes(root.battery.State)
0184                 readonly property bool isEstimatingRemainingTime: root.battery !== null
0185                     && root.isPowerSupply
0186                     && root.remainingTime === 0
0187                     && root.battery.State === "Discharging"
0188 
0189                 LeftLabel {
0190                     text: root.battery.State === "Charging"
0191                         ? i18n("Time To Full:")
0192                         : i18n("Remaining Time:")
0193                     visible: details.remainingTimeRowVisible || details.isEstimatingRemainingTime
0194                 }
0195 
0196                 RightLabel {
0197                     text: details.isEstimatingRemainingTime ? i18nc("@info", "Estimating…")
0198                         : KCoreAddons.Format.formatDuration(root.remainingTime, KCoreAddons.FormatTypes.HideSeconds)
0199                     visible: details.remainingTimeRowVisible || details.isEstimatingRemainingTime
0200                 }
0201 
0202                 readonly property bool healthRowVisible: root.battery !== null
0203                     && root.battery["Is Power Supply"]
0204                     && root.battery.Capacity !== ""
0205                     && typeof root.battery.Capacity === "number"
0206                     && !root.isBroken
0207 
0208                 LeftLabel {
0209                     text: i18n("Battery Health:")
0210                     visible: details.healthRowVisible
0211                 }
0212 
0213                 RightLabel {
0214                     text: details.healthRowVisible
0215                         ? i18nc("Placeholder is battery health percentage", "%1%", root.battery.Capacity)
0216                         : ""
0217                     visible: details.healthRowVisible
0218                 }
0219             }
0220 
0221             InhibitionHint {
0222                 Layout.fillWidth: true
0223                 Layout.topMargin: Kirigami.Units.smallSpacing
0224 
0225                 readonly property var chargeStopThreshold: pmSource.data["Battery"] ? pmSource.data["Battery"]["Charge Stop Threshold"] : undefined
0226                 readonly property bool pluggedIn: pmSource.data["AC Adapter"] !== undefined && pmSource.data["AC Adapter"]["Plugged in"]
0227                 visible: pluggedIn && root.isPowerSupply && typeof chargeStopThreshold === "number" && chargeStopThreshold > 0 && chargeStopThreshold < 100
0228                 iconSource: "kt-speed-limits" // FIXME good icon
0229                 text: i18n("Battery is configured to charge up to approximately %1%.", chargeStopThreshold || 0)
0230             }
0231         }
0232     }
0233 }