331 lines
10 KiB
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 }
|
|
}
|
|
}
|