powerprofile switcher

This commit is contained in:
Zacharias-Brohn
2026-02-12 14:31:33 +01:00
parent ae23c309a2
commit 7efe7f44bf
10 changed files with 266 additions and 12 deletions
+1 -1
View File
@@ -7,7 +7,7 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib")
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
set(ENABLE_MODULES "plugin;shell" CACHE STRING "Modules to build/install")
set(ENABLE_MODULES "plugin" CACHE STRING "Modules to build/install")
set(INSTALL_LIBDIR "usr/lib/ZShell" CACHE STRING "Library install dir")
set(INSTALL_QMLDIR "usr/lib/qt6/qml" CACHE STRING "QML install dir")
+6
View File
@@ -40,6 +40,10 @@ JsonObject {
id: "upower",
enabled: false
},
{
id: "network",
enabled: false
},
{
id: "clock",
enabled: true
@@ -56,5 +60,7 @@ JsonObject {
property bool activeWindow: true
property bool resources: true
property bool clock: true
property bool network: true
property bool upower: true
}
}
+1 -1
View File
@@ -223,7 +223,7 @@ Singleton {
const hash = (h2 >>> 0).toString(16).padStart(8, 0) + (h1 >>> 0).toString(16).padStart(8, 0);
const cache = `${Paths.notifimagecache}/${hash}.png`;
ZShell.saveItem(this, Qt.resolvedUrl(cache), () => {
ZShellIo.saveItem(this, Qt.resolvedUrl(cache), () => {
notif.image = cache;
notif.dummyImageLoader.active = false;
});
+1 -1
View File
@@ -6,6 +6,6 @@ import Quickshell.Networking
Singleton {
id: root
property list<NetworkDevice> devices: Networking.devices
property list<NetworkDevice> devices: Networking.devices.values
property NetworkDevice activeDevice: devices.find(d => d.connected)
}
+15
View File
@@ -10,6 +10,7 @@ import qs.Helpers
import qs.Daemons
import qs.Modules.Polkit
import qs.Modules.UPower
import qs.Modules.Network
RowLayout {
id: root
@@ -66,6 +67,14 @@ RowLayout {
popouts.currentName = "dash";
popouts.currentCenter = root.width / 2;
popouts.hasCurrent = true;
} else if ( id === "network" && Config.barConfig.popouts.network ) {
popouts.currentName = "network";
popouts.currentCenter = Qt.binding( () => item.mapToItem( root, itemWidth / 2, 0 ).x );
popouts.hasCurrent = true;
} else if ( id === "upower" && Config.barConfig.popouts.upower ) {
popouts.currentName = "upower";
popouts.currentCenter = Qt.binding( () => item.mapToItem( root, itemWidth / 2, 0 ).x );
popouts.hasCurrent = true;
}
}
@@ -167,6 +176,12 @@ RowLayout {
sourceComponent: UPowerWidget {}
}
}
DelegateChoice {
roleValue: "network"
delegate: WrappedLoader {
sourceComponent: NetworkWidget {}
}
}
}
}
+18
View File
@@ -8,6 +8,8 @@ import qs.Modules.Calendar
import qs.Modules.WSOverview
import qs.Modules.Polkit
import qs.Modules.Dashboard
import qs.Modules.Network
import qs.Modules.UPower
Item {
id: root
@@ -97,6 +99,22 @@ Item {
wrapper: root.wrapper
}
}
Popout {
name: "upower"
sourceComponent: UPowerPopout {
wrapper: root.wrapper
}
}
Popout {
name: "network"
sourceComponent: NetworkPopout {
wrapper: root.wrapper
}
}
}
component Popout: Loader {
+7 -4
View File
@@ -4,21 +4,25 @@ import Quickshell
import Quickshell.Networking
import QtQuick
import QtQuick.Layouts
import qs.Components
import qs.Config
import qs.Modules
import qs.Helpers
import qs.Helpers as Helpers
Item {
id: root
required property var wrapper
Component.onCompleted: console.log(Networking.backend.toString())
ColumnLayout {
id: layout
spacing: 8
Repeater {
model: Network.devices
model: Helpers.Network.devices
CustomRadioButton {
id: network
@@ -26,8 +30,7 @@ Item {
required property NetworkDevice modelData
checked: Network.activeDevice?.name === modelData.name
onClicked:
checked: Helpers.Network.activeDevice?.name === modelData.name
text: modelData.description
}
}
+25
View File
@@ -0,0 +1,25 @@
import Quickshell
import QtQuick
import QtQuick.Layouts
import qs.Components
import qs.Modules
Item {
id: root
anchors.top: parent.top
anchors.bottom: parent.bottom
implicitWidth: layout.implicitWidth
RowLayout {
id: layout
anchors.top: parent.top
anchors.bottom: parent.bottom
MaterialIcon {
text: "android_wifi_4_bar"
Layout.alignment: Qt.AlignVCenter
}
}
}
+179
View File
@@ -0,0 +1,179 @@
pragma ComponentBehavior: Bound
import QtQuick
import Quickshell.Services.UPower
import qs.Config
import qs.Components
import qs.Modules
Item {
id: root
required property var wrapper
implicitWidth: profiles.implicitWidth
implicitHeight: profiles.implicitHeight
CustomRect {
id: profiles
property string current: {
const p = PowerProfiles.profile;
if (p === PowerProfile.PowerSaver)
return saver.icon;
if (p === PowerProfile.Performance)
return perf.icon;
return balance.icon;
}
anchors.horizontalCenter: parent.horizontalCenter
implicitWidth: saver.implicitHeight + balance.implicitHeight + perf.implicitHeight + 8 * 2 + saverLabel.contentWidth
implicitHeight: Math.max(saver.implicitHeight, balance.implicitHeight, perf.implicitHeight) + 5 * 2 + saverLabel.contentHeight
color: DynamicColors.tPalette.m3surfaceContainer
radius: 6
CustomRect {
id: indicator
color: DynamicColors.palette.m3primary
radius: 1000
state: profiles.current
states: [
State {
name: saver.icon
Fill {
item: saver
}
},
State {
name: balance.icon
Fill {
item: balance
}
},
State {
name: perf.icon
Fill {
item: perf
}
}
]
transitions: Transition {
AnchorAnimation {
duration: MaterialEasing.expressiveEffectsTime
easing.bezierCurve: MaterialEasing.expressiveEffects
easing.type: Easing.BezierSpline
}
}
}
Profile {
id: saver
anchors.top: parent.top
anchors.topMargin: 8
anchors.left: parent.left
anchors.leftMargin: 25
text: "Power Saver"
profile: PowerProfile.PowerSaver
icon: "nest_eco_leaf"
}
CustomText {
id: saverLabel
anchors.top: saver.bottom
anchors.horizontalCenter: saver.horizontalCenter
text: saver.text
}
Profile {
id: balance
anchors.top: parent.top
anchors.topMargin: 8
anchors.horizontalCenter: parent.horizontalCenter
text: "Balanced"
profile: PowerProfile.Balanced
icon: "power_settings_new"
}
CustomText {
id: balanceLabel
anchors.top: balance.bottom
anchors.horizontalCenter: balance.horizontalCenter
text: balance.text
}
Profile {
id: perf
anchors.top: parent.top
anchors.topMargin: 8
anchors.right: parent.right
anchors.rightMargin: 25
text: "Performance"
profile: PowerProfile.Performance
icon: "bolt"
}
CustomText {
id: perfLabel
anchors.top: perf.bottom
anchors.horizontalCenter: perf.horizontalCenter
text: perf.text
}
}
component Fill: AnchorChanges {
required property Item item
target: indicator
anchors.left: item.left
anchors.right: item.right
anchors.top: item.top
anchors.bottom: item.bottom
}
component Profile: Item {
required property string icon
required property int profile
required property string text
implicitWidth: icon.implicitHeight + 5 * 2
implicitHeight: icon.implicitHeight + 5 * 2
StateLayer {
radius: 1000
color: profiles.current === parent.icon ? DynamicColors.palette.m3onPrimary : DynamicColors.palette.m3onSurface
function onClicked(): void {
PowerProfiles.profile = parent.profile;
}
}
MaterialIcon {
id: icon
anchors.centerIn: parent
text: parent.icon
font.pointSize: 36
color: profiles.current === text ? DynamicColors.palette.m3onPrimary : DynamicColors.palette.m3onSurface
fill: profiles.current === text ? 1 : 0
Behavior on fill {
Anim {}
}
}
}
}
+13 -5
View File
@@ -10,10 +10,18 @@ import qs.Modules
Item {
id: root
implicitWidth: layout.childrenRect.width
implicitWidth: layout.childrenRect.width + 10 * 2
anchors.top: parent.top
anchors.bottom: parent.bottom
CustomRect {
anchors.fill: parent
anchors.topMargin: 3
anchors.bottomMargin: 3
color: DynamicColors.tPalette.m3surfaceContainer
radius: 1000
}
RowLayout {
id: layout
anchors.centerIn: parent
@@ -24,10 +32,10 @@ Item {
text: {
if (!Helpers.UPower.displayDevice.isLaptopBattery) {
if (PowerProfiles.profile === PowerProfile.PowerSaver)
return "energy_savings_leaf";
return "nest_eco_leaf";
if (PowerProfiles.profile === PowerProfile.Performance)
return "rocket_launch";
return "balance";
return "bolt";
return "power_settings_new";
}
const perc = Helpers.UPower.displayDevice.percentage;
@@ -45,7 +53,7 @@ Item {
CustomText {
Layout.alignment: Qt.AlignVCenter
text: Helpers.UPower.displayDevice.isLaptopBattery ? qsTr("%1%").arg(Math.round(UPower.displayDevice.percentage * 100)) : qsTr("NaN")
text: Helpers.UPower.displayDevice.isLaptopBattery ? qsTr("%1%").arg(Math.round(UPower.displayDevice.percentage * 100)) : (PowerProfiles.profile === PowerProfile.PowerSaver ? qsTr("Pwr Sav") : PowerProfiles.profile === PowerProfile.Performance ? qsTr("Perf") : qsTr("Bal"))
}
}
}