pragma Singleton pragma ComponentBehavior: Bound import QtQuick import QtCore import Quickshell import Quickshell.Io import "functions" Singleton { id: root function themeValue(path, fallback = undefined) { let current = root.themeData; for (let i = 0; i < path.length; i++) { if (current === null || current === undefined) return fallback; current = current[path[i]]; } return current === undefined || current === null ? fallback : current; } function parseThemeData() { try { const content = themeFile.text(); if (!content || content.trim().length === 0) return ({}); return JSON.parse(content); } catch (error) { console.warn(`Failed to parse theme json: ${error}`); return ({}); } } property string configDirectory: StandardPaths.standardLocations(StandardPaths.ConfigLocation)[0] property var themeData: ({}) property QtObject animation property QtObject animationCurves property QtObject colors property QtObject rounding property QtObject font property QtObject sizes FileView { id: themeFile path: `${root.configDirectory}/overzicht/colors.json` blockLoading: true watchChanges: true onLoadedChanged: if (loaded) root.themeData = root.parseThemeData() onFileChanged: { reload(); root.themeData = root.parseThemeData(); } } Component.onCompleted: themeData = parseThemeData() colors: QtObject { property color accent: root.themeValue(["accent"], root.themeValue(["secondary"], "#D5C0D7")) property color border: root.themeValue(["border"], root.themeValue(["outlineVariant"], "#4C444D")) property color outline: root.themeValue(["outline"], "#988E97") property color panel: root.themeValue(["panel"], root.themeValue(["background"], "#161217")) property color panelText: root.themeValue(["panelText"], root.themeValue(["onBackground"], "#EAE0E7")) property color shadow: ColorUtils.transparentize(root.themeValue(["shadow"], "#000000"), 0.7) property color tooltip: root.themeValue(["tooltip"], root.themeValue(["inverseSurface"], "#EAE0E7")) property color tooltipText: root.themeValue(["tooltipText"], root.themeValue(["inverseOnSurface"], "#342F34")) property color window: root.themeValue(["window"], root.themeValue(["surfaceContainer"], "#231E23")) property color windowText: root.themeValue(["windowText"], root.themeValue(["onSurface"], "#EAE0E7")) property color workspace: root.themeValue(["workspace"], root.themeValue(["surfaceContainerLow"], "#1F1A1F")) property color workspaceText: root.themeValue(["workspaceText"], root.themeValue(["onSurfaceVariant"], "#CFC3CD")) readonly property color panelBorder: ColorUtils.mix(border, panel, 0.4) readonly property color tooltipBorder: ColorUtils.transparentize(tooltipText, 0.7) readonly property color windowActive: ColorUtils.mix(window, windowText, 0.80) readonly property color windowBorder: ColorUtils.transparentize(outline, 0.7) readonly property color windowHover: ColorUtils.mix(window, windowText, 0.90) readonly property color workspaceHover: ColorUtils.mix(workspace, workspaceText, 0.92) } rounding: QtObject { property int unsharpen: Config.options.appearance.rounding.unsharpen property int verysmall: Config.options.appearance.rounding.verysmall property int small: Config.options.appearance.rounding.small property int normal: Config.options.appearance.rounding.normal property int large: Config.options.appearance.rounding.large property int full: Config.options.appearance.rounding.full property int screenRounding: Config.options.appearance.rounding.screenRounding property int windowRounding: Config.options.appearance.rounding.windowRounding } font: QtObject { property QtObject family: QtObject { property string main: Config.optionValue(["appearance", "font", "family", "main"], root.themeValue(["font", "family", "main"], "sans-serif")) property string title: Config.optionValue(["appearance", "font", "family", "title"], root.themeValue(["font", "family", "title"], "sans-serif")) property string expressive: Config.optionValue(["appearance", "font", "family", "expressive"], root.themeValue(["font", "family", "expressive"], "sans-serif")) } property QtObject pixelSize: QtObject { property int smaller: Config.optionValue(["appearance", "font", "pixelSize", "smaller"], root.themeValue(["font", "pixelSize", "smaller"], 12)) property int small: Config.optionValue(["appearance", "font", "pixelSize", "small"], root.themeValue(["font", "pixelSize", "small"], 15)) property int normal: Config.optionValue(["appearance", "font", "pixelSize", "normal"], root.themeValue(["font", "pixelSize", "normal"], 16)) property int larger: Config.optionValue(["appearance", "font", "pixelSize", "larger"], root.themeValue(["font", "pixelSize", "larger"], 19)) property int huge: Config.optionValue(["appearance", "font", "pixelSize", "huge"], root.themeValue(["font", "pixelSize", "huge"], 22)) } } animationCurves: QtObject { readonly property list expressiveDefaultSpatial: [0.38, 1.21, 0.22, 1.00, 1, 1] readonly property list expressiveEffects: [0.34, 0.80, 0.34, 1.00, 1, 1] readonly property list emphasizedDecel: [0.05, 0.7, 0.1, 1, 1, 1] readonly property real expressiveDefaultSpatialDuration: Config.options.appearance.animation.duration.elementMove readonly property real expressiveEffectsDuration: Config.options.appearance.animation.duration.elementMoveFast } animation: QtObject { property QtObject elementMove: QtObject { property int duration: animationCurves.expressiveDefaultSpatialDuration property int type: Easing.BezierSpline property list bezierCurve: animationCurves.expressiveDefaultSpatial property Component numberAnimation: Component { NumberAnimation { duration: root.animation.elementMove.duration easing.type: root.animation.elementMove.type easing.bezierCurve: root.animation.elementMove.bezierCurve } } } property QtObject elementMoveEnter: QtObject { property int duration: Config.options.appearance.animation.duration.elementMoveEnter property int type: Easing.BezierSpline property list bezierCurve: animationCurves.emphasizedDecel property Component numberAnimation: Component { NumberAnimation { duration: root.animation.elementMoveEnter.duration easing.type: root.animation.elementMoveEnter.type easing.bezierCurve: root.animation.elementMoveEnter.bezierCurve } } } property QtObject elementMoveFast: QtObject { property int duration: animationCurves.expressiveEffectsDuration property int type: Easing.BezierSpline property list bezierCurve: animationCurves.expressiveEffects property Component numberAnimation: Component { NumberAnimation { duration: root.animation.elementMoveFast.duration easing.type: root.animation.elementMoveFast.type easing.bezierCurve: root.animation.elementMoveFast.bezierCurve } } } } sizes: QtObject { property real elevationMargin: Config.options.appearance.sizes.elevationMargin } }