From 1690e4f63b3c128f4704d5e3fb560e2604eeebb8 Mon Sep 17 00:00:00 2001 From: sam Date: Thu, 25 Sep 2025 20:27:54 +0800 Subject: [PATCH] feat: expose matugen palette selection (#251) Looks good, thanks! --- Common/SettingsData.qml | 19 ++++++++++++ Common/Theme.qml | 40 +++++++++++++++++++++---- Modules/Settings/PersonalizationTab.qml | 31 +++++++++++++++++++ Modules/Settings/ThemeColorsTab.qml | 31 +++++++++++++++++++ 4 files changed, 115 insertions(+), 6 deletions(-) diff --git a/Common/SettingsData.qml b/Common/SettingsData.qml index d25ee38a..f51f3c0c 100644 --- a/Common/SettingsData.qml +++ b/Common/SettingsData.qml @@ -15,6 +15,7 @@ Singleton { // Theme settings property string currentThemeName: "blue" property string customThemeFile: "" + property string matugenScheme: "scheme-tonal-spot" property real topBarTransparency: 0.75 property real topBarWidgetTransparency: 0.85 property real popupTransparency: 0.92 @@ -206,6 +207,7 @@ Singleton { currentThemeName = settings.currentThemeName !== undefined ? settings.currentThemeName : "blue" } customThemeFile = settings.customThemeFile !== undefined ? settings.customThemeFile : "" + matugenScheme = settings.matugenScheme !== undefined ? settings.matugenScheme : "scheme-tonal-spot" topBarTransparency = settings.topBarTransparency !== undefined ? (settings.topBarTransparency > 1 ? settings.topBarTransparency / 100 : settings.topBarTransparency) : 0.75 topBarWidgetTransparency = settings.topBarWidgetTransparency !== undefined ? (settings.topBarWidgetTransparency > 1 ? settings.topBarWidgetTransparency / 100 : settings.topBarWidgetTransparency) : 0.85 popupTransparency = settings.popupTransparency !== undefined ? (settings.popupTransparency > 1 ? settings.popupTransparency / 100 : settings.popupTransparency) : 0.92 @@ -344,6 +346,7 @@ Singleton { settingsFile.setText(JSON.stringify({ "currentThemeName": currentThemeName, "customThemeFile": customThemeFile, + "matugenScheme": matugenScheme, "topBarTransparency": topBarTransparency, "topBarWidgetTransparency": topBarWidgetTransparency, "popupTransparency": popupTransparency, @@ -567,6 +570,22 @@ Singleton { saveSettings() } + function setMatugenScheme(scheme) { + var normalized = scheme || "scheme-tonal-spot" + if (matugenScheme === normalized) + return + + matugenScheme = normalized + saveSettings() + + if (typeof Theme !== "undefined") { + if (Theme.currentTheme === Theme.dynamic) { + Theme.extractColors() + } + Theme.generateSystemThemesFromCurrentTheme() + } + } + function setTopBarTransparency(transparency) { topBarTransparency = transparency saveSettings() diff --git a/Common/Theme.qml b/Common/Theme.qml index aaf1fc5c..b9a57d52 100644 --- a/Common/Theme.qml +++ b/Common/Theme.qml @@ -130,6 +130,26 @@ Singleton { } } + readonly property var availableMatugenSchemes: [ + ({ "value": "scheme-tonal-spot", "label": "Tonal Spot", "description": "Balanced palette with focused accents (default)." }), + ({ "value": "scheme-content", "label": "Content", "description": "Derives colors that closely match the underlying image." }), + ({ "value": "scheme-expressive", "label": "Expressive", "description": "Vibrant palette with playful saturation." }), + ({ "value": "scheme-fidelity", "label": "Fidelity", "description": "High-fidelity palette that preserves source hues." }), + ({ "value": "scheme-fruit-salad", "label": "Fruit Salad", "description": "Colorful mix of bright contrasting accents." }), + ({ "value": "scheme-monochrome", "label": "Monochrome", "description": "Minimal palette built around a single hue." }), + ({ "value": "scheme-neutral", "label": "Neutral", "description": "Muted palette with subdued, calming tones." }), + ({ "value": "scheme-rainbow", "label": "Rainbow", "description": "Diverse palette spanning the full spectrum." }) + ] + + function getMatugenScheme(value) { + const schemes = availableMatugenSchemes + for (let i = 0; i < schemes.length; i++) { + if (schemes[i].value === value) + return schemes[i] + } + return schemes[0] + } + property color primary: currentThemeData.primary property color primaryText: currentThemeData.primaryText property color primaryContainer: currentThemeData.primaryContainer @@ -552,10 +572,11 @@ Singleton { if (!wallpaperPath) { return } + const selectedMatugenType = (typeof SettingsData !== "undefined" && SettingsData.matugenScheme) ? SettingsData.matugenScheme : "scheme-tonal-spot" if (wallpaperPath.startsWith("#")) { - setDesiredTheme("hex", wallpaperPath, isLight, iconTheme) + setDesiredTheme("hex", wallpaperPath, isLight, iconTheme, selectedMatugenType) } else { - setDesiredTheme("image", wallpaperPath, isLight, iconTheme) + setDesiredTheme("image", wallpaperPath, isLight, iconTheme, selectedMatugenType) } } else { let primaryColor @@ -684,10 +705,11 @@ Singleton { if (currentTheme === dynamic) { if (wallpaperPath) { Quickshell.execDetached(["rm", "-f", stateDir + "/matugen.key"]) + const selectedMatugenType = (typeof SettingsData !== "undefined" && SettingsData.matugenScheme) ? SettingsData.matugenScheme : "scheme-tonal-spot" if (wallpaperPath.startsWith("#")) { - setDesiredTheme("hex", wallpaperPath, isLight, iconTheme) + setDesiredTheme("hex", wallpaperPath, isLight, iconTheme, selectedMatugenType) } else { - setDesiredTheme("image", wallpaperPath, isLight, iconTheme) + setDesiredTheme("image", wallpaperPath, isLight, iconTheme, selectedMatugenType) } } } else { @@ -734,7 +756,10 @@ Singleton { Process { id: matugenProcess - command: ["matugen", "image", wallpaperPath, "--json", "hex"] + command: { + const scheme = (typeof SettingsData !== "undefined" && SettingsData.matugenScheme) ? SettingsData.matugenScheme : "scheme-tonal-spot" + return ["matugen", "image", wallpaperPath, "--json", "hex", "-t", scheme] + } stdout: StdioCollector { id: matugenCollector @@ -782,7 +807,10 @@ Singleton { Process { id: colorMatugenProcess - command: ["matugen", "color", "hex", wallpaperPath, "--json", "hex"] + command: { + const scheme = (typeof SettingsData !== "undefined" && SettingsData.matugenScheme) ? SettingsData.matugenScheme : "scheme-tonal-spot" + return ["matugen", "color", "hex", wallpaperPath, "--json", "hex", "-t", scheme] + } stdout: StdioCollector { id: colorMatugenCollector diff --git a/Modules/Settings/PersonalizationTab.qml b/Modules/Settings/PersonalizationTab.qml index b6666ff8..d0db7cd5 100644 --- a/Modules/Settings/PersonalizationTab.qml +++ b/Modules/Settings/PersonalizationTab.qml @@ -889,6 +889,37 @@ Item { } } + DankDropdown { + id: personalizationMatugenPaletteDropdown + width: parent.width + text: "Matugen Palette" + description: "Select the palette algorithm used for wallpaper-based colors" + options: Theme.availableMatugenSchemes.map(function (option) { return option.label }) + currentValue: Theme.getMatugenScheme(SettingsData.matugenScheme).label + enabled: Theme.matugenAvailable + opacity: enabled ? 1 : 0.4 + onValueChanged: value => { + for (var i = 0; i < Theme.availableMatugenSchemes.length; i++) { + var option = Theme.availableMatugenSchemes[i] + if (option.label === value) { + SettingsData.setMatugenScheme(option.value) + break + } + } + } + } + + StyledText { + text: { + var scheme = Theme.getMatugenScheme(SettingsData.matugenScheme) + return scheme.description + " (" + scheme.value + ")" + } + font.pixelSize: Theme.fontSizeSmall + color: Theme.surfaceVariantText + wrapMode: Text.WordWrap + width: parent.width + } + StyledText { text: "matugen not detected - dynamic theming unavailable" font.pixelSize: Theme.fontSizeSmall diff --git a/Modules/Settings/ThemeColorsTab.qml b/Modules/Settings/ThemeColorsTab.qml index 0312d33c..17876a9a 100644 --- a/Modules/Settings/ThemeColorsTab.qml +++ b/Modules/Settings/ThemeColorsTab.qml @@ -608,6 +608,37 @@ Item { } } } + + DankDropdown { + id: matugenPaletteDropdown + width: parent.width + text: "Matugen Palette" + description: "Select the palette algorithm used for wallpaper-based colors" + options: Theme.availableMatugenSchemes.map(function (option) { return option.label }) + currentValue: Theme.getMatugenScheme(SettingsData.matugenScheme).label + enabled: Theme.matugenAvailable + opacity: enabled ? 1 : 0.4 + onValueChanged: value => { + for (var i = 0; i < Theme.availableMatugenSchemes.length; i++) { + var option = Theme.availableMatugenSchemes[i] + if (option.label === value) { + SettingsData.setMatugenScheme(option.value) + break + } + } + } + } + + StyledText { + text: { + var scheme = Theme.getMatugenScheme(SettingsData.matugenScheme) + return scheme.description + " (" + scheme.value + ")" + } + font.pixelSize: Theme.fontSizeSmall + color: Theme.surfaceVariantText + wrapMode: Text.WordWrap + width: parent.width + } } Column {