nova-shell/shell/applets/TemperatureApplet.qml

208 lines
5.8 KiB
QML

import QtQuick
import "../services" as S
Column {
id: root
required property int temp
required property int warm
required property int hot
required property var history
required property var devices
required property color accentColor
property bool active: true
property string deviceFilter: ""
property color stateColor: temp > hot ? S.Theme.base08 : temp > warm ? S.Theme.base0A : root.accentColor
Behavior on stateColor {
ColorAnimation {
duration: 300
}
}
// Header - current temp
Item {
width: root.width
height: 28
Text {
anchors.right: parent.right
anchors.rightMargin: 12
anchors.verticalCenter: parent.verticalCenter
text: root.temp + "\u00B0C"
color: root.stateColor
font.pixelSize: S.Theme.fontSize
font.family: S.Theme.fontFamily
font.bold: true
width: _tempSizer.implicitWidth
horizontalAlignment: Text.AlignRight
Text {
id: _tempSizer
visible: false
text: "100\u00B0C"
font: parent.font
}
}
}
// Gauge bar (0-100C), with warm/hot threshold markers
Item {
width: root.width
height: 16
Item {
id: _gaugeBar
anchors.left: parent.left
anchors.leftMargin: 12
anchors.right: parent.right
anchors.rightMargin: 12
anchors.verticalCenter: parent.verticalCenter
height: 6
Rectangle {
anchors.fill: parent
color: S.Theme.base02
radius: 3
}
Rectangle {
width: parent.width * Math.min(1, root.temp / 100)
height: parent.height
color: root.stateColor
radius: 3
Behavior on width {
enabled: root.active
NumberAnimation {
duration: 300
easing.type: Easing.OutCubic
}
}
}
// Warm threshold marker
Rectangle {
x: parent.width * (root.warm / 100) - 1
width: 1
height: parent.height + 4
anchors.verticalCenter: parent.verticalCenter
color: S.Theme.base0A
opacity: 0.6
}
// Hot threshold marker
Rectangle {
x: parent.width * (root.hot / 100) - 1
width: 1
height: parent.height + 4
anchors.verticalCenter: parent.verticalCenter
color: S.Theme.base08
opacity: 0.6
}
}
}
// History sparkline
SparklineCanvas {
anchors.left: parent.left
anchors.leftMargin: 12
anchors.right: parent.right
anchors.rightMargin: 12
height: 40
history: root.history
color: root.stateColor
active: root.active
backgroundTint: 0.08
thresholds: [
{
value: root.warm,
color: S.Theme.base0A
},
{
value: root.hot,
color: S.Theme.base08
}
]
colorFunction: v => v > root.hot ? S.Theme.base08 : v > root.warm ? S.Theme.base0A : root.stateColor
}
// Threshold labels
Item {
width: root.width
height: 16
Text {
anchors.left: parent.left
anchors.leftMargin: 12
anchors.verticalCenter: parent.verticalCenter
text: "warm " + root.warm + "\u00B0 hot " + root.hot + "\u00B0"
color: S.Theme.base03
font.pixelSize: S.Theme.fontSize - 3
font.family: S.Theme.fontFamily
font.letterSpacing: 0.5
}
Text {
anchors.right: parent.right
anchors.rightMargin: 12
anchors.verticalCenter: parent.verticalCenter
text: "10 min"
color: S.Theme.base03
font.pixelSize: S.Theme.fontSize - 3
font.family: S.Theme.fontFamily
}
}
// Per-device breakdown
Separator {
visible: root.devices.length > 0
}
Repeater {
model: root.devices
delegate: Item {
required property var modelData
width: root.width
height: 22
readonly property bool _isActive: root.deviceFilter === modelData.name
Rectangle {
anchors.fill: parent
anchors.leftMargin: 8
anchors.rightMargin: 8
color: _isActive ? Qt.rgba(root.accentColor.r, root.accentColor.g, root.accentColor.b, 0.12) : "transparent"
radius: 3
}
Text {
anchors.left: parent.left
anchors.leftMargin: 12
anchors.verticalCenter: parent.verticalCenter
text: modelData.name
color: _isActive ? root.accentColor : S.Theme.base04
font.pixelSize: S.Theme.fontSize - 2
font.family: S.Theme.fontFamily
elide: Text.ElideRight
width: parent.width - 80
}
Text {
anchors.right: parent.right
anchors.rightMargin: 12
anchors.verticalCenter: parent.verticalCenter
text: modelData.celsius + "\u00B0C"
color: S.Theme.loadColor(modelData.celsius)
font.pixelSize: S.Theme.fontSize - 2
font.family: S.Theme.fontFamily
font.bold: _isActive
}
}
}
Item {
width: 1
height: 4
}
}