import QtQuick import QtQuick.Layouts import Quickshell import Quickshell.Io import Quickshell.Widgets import qs.config import qs.modules.components import qs.services import qs.plugins ContentMenu { title: "Appearance" description: "Adjust how the desktop looks like." ContentCard { ColumnLayout { Layout.fillWidth: true spacing: Metrics.spacing(16) ColumnLayout { spacing: Metrics.spacing(4) StyledText { text: "Select Theme" font.pixelSize: Metrics.fontSize(16) } StyledText { text: "Choose between dark or light mode." font.pixelSize: Metrics.fontSize(12) color: "#888888" } } RowLayout { Layout.leftMargin: Metrics.margin(15) Layout.fillWidth: true Layout.alignment: Qt.AlignHCenter spacing: Metrics.spacing(16) StyledButton { Layout.preferredHeight: 300 Layout.preferredWidth: 460 Layout.maximumHeight: 400 Layout.maximumWidth: 500 icon: "dark_mode" iconSize: Metrics.iconSize(64) checked: Config.runtime.appearance.theme === "dark" hoverEnabled: true onClicked: { if (!Config.runtime.appearance.colors.autogenerated) { const scheme = Config.runtime.appearance.colors.scheme const file = Theme.map[scheme]?.dark if (!file) { Theme.notifyMissingVariant(scheme, "dark") return } Config.updateKey("appearance.theme", "dark") Quickshell.execDetached([ "nucleus", "theme", "switch", file ]) } else { Config.updateKey("appearance.theme", "dark") Quickshell.execDetached([ "nucleus", "ipc", "call", "global", "regenColors" ]) } } } StyledButton { Layout.preferredHeight: 300 Layout.preferredWidth: 460 Layout.maximumHeight: 400 Layout.maximumWidth: 500 icon: "light_mode" iconSize: Metrics.iconSize(64) checked: Config.runtime.appearance.theme === "light" hoverEnabled: true onClicked: { if (!Config.runtime.appearance.colors.autogenerated) { const scheme = Config.runtime.appearance.colors.scheme const file = Theme.map[scheme]?.light if (!file) { Theme.notifyMissingVariant(scheme, "light") return } Config.updateKey("appearance.theme", "light") Quickshell.execDetached([ "nucleus", "theme", "switch", file ]) } else { Config.updateKey("appearance.theme", "light") Quickshell.execDetached([ "nucleus", "ipc", "call", "global", "regenColors" ]) } } } } Item { width: Metrics.spacing(30) } } } ContentCard { RowLayout { opacity: autogeneratedColorsSelector.enabled ? 1 : 0.8 ColumnLayout { StyledText { text: "Color Generation Schemes:" font.pixelSize: Metrics.fontSize(16) } StyledText { text: "Choose the scheme for autogenerated color generation." font.pixelSize: Metrics.fontSize(12) } } Item { Layout.fillWidth: true } StyledDropDown { id: autogeneratedColorsSelector label: "Color Scheme" model: [ "scheme-content", "scheme-expressive", "scheme-fidelity", "scheme-fruit-salad", "scheme-monochrome", "scheme-neutral", "scheme-rainbow", "scheme-tonal-spot" ] currentIndex: model.indexOf(Config.runtime.appearance.colors.matugenScheme) onSelectedIndexChanged: (index) => { if (!Config.runtime.appearance.colors.autogenerated) return const selectedScheme = model[index] Config.updateKey("appearance.colors.matugenScheme", selectedScheme) Quickshell.execDetached([ "nucleus", "ipc", "call", "global", "regenColors" ]) } enabled: Config.runtime.appearance.colors.autogenerated } } RowLayout { opacity: predefinedThemeSelector.enabled ? 1 : 0.8 ColumnLayout { StyledText { font.pixelSize: Metrics.fontSize(16) text: "Predefined/Custom Themes:" } StyledText { font.pixelSize: Metrics.fontSize(12) text: "Choose a pre-defined theme for your interface." } } Item { Layout.fillWidth: true } StyledDropDown { id: predefinedThemeSelector label: "Theme" model: Object.keys(Theme.map) currentIndex: model.indexOf(Config.runtime.appearance.colors.scheme) onSelectedIndexChanged: (index) => { if (Config.runtime.appearance.colors.autogenerated) return const selectedTheme = model[index] const variant = Config.runtime.appearance.theme const file = Theme.map[selectedTheme][variant] if (!file) return Config.updateKey("appearance.colors.scheme", selectedTheme) Quickshell.execDetached([ "nucleus", "theme", "switch", file ]) } enabled: !Config.runtime.appearance.colors.autogenerated } } } ContentCard { StyledSwitchOption { title: "Tint Icons" description: "Either tint icons across the shell or keep them colorized." prefField: "appearance.tintIcons" } StyledSwitchOption { title: "Use Autogenerated Themes" description: "Use autogenerated themes." prefField: "appearance.colors.autogenerated" } StyledSwitchOption { title: "Use User Defined Themes" description: "Enabling this will also run the default `config.toml` in `~/.config/matugen` dir." prefField: "appearance.colors.runMatugenUserWide" } } ContentCard { StyledText { text: "Clock" font.pixelSize: Metrics.fontSize(20) font.bold: true } StyledSwitchOption { title: "Show Clock" description: "Whether to show or disable the clock on the background." prefField: "appearance.background.clock.enabled" } StyledSwitchOption { title: "Analog Variant" description: "Whether to use analog clock or not." prefField: "appearance.background.clock.isAnalog" } StyledSwitchOption { title: "Rotate Clock Polygon" description: "Rotate the shape polygon of the analog clock." prefField: "appearance.background.clock.rotatePolygonBg" enabled: Config.runtime.appearance.background.clock.isAnalog opacity: enabled ? 1 : 0.8 } NumberStepper { label: "Rotation Duration" description: "Adjust the duration in which the clock rotates 360* (Seconds)." prefField: "appearance.background.clock.rotationDuration" minimum: 1 maximum: 40 step: 1 } RowLayout { id: shapeSelector ColumnLayout { StyledText { text: "Analog Clock Shape" font.pixelSize: Metrics.fontSize(16) } StyledText { text: "Choose the analog clock's shape." font.pixelSize: Metrics.fontSize(12) } } Item { Layout.fillWidth: true } StyledDropDown { label: "Shape Type" model: ["Cookie 7 Sided", "Cookie 9 Sided", "Cookie 12 Sided", "Pixelated Circle", "Circle"] currentIndex: Config.runtime.appearance.background.clock.shape onSelectedIndexChanged: (index) => { Config.updateKey( "appearance.background.clock.shape", index ) } } } } ContentCard { StyledText { text: "Rounding" font.pixelSize: Metrics.fontSize(20) font.bold: true } NumberStepper { label: "Factor" description: "Adjust the rounding factor." prefField: "appearance.rounding.factor" minimum: 0 maximum: 1 step: 0.1 } } ContentCard { StyledText { text: "Font" font.pixelSize: Metrics.fontSize(20) font.bold: true } NumberStepper { label: "Scale" description: "Adjust the font scale." prefField: "appearance.font.scale" minimum: 0.1 maximum: 2 step: 0.1 } } ContentCard { StyledText { text: "Transparency" font.pixelSize: Metrics.fontSize(20) font.bold: true } StyledSwitchOption { title: "Enabled" description: "Whether to enable or disable transparency." prefField: "appearance.transparency.enabled" } NumberStepper { label: "Factor" description: "Adjust the alpha value for transparency." prefField: "appearance.transparency.alpha" minimum: 0.1 maximum: 1 step: 0.1 } } ContentCard { StyledText { text: "Animations" font.pixelSize: Metrics.fontSize(20) font.bold: true } StyledSwitchOption { title: "Enabled" description: "Whether to enable or disable animations (applies everywhere in the shell)." prefField: "appearance.animations.enabled" } NumberStepper { label: "Duration Scale" description: "Adjust the duration scale of the animations." prefField: "appearance.animations.durationScale" minimum: 0.1 maximum: 1 step: 0.1 } } }