mirror of
https://github.com/samjage/weather-and-stats.git
synced 2026-06-06 00:20:42 +00:00
80f7716f21
Move hardcodedd nerd fonts codepoints into a table. The default behavior is still nerdFont. There is no general icon for network so drop the icon in favor of the very clear up and down arrows.
247 lines
7.9 KiB
QML
247 lines
7.9 KiB
QML
import QtQuick
|
|
import QtQuick.Controls as QQC2
|
|
import QtQuick.Layouts
|
|
|
|
Item {
|
|
id: root
|
|
implicitHeight: col.implicitHeight
|
|
|
|
property double cfg_latitude: 0
|
|
property double cfg_longitude: 0
|
|
property string cfg_locationName: ""
|
|
property bool cfg_useFahrenheit: true
|
|
property bool cfg_showCondition: false
|
|
property int cfg_weatherRefresh: 5
|
|
property bool cfg_cpuTempFahrenheit: false
|
|
property int cfg_cpuTempThreshold: 80
|
|
property int cfg_statsRefresh: 3
|
|
property bool cfg_showCpuTemp: true
|
|
property bool cfg_showCpuUsage: true
|
|
property bool cfg_showMemory: true
|
|
property bool cfg_showNetwork: true
|
|
property bool cfg_useNerdFont: true
|
|
|
|
component SectionHeader: ColumnLayout {
|
|
property string title: ""
|
|
Layout.fillWidth: true
|
|
Layout.topMargin: 8
|
|
spacing: 4
|
|
|
|
QQC2.Label {
|
|
text: title
|
|
font.bold: true
|
|
font.pointSize: 9
|
|
font.letterSpacing: 2
|
|
opacity: 0.5
|
|
}
|
|
Rectangle {
|
|
Layout.fillWidth: true
|
|
height: 1
|
|
opacity: 0.15
|
|
color: "white"
|
|
}
|
|
}
|
|
|
|
ColumnLayout {
|
|
id: col
|
|
anchors.fill: parent
|
|
anchors.margins: 20
|
|
anchors.topMargin: 16
|
|
spacing: 10
|
|
|
|
// ── WEATHER ──────────────────────────────────────────────────────────
|
|
|
|
SectionHeader { title: "WEATHER" }
|
|
|
|
QQC2.Label {
|
|
text: cfg_locationName ? "📍 " + cfg_locationName : "No location set"
|
|
opacity: 0.7
|
|
font.italic: !cfg_locationName
|
|
Layout.fillWidth: true
|
|
}
|
|
|
|
RowLayout {
|
|
Layout.fillWidth: true
|
|
QQC2.TextField {
|
|
id: searchField
|
|
Layout.fillWidth: true
|
|
placeholderText: "Search for a city..."
|
|
onAccepted: doSearch()
|
|
}
|
|
QQC2.Button {
|
|
text: "Search"
|
|
onClicked: doSearch()
|
|
}
|
|
}
|
|
|
|
ListView {
|
|
id: resultsList
|
|
Layout.fillWidth: true
|
|
Layout.preferredHeight: Math.min(resultsModel.count * 40, 160)
|
|
visible: resultsModel.count > 0
|
|
clip: true
|
|
model: ListModel { id: resultsModel }
|
|
delegate: QQC2.ItemDelegate {
|
|
width: resultsList.width
|
|
text: model.name
|
|
onClicked: {
|
|
cfg_latitude = model.lat
|
|
cfg_longitude = model.lon
|
|
cfg_locationName = model.name
|
|
resultsModel.clear()
|
|
searchField.text = ""
|
|
}
|
|
}
|
|
}
|
|
|
|
RowLayout {
|
|
Layout.fillWidth: true
|
|
spacing: 12
|
|
|
|
QQC2.Label { text: "Temperature:" }
|
|
QQC2.RadioButton {
|
|
text: "°F"
|
|
checked: cfg_useFahrenheit
|
|
onToggled: if (checked) cfg_useFahrenheit = true
|
|
}
|
|
QQC2.RadioButton {
|
|
text: "°C"
|
|
checked: !cfg_useFahrenheit
|
|
onToggled: if (checked) cfg_useFahrenheit = false
|
|
}
|
|
|
|
Item { Layout.fillWidth: true }
|
|
|
|
QQC2.Label { text: "Refresh every" }
|
|
QQC2.SpinBox {
|
|
value: cfg_weatherRefresh
|
|
from: 1; to: 60
|
|
onValueChanged: cfg_weatherRefresh = value
|
|
}
|
|
QQC2.Label { text: "min" }
|
|
}
|
|
|
|
QQC2.CheckBox {
|
|
text: "Show condition text (e.g. \"Partly Cloudy\")"
|
|
checked: cfg_showCondition
|
|
onToggled: cfg_showCondition = checked
|
|
}
|
|
|
|
// ── STATS ─────────────────────────────────────────────────────────────
|
|
|
|
SectionHeader { title: "STATS" }
|
|
|
|
RowLayout {
|
|
Layout.fillWidth: true
|
|
spacing: 12
|
|
|
|
QQC2.Label { text: "CPU Temp:" }
|
|
QQC2.RadioButton {
|
|
text: "°F"
|
|
checked: cfg_cpuTempFahrenheit
|
|
onToggled: if (checked) cfg_cpuTempFahrenheit = true
|
|
}
|
|
QQC2.RadioButton {
|
|
text: "°C"
|
|
checked: !cfg_cpuTempFahrenheit
|
|
onToggled: if (checked) cfg_cpuTempFahrenheit = false
|
|
}
|
|
|
|
Item { Layout.fillWidth: true }
|
|
|
|
QQC2.Label { text: "Refresh every" }
|
|
QQC2.SpinBox {
|
|
value: cfg_statsRefresh
|
|
from: 2; to: 60
|
|
onValueChanged: cfg_statsRefresh = value
|
|
}
|
|
QQC2.Label { text: "sec" }
|
|
}
|
|
|
|
RowLayout {
|
|
Layout.fillWidth: true
|
|
spacing: 12
|
|
|
|
QQC2.Label { text: "Alert when CPU temp exceeds:" }
|
|
QQC2.SpinBox {
|
|
from: cfg_cpuTempFahrenheit ? 122 : 50
|
|
to: cfg_cpuTempFahrenheit ? 230 : 110
|
|
value: cfg_cpuTempFahrenheit ? Math.round(cfg_cpuTempThreshold * 9/5 + 32) : cfg_cpuTempThreshold
|
|
onValueChanged: cfg_cpuTempThreshold = cfg_cpuTempFahrenheit ? Math.round((value - 32) * 5/9) : value
|
|
}
|
|
QQC2.Label { text: cfg_cpuTempFahrenheit ? "°F" : "°C" }
|
|
}
|
|
|
|
QQC2.Label {
|
|
text: "Visible stats:"
|
|
opacity: 0.7
|
|
Layout.topMargin: 2
|
|
}
|
|
|
|
GridLayout {
|
|
columns: 2
|
|
Layout.fillWidth: true
|
|
columnSpacing: 32
|
|
rowSpacing: 2
|
|
|
|
QQC2.CheckBox {
|
|
text: "CPU Temperature"
|
|
checked: cfg_showCpuTemp
|
|
onToggled: cfg_showCpuTemp = checked
|
|
}
|
|
QQC2.CheckBox {
|
|
text: "CPU Usage"
|
|
checked: cfg_showCpuUsage
|
|
onToggled: cfg_showCpuUsage = checked
|
|
}
|
|
QQC2.CheckBox {
|
|
text: "Memory Usage"
|
|
checked: cfg_showMemory
|
|
onToggled: cfg_showMemory = checked
|
|
}
|
|
QQC2.CheckBox {
|
|
text: "Network Speed"
|
|
checked: cfg_showNetwork
|
|
onToggled: cfg_showNetwork = checked
|
|
}
|
|
}
|
|
|
|
// ── APPEARANCE ────────────────────────────────────────────────────────
|
|
|
|
SectionHeader { title: "APPEARANCE" }
|
|
|
|
QQC2.CheckBox {
|
|
text: "Use Nerd Font icons (disable for plain Unicode fallback)"
|
|
checked: cfg_useNerdFont
|
|
onToggled: cfg_useNerdFont = checked
|
|
}
|
|
|
|
Item { Layout.fillHeight: true; Layout.minimumHeight: 16 }
|
|
}
|
|
|
|
function doSearch() {
|
|
var query = searchField.text.trim()
|
|
if (query.length < 2) return
|
|
var url = "https://geocoding-api.open-meteo.com/v1/search"
|
|
+ "?name=" + encodeURIComponent(query)
|
|
+ "&count=8&language=en&format=json"
|
|
var req = new XMLHttpRequest()
|
|
req.open("GET", url)
|
|
req.onreadystatechange = function() {
|
|
if (req.readyState === XMLHttpRequest.DONE && req.status === 200) {
|
|
var data = JSON.parse(req.responseText)
|
|
resultsModel.clear()
|
|
if (data.results) {
|
|
data.results.forEach(function(r) {
|
|
var label = r.name
|
|
if (r.admin1) label += ", " + r.admin1
|
|
if (r.country) label += ", " + r.country
|
|
resultsModel.append({ name: label, lat: r.latitude, lon: r.longitude })
|
|
})
|
|
}
|
|
}
|
|
}
|
|
req.send()
|
|
}
|
|
}
|