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": [