config fixes

This commit is contained in:
Zacharias-Brohn
2026-02-17 12:46:25 +01:00
parent 7d9ba3d570
commit e818ac5515
39 changed files with 888 additions and 144 deletions
+4 -4
View File
@@ -31,7 +31,7 @@ Variants {
WlrLayershell.namespace: "ZShell-Bar-Exclusion"
screen: bar.screen
WlrLayershell.layer: WlrLayer.Bottom
WlrLayershell.exclusionMode: Config.autoHide ? ExclusionMode.Ignore : ExclusionMode.Auto
WlrLayershell.exclusionMode: Config.barConfig.autoHide ? ExclusionMode.Ignore : ExclusionMode.Auto
anchors {
left: true
right: true
@@ -51,7 +51,7 @@ Variants {
mask: Region {
id: region
x: 0
y: Config.autoHide && !visibilities.bar ? 4 : 34
y: Config.barConfig.autoHide && !visibilities.bar ? 4 : 34
property list<Region> nullRegions: []
property bool hcurrent: ( panels.popouts.hasCurrent && panels.popouts.currentName.startsWith("traymenu") ) || visibilities.sidebar || visibilities.dashboard
@@ -99,7 +99,7 @@ Variants {
Item {
anchors.fill: parent
opacity: Config.transparency.enabled ? DynamicColors.transparency.base : 1
opacity: Appearance.transparency.enabled ? DynamicColors.transparency.base : 1
layer.enabled: true
layer.effect: MultiEffect {
shadowEnabled: true
@@ -142,7 +142,7 @@ Variants {
anchors.left: parent.left
anchors.right: parent.right
implicitHeight: 34
anchors.topMargin: Config.autoHide && !visibilities.bar ? -30 : 0
anchors.topMargin: Config.barConfig.autoHide && !visibilities.bar ? -30 : 0
color: "transparent"
radius: 0
+1 -1
View File
@@ -16,7 +16,7 @@ Text {
renderType: Text.NativeRendering
textFormat: Text.PlainText
color: DynamicColors.palette.m3onSurface
font.family: Config.baseFont
font.family: Appearance.font.family.sans
font.pointSize: 12
Behavior on color {
+135
View File
@@ -0,0 +1,135 @@
import ZShell
import QtQuick
import QtQuick.Layouts
import qs.Modules
import qs.Components
import qs.Helpers
import qs.Config
CustomRect {
id: root
required property Toast modelData
anchors.left: parent.left
anchors.right: parent.right
implicitHeight: layout.implicitHeight + Appearance.padding.smaller * 2
radius: Appearance.rounding.normal
color: {
if (root.modelData.type === Toast.Success)
return DynamicColors.palette.m3successContainer;
if (root.modelData.type === Toast.Warning)
return DynamicColors.palette.m3secondary;
if (root.modelData.type === Toast.Error)
return DynamicColors.palette.m3errorContainer;
return DynamicColors.palette.m3surface;
}
border.width: 1
border.color: {
let colour = DynamicColors.palette.m3outlineVariant;
if (root.modelData.type === Toast.Success)
colour = DynamicColors.palette.m3success;
if (root.modelData.type === Toast.Warning)
colour = DynamicColors.palette.m3secondaryContainer;
if (root.modelData.type === Toast.Error)
colour = DynamicColors.palette.m3error;
return Qt.alpha(colour, 0.3);
}
Elevation {
anchors.fill: parent
radius: parent.radius
opacity: parent.opacity
z: -1
level: 3
}
RowLayout {
id: layout
anchors.fill: parent
anchors.margins: Appearance.padding.smaller
anchors.leftMargin: Appearance.padding.normal
anchors.rightMargin: Appearance.padding.normal
spacing: Appearance.spacing.normal
CustomRect {
radius: Appearance.rounding.normal
color: {
if (root.modelData.type === Toast.Success)
return DynamicColors.palette.m3success;
if (root.modelData.type === Toast.Warning)
return DynamicColors.palette.m3secondaryContainer;
if (root.modelData.type === Toast.Error)
return DynamicColors.palette.m3error;
return DynamicColors.palette.m3surfaceContainerHigh;
}
implicitWidth: implicitHeight
implicitHeight: icon.implicitHeight + Appearance.padding.smaller * 2
MaterialIcon {
id: icon
anchors.centerIn: parent
text: root.modelData.icon
color: {
if (root.modelData.type === Toast.Success)
return DynamicColors.palette.m3onSuccess;
if (root.modelData.type === Toast.Warning)
return DynamicColors.palette.m3onSecondaryContainer;
if (root.modelData.type === Toast.Error)
return DynamicColors.palette.m3onError;
return DynamicColors.palette.m3onSurfaceVariant;
}
font.pointSize: Math.round(Appearance.font.size.large * 1.2)
}
}
ColumnLayout {
Layout.fillWidth: true
spacing: 0
CustomText {
id: title
Layout.fillWidth: true
text: root.modelData.title
color: {
if (root.modelData.type === Toast.Success)
return DynamicColors.palette.m3onSuccessContainer;
if (root.modelData.type === Toast.Warning)
return DynamicColors.palette.m3onSecondary;
if (root.modelData.type === Toast.Error)
return DynamicColors.palette.m3onErrorContainer;
return DynamicColors.palette.m3onSurface;
}
font.pointSize: Appearance.font.size.normal
elide: Text.ElideRight
}
CustomText {
Layout.fillWidth: true
textFormat: Text.StyledText
text: root.modelData.message
color: {
if (root.modelData.type === Toast.Success)
return DynamicColors.palette.m3onSuccessContainer;
if (root.modelData.type === Toast.Warning)
return DynamicColors.palette.m3onSecondary;
if (root.modelData.type === Toast.Error)
return DynamicColors.palette.m3onErrorContainer;
return DynamicColors.palette.m3onSurface;
}
opacity: 0.8
elide: Text.ElideRight
}
}
}
Behavior on border.color {
CAnim {}
}
}
+144
View File
@@ -0,0 +1,144 @@
pragma ComponentBehavior: Bound
import qs.Components
import qs.Config
import qs.Modules
import ZShell
import Quickshell
import QtQuick
Item {
id: root
readonly property int spacing: Appearance.spacing.small
property bool flag
implicitWidth: Config.utilities.sizes.toastWidth - Appearance.padding.normal * 2
implicitHeight: {
let h = -spacing;
for (let i = 0; i < repeater.count; i++) {
const item = repeater.itemAt(i) as ToastWrapper;
if (!item.modelData.closed && !item.previewHidden)
h += item.implicitHeight + spacing;
}
return h;
}
Repeater {
id: repeater
model: ScriptModel {
values: {
const toasts = [];
let count = 0;
for (const toast of Toaster.toasts) {
toasts.push(toast);
if (!toast.closed) {
count++;
if (count > Config.utilities.maxToasts)
break;
}
}
return toasts;
}
onValuesChanged: root.flagChanged()
}
ToastWrapper {}
}
component ToastWrapper: MouseArea {
id: toast
required property int index
required property Toast modelData
readonly property bool previewHidden: {
let extraHidden = 0;
for (let i = 0; i < index; i++)
if (Toaster.toasts[i].closed)
extraHidden++;
return index >= Config.utilities.maxToasts + extraHidden;
}
onPreviewHiddenChanged: {
if (initAnim.running && previewHidden)
initAnim.stop();
}
opacity: modelData.closed || previewHidden ? 0 : 1
scale: modelData.closed || previewHidden ? 0.7 : 1
anchors.bottomMargin: {
root.flag; // Force update
let y = 0;
for (let i = 0; i < index; i++) {
const item = repeater.itemAt(i) as ToastWrapper;
if (item && !item.modelData.closed && !item.previewHidden)
y += item.implicitHeight + root.spacing;
}
return y;
}
anchors.left: parent.left
anchors.right: parent.right
anchors.bottom: parent.bottom
implicitHeight: toastInner.implicitHeight
acceptedButtons: Qt.LeftButton | Qt.MiddleButton | Qt.RightButton
onClicked: modelData.close()
Component.onCompleted: modelData.lock(this)
Anim {
id: initAnim
Component.onCompleted: running = !toast.previewHidden
target: toast
properties: "opacity,scale"
from: 0
to: 1
duration: Appearance.anim.durations.expressiveDefaultSpatial
easing.bezierCurve: Appearance.anim.curves.expressiveDefaultSpatial
}
ParallelAnimation {
running: toast.modelData.closed
onStarted: toast.anchors.bottomMargin = toast.anchors.bottomMargin
onFinished: toast.modelData.unlock(toast)
Anim {
target: toast
property: "opacity"
to: 0
}
Anim {
target: toast
property: "scale"
to: 0.7
}
}
ToastItem {
id: toastInner
modelData: toast.modelData
}
Behavior on opacity {
Anim {}
}
Behavior on scale {
Anim {}
}
Behavior on anchors.bottomMargin {
Anim {
duration: Appearance.anim.durations.expressiveDefaultSpatial
easing.bezierCurve: Appearance.anim.curves.expressiveDefaultSpatial
}
}
}
}
+1 -1
View File
@@ -35,7 +35,7 @@ JsonObject {
}
component FontFamily: JsonObject {
property string sans: "Rubik"
property string sans: "Segoe UI Variable Text"
property string mono: "CaskaydiaCove NF"
property string material: "Material Symbols Rounded"
property string clock: "Rubik"
-1
View File
@@ -1,5 +1,4 @@
import Quickshell.Io
import qs.Modules
import qs.Config
JsonObject {
+1
View File
@@ -1,6 +1,7 @@
import Quickshell.Io
JsonObject {
property bool autoHide: false
property Popouts popouts: Popouts {}
property list<var> entries: [
-5
View File
@@ -1,10 +1,5 @@
import Quickshell.Io
JsonObject {
property BgColors backgrounds: BgColors {}
property string schemeType: "vibrant"
component BgColors: JsonObject {
property string hover: "#15ffffff"
}
}
+315 -40
View File
@@ -2,28 +2,17 @@ pragma Singleton
import Quickshell
import Quickshell.Io
import qs.Modules
import ZShell
import QtQuick
import qs.Modules as Modules
import qs.Paths
Singleton {
id: root
property alias appCount: adapter.appCount
property alias baseBgColor: adapter.baseBgColor
property alias baseBorderColor: adapter.baseBorderColor
property alias accentColor: adapter.accentColor
property alias wallpaperPath: adapter.wallpaperPath
property alias maxWallpapers: adapter.maxWallpapers
property alias wallust: adapter.wallust
property alias workspaceWidget: adapter.workspaceWidget
property alias colors: adapter.colors
property alias gpuType: adapter.gpuType
property alias background: adapter.background
property alias useDynamicColors: adapter.useDynamicColors
property alias barConfig: adapter.barConfig
property alias transparency: adapter.transparency
property alias baseFont: adapter.baseFont
property alias animScale: adapter.animScale
property alias lock: adapter.lock
property alias idle: adapter.idle
property alias overview: adapter.overview
property alias services: adapter.services
property alias notifs: adapter.notifs
@@ -32,41 +21,327 @@ Singleton {
property alias general: adapter.general
property alias dashboard: adapter.dashboard
property alias appearance: adapter.appearance
property alias autoHide: adapter.autoHide
property alias macchiato: adapter.macchiato
property alias osd: adapter.osd
property alias launcher: adapter.launcher
property alias colors: adapter.colors
function save(): void {
saveTimer.restart();
recentlySaved = true;
recentSaveCooldown.restart();
}
property bool recentlySaved: false
ElapsedTimer {
id: timer
}
Timer {
running: true
interval: 5000
repeat: false
onTriggered: {
root.save();
}
}
Timer {
id: saveTimer
interval: 500
onTriggered: {
timer.restart();
try {
let config = {};
try {
config = JSON.parse(fileView.text());
} catch (e) {
config = {};
}
config = root.serializeConfig();
fileView.setText(JSON.stringify(config, null, 4));
} catch (e) {
Toaster.toast(qsTr("Failed to serialize config"), e.message, "settings_alert", Toast.Error);
}
}
}
Timer {
id: recentSaveCooldown
interval: 2000
onTriggered: {
root.recentlySaved = false;
}
}
function serializeConfig(): var {
return {
barConfig: serializeBar(),
lock: serializeLock(),
general: serializeGeneral(),
services: serializeServices(),
notifs: serializeNotifs(),
sidebar: serializeSidebar(),
utilities: serializeUtilities(),
dashboard: serializeDashboard(),
appearance: serializeAppearance(),
osd: serializeOsd(),
background: serializeBackground(),
launcher: serializeLauncher(),
colors: serializeColors()
}
}
function serializeBar(): var {
return {
autoHide: barConfig.autoHide,
popouts: {
tray: barConfig.popouts.tray,
audio: barConfig.popouts.audio,
activeWindow: barConfig.popouts.activeWindow,
resources: barConfig.popouts.resources,
clock: barConfig.popouts.clock,
network: barConfig.popouts.network,
upower: barConfig.popouts.upower
},
entries: barConfig.entries
}
}
function serializeLock(): var {
return {
recolorLogo: lock.recolorLogo,
enableFprint: lock.enableFprint,
maxFprintTries: lock.maxFprintTries,
sizes: {
heightMult: lock.sizes.heightMult,
ratio: lock.sizes.ratio,
centerWidth: lock.sizes.centerWidth
}
};
}
function serializeGeneral(): var {
return {
logo: general.logo,
wallpaperPath: general.wallpaperPath,
wallust: general.wallust,
idle: {
timouts: general.idle.timeouts
}
}
}
function serializeServices(): var {
return {
weatherLocation: services.weatherLocation,
useFahrenheit: services.useFahrenheit,
useTwelveHourClock: services.useTwelveHourClock,
gpuType: services.gpuType,
audioIncrement: services.audioIncrement,
brightnessIncrement: services.brightnessIncrement,
maxVolume: services.maxVolume,
defaultPlayer: services.defaultPlayer,
playerAliases: services.playerAliases
};
}
function serializeNotifs(): var {
return {
expire: notifs.expire,
defaultExpireTimeout: notifs.defaultExpireTimeout,
clearThreshold: notifs.clearThreshold,
expandThreshold: notifs.expandThreshold,
actionOnClick: notifs.actionOnClick,
groupPreviewNum: notifs.groupPreviewNum,
sizes: {
width: notifs.sizes.width,
image: notifs.sizes.image,
badge: notifs.sizes.badge
}
};
}
function serializeSidebar(): var {
return {
enabled: sidebar.enabled,
sizes: {
width: sidebar.sizes.width
}
};
}
function serializeUtilities(): var {
return {
enabled: utilities.enabled,
maxToasts: utilities.maxToasts,
sizes: {
width: utilities.sizes.width,
toastWidth: utilities.sizes.toastWidth
},
toasts: {
configLoaded: utilities.toasts.configLoaded,
chargingChanged: utilities.toasts.chargingChanged,
gameModeChanged: utilities.toasts.gameModeChanged,
dndChanged: utilities.toasts.dndChanged,
audioOutputChanged: utilities.toasts.audioOutputChanged,
audioInputChanged: utilities.toasts.audioInputChanged,
capsLockChanged: utilities.toasts.capsLockChanged,
numLockChanged: utilities.toasts.numLockChanged,
kbLayoutChanged: utilities.toasts.kbLayoutChanged,
vpnChanged: utilities.toasts.vpnChanged,
nowPlaying: utilities.toasts.nowPlaying
},
vpn: {
enabled: utilities.vpn.enabled,
provider: utilities.vpn.provider
}
};
}
function serializeDashboard(): var {
return {
enabled: dashboard.enabled,
mediaUpdateInterval: dashboard.mediaUpdateInterval,
dragThreshold: dashboard.dragThreshold,
sizes: {
tabIndicatorHeight: dashboard.sizes.tabIndicatorHeight,
tabIndicatorSpacing: dashboard.sizes.tabIndicatorSpacing,
infoWidth: dashboard.sizes.infoWidth,
infoIconSize: dashboard.sizes.infoIconSize,
dateTimeWidth: dashboard.sizes.dateTimeWidth,
mediaWidth: dashboard.sizes.mediaWidth,
mediaProgressSweep: dashboard.sizes.mediaProgressSweep,
mediaProgressThickness: dashboard.sizes.mediaProgressThickness,
resourceProgessThickness: dashboard.sizes.resourceProgessThickness,
weatherWidth: dashboard.sizes.weatherWidth,
mediaCoverArtSize: dashboard.sizes.mediaCoverArtSize,
mediaVisualiserSize: dashboard.sizes.mediaVisualiserSize,
resourceSize: dashboard.sizes.resourceSize
}
};
}
function serializeOsd(): var {
return {
enabled: osd.enabled,
hideDelay: osd.hideDelay,
enableBrightness: osd.enableBrightness,
enableMicrophone: osd.enableMicrophone,
sizes: {
sliderWidth: osd.sizes.sliderWidth,
sliderHeight: osd.sizes.sliderHeight
}
};
}
function serializeLauncher(): var {
return {
maxAppsShown: launcher.maxAppsShown,
maxWallpapers: launcher.maxWallpapers,
wallpaperPrefix: launcher.wallpaperPrefix
}
}
function serializeBackground(): var {
return {
wallFadeDuration: background.wallFadeDuration,
enabled: background.enabled
}
}
function serializeAppearance(): var {
return {
rounding: {
scale: appearance.rounding.scale
},
spacing: {
scale: appearance.spacing.scale
},
padding: {
scale: appearance.padding.scale
},
font: {
family: {
sans: appearance.font.family.sans,
mono: appearance.font.family.mono,
material: appearance.font.family.material,
clock: appearance.font.family.clock
},
size: {
scale: appearance.font.size.scale
}
},
anim: {
mediaGifSpeedAdjustment: 300,
sessionGifSpeed: 0.7,
durations: {
scale: appearance.anim.durations.scale
}
},
transparency: {
enabled: appearance.transparency.enabled,
base: appearance.transparency.base,
layers: appearance.transparency.layers
}
};
}
function serializeColors(): var {
return {
schemeType: colors.schemeType,
}
}
FileView {
id: root
property var configRoot: Quickshell.env("HOME")
id: fileView
path: configRoot + "/.config/z-bar/config.json"
path: `${Paths.config}/config.json`
watchChanges: true
onFileChanged: reload()
onAdapterChanged: writeAdapter()
onFileChanged: {
if ( !root.recentlySaved ) {
timer.restart();
reload();
} else {
reload();
}
}
onLoaded: {
try {
JSON.parse(text());
const elapsed = timer.elapsedMs();
if ( adapter.utilities.toasts.configLoaded && !root.recentlySaved ) {
Toaster.toast(qsTr("Config loaded"), qsTr("Config loaded in %1ms").arg(elapsed), "rule_settings");
} else if ( adapter.utilities.toasts.configLoaded && root.recentlySaved ) {
Toaster.toast(qsTr("Config saved"), qsTr("Config reloaded in %1ms").arg(elapsed), "settings_alert");
}
} catch (e) {
Toaster.toast(qsTr("Failed to load config"), e.message, "settings_alert", Toast.Error);
}
}
onLoadFailed: err => {
if ( err !== FileViewError.FileNotFound )
Toaster.toast(qsTr("Failed to read config"), FileViewError.toString(err), "settings_alert", Toast.Warning);
}
onSaveFailed: err => Toaster.toast(qsTr("Failed to save config"), FileViewError.toString(err), "settings_alert", Toast.Error)
JsonAdapter {
id: adapter
property int appCount: 20
property string wallpaperPath: Quickshell.env("HOME") + "/Pictures/Wallpapers"
property string baseBgColor: "#801a1a1a"
property string baseBorderColor: "#444444"
property AccentColor accentColor: AccentColor {}
property int maxWallpapers: 7
property bool wallust: false
property WorkspaceWidget workspaceWidget: WorkspaceWidget {}
property Colors colors: Colors {}
property string gpuType: ""
property BackgroundConfig background: BackgroundConfig {}
property bool useDynamicColors: false
property BarConfig barConfig: BarConfig {}
property Transparency transparency: Transparency {}
property string baseFont: "Segoe UI Variable Text"
property real animScale: 1.0
property LockConf lock: LockConf {}
property IdleTimeout idle: IdleTimeout {}
property Overview overview: Overview {}
property Services services: Services {}
property NotifConfig notifs: NotifConfig {}
@@ -75,9 +350,9 @@ Singleton {
property General general: General {}
property DashboardConfig dashboard: DashboardConfig {}
property AppearanceConf appearance: AppearanceConf {}
property bool autoHide: false
property bool macchiato: false
property Osd osd: Osd {}
property Launcher launcher: Launcher {}
property Colors colors: Colors {}
}
}
}
-1
View File
@@ -2,7 +2,6 @@ import Quickshell.Io
JsonObject {
property bool enabled: true
property bool showOnHover: true
property int mediaUpdateInterval: 500
property int dragThreshold: 50
property Sizes sizes: Sizes {}
+3 -3
View File
@@ -88,9 +88,9 @@ Singleton {
}
component Transparency: QtObject {
readonly property bool enabled: Config.transparency.enabled
readonly property real base: Config.transparency.base - (root.light ? 0.1 : 0)
readonly property real layers: Config.transparency.layers
readonly property bool enabled: Appearance.transparency.enabled
readonly property real base: Appearance.transparency.base - (root.light ? 0.1 : 0)
readonly property real layers: Appearance.transparency.layers
}
component M3TPalette: QtObject {
+18
View File
@@ -1,5 +1,23 @@
import Quickshell.Io
import Quickshell
JsonObject {
property string logo: ""
property string wallpaperPath: Quickshell.env("HOME") + "/Pictures/Wallpapers"
property bool wallust: false
property Idle idle: Idle {}
component Idle: JsonObject {
property list<var> timeouts: [
{
timeout: 180,
idleAction: "lock"
},
{
timeout: 300,
idleAction: "dpms off",
activeAction: "dpms on"
}
]
}
}
+7
View File
@@ -0,0 +1,7 @@
import Quickshell.Io
JsonObject {
property int maxAppsShown: 10
property int maxWallpapers: 7
property string wallpaperPrefix: ">"
}
+1 -1
View File
@@ -4,7 +4,7 @@ import Quickshell
Singleton {
id: root
property real scale: Config.animScale
property real scale: Appearance.anim.durations.scale
readonly property list<real> emphasized: [0.05, 0, 2 / 15, 0.06, 1 / 6, 0.4, 5 / 24, 0.82, 0.25, 1, 1, 1]
readonly property list<real> emphasizedAccel: [0.3, 0, 0.8, 0.15, 1, 1]
+2 -2
View File
@@ -75,7 +75,7 @@ CustomMouseArea {
popouts.hasCurrent = false;
}
if (Config.autoHide && !root.visibilities.sidebar && !root.visibilities.dashboard)
if (Config.barConfig.autoHide && !root.visibilities.sidebar && !root.visibilities.dashboard)
root.visibilities.bar = false;
}
}
@@ -90,7 +90,7 @@ CustomMouseArea {
const dragY = y - dragStart.y;
// Show bar in non-exclusive mode on hover
if (!visibilities.bar && Config.autoHide && y < bar.implicitHeight + bar.anchors.topMargin)
if (!visibilities.bar && Config.barConfig.autoHide && y < bar.implicitHeight + bar.anchors.topMargin)
visibilities.bar = true;
if (panels.sidebar.width === 0) {
+11 -1
View File
@@ -7,6 +7,7 @@ import qs.Modules.Notifications.Sidebar as Sidebar
import qs.Modules.Notifications.Sidebar.Utils as Utils
import qs.Modules.Dashboard as Dashboard
import qs.Modules.Osd as Osd
import qs.Components.Toast as Toasts
import qs.Config
Item {
@@ -22,6 +23,7 @@ Item {
readonly property alias utilities: utilities
readonly property alias dashboard: dashboard
readonly property alias osd: osd
readonly property alias toasts: toasts
anchors.fill: parent
// anchors.margins: 8
@@ -30,7 +32,7 @@ Item {
Osd.Wrapper {
id: osd
clip: session.width > 0 || sidebar.width > 0
clip: sidebar.width > 0
screen: root.screen
visibilities: root.visibilities
@@ -55,6 +57,14 @@ Item {
}
}
Toasts.Toasts {
id: toasts
anchors.bottom: sidebar.visible ? parent.bottom : utilities.top
anchors.right: sidebar.left
anchors.margins: Appearance.padding.normal
}
Notifications.Wrapper {
id: notifications
+1 -1
View File
@@ -43,7 +43,7 @@ Searcher {
id: wallpapers
recursive: true
path: Config.wallpaperPath
path: Config.general.wallpaperPath
filter: FileSystemModel.Images
}
}
+2 -2
View File
@@ -10,7 +10,7 @@ Singleton {
property real cpuPerc
property real cpuTemp
readonly property string gpuType: Config.gpuType.toUpperCase() || autoGpuType
readonly property string gpuType: Config.services.gpuType.toUpperCase() || autoGpuType
property string autoGpuType: "NONE"
property real gpuPerc
property real gpuTemp
@@ -145,7 +145,7 @@ Singleton {
Process {
id: gpuTypeCheck
running: !Config.gpuType
running: !Config.services.gpuType
command: ["sh", "-c", "if command -v nvidia-smi &>/dev/null && nvidia-smi -L &>/dev/null; then echo NVIDIA; elif ls /sys/class/drm/card*/device/gpu_busy_percent 2>/dev/null | grep -q .; then echo GENERIC; else echo NONE; fi"]
stdout: StdioCollector {
onStreamFinished: root.autoGpuType = text.trim()
+5 -5
View File
@@ -13,8 +13,8 @@ Item {
anchors.bottom: parent.bottom
property bool expanded: false
property color textColor: Config.useDynamicColors ? DynamicColors.palette.m3tertiaryFixed : "#ffffff"
property color barColor: Config.useDynamicColors ? DynamicColors.palette.m3primary : "#ffffff"
property color textColor: DynamicColors.palette.m3tertiaryFixed
property color barColor: DynamicColors.palette.m3primary
Behavior on implicitWidth {
NumberAnimation {
@@ -37,7 +37,7 @@ Item {
anchors.right: parent.right
height: 22
radius: height / 2
color: Config.useDynamicColors ? DynamicColors.tPalette.m3surfaceContainer : "#40000000"
color: DynamicColors.tPalette.m3surfaceContainer
Behavior on color {
CAnim {}
@@ -95,7 +95,7 @@ Item {
Layout.alignment: Qt.AlignVCenter
font.pixelSize: 18
text: Pipewire.defaultAudioSource?.audio.muted ? "mic_off" : "mic"
color: ( Pipewire.defaultAudioSource?.audio.muted ?? false ) ? (Config.useDynamicColors ? DynamicColors.palette.m3error : "#ff4444") : root.textColor
color: ( Pipewire.defaultAudioSource?.audio.muted ?? false ) ? DynamicColors.palette.m3error : root.textColor
}
Rectangle {
@@ -115,7 +115,7 @@ Item {
implicitWidth: parent.width * ( Pipewire.defaultAudioSource?.audio.volume ?? 0 )
radius: parent.radius
color: ( Pipewire.defaultAudioSource?.audio.muted ?? false ) ? (Config.useDynamicColors ? DynamicColors.palette.m3error : "#ff4444") : root.barColor
color: ( Pipewire.defaultAudioSource?.audio.muted ?? false ) ? DynamicColors.palette.m3error : root.barColor
Behavior on color {
CAnim {}
+2 -2
View File
@@ -17,7 +17,7 @@ Item {
CustomRect {
anchors.fill: parent
color: Config.autoHide && !root.visibilities.bar ? "transparent" : DynamicColors.palette.m3surface
color: Config.barConfig.autoHide && !root.visibilities.bar ? "transparent" : DynamicColors.palette.m3surface
layer.enabled: true
@@ -38,7 +38,7 @@ Item {
Rectangle {
anchors.fill: parent
anchors.topMargin: Config.autoHide && !root.visibilities.bar ? 4 : root.bar.implicitHeight
anchors.topMargin: Config.barConfig.autoHide && !root.visibilities.bar ? 4 : root.bar.implicitHeight
topLeftRadius: 8
topRightRadius: 8
Behavior on anchors.topMargin {
+1 -1
View File
@@ -27,7 +27,7 @@ Item {
anchors.centerIn: parent
text: Time.dateStr
color: Config.useDynamicColors ? DynamicColors.palette.m3tertiary : "white"
color: DynamicColors.palette.m3tertiary
Behavior on color {
CAnim {}
+1 -1
View File
@@ -85,7 +85,7 @@ TextField {
launcherWindow.visible = false;
} else if ( wallpaperPickerLoader.active ) {
SearchWallpapers.setWallpaper(wallpaperPickerLoader.item.currentItem.modelData.path)
if ( Config.wallust ) {
if ( Config.general.wallust ) {
Wallust.generateColors(WallpaperPath.currentWallpaperPath);
}
closeAnim.start();
-18
View File
@@ -202,24 +202,6 @@ Item {
}
}
AnimatedImage {
id: bongocat
anchors.top: controls.bottom
anchors.bottom: parent.bottom
anchors.left: parent.left
anchors.right: parent.right
anchors.topMargin: Appearance.spacing.small
anchors.bottomMargin: Appearance.padding.large
anchors.margins: Appearance.padding.large * 2
playing: Players.active?.isPlaying ?? false
speed: Audio.beatTracker.bpm / Appearance.anim.mediaGifSpeedAdjustment
source: Paths.absolutePath(Config.paths.mediaGif)
asynchronous: true
fillMode: AnimatedImage.PreserveAspectFit
}
component Control: CustomRect {
id: control
+3 -3
View File
@@ -30,7 +30,7 @@ Repeater {
property bool shouldShow: false
property bool isExpanded: false
property bool collapseAnimRunning: false
property color textColor: Config.useDynamicColors ? DynamicColors.palette.m3onSurface : "white"
property color textColor: DynamicColors.palette.m3onSurface
function closeAll(): void {
for ( const n of NotifServer.notClosed.filter( n => n.appName === modelData ))
@@ -120,8 +120,8 @@ Repeater {
Rectangle {
id: collapseRect
property color notifyBgColor: Config.useDynamicColors ? DynamicColors.palette.m3primary : "#E53935"
property color notifyColor: Config.useDynamicColors ? DynamicColors.palette.m3onPrimary : "#FFCDD2"
property color notifyBgColor: DynamicColors.palette.m3primary
property color notifyColor: DynamicColors.palette.m3onPrimary
Layout.alignment: Qt.AlignVCenter | Qt.AlignRight
Layout.fillHeight: true
+6 -10
View File
@@ -65,17 +65,15 @@ Scope {
Rectangle {
id: backgroundRect
property color backgroundColor: Config.useDynamicColors ? DynamicColors.tPalette.m3surface : Config.baseBgColor
property color backgroundColor: DynamicColors.tPalette.m3surface
anchors.bottom: parent.bottom
anchors.bottomMargin: Config.useDynamicColors ? 0 : -1
anchors.bottomMargin: 0
implicitHeight: mainLayout.childrenRect.height + 20
implicitWidth: appListRect.implicitWidth
x: Math.round(( parent.width - width ) / 2 )
color: backgroundColor
opacity: 1
border.width: Config.useDynamicColors ? 0 : 1
border.color: Config.useDynamicColors ? "transparent" : Config.baseBorderColor
ParallelAnimation {
id: openAnim
@@ -176,11 +174,9 @@ Scope {
implicitWidth: appListContainer.implicitWidth + 20
implicitHeight: appListContainer.implicitHeight + 20
anchors.bottom: backgroundRect.top
anchors.bottomMargin: Config.useDynamicColors ? 0 : -1
color: backgroundRect.color
topRightRadius: 8
topLeftRadius: 8
border.color: Config.useDynamicColors ? "transparent" : backgroundRect.border.color
clip: true
Behavior on implicitHeight {
@@ -252,7 +248,7 @@ Scope {
const maxItemsOnScreen = Math.floor( maxWidth / itemWidth );
const visible = Math.min( maxItemsOnScreen, Config.maxWallpapers, wallpaperModel.values.length );
const visible = Math.min( maxItemsOnScreen, Config.launcher.maxWallpapers, wallpaperModel.values.length );
if ( visible === 2 )
return 1;
@@ -313,7 +309,7 @@ Scope {
sourceComponent: ListView {
id: appListView
property color highlightColor: Config.useDynamicColors ? DynamicColors.tPalette.m3onSurface : "#FFFFFF"
property color highlightColor: DynamicColors.tPalette.m3onSurface
anchors.fill: parent
model: ScriptModel {
@@ -325,7 +321,7 @@ Scope {
}
verticalLayoutDirection: ListView.BottomToTop
implicitHeight: Math.min( count, Config.appCount ) * 48
implicitHeight: Math.min( count, Config.launcher.maxAppsShown ) * 48
preferredHighlightBegin: 0
preferredHighlightEnd: appListView.height
@@ -335,7 +331,7 @@ Scope {
highlight: Rectangle {
radius: 4
color: appListView.highlightColor
opacity: Config.useDynamicColors ? 0.20 : 0.08
opacity: 0.20
y: appListView.currentItem?.y
implicitWidth: appListView.width
+1 -1
View File
@@ -26,7 +26,7 @@ Scope {
}
Variants {
model: Config.idle.timeouts
model: Config.general.idle.timeouts
IdleMonitor {
required property var modelData
+1 -16
View File
@@ -109,21 +109,8 @@ WlSessionLockSurface {
duration: Appearance.anim.durations.expressiveFastSpatial
easing.bezierCurve: Appearance.anim.curves.expressiveFastSpatial
}
Modules.Anim {
target: lockContent
property: "rotation"
to: 360
duration: Appearance.anim.durations.expressiveFastSpatial
easing.bezierCurve: Appearance.anim.curves.standardAccel
}
}
ParallelAnimation {
Modules.Anim {
target: lockIcon
property: "rotation"
to: 360
easing.bezierCurve: Appearance.anim.curves.standardDecel
}
Modules.Anim {
target: lockIcon
property: "opacity"
@@ -185,7 +172,6 @@ WlSessionLockSurface {
implicitWidth: size
implicitHeight: size
rotation: 180
scale: 0
CustomRect {
@@ -193,7 +179,7 @@ WlSessionLockSurface {
anchors.fill: parent
color: DynamicColors.palette.m3surface
radius: parent.radius
radius: lockContent.radius
opacity: DynamicColors.transparency.enabled ? DynamicColors.transparency.base : 1
layer.enabled: true
@@ -211,7 +197,6 @@ WlSessionLockSurface {
text: "lock"
font.pointSize: Appearance.font.size.extraLarge * 4
font.bold: true
rotation: 180
}
Content {
+1 -1
View File
@@ -156,7 +156,7 @@ Item {
implicitHeight: controlIcon.implicitHeight + Appearance.padding.normal * 2
color: active ? DynamicColors.palette[`m3${colour.toLowerCase()}`] : DynamicColors.palette[`m3${colour.toLowerCase()}Container`]
radius: active || controlState.pressed ? Appearance.rounding.normal : Math.min(implicitWidth, implicitHeight) / 2 * Math.min(1, Appearance.rounding.scale)
radius: active || controlState.pressed ? Appearance.rounding.small : Appearance.rounding.normal
Elevation {
anchors.fill: parent
+1 -1
View File
@@ -26,7 +26,7 @@ Item {
anchors.centerIn: parent
property color iconColor: Config.useDynamicColors ? DynamicColors.palette.m3tertiaryFixed : "white"
property color iconColor: DynamicColors.palette.m3tertiaryFixed
text: HasNotifications.hasNotifications ? "\uf4fe" : "\ue7f4"
font.family: "Material Symbols Rounded"
+2 -2
View File
@@ -15,8 +15,8 @@ Item {
implicitWidth: resourceRowLayout.x < 0 ? 0 : resourceRowLayout.implicitWidth
implicitHeight: 22
property bool warning: percentage * 100 >= warningThreshold
property color usageColor: Config.useDynamicColors ? ( warning ? DynamicColors.palette.m3error : DynamicColors.palette.m3primary ) : ( warning ? Config.accentColor.accents.warning : Config.accentColor.accents.primary )
property color borderColor: Config.useDynamicColors ? ( warning ? DynamicColors.palette.m3onError : DynamicColors.palette.m3onPrimary ) : ( warning ? Config.accentColor.accents.warningAlt : Config.accentColor.accents.primaryAlt )
property color usageColor: warning ? DynamicColors.palette.m3error : DynamicColors.palette.m3primary
property color borderColor: warning ? DynamicColors.palette.m3onError : DynamicColors.palette.m3onPrimary
Behavior on percentage {
NumberAnimation {
+3 -3
View File
@@ -11,9 +11,9 @@ Item {
required property int warningThreshold
required property string details
required property string iconString
property color barColor: Config.useDynamicColors ? DynamicColors.palette.m3primary : Config.accentColor.accents.primary
property color warningBarColor: Config.useDynamicColors ? DynamicColors.palette.m3error : Config.accentColor.accents.warning
property color textColor: Config.useDynamicColors ? DynamicColors.palette.m3onSurface : "#ffffff"
property color barColor: DynamicColors.palette.m3primary
property color warningBarColor: DynamicColors.palette.m3error
property color textColor: DynamicColors.palette.m3onSurface
Layout.preferredWidth: 158
Layout.preferredHeight: columnLayout.implicitHeight
+2 -2
View File
@@ -21,7 +21,7 @@ Singleton {
property double gpuUsage: 0
property double gpuMemUsage: 0
property double totalMem: 0
readonly property string gpuType: Config.gpuType.toUpperCase() || autoGpuType
readonly property string gpuType: Config.services.gpuType.toUpperCase() || autoGpuType
property string autoGpuType: "NONE"
Timer {
@@ -70,7 +70,7 @@ Singleton {
Process {
id: gpuTypeCheck
running: !Config.gpuType
running: !Config.services.gpuType
command: ["sh", "-c", "if command -v nvidia-smi &>/dev/null && nvidia-smi -L &>/dev/null; then echo NVIDIA; elif ls /sys/class/drm/card*/device/gpu_busy_percent 2>/dev/null | grep -q .; then echo GENERIC; else echo NONE; fi"]
stdout: StdioCollector {
onStreamFinished: root.autoGpuType = text.trim()
+2 -2
View File
@@ -13,7 +13,7 @@ Item {
id: root
implicitWidth: rowLayout.implicitWidth + rowLayout.anchors.leftMargin + rowLayout.anchors.rightMargin
implicitHeight: 34
property color textColor: Config.useDynamicColors ? DynamicColors.palette.m3tertiaryFixed : "#ffffff"
property color textColor: DynamicColors.palette.m3tertiaryFixed
clip: true
Rectangle {
@@ -24,7 +24,7 @@ Item {
verticalCenter: parent.verticalCenter
}
implicitHeight: 22
color: Config.useDynamicColors ? DynamicColors.tPalette.m3surfaceContainer : "#40000000"
color: DynamicColors.tPalette.m3surfaceContainer
radius: height / 2
Behavior on color {
CAnim {}
+5 -7
View File
@@ -26,11 +26,11 @@ PanelWindow {
property int biggestWidth: 0
property int menuItemCount: menuOpener.children.values.length
property color backgroundColor: Config.useDynamicColors ? DynamicColors.tPalette.m3surface : Config.baseBgColor
property color highlightColor: Config.useDynamicColors ? DynamicColors.tPalette.m3primaryContainer : "#15FFFFFF"
property color textColor: Config.useDynamicColors ? DynamicColors.palette.m3onSurface : "white"
property color disabledHighlightColor: Config.useDynamicColors ? DynamicColors.layer(DynamicColors.palette.m3primaryContainer, 0) : "#08FFFFFF"
property color disabledTextColor: Config.useDynamicColors ? DynamicColors.layer(DynamicColors.palette.m3onSurface, 0) : "#80FFFFFF"
property color backgroundColor: DynamicColors.tPalette.m3surface
property color highlightColor: DynamicColors.tPalette.m3primaryContainer
property color textColor: DynamicColors.palette.m3onSurface
property color disabledHighlightColor: DynamicColors.layer(DynamicColors.palette.m3primaryContainer, 0)
property color disabledTextColor: DynamicColors.layer(DynamicColors.palette.m3onSurface, 0)
QsMenuOpener {
id: menuOpener
@@ -193,8 +193,6 @@ PanelWindow {
implicitHeight: listLayout.contentHeight + ( root.menuStack.length > 0 ? root.entryHeight + 10 : 10 )
color: root.backgroundColor
radius: 8
border.width: Config.useDynamicColors ? 0 : 1
border.color: "#40FFFFFF"
clip: true
Behavior on implicitWidth {
+2 -2
View File
@@ -9,7 +9,7 @@ Item {
implicitWidth: textMetrics.width + contentRow.spacing + 30
anchors.top: parent.top
anchors.bottom: parent.bottom
property color textColor: Config.useDynamicColors ? DynamicColors.palette.m3tertiaryFixed : "#ffffff"
property color textColor: DynamicColors.palette.m3tertiaryFixed
Rectangle {
anchors.left: parent.left
@@ -17,7 +17,7 @@ Item {
anchors.verticalCenter: parent.verticalCenter
implicitHeight: 22
radius: height / 2
color: Config.useDynamicColors ? DynamicColors.tPalette.m3surfaceContainer : "#40000000"
color: DynamicColors.tPalette.m3surfaceContainer
Behavior on color {
CAnim {}
}
+4 -4
View File
@@ -43,7 +43,7 @@ Item {
}
}
color: Config.useDynamicColors ? DynamicColors.tPalette.m3surfaceContainer : "#40000000"
color: DynamicColors.tPalette.m3surfaceContainer
radius: height / 2
Behavior on color {
@@ -67,7 +67,7 @@ Item {
CustomText {
text: workspaceIndicator.modelData.name
font.pointSize: 12
color: workspaceIndicator.modelData.id === Hyprland.focusedWorkspace.id ? ( Config.useDynamicColors ? DynamicColors.palette.m3primary : Config.accentColor.accents.primary ) : ( Config.useDynamicColors ? DynamicColors.palette.m3onSurfaceVariant : "#606060" )
color: workspaceIndicator.modelData.id === Hyprland.focusedWorkspace.id ? DynamicColors.palette.m3primary : DynamicColors.palette.m3onSurfaceVariant
visible: true
}
@@ -79,7 +79,7 @@ Item {
border.width: 1
color: "transparent"
border.color: workspaceIndicator.modelData.id === Hyprland.focusedWorkspace.id ? ( Config.useDynamicColors ? DynamicColors.palette.m3primary : Config.accentColor.accents.primary ) : ( Config.useDynamicColors ? DynamicColors.palette.m3onSurfaceVariant : "#606060" )
border.color: workspaceIndicator.modelData.id === Hyprland.focusedWorkspace.id ? DynamicColors.palette.m3primary : DynamicColors.palette.m3onSurfaceVariant
scale: 1.0
@@ -91,7 +91,7 @@ Item {
implicitHeight: 8
radius: implicitHeight / 2
color: workspaceIndicator.modelData.id === Hyprland.focusedWorkspace.id ? ( Config.useDynamicColors ? DynamicColors.palette.m3primary : Config.accentColor.accents.primary ) : "transparent"
color: workspaceIndicator.modelData.id === Hyprland.focusedWorkspace.id ? DynamicColors.palette.m3primary : "transparent"
}
Behavior on border.color {
+1
View File
@@ -42,6 +42,7 @@ qml_module(ZShell
appdb.hpp appdb.cpp
imageanalyser.hpp imageanalyser.cpp
requests.hpp requests.cpp
toaster.hpp toaster.cpp
LIBRARIES
Qt::Gui
Qt::Quick
+117
View File
@@ -0,0 +1,117 @@
#include "toaster.hpp"
#include <qdebug.h>
#include <qlogging.h>
#include <qtimer.h>
namespace ZShell {
Toast::Toast(const QString& title, const QString& message, const QString& icon, Type type, int timeout, QObject* parent)
: QObject(parent)
, m_closed(false)
, m_title(title)
, m_message(message)
, m_icon(icon)
, m_type(type)
, m_timeout(timeout) {
QTimer::singleShot(timeout, this, &Toast::close);
if (m_icon.isEmpty()) {
switch (m_type) {
case Type::Success:
m_icon = "check_circle_unread";
break;
case Type::Warning:
m_icon = "warning";
break;
case Type::Error:
m_icon = "error";
break;
default:
m_icon = "info";
break;
}
}
if (timeout <= 0) {
switch (m_type) {
case Type::Warning:
m_timeout = 7000;
break;
case Type::Error:
m_timeout = 10000;
break;
default:
m_timeout = 5000;
break;
}
}
}
bool Toast::closed() const {
return m_closed;
}
QString Toast::title() const {
return m_title;
}
QString Toast::message() const {
return m_message;
}
QString Toast::icon() const {
return m_icon;
}
int Toast::timeout() const {
return m_timeout;
}
Toast::Type Toast::type() const {
return m_type;
}
void Toast::close() {
if (!m_closed) {
m_closed = true;
emit closedChanged();
}
if (m_locks.isEmpty()) {
emit finishedClose();
}
}
void Toast::lock(QObject* sender) {
m_locks << sender;
QObject::connect(sender, &QObject::destroyed, this, &Toast::unlock);
}
void Toast::unlock(QObject* sender) {
if (m_locks.remove(sender) && m_closed) {
close();
}
}
Toaster::Toaster(QObject* parent)
: QObject(parent) {
}
QQmlListProperty<Toast> Toaster::toasts() {
return QQmlListProperty<Toast>(this, &m_toasts);
}
void Toaster::toast(const QString& title, const QString& message, const QString& icon, Toast::Type type, int timeout) {
auto* toast = new Toast(title, message, icon, type, timeout, this);
QObject::connect(toast, &Toast::finishedClose, this, [toast, this]() {
if (m_toasts.removeOne(toast)) {
emit toastsChanged();
toast->deleteLater();
}
});
m_toasts.push_front(toast);
emit toastsChanged();
}
} // namespace ZShell
+82
View File
@@ -0,0 +1,82 @@
#pragma once
#include <qobject.h>
#include <qqmlintegration.h>
#include <qqmllist.h>
#include <qset.h>
namespace ZShell {
class Toast : public QObject {
Q_OBJECT
QML_ELEMENT
QML_UNCREATABLE("Toast instances can only be retrieved from a Toaster")
Q_PROPERTY(bool closed READ closed NOTIFY closedChanged)
Q_PROPERTY(QString title READ title CONSTANT)
Q_PROPERTY(QString message READ message CONSTANT)
Q_PROPERTY(QString icon READ icon CONSTANT)
Q_PROPERTY(int timeout READ timeout CONSTANT)
Q_PROPERTY(Type type READ type CONSTANT)
public:
enum class Type {
Info = 0,
Success,
Warning,
Error
};
Q_ENUM(Type)
explicit Toast(const QString& title, const QString& message, const QString& icon, Type type, int timeout,
QObject* parent = nullptr);
[[nodiscard]] bool closed() const;
[[nodiscard]] QString title() const;
[[nodiscard]] QString message() const;
[[nodiscard]] QString icon() const;
[[nodiscard]] int timeout() const;
[[nodiscard]] Type type() const;
Q_INVOKABLE void close();
Q_INVOKABLE void lock(QObject* sender);
Q_INVOKABLE void unlock(QObject* sender);
signals:
void closedChanged();
void finishedClose();
private:
QSet<QObject*> m_locks;
bool m_closed;
QString m_title;
QString m_message;
QString m_icon;
Type m_type;
int m_timeout;
};
class Toaster : public QObject {
Q_OBJECT
QML_ELEMENT
QML_SINGLETON
Q_PROPERTY(QQmlListProperty<ZShell::Toast> toasts READ toasts NOTIFY toastsChanged)
public:
explicit Toaster(QObject* parent = nullptr);
[[nodiscard]] QQmlListProperty<Toast> toasts();
Q_INVOKABLE void toast(const QString& title, const QString& message, const QString& icon = QString(),
ZShell::Toast::Type type = Toast::Type::Info, int timeout = 5000);
signals:
void toastsChanged();
private:
QList<Toast*> m_toasts;
};
} // namespace ZShell