Krolyxon
Commit eec80fe

Branches

Refs →

aurora.configquickshellauroraSysPage.qml

179 lines · 6.7 KB · QML

1import QtQuick
2import QtQuick.Layouts
3import Quickshell.Services.UPower
4
5Flickable {
6 id: flick
7 clip: true
8 contentWidth: width
9 contentHeight: col.implicitHeight
10 boundsBehavior: Flickable.StopAtBounds
11
12 readonly property var bat: UPower.displayDevice
13 readonly property bool hasBat: bat !== null && bat.isPresent
14 readonly property real batPct: hasBat ? (bat.percentage > 1 ? bat.percentage / 100 : bat.percentage) : 0
15 readonly property bool charging: hasBat && bat.state === UPowerDeviceState.Charging
16
17 property string armedGpu: ""
18 Timer { id: disarm; interval: 3000; onTriggered: flick.armedGpu = "" }
19
20 function gpuClick(m) {
21 if (Gpu.mode === m || Gpu.busy) return
22 if (armedGpu !== m) { armedGpu = m; disarm.restart(); return }
23 armedGpu = ""
24 Gpu.set(m)
25 }
26 function stateText() {
27 if (!hasBat) return ""
28 switch (bat.state) {
29 case UPowerDeviceState.Charging: return "charging"
30 case UPowerDeviceState.Discharging: return "discharging"
31 case UPowerDeviceState.FullyCharged: return "full"
32 default: return "idle"
33 }
34 }
35 function g(v) { return v.toFixed(1) + "G" }
36
37 ColumnLayout {
38 id: col
39 width: flick.width
40 spacing: 8
41
42 SectionLabel { text: "cpu" }
43 RowLayout {
44 Layout.fillWidth: true
45 spacing: 10
46 Text {
47 text: Theme.iChip + " " + Math.round(SysStats.cpu * 100) + "%"
48 Layout.preferredWidth: 80
49 color: Theme.fg
50 font.family: Theme.font
51 font.pixelSize: Theme.fontSize + 2
52 font.bold: true
53 }
54 Spark { Layout.fillWidth: true; values: SysStats.history }
55 }
56
57 SectionLabel { text: "memory & disk"; Layout.topMargin: 6 }
58 StatBar {
59 label: "memory"
60 frac: SysStats.memTotal > 0 ? SysStats.memUsed / SysStats.memTotal : 0
61 valueText: flick.g(SysStats.memUsed) + " / " + flick.g(SysStats.memTotal)
62 }
63 StatBar {
64 label: "disk /"
65 frac: SysStats.diskTotal > 0 ? SysStats.diskUsed / SysStats.diskTotal : 0
66 valueText: Math.round(SysStats.diskUsed) + "G / " + Math.round(SysStats.diskTotal) + "G"
67 }
68
69 ColumnLayout {
70 visible: flick.hasBat
71 Layout.fillWidth: true
72 Layout.topMargin: 6
73 spacing: 8
74 SectionLabel { text: "battery" }
75 StatBar {
76 label: "charge"
77 frac: flick.batPct
78 fill: flick.batPct <= 0.15 && !flick.charging ? Theme.err : Theme.accent
79 valueText: Math.round(flick.batPct * 100) + "% " + flick.stateText()
80 }
81 Text {
82 Layout.fillWidth: true
83 wrapMode: Text.Wrap
84 color: Theme.dim
85 font.family: Theme.font
86 font.pixelSize: Theme.fontSize - 1
87 lineHeight: 1.3
88 text: {
89 if (!flick.hasBat) return ""
90 var lines = []
91 var t = flick.charging ? flick.bat.timeToFull : flick.bat.timeToEmpty
92 lines.push((flick.charging ? "time to full " : "time left ") + Theme.fmtTime(t))
93 if (flick.bat.changeRate !== undefined)
94 lines.push("power draw " + Math.abs(flick.bat.changeRate).toFixed(1) + " W")
95 if (flick.bat.healthSupported)
96 lines.push("health " + Math.round(flick.bat.healthPercentage) + "%")
97 return lines.join("\n")
98 }
99 }
100 }
101
102 ColumnLayout {
103 visible: PowerProfiles.hasPerformanceProfile !== undefined
104 Layout.fillWidth: true
105 Layout.topMargin: 6
106 spacing: 8
107 SectionLabel { text: "power profile" }
108 RowLayout {
109 Layout.fillWidth: true
110 spacing: 6
111 IconBtn {
112 Layout.fillWidth: true
113 icon: Theme.iLeaf
114 label: "saver"
115 active: PowerProfiles.profile === PowerProfile.PowerSaver
116 onClicked: PowerProfiles.profile = PowerProfile.PowerSaver
117 }
118 IconBtn {
119 Layout.fillWidth: true
120 icon: Theme.iBalance
121 label: "balanced"
122 active: PowerProfiles.profile === PowerProfile.Balanced
123 onClicked: PowerProfiles.profile = PowerProfile.Balanced
124 }
125 IconBtn {
126 Layout.fillWidth: true
127 visible: PowerProfiles.hasPerformanceProfile
128 icon: Theme.iSpeed
129 label: "perf"
130 active: PowerProfiles.profile === PowerProfile.Performance
131 onClicked: PowerProfiles.profile = PowerProfile.Performance
132 }
133 }
134 }
135
136 ColumnLayout {
137 visible: Gpu.mode !== ""
138 Layout.fillWidth: true
139 Layout.topMargin: 6
140 spacing: 8
141 SectionLabel { text: "graphics · envycontrol" }
142 RowLayout {
143 Layout.fillWidth: true
144 spacing: 6
145 Repeater {
146 model: ["integrated", "hybrid", "nvidia"]
147 delegate: IconBtn {
148 required property string modelData
149 Layout.fillWidth: true
150 icon: Theme.iGpu
151 label: flick.armedGpu === modelData ? "sure?" : modelData
152 active: Gpu.mode === modelData
153 opacity: Gpu.busy ? 0.5 : 1
154 onClicked: flick.gpuClick(modelData)
155 }
156 }
157 }
158 Text {
159 visible: Gpu.pending !== "" || Gpu.message !== "" || Gpu.busy
160 Layout.fillWidth: true
161 wrapMode: Text.Wrap
162 color: Gpu.message !== "" ? Theme.err : Theme.accent
163 font.family: Theme.font
164 font.pixelSize: Theme.fontSize - 2
165 text: Gpu.busy ? "switching…" : (Gpu.message !== "" ? Gpu.message : "queued: " + Gpu.pending + " · reboot to apply")
166 }
167 }
168
169 Text {
170 Layout.topMargin: 10
171 Layout.alignment: Qt.AlignRight
172 text: "up " + Theme.fmtTime(SysStats.uptime)
173 color: Theme.dim
174 font.family: Theme.font
175 font.pixelSize: Theme.fontSize - 2
176 }
177 Item { Layout.preferredHeight: 6 }
178 }
179}