diff --git a/contents/config/config.qml b/contents/config/config.qml index eeba674..501e94e 100644 --- a/contents/config/config.qml +++ b/contents/config/config.qml @@ -5,7 +5,12 @@ import org.kde.plasma.configuration ConfigModel { ConfigCategory { name: "General" - icon: "weather-clear" + icon: "weather-and-stats" source: "configGeneral.qml" } + ConfigCategory { + name: "Appearance" + icon: "preferences-desktop-theme" + source: "configAppearance.qml" + } } diff --git a/contents/config/main.xml b/contents/config/main.xml index 03ca8ec..ddc7c9e 100644 --- a/contents/config/main.xml +++ b/contents/config/main.xml @@ -47,5 +47,11 @@ true + + 0 + + + weather,cputemp,cpuusage,memory,network + diff --git a/contents/ui/configAppearance.qml b/contents/ui/configAppearance.qml new file mode 100644 index 0000000..be5e5e8 --- /dev/null +++ b/contents/ui/configAppearance.qml @@ -0,0 +1,134 @@ +import QtQuick +import QtQuick.Controls as QQC2 +import QtQuick.Layouts + +Item { + id: root + implicitHeight: col.implicitHeight + + property int cfg_fontSize: 0 + property string cfg_statOrder: "weather,cputemp,cpuusage,memory,network" + + // ── Order model ─────────────────────────────────────────────────────────── + + property bool syncingOrder: false + + ListModel { id: orderModel } + + readonly property var labelMap: ({ + weather: "Weather", + cputemp: "CPU Temp", + cpuusage: "CPU Usage", + memory: "Memory", + network: "Network" + }) + + // Plasma sets cfg_statOrder from saved config after the component loads, + // so we populate the model on the first external change rather than onCompleted. + onCfg_statOrderChanged: { + if (syncingOrder) return + orderModel.clear() + var keys = cfg_statOrder.split(",") + for (var i = 0; i < keys.length; i++) { + var key = keys[i].trim() + orderModel.append({ key: key, label: labelMap[key] || key }) + } + } + + function syncOrder() { + syncingOrder = true + var keys = [] + for (var i = 0; i < orderModel.count; i++) keys.push(orderModel.get(i).key) + cfg_statOrder = keys.join(",") + syncingOrder = false + } + + // ── Section header component ────────────────────────────────────────────── + + 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" + } + } + + // ── Layout ──────────────────────────────────────────────────────────────── + + ColumnLayout { + id: col + anchors.fill: parent + anchors.margins: 20 + anchors.topMargin: 16 + spacing: 10 + + // ── FONT ───────────────────────────────────────────────────────────── + + SectionHeader { title: "FONT" } + + RowLayout { + Layout.fillWidth: true + spacing: 12 + + QQC2.Label { text: "Font size:" } + QQC2.SpinBox { + from: 0; to: 32 + value: cfg_fontSize + onValueChanged: cfg_fontSize = value + textFromValue: function(val) { return val === 0 ? "Auto" : val + " pt" } + valueFromText: function(text) { return text === "Auto" ? 0 : parseInt(text) || 0 } + } + QQC2.Label { text: "(0 = inherit from panel)"; opacity: 0.6 } + } + + // ── ORDER ───────────────────────────────────────────────────────────── + + SectionHeader { title: "ORDER" } + + QQC2.Label { + text: "Use ↑ ↓ to set left-to-right order:" + opacity: 0.7 + Layout.fillWidth: true + } + + Repeater { + model: orderModel + RowLayout { + Layout.fillWidth: true + spacing: 8 + + QQC2.Label { + text: (index + 1) + ". " + model.label + Layout.fillWidth: true + } + QQC2.Button { + text: "↑" + enabled: index > 0 + implicitWidth: 36 + onClicked: { orderModel.move(index, index - 1, 1); root.syncOrder() } + } + QQC2.Button { + text: "↓" + enabled: index < orderModel.count - 1 + implicitWidth: 36 + onClicked: { orderModel.move(index, index + 1, 1); root.syncOrder() } + } + } + } + + Item { Layout.fillHeight: true; Layout.minimumHeight: 16 } + } +} diff --git a/contents/ui/main.qml b/contents/ui/main.qml index e037a0e..c94dc87 100644 --- a/contents/ui/main.qml +++ b/contents/ui/main.qml @@ -22,6 +22,8 @@ PlasmoidItem { property bool showMemory: Plasmoid.configuration.showMemory !== false property bool showNetwork: Plasmoid.configuration.showNetwork !== false property bool useNerdFont: Plasmoid.configuration.useNerdFont !== false + property int fontSize: Plasmoid.configuration.fontSize || 0 + property string statOrder: Plasmoid.configuration.statOrder || "weather,cputemp,cpuusage,memory,network" readonly property var ic: useNerdFont ? ({ cpuTemp: "\uf2c8", cpu: "\uf2db", mem: "\ue266", @@ -71,32 +73,37 @@ PlasmoidItem { Layout.preferredWidth: implicitWidth + 16 verticalAlignment: Text.AlignVCenter textFormat: Text.RichText + leftPadding: 6 + font.pointSize: root.fontSize > 0 ? root.fontSize : Kirigami.Theme.defaultFont.pointSize text: { var hot = root.cpuTempRaw > 0 && root.cpuTempRaw >= root.cpuTempThreshold var sp = "\u00a0\u00a0\u00a0\u00a0" var div = "\u00a0\u00a0\u2502\u00a0\u00a0" - var s = root.weatherIcon + "\u00a0\u00a0" + root.temperature + "°" + (root.fahrenheit ? "F" : "C") - if (root.showCondition && root.weatherCondition !== "") - s += " " + root.weatherCondition + var order = root.statOrder.split(",") + var segments = [] - var cpuMem = [] - if (root.showCpuTemp) { - var tempStr = root.ic.cpuTemp + "\u00a0\u00a0" + root.cpuTempDisplay - cpuMem.push(hot ? "" + tempStr + "" : tempStr) + for (var i = 0; i < order.length; i++) { + var key = order[i].trim() + if (key === "weather") { + var seg = root.weatherIcon + "\u00a0\u00a0" + root.temperature + "°" + (root.fahrenheit ? "F" : "C") + if (root.showCondition && root.weatherCondition !== "") + seg += " " + root.weatherCondition + segments.push(seg) + } else if (key === "cputemp" && root.showCpuTemp) { + var tempStr = root.ic.cpuTemp + "\u00a0\u00a0" + root.cpuTempDisplay + segments.push(hot ? "" + tempStr + "" : tempStr) + } else if (key === "cpuusage" && root.showCpuUsage) { + segments.push(root.ic.cpu + "\u00a0\u00a0" + (root.cpuUsage >= 0 ? padPct(root.cpuUsage) : "\u00a0--")) + } else if (key === "memory" && root.showMemory) { + segments.push(root.ic.mem + "\u00a0\u00a0" + (root.memUsage >= 0 ? padPct(root.memUsage) : "\u00a0--")) + } else if (key === "network" && root.showNetwork) { + segments.push(root.ic.down + "\u00a0\u00a0" + formatNetSpeed(root.netDown) + sp + root.ic.up + "\u00a0\u00a0" + formatNetSpeed(root.netUp)) + } } - if (root.showCpuUsage) - cpuMem.push(root.ic.cpu + "\u00a0\u00a0" + (root.cpuUsage >= 0 ? padPct(root.cpuUsage) : "\u00a0--")) - if (root.showMemory) - cpuMem.push(root.ic.mem + "\u00a0\u00a0" + (root.memUsage >= 0 ? padPct(root.memUsage) : "\u00a0--")) - if (cpuMem.length > 0) s += div + cpuMem.join(sp) - - if (root.showNetwork) - s += div + root.ic.down + "\u00a0\u00a0" + formatNetSpeed(root.netDown) + sp + root.ic.up + "\u00a0\u00a0" + formatNetSpeed(root.netUp) - - return s + " " + return segments.join(div) + " " } } diff --git a/metadata.json b/metadata.json index 04e1c6e..9e36122 100644 --- a/metadata.json +++ b/metadata.json @@ -4,7 +4,7 @@ "Description": "Live weather and system stats for the KDE panel", "Icon": "weather-and-stats", "Id": "com.github.samjage.weatherstats", - "Version": "1.3", + "Version": "1.4", "License": "GPL-2.0", "Category": "System Information", "Authors": [