Files
quickdots/widgets/sidebar/weather/WeatherWidget.qml

331 lines
10 KiB
QML

import QtQuick
import QtQuick.Layouts
import Quickshell.Io
import "../../../config" as Cfg
Item {
id: root
implicitHeight: contentCol.implicitHeight
readonly property var t: Cfg.Config.theme
property string icon: "—"
property string condition: "—"
property string temp: "—"
property string feelsLike: "—"
property string humidity: "—"
property string wind: "—"
property string location: "—"
readonly property string _url: {
var loc = Cfg.Config.weatherLocation.trim()
if (!loc) return "wttr.in?format=%t|%f|%c|%C|%h|%w|%l&m"
loc = loc.replace(/ /g, "+")
return "wttr.in/" + loc + "?format=%t|%f|%c|%C|%h|%w|%l&m"
}
function fetchWeather() {
weatherProc.command = ["sh", "-c", "curl -s \"" + root._url + "\""]
weatherProc.running = true
}
Timer {
interval: Cfg.Config.weatherRefreshMin * 60000
running: true
repeat: true
triggeredOnStart: true
onTriggered: root.fetchWeather()
}
Process {
id: weatherProc
property string _buf: ""
command: ["sh", "-c", ""]
stdout: SplitParser {
onRead: d => { weatherProc._buf = d }
}
onRunningChanged: {
if (running || !_buf) return
var parts = _buf.trim().split("|")
if (parts.length >= 7) {
root.temp = parts[0] || "—"
root.feelsLike = parts[1] || "—"
root.icon = parts[2] || "—"
root.condition = parts[3] || "—"
root.humidity = parts[4] || "—"
root.wind = parts[5] || "—"
root.location = parts[6] || "—"
}
_buf = ""
}
}
ColumnLayout {
id: contentCol
anchors { left: parent.left; right: parent.right; top: parent.top }
spacing: 0
Rectangle {
Layout.fillWidth: true
height: 32
color: "transparent"
RowLayout {
anchors.fill: parent
spacing: 10
Rectangle {
width: 32; height: 32
radius: 8
color: Qt.alpha(root.t.weatherAccent, 0.12)
border.color: Qt.alpha(root.t.weatherAccent, 0.22)
border.width: 1
Layout.alignment: Qt.AlignVCenter
Text {
anchors.centerIn: parent
text: root.icon
color: root.t.weatherAccent
font.pixelSize: 18
font.weight: Font.Bold
}
}
ColumnLayout {
spacing: 2
Layout.fillWidth: true
Layout.alignment: Qt.AlignVCenter
Text {
text: root.condition
color: root.t.weatherTextMain
font.pixelSize: 13
font.weight: Font.Bold
elide: Text.ElideRight
Layout.fillWidth: true
}
Text {
text: root.location
color: root.t.weatherTextDim
font.pixelSize: 10
font.weight: Font.Bold
opacity: 0.75
elide: Text.ElideRight
Layout.fillWidth: true
}
}
Rectangle {
width: 24; height: 24
radius: 6
color: refreshMouse.containsMouse
? (refreshMouse.pressed ? Qt.alpha(root.t.weatherAccent, 0.25) : Qt.alpha(root.t.weatherAccent, 0.12))
: "transparent"
Layout.alignment: Qt.AlignVCenter
Behavior on color { ColorAnimation { duration: 150 } }
Text {
id: refreshIcon
anchors.centerIn: parent
text: "󰑐"
color: refreshMouse.containsMouse ? root.t.weatherAccent : root.t.weatherTextDim
font.pixelSize: 14
font.weight: Font.Bold
Behavior on color { ColorAnimation { duration: 150 } }
RotationAnimator {
id: spinAnim
target: refreshIcon
from: 0; to: 360
duration: 600
easing.type: Easing.OutCubic
running: false
}
}
MouseArea {
id: refreshMouse
anchors.fill: parent; hoverEnabled: true; cursorShape: Qt.PointingHandCursor
onClicked: {
spinAnim.restart()
root.fetchWeather()
}
}
}
}
}
Item { Layout.preferredHeight: 12 }
Rectangle {
Layout.fillWidth: true
height: 1
gradient: Gradient {
orientation: Gradient.Horizontal
GradientStop { position: 0.0; color: Qt.alpha(root.t.weatherAccent, 0.5) }
GradientStop { position: 1.0; color: "transparent" }
}
}
Item { Layout.preferredHeight: 10 }
RowLayout {
Layout.fillWidth: true
spacing: 10
Rectangle {
width: 18; height: 18
radius: 4
color: Qt.alpha(root.t.weatherTempColor, 0.15)
Layout.alignment: Qt.AlignVCenter
Text {
anchors.centerIn: parent
text: "󰔄"
color: root.t.weatherTempColor
font.pixelSize: 12
font.weight: Font.Bold
}
}
Text {
text: "Temperature"
color: root.t.weatherTextDim
font.pixelSize: 12
font.weight: Font.Bold
Layout.fillWidth: true
Layout.alignment: Qt.AlignVCenter
}
Text {
text: root.temp
color: root.t.weatherTextMain
font.pixelSize: 12
font.weight: Font.Bold
Layout.alignment: Qt.AlignVCenter
}
}
Item { Layout.preferredHeight: 9 }
RowLayout {
Layout.fillWidth: true
spacing: 10
Rectangle {
width: 18; height: 18
radius: 4
color: Qt.alpha(root.t.weatherFeelsColor, 0.15)
Layout.alignment: Qt.AlignVCenter
Text {
anchors.centerIn: parent
text: "󰔄"
color: root.t.weatherFeelsColor
font.pixelSize: 12
font.weight: Font.Bold
}
}
Text {
text: "Feels like"
color: root.t.weatherTextDim
font.pixelSize: 12
font.weight: Font.Bold
Layout.fillWidth: true
Layout.alignment: Qt.AlignVCenter
}
Text {
text: root.feelsLike
color: root.t.weatherTextMain
font.pixelSize: 12
font.weight: Font.Bold
Layout.alignment: Qt.AlignVCenter
}
}
Item { Layout.preferredHeight: 9 }
RowLayout {
Layout.fillWidth: true
spacing: 10
Rectangle {
width: 18; height: 18
radius: 4
color: Qt.alpha(root.t.weatherHumidColor, 0.15)
Layout.alignment: Qt.AlignVCenter
Text {
anchors.centerIn: parent
text: "󰃚"
color: root.t.weatherHumidColor
font.pixelSize: 12
font.weight: Font.Bold
}
}
Text {
text: "Humidity"
color: root.t.weatherTextDim
font.pixelSize: 12
font.weight: Font.Bold
Layout.fillWidth: true
Layout.alignment: Qt.AlignVCenter
}
Text {
text: root.humidity
color: root.t.weatherTextMain
font.pixelSize: 12
font.weight: Font.Bold
Layout.alignment: Qt.AlignVCenter
}
}
Item { Layout.preferredHeight: 9 }
RowLayout {
Layout.fillWidth: true
spacing: 10
Rectangle {
width: 18; height: 18
radius: 4
color: Qt.alpha(root.t.weatherWindColor, 0.15)
Layout.alignment: Qt.AlignVCenter
Text {
anchors.centerIn: parent
text: "󰖝"
color: root.t.weatherWindColor
font.pixelSize: 12
font.weight: Font.Bold
}
}
Text {
text: "Wind"
color: root.t.weatherTextDim
font.pixelSize: 12
font.weight: Font.Bold
Layout.fillWidth: true
Layout.alignment: Qt.AlignVCenter
}
Text {
text: root.wind
color: root.t.weatherTextMain
font.pixelSize: 12
font.weight: Font.Bold
Layout.alignment: Qt.AlignVCenter
}
}
Item { Layout.preferredHeight: 6 }
}
}