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" WlrLayershell.namespace: "ZShell-Bar-Exclusion"
screen: bar.screen screen: bar.screen
WlrLayershell.layer: WlrLayer.Bottom WlrLayershell.layer: WlrLayer.Bottom
WlrLayershell.exclusionMode: Config.autoHide ? ExclusionMode.Ignore : ExclusionMode.Auto WlrLayershell.exclusionMode: Config.barConfig.autoHide ? ExclusionMode.Ignore : ExclusionMode.Auto
anchors { anchors {
left: true left: true
right: true right: true
@@ -51,7 +51,7 @@ Variants {
mask: Region { mask: Region {
id: region id: region
x: 0 x: 0
y: Config.autoHide && !visibilities.bar ? 4 : 34 y: Config.barConfig.autoHide && !visibilities.bar ? 4 : 34
property list<Region> nullRegions: [] property list<Region> nullRegions: []
property bool hcurrent: ( panels.popouts.hasCurrent && panels.popouts.currentName.startsWith("traymenu") ) || visibilities.sidebar || visibilities.dashboard property bool hcurrent: ( panels.popouts.hasCurrent && panels.popouts.currentName.startsWith("traymenu") ) || visibilities.sidebar || visibilities.dashboard
@@ -99,7 +99,7 @@ Variants {
Item { Item {
anchors.fill: parent anchors.fill: parent
opacity: Config.transparency.enabled ? DynamicColors.transparency.base : 1 opacity: Appearance.transparency.enabled ? DynamicColors.transparency.base : 1
layer.enabled: true layer.enabled: true
layer.effect: MultiEffect { layer.effect: MultiEffect {
shadowEnabled: true shadowEnabled: true
@@ -142,7 +142,7 @@ Variants {
anchors.left: parent.left anchors.left: parent.left
anchors.right: parent.right anchors.right: parent.right
implicitHeight: 34 implicitHeight: 34
anchors.topMargin: Config.autoHide && !visibilities.bar ? -30 : 0 anchors.topMargin: Config.barConfig.autoHide && !visibilities.bar ? -30 : 0
color: "transparent" color: "transparent"
radius: 0 radius: 0
+1 -1
View File
@@ -16,7 +16,7 @@ Text {
renderType: Text.NativeRendering renderType: Text.NativeRendering
textFormat: Text.PlainText textFormat: Text.PlainText
color: DynamicColors.palette.m3onSurface color: DynamicColors.palette.m3onSurface
font.family: Config.baseFont font.family: Appearance.font.family.sans
font.pointSize: 12 font.pointSize: 12
Behavior on color { 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 { component FontFamily: JsonObject {
property string sans: "Rubik" property string sans: "Segoe UI Variable Text"
property string mono: "CaskaydiaCove NF" property string mono: "CaskaydiaCove NF"
property string material: "Material Symbols Rounded" property string material: "Material Symbols Rounded"
property string clock: "Rubik" property string clock: "Rubik"
-1
View File
@@ -1,5 +1,4 @@
import Quickshell.Io import Quickshell.Io
import qs.Modules
import qs.Config import qs.Config
JsonObject { JsonObject {
+1
View File
@@ -1,6 +1,7 @@
import Quickshell.Io import Quickshell.Io
JsonObject { JsonObject {
property bool autoHide: false
property Popouts popouts: Popouts {} property Popouts popouts: Popouts {}
property list<var> entries: [ property list<var> entries: [
-5
View File
@@ -1,10 +1,5 @@
import Quickshell.Io import Quickshell.Io
JsonObject { JsonObject {
property BgColors backgrounds: BgColors {}
property string schemeType: "vibrant" 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
import Quickshell.Io import Quickshell.Io
import qs.Modules import ZShell
import QtQuick
import qs.Modules as Modules
import qs.Paths
Singleton { 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 background: adapter.background
property alias useDynamicColors: adapter.useDynamicColors
property alias barConfig: adapter.barConfig 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 lock: adapter.lock
property alias idle: adapter.idle
property alias overview: adapter.overview property alias overview: adapter.overview
property alias services: adapter.services property alias services: adapter.services
property alias notifs: adapter.notifs property alias notifs: adapter.notifs
@@ -32,41 +21,327 @@ Singleton {
property alias general: adapter.general property alias general: adapter.general
property alias dashboard: adapter.dashboard property alias dashboard: adapter.dashboard
property alias appearance: adapter.appearance property alias appearance: adapter.appearance
property alias autoHide: adapter.autoHide
property alias macchiato: adapter.macchiato
property alias osd: adapter.osd 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 { FileView {
id: root id: fileView
property var configRoot: Quickshell.env("HOME")
path: configRoot + "/.config/z-bar/config.json" path: `${Paths.config}/config.json`
watchChanges: true 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 { JsonAdapter {
id: adapter 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 BackgroundConfig background: BackgroundConfig {}
property bool useDynamicColors: false
property BarConfig barConfig: BarConfig {} 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 LockConf lock: LockConf {}
property IdleTimeout idle: IdleTimeout {}
property Overview overview: Overview {} property Overview overview: Overview {}
property Services services: Services {} property Services services: Services {}
property NotifConfig notifs: NotifConfig {} property NotifConfig notifs: NotifConfig {}
@@ -75,9 +350,9 @@ Singleton {
property General general: General {} property General general: General {}
property DashboardConfig dashboard: DashboardConfig {} property DashboardConfig dashboard: DashboardConfig {}
property AppearanceConf appearance: AppearanceConf {} property AppearanceConf appearance: AppearanceConf {}
property bool autoHide: false
property bool macchiato: false
property Osd osd: Osd {} property Osd osd: Osd {}
property Launcher launcher: Launcher {}
property Colors colors: Colors {}
} }
} }
} }
-1
View File
@@ -2,7 +2,6 @@ import Quickshell.Io
JsonObject { JsonObject {
property bool enabled: true property bool enabled: true
property bool showOnHover: true
property int mediaUpdateInterval: 500 property int mediaUpdateInterval: 500
property int dragThreshold: 50 property int dragThreshold: 50
property Sizes sizes: Sizes {} property Sizes sizes: Sizes {}
+3 -3
View File
@@ -88,9 +88,9 @@ Singleton {
} }
component Transparency: QtObject { component Transparency: QtObject {
readonly property bool enabled: Config.transparency.enabled readonly property bool enabled: Appearance.transparency.enabled
readonly property real base: Config.transparency.base - (root.light ? 0.1 : 0) readonly property real base: Appearance.transparency.base - (root.light ? 0.1 : 0)
readonly property real layers: Config.transparency.layers readonly property real layers: Appearance.transparency.layers
} }
component M3TPalette: QtObject { component M3TPalette: QtObject {
+18
View File
@@ -1,5 +1,23 @@
import Quickshell.Io import Quickshell.Io
import Quickshell
JsonObject { JsonObject {
property string logo: "" 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 { Singleton {
id: root 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> 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] 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; 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; root.visibilities.bar = false;
} }
} }
@@ -90,7 +90,7 @@ CustomMouseArea {
const dragY = y - dragStart.y; const dragY = y - dragStart.y;
// Show bar in non-exclusive mode on hover // 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; visibilities.bar = true;
if (panels.sidebar.width === 0) { 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.Notifications.Sidebar.Utils as Utils
import qs.Modules.Dashboard as Dashboard import qs.Modules.Dashboard as Dashboard
import qs.Modules.Osd as Osd import qs.Modules.Osd as Osd
import qs.Components.Toast as Toasts
import qs.Config import qs.Config
Item { Item {
@@ -22,6 +23,7 @@ Item {
readonly property alias utilities: utilities readonly property alias utilities: utilities
readonly property alias dashboard: dashboard readonly property alias dashboard: dashboard
readonly property alias osd: osd readonly property alias osd: osd
readonly property alias toasts: toasts
anchors.fill: parent anchors.fill: parent
// anchors.margins: 8 // anchors.margins: 8
@@ -30,7 +32,7 @@ Item {
Osd.Wrapper { Osd.Wrapper {
id: osd id: osd
clip: session.width > 0 || sidebar.width > 0 clip: sidebar.width > 0
screen: root.screen screen: root.screen
visibilities: root.visibilities 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 { Notifications.Wrapper {
id: notifications id: notifications
+1 -1
View File
@@ -43,7 +43,7 @@ Searcher {
id: wallpapers id: wallpapers
recursive: true recursive: true
path: Config.wallpaperPath path: Config.general.wallpaperPath
filter: FileSystemModel.Images filter: FileSystemModel.Images
} }
} }
+2 -2
View File
@@ -10,7 +10,7 @@ Singleton {
property real cpuPerc property real cpuPerc
property real cpuTemp 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 string autoGpuType: "NONE"
property real gpuPerc property real gpuPerc
property real gpuTemp property real gpuTemp
@@ -145,7 +145,7 @@ Singleton {
Process { Process {
id: gpuTypeCheck 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"] 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 { stdout: StdioCollector {
onStreamFinished: root.autoGpuType = text.trim() onStreamFinished: root.autoGpuType = text.trim()
+5 -5
View File
@@ -13,8 +13,8 @@ Item {
anchors.bottom: parent.bottom anchors.bottom: parent.bottom
property bool expanded: false property bool expanded: false
property color textColor: Config.useDynamicColors ? DynamicColors.palette.m3tertiaryFixed : "#ffffff" property color textColor: DynamicColors.palette.m3tertiaryFixed
property color barColor: Config.useDynamicColors ? DynamicColors.palette.m3primary : "#ffffff" property color barColor: DynamicColors.palette.m3primary
Behavior on implicitWidth { Behavior on implicitWidth {
NumberAnimation { NumberAnimation {
@@ -37,7 +37,7 @@ Item {
anchors.right: parent.right anchors.right: parent.right
height: 22 height: 22
radius: height / 2 radius: height / 2
color: Config.useDynamicColors ? DynamicColors.tPalette.m3surfaceContainer : "#40000000" color: DynamicColors.tPalette.m3surfaceContainer
Behavior on color { Behavior on color {
CAnim {} CAnim {}
@@ -95,7 +95,7 @@ Item {
Layout.alignment: Qt.AlignVCenter Layout.alignment: Qt.AlignVCenter
font.pixelSize: 18 font.pixelSize: 18
text: Pipewire.defaultAudioSource?.audio.muted ? "mic_off" : "mic" 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 { Rectangle {
@@ -115,7 +115,7 @@ Item {
implicitWidth: parent.width * ( Pipewire.defaultAudioSource?.audio.volume ?? 0 ) implicitWidth: parent.width * ( Pipewire.defaultAudioSource?.audio.volume ?? 0 )
radius: parent.radius 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 { Behavior on color {
CAnim {} CAnim {}
+2 -2
View File
@@ -17,7 +17,7 @@ Item {
CustomRect { CustomRect {
anchors.fill: parent 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 layer.enabled: true
@@ -38,7 +38,7 @@ Item {
Rectangle { Rectangle {
anchors.fill: parent 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 topLeftRadius: 8
topRightRadius: 8 topRightRadius: 8
Behavior on anchors.topMargin { Behavior on anchors.topMargin {
+1 -1
View File
@@ -27,7 +27,7 @@ Item {
anchors.centerIn: parent anchors.centerIn: parent
text: Time.dateStr text: Time.dateStr
color: Config.useDynamicColors ? DynamicColors.palette.m3tertiary : "white" color: DynamicColors.palette.m3tertiary
Behavior on color { Behavior on color {
CAnim {} CAnim {}
+1 -1
View File
@@ -85,7 +85,7 @@ TextField {
launcherWindow.visible = false; launcherWindow.visible = false;
} else if ( wallpaperPickerLoader.active ) { } else if ( wallpaperPickerLoader.active ) {
SearchWallpapers.setWallpaper(wallpaperPickerLoader.item.currentItem.modelData.path) SearchWallpapers.setWallpaper(wallpaperPickerLoader.item.currentItem.modelData.path)
if ( Config.wallust ) { if ( Config.general.wallust ) {
Wallust.generateColors(WallpaperPath.currentWallpaperPath); Wallust.generateColors(WallpaperPath.currentWallpaperPath);
} }
closeAnim.start(); 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 { component Control: CustomRect {
id: control id: control
+3 -3
View File
@@ -30,7 +30,7 @@ Repeater {
property bool shouldShow: false property bool shouldShow: false
property bool isExpanded: false property bool isExpanded: false
property bool collapseAnimRunning: false property bool collapseAnimRunning: false
property color textColor: Config.useDynamicColors ? DynamicColors.palette.m3onSurface : "white" property color textColor: DynamicColors.palette.m3onSurface
function closeAll(): void { function closeAll(): void {
for ( const n of NotifServer.notClosed.filter( n => n.appName === modelData )) for ( const n of NotifServer.notClosed.filter( n => n.appName === modelData ))
@@ -120,8 +120,8 @@ Repeater {
Rectangle { Rectangle {
id: collapseRect id: collapseRect
property color notifyBgColor: Config.useDynamicColors ? DynamicColors.palette.m3primary : "#E53935" property color notifyBgColor: DynamicColors.palette.m3primary
property color notifyColor: Config.useDynamicColors ? DynamicColors.palette.m3onPrimary : "#FFCDD2" property color notifyColor: DynamicColors.palette.m3onPrimary
Layout.alignment: Qt.AlignVCenter | Qt.AlignRight Layout.alignment: Qt.AlignVCenter | Qt.AlignRight
Layout.fillHeight: true Layout.fillHeight: true
+6 -10
View File
@@ -65,17 +65,15 @@ Scope {
Rectangle { Rectangle {
id: backgroundRect id: backgroundRect
property color backgroundColor: Config.useDynamicColors ? DynamicColors.tPalette.m3surface : Config.baseBgColor property color backgroundColor: DynamicColors.tPalette.m3surface
anchors.bottom: parent.bottom anchors.bottom: parent.bottom
anchors.bottomMargin: Config.useDynamicColors ? 0 : -1 anchors.bottomMargin: 0
implicitHeight: mainLayout.childrenRect.height + 20 implicitHeight: mainLayout.childrenRect.height + 20
implicitWidth: appListRect.implicitWidth implicitWidth: appListRect.implicitWidth
x: Math.round(( parent.width - width ) / 2 ) x: Math.round(( parent.width - width ) / 2 )
color: backgroundColor color: backgroundColor
opacity: 1 opacity: 1
border.width: Config.useDynamicColors ? 0 : 1
border.color: Config.useDynamicColors ? "transparent" : Config.baseBorderColor
ParallelAnimation { ParallelAnimation {
id: openAnim id: openAnim
@@ -176,11 +174,9 @@ Scope {
implicitWidth: appListContainer.implicitWidth + 20 implicitWidth: appListContainer.implicitWidth + 20
implicitHeight: appListContainer.implicitHeight + 20 implicitHeight: appListContainer.implicitHeight + 20
anchors.bottom: backgroundRect.top anchors.bottom: backgroundRect.top
anchors.bottomMargin: Config.useDynamicColors ? 0 : -1
color: backgroundRect.color color: backgroundRect.color
topRightRadius: 8 topRightRadius: 8
topLeftRadius: 8 topLeftRadius: 8
border.color: Config.useDynamicColors ? "transparent" : backgroundRect.border.color
clip: true clip: true
Behavior on implicitHeight { Behavior on implicitHeight {
@@ -252,7 +248,7 @@ Scope {
const maxItemsOnScreen = Math.floor( maxWidth / itemWidth ); 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 ) if ( visible === 2 )
return 1; return 1;
@@ -313,7 +309,7 @@ Scope {
sourceComponent: ListView { sourceComponent: ListView {
id: appListView id: appListView
property color highlightColor: Config.useDynamicColors ? DynamicColors.tPalette.m3onSurface : "#FFFFFF" property color highlightColor: DynamicColors.tPalette.m3onSurface
anchors.fill: parent anchors.fill: parent
model: ScriptModel { model: ScriptModel {
@@ -325,7 +321,7 @@ Scope {
} }
verticalLayoutDirection: ListView.BottomToTop verticalLayoutDirection: ListView.BottomToTop
implicitHeight: Math.min( count, Config.appCount ) * 48 implicitHeight: Math.min( count, Config.launcher.maxAppsShown ) * 48
preferredHighlightBegin: 0 preferredHighlightBegin: 0
preferredHighlightEnd: appListView.height preferredHighlightEnd: appListView.height
@@ -335,7 +331,7 @@ Scope {
highlight: Rectangle { highlight: Rectangle {
radius: 4 radius: 4
color: appListView.highlightColor color: appListView.highlightColor
opacity: Config.useDynamicColors ? 0.20 : 0.08 opacity: 0.20
y: appListView.currentItem?.y y: appListView.currentItem?.y
implicitWidth: appListView.width implicitWidth: appListView.width
+1 -1
View File
@@ -26,7 +26,7 @@ Scope {
} }
Variants { Variants {
model: Config.idle.timeouts model: Config.general.idle.timeouts
IdleMonitor { IdleMonitor {
required property var modelData required property var modelData
+1 -16
View File
@@ -109,21 +109,8 @@ WlSessionLockSurface {
duration: Appearance.anim.durations.expressiveFastSpatial duration: Appearance.anim.durations.expressiveFastSpatial
easing.bezierCurve: Appearance.anim.curves.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 { ParallelAnimation {
Modules.Anim {
target: lockIcon
property: "rotation"
to: 360
easing.bezierCurve: Appearance.anim.curves.standardDecel
}
Modules.Anim { Modules.Anim {
target: lockIcon target: lockIcon
property: "opacity" property: "opacity"
@@ -185,7 +172,6 @@ WlSessionLockSurface {
implicitWidth: size implicitWidth: size
implicitHeight: size implicitHeight: size
rotation: 180
scale: 0 scale: 0
CustomRect { CustomRect {
@@ -193,7 +179,7 @@ WlSessionLockSurface {
anchors.fill: parent anchors.fill: parent
color: DynamicColors.palette.m3surface color: DynamicColors.palette.m3surface
radius: parent.radius radius: lockContent.radius
opacity: DynamicColors.transparency.enabled ? DynamicColors.transparency.base : 1 opacity: DynamicColors.transparency.enabled ? DynamicColors.transparency.base : 1
layer.enabled: true layer.enabled: true
@@ -211,7 +197,6 @@ WlSessionLockSurface {
text: "lock" text: "lock"
font.pointSize: Appearance.font.size.extraLarge * 4 font.pointSize: Appearance.font.size.extraLarge * 4
font.bold: true font.bold: true
rotation: 180
} }
Content { Content {
+1 -1
View File
@@ -156,7 +156,7 @@ Item {
implicitHeight: controlIcon.implicitHeight + Appearance.padding.normal * 2 implicitHeight: controlIcon.implicitHeight + Appearance.padding.normal * 2
color: active ? DynamicColors.palette[`m3${colour.toLowerCase()}`] : DynamicColors.palette[`m3${colour.toLowerCase()}Container`] 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 { Elevation {
anchors.fill: parent anchors.fill: parent
+1 -1
View File
@@ -26,7 +26,7 @@ Item {
anchors.centerIn: parent anchors.centerIn: parent
property color iconColor: Config.useDynamicColors ? DynamicColors.palette.m3tertiaryFixed : "white" property color iconColor: DynamicColors.palette.m3tertiaryFixed
text: HasNotifications.hasNotifications ? "\uf4fe" : "\ue7f4" text: HasNotifications.hasNotifications ? "\uf4fe" : "\ue7f4"
font.family: "Material Symbols Rounded" font.family: "Material Symbols Rounded"
+2 -2
View File
@@ -15,8 +15,8 @@ Item {
implicitWidth: resourceRowLayout.x < 0 ? 0 : resourceRowLayout.implicitWidth implicitWidth: resourceRowLayout.x < 0 ? 0 : resourceRowLayout.implicitWidth
implicitHeight: 22 implicitHeight: 22
property bool warning: percentage * 100 >= warningThreshold 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 usageColor: warning ? DynamicColors.palette.m3error : DynamicColors.palette.m3primary
property color borderColor: Config.useDynamicColors ? ( warning ? DynamicColors.palette.m3onError : DynamicColors.palette.m3onPrimary ) : ( warning ? Config.accentColor.accents.warningAlt : Config.accentColor.accents.primaryAlt ) property color borderColor: warning ? DynamicColors.palette.m3onError : DynamicColors.palette.m3onPrimary
Behavior on percentage { Behavior on percentage {
NumberAnimation { NumberAnimation {
+3 -3
View File
@@ -11,9 +11,9 @@ Item {
required property int warningThreshold required property int warningThreshold
required property string details required property string details
required property string iconString required property string iconString
property color barColor: Config.useDynamicColors ? DynamicColors.palette.m3primary : Config.accentColor.accents.primary property color barColor: DynamicColors.palette.m3primary
property color warningBarColor: Config.useDynamicColors ? DynamicColors.palette.m3error : Config.accentColor.accents.warning property color warningBarColor: DynamicColors.palette.m3error
property color textColor: Config.useDynamicColors ? DynamicColors.palette.m3onSurface : "#ffffff" property color textColor: DynamicColors.palette.m3onSurface
Layout.preferredWidth: 158 Layout.preferredWidth: 158
Layout.preferredHeight: columnLayout.implicitHeight Layout.preferredHeight: columnLayout.implicitHeight
+2 -2
View File
@@ -21,7 +21,7 @@ Singleton {
property double gpuUsage: 0 property double gpuUsage: 0
property double gpuMemUsage: 0 property double gpuMemUsage: 0
property double totalMem: 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" property string autoGpuType: "NONE"
Timer { Timer {
@@ -70,7 +70,7 @@ Singleton {
Process { Process {
id: gpuTypeCheck 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"] 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 { stdout: StdioCollector {
onStreamFinished: root.autoGpuType = text.trim() onStreamFinished: root.autoGpuType = text.trim()
+2 -2
View File
@@ -13,7 +13,7 @@ Item {
id: root id: root
implicitWidth: rowLayout.implicitWidth + rowLayout.anchors.leftMargin + rowLayout.anchors.rightMargin implicitWidth: rowLayout.implicitWidth + rowLayout.anchors.leftMargin + rowLayout.anchors.rightMargin
implicitHeight: 34 implicitHeight: 34
property color textColor: Config.useDynamicColors ? DynamicColors.palette.m3tertiaryFixed : "#ffffff" property color textColor: DynamicColors.palette.m3tertiaryFixed
clip: true clip: true
Rectangle { Rectangle {
@@ -24,7 +24,7 @@ Item {
verticalCenter: parent.verticalCenter verticalCenter: parent.verticalCenter
} }
implicitHeight: 22 implicitHeight: 22
color: Config.useDynamicColors ? DynamicColors.tPalette.m3surfaceContainer : "#40000000" color: DynamicColors.tPalette.m3surfaceContainer
radius: height / 2 radius: height / 2
Behavior on color { Behavior on color {
CAnim {} CAnim {}
+5 -7
View File
@@ -26,11 +26,11 @@ PanelWindow {
property int biggestWidth: 0 property int biggestWidth: 0
property int menuItemCount: menuOpener.children.values.length property int menuItemCount: menuOpener.children.values.length
property color backgroundColor: Config.useDynamicColors ? DynamicColors.tPalette.m3surface : Config.baseBgColor property color backgroundColor: DynamicColors.tPalette.m3surface
property color highlightColor: Config.useDynamicColors ? DynamicColors.tPalette.m3primaryContainer : "#15FFFFFF" property color highlightColor: DynamicColors.tPalette.m3primaryContainer
property color textColor: Config.useDynamicColors ? DynamicColors.palette.m3onSurface : "white" property color textColor: DynamicColors.palette.m3onSurface
property color disabledHighlightColor: Config.useDynamicColors ? DynamicColors.layer(DynamicColors.palette.m3primaryContainer, 0) : "#08FFFFFF" property color disabledHighlightColor: DynamicColors.layer(DynamicColors.palette.m3primaryContainer, 0)
property color disabledTextColor: Config.useDynamicColors ? DynamicColors.layer(DynamicColors.palette.m3onSurface, 0) : "#80FFFFFF" property color disabledTextColor: DynamicColors.layer(DynamicColors.palette.m3onSurface, 0)
QsMenuOpener { QsMenuOpener {
id: menuOpener id: menuOpener
@@ -193,8 +193,6 @@ PanelWindow {
implicitHeight: listLayout.contentHeight + ( root.menuStack.length > 0 ? root.entryHeight + 10 : 10 ) implicitHeight: listLayout.contentHeight + ( root.menuStack.length > 0 ? root.entryHeight + 10 : 10 )
color: root.backgroundColor color: root.backgroundColor
radius: 8 radius: 8
border.width: Config.useDynamicColors ? 0 : 1
border.color: "#40FFFFFF"
clip: true clip: true
Behavior on implicitWidth { Behavior on implicitWidth {
+2 -2
View File
@@ -9,7 +9,7 @@ Item {
implicitWidth: textMetrics.width + contentRow.spacing + 30 implicitWidth: textMetrics.width + contentRow.spacing + 30
anchors.top: parent.top anchors.top: parent.top
anchors.bottom: parent.bottom anchors.bottom: parent.bottom
property color textColor: Config.useDynamicColors ? DynamicColors.palette.m3tertiaryFixed : "#ffffff" property color textColor: DynamicColors.palette.m3tertiaryFixed
Rectangle { Rectangle {
anchors.left: parent.left anchors.left: parent.left
@@ -17,7 +17,7 @@ Item {
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
implicitHeight: 22 implicitHeight: 22
radius: height / 2 radius: height / 2
color: Config.useDynamicColors ? DynamicColors.tPalette.m3surfaceContainer : "#40000000" color: DynamicColors.tPalette.m3surfaceContainer
Behavior on color { Behavior on color {
CAnim {} CAnim {}
} }
+4 -4
View File
@@ -43,7 +43,7 @@ Item {
} }
} }
color: Config.useDynamicColors ? DynamicColors.tPalette.m3surfaceContainer : "#40000000" color: DynamicColors.tPalette.m3surfaceContainer
radius: height / 2 radius: height / 2
Behavior on color { Behavior on color {
@@ -67,7 +67,7 @@ Item {
CustomText { CustomText {
text: workspaceIndicator.modelData.name text: workspaceIndicator.modelData.name
font.pointSize: 12 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 visible: true
} }
@@ -79,7 +79,7 @@ Item {
border.width: 1 border.width: 1
color: "transparent" 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 scale: 1.0
@@ -91,7 +91,7 @@ Item {
implicitHeight: 8 implicitHeight: 8
radius: implicitHeight / 2 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 { Behavior on border.color {
+1
View File
@@ -42,6 +42,7 @@ qml_module(ZShell
appdb.hpp appdb.cpp appdb.hpp appdb.cpp
imageanalyser.hpp imageanalyser.cpp imageanalyser.hpp imageanalyser.cpp
requests.hpp requests.cpp requests.hpp requests.cpp
toaster.hpp toaster.cpp
LIBRARIES LIBRARIES
Qt::Gui Qt::Gui
Qt::Quick 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