From 42af310ccf39730a7664a1860b721b72489f7d34 Mon Sep 17 00:00:00 2001 From: Ly-sec Date: Thu, 2 Oct 2025 00:44:38 +0200 Subject: [PATCH] matugen: initial commit for predefined color schemes --- Assets/Matugen/templates/kitty.conf | 10 +- Assets/Translations/de.json | 4 + Assets/Translations/en.json | 4 + Assets/Translations/es.json | 4 + Assets/Translations/fr.json | 4 + Assets/Translations/pt.json | 4 + Assets/Translations/zh-CN.json | 4 + Commons/Settings.qml | 1 + Modules/Settings/Tabs/ColorSchemeTab.qml | 15 ++ Services/ColorSchemeService.qml | 10 + Services/MatugenService.qml | 314 +++++++++++++++++++++++ 11 files changed, 369 insertions(+), 5 deletions(-) diff --git a/Assets/Matugen/templates/kitty.conf b/Assets/Matugen/templates/kitty.conf index ed0aee42..29c9a17b 100644 --- a/Assets/Matugen/templates/kitty.conf +++ b/Assets/Matugen/templates/kitty.conf @@ -3,15 +3,15 @@ color1 {{colors.error.default.hex}} color2 {{colors.tertiary.default.hex}} color3 {{colors.secondary.default.hex}} color4 {{colors.primary.default.hex}} -color5 {{colors.primary.default.hex}} -color6 {{colors.secondary.default.hex}} -color7 {{colors.on_background.default.hex}} +color5 {{colors.primary_fixed_dim.default.hex}} +color6 {{colors.secondary_fixed_dim.default.hex}} +color7 {{colors.on_surface.default.hex}} color8 {{colors.outline.default.hex}} -color9 {{colors.secondary_fixed_dim.default.hex}} +color9 {{colors.tertiary_fixed_dim.default.hex}} color10 {{colors.tertiary_container.default.hex}} color11 {{colors.surface_container.default.hex}} color12 {{colors.primary_container.default.hex}} -color13 {{colors.on_primary_container.default.hex}} +color13 {{colors.surface_dim.default.hex}} color14 {{colors.surface_variant.default.hex}} color15 {{colors.on_background.default.hex}} diff --git a/Assets/Translations/de.json b/Assets/Translations/de.json index 3791ae2a..f5fe0a46 100644 --- a/Assets/Translations/de.json +++ b/Assets/Translations/de.json @@ -505,6 +505,10 @@ "section": { "label": "Vordefinierte Farbschemata", "description": "Wählen Sie aus einer Sammlung vordefinierter Farbschemata." + }, + "generate-templates": { + "label": "Templates für vordefinierte Schemata generieren", + "description": "Generiert Matugen-Templates (GTK, Terminal-Themes, etc.) bei der Verwendung vordefinierter Farbschemata." } }, "matugen": { diff --git a/Assets/Translations/en.json b/Assets/Translations/en.json index a17e1d2a..8388ebdd 100644 --- a/Assets/Translations/en.json +++ b/Assets/Translations/en.json @@ -503,6 +503,10 @@ "section": { "label": "Predefined color schemes", "description": "Choose from a collection of predefined color schemes." + }, + "generate-templates": { + "label": "Generate templates for predefined schemes", + "description": "Generate Matugen templates (GTK, terminal themes, etc.) when using predefined color schemes." } }, "matugen": { diff --git a/Assets/Translations/es.json b/Assets/Translations/es.json index 13ced157..3a9490e2 100644 --- a/Assets/Translations/es.json +++ b/Assets/Translations/es.json @@ -501,6 +501,10 @@ "section": { "label": "Esquemas de colores predefinidos", "description": "Elige entre una colección de esquemas de colores predefinidos." + }, + "generate-templates": { + "label": "Generar plantillas para esquemas predefinidos", + "description": "Genera plantillas de Matugen (GTK, temas de terminal, etc.) al usar esquemas de colores predefinidos." } }, "matugen": { diff --git a/Assets/Translations/fr.json b/Assets/Translations/fr.json index dabb0761..27e23a58 100644 --- a/Assets/Translations/fr.json +++ b/Assets/Translations/fr.json @@ -501,6 +501,10 @@ "section": { "label": "Jeux de couleurs prédéfinis", "description": "Choisissez parmi une collection de jeux de couleurs prédéfinis." + }, + "generate-templates": { + "label": "Générer des modèles pour les schémas prédéfinis", + "description": "Génère des modèles Matugen (GTK, thèmes de terminal, etc.) lors de l'utilisation de schémas de couleurs prédéfinis." } }, "matugen": { diff --git a/Assets/Translations/pt.json b/Assets/Translations/pt.json index 6b00b036..19cd6b28 100644 --- a/Assets/Translations/pt.json +++ b/Assets/Translations/pt.json @@ -467,6 +467,10 @@ "section": { "label": "Esquemas de cores predefinidos", "description": "Escolha entre uma coleção de esquemas de cores predefinidos." + }, + "generate-templates": { + "label": "Gerar modelos para esquemas predefinidos", + "description": "Gera modelos Matugen (GTK, temas de terminal, etc.) ao usar esquemas de cores predefinidos." } }, "matugen": { diff --git a/Assets/Translations/zh-CN.json b/Assets/Translations/zh-CN.json index c0f12485..e6529a0e 100644 --- a/Assets/Translations/zh-CN.json +++ b/Assets/Translations/zh-CN.json @@ -501,6 +501,10 @@ "section": { "label": "预定义配色方案", "description": "从预定义配色方案集合中选择。" + }, + "generate-templates": { + "label": "为预定义方案生成模板", + "description": "使用预定义配色方案时生成 Matugen 模板(GTK、终端主题等)。" } }, "matugen": { diff --git a/Commons/Settings.qml b/Commons/Settings.qml index 0f19afbb..71db7fbf 100644 --- a/Commons/Settings.qml +++ b/Commons/Settings.qml @@ -310,6 +310,7 @@ Singleton { property string predefinedScheme: "Noctalia (default)" property bool darkMode: true property string matugenSchemeType: "scheme-fruit-salad" + property bool generateTemplatesForPredefined: true } // matugen templates toggles diff --git a/Modules/Settings/Tabs/ColorSchemeTab.qml b/Modules/Settings/Tabs/ColorSchemeTab.qml index 5855d755..383c7de9 100644 --- a/Modules/Settings/Tabs/ColorSchemeTab.qml +++ b/Modules/Settings/Tabs/ColorSchemeTab.qml @@ -202,6 +202,21 @@ ColumnLayout { description: I18n.tr("settings.color-scheme.predefined.section.description") } + // Generate templates for predefined schemes + NCheckbox { + Layout.fillWidth: true + label: I18n.tr("settings.color-scheme.predefined.generate-templates.label") + description: I18n.tr("settings.color-scheme.predefined.generate-templates.description") + checked: Settings.data.colorSchemes.generateTemplatesForPredefined + onToggled: checked => { + Settings.data.colorSchemes.generateTemplatesForPredefined = checked + // Re-generate templates if a predefined scheme is currently active + if (!Settings.data.colorSchemes.useWallpaperColors && Settings.data.colorSchemes.predefinedScheme) { + ColorSchemeService.applyScheme(Settings.data.colorSchemes.predefinedScheme) + } + } + } + // Color Schemes Grid GridLayout { columns: 3 diff --git a/Services/ColorSchemeService.qml b/Services/ColorSchemeService.qml index 08a76b03..4d0311d6 100644 --- a/Services/ColorSchemeService.qml +++ b/Services/ColorSchemeService.qml @@ -119,12 +119,22 @@ Singleton { } writeColorsToDisk(variant) Logger.log("ColorScheme", "Applying color scheme:", getBasename(path)) + + // Generate Matugen templates if any are enabled and setting allows it + if (Settings.data.colorSchemes.generateTemplatesForPredefined && hasEnabledMatugenTemplates()) { + MatugenService.generateFromPredefinedScheme(data) + } } catch (e) { Logger.error("ColorScheme", "Failed to parse scheme JSON:", e) } } } + // Check if any Matugen templates are enabled + function hasEnabledMatugenTemplates() { + return Settings.data.matugen.gtk4 || Settings.data.matugen.gtk3 || Settings.data.matugen.qt6 || Settings.data.matugen.qt5 || Settings.data.matugen.kitty || Settings.data.matugen.ghostty || Settings.data.matugen.foot || Settings.data.matugen.fuzzel || Settings.data.matugen.vesktop || Settings.data.matugen.pywalfox + } + // Writer to colors.json using a JsonAdapter for safety FileView { id: colorsWriter diff --git a/Services/MatugenService.qml b/Services/MatugenService.qml index 694bb1e7..a420ba8f 100644 --- a/Services/MatugenService.qml +++ b/Services/MatugenService.qml @@ -40,6 +40,258 @@ Singleton { Logger.log("Matugen", "Service started") } + // Convert predefined color scheme to Matugen format + function convertPredefinedSchemeToMatugen(schemeData) { + var variant = schemeData + // If scheme provides dark/light variants, pick based on settings + if (schemeData && (schemeData.dark || schemeData.light)) { + if (Settings.data.colorSchemes.darkMode) { + variant = schemeData.dark || schemeData.light + } else { + variant = schemeData.light || schemeData.dark + } + } + + // Map predefined scheme colors to Matugen color structure - only core Material 3 colors + var matugenColors = { + "colors": { + "primary": { + "light": { + "color": variant.mPrimary + }, + "default": { + "color": variant.mPrimary + }, + "dark": { + "color": variant.mPrimary + } + }, + "on_primary": { + "light": { + "color": variant.mOnPrimary + }, + "default": { + "color": variant.mOnPrimary + }, + "dark": { + "color": variant.mOnPrimary + } + }, + "secondary": { + "light": { + "color": variant.mSecondary + }, + "default": { + "color": variant.mSecondary + }, + "dark": { + "color": variant.mSecondary + } + }, + "on_secondary": { + "light": { + "color": variant.mOnSecondary + }, + "default": { + "color": variant.mOnSecondary + }, + "dark": { + "color": variant.mOnSecondary + } + }, + "tertiary": { + "light": { + "color": variant.mTertiary + }, + "default": { + "color": variant.mTertiary + }, + "dark": { + "color": variant.mTertiary + } + }, + "on_tertiary": { + "light": { + "color": variant.mOnTertiary + }, + "default": { + "color": variant.mOnTertiary + }, + "dark": { + "color": variant.mOnTertiary + } + }, + "error": { + "light": { + "color": variant.mError + }, + "default": { + "color": variant.mError + }, + "dark": { + "color": variant.mError + } + }, + "on_error": { + "light": { + "color": variant.mOnError + }, + "default": { + "color": variant.mOnError + }, + "dark": { + "color": variant.mOnError + } + }, + "surface": { + "light": { + "color": variant.mSurface + }, + "default": { + "color": variant.mSurface + }, + "dark": { + "color": variant.mSurface + } + }, + "on_surface": { + "light": { + "color": variant.mOnSurface + }, + "default": { + "color": variant.mOnSurface + }, + "dark": { + "color": variant.mOnSurface + } + }, + "on_background": { + "light": { + "color": variant.mOnSurface + }, + "default": { + "color": variant.mOnSurface + }, + "dark": { + "color": variant.mOnSurface + } + }, + "outline": { + "light": { + "color": variant.mOutline + }, + "default": { + "color": variant.mOutline + }, + "dark": { + "color": variant.mOutline + } + }, + "secondary_fixed_dim": { + "light": { + "color": variant.mSecondary + }, + "default": { + "color": variant.mSecondary + }, + "dark": { + "color": variant.mSecondary + } + }, + "tertiary_container": { + "light": { + "color": variant.mTertiary + }, + "default": { + "color": variant.mTertiary + }, + "dark": { + "color": variant.mTertiary + } + }, + "surface_container": { + "light": { + "color": variant.mSurfaceVariant + }, + "default": { + "color": variant.mSurfaceVariant + }, + "dark": { + "color": variant.mSurfaceVariant + } + }, + "primary_container": { + "light": { + "color": variant.mPrimary + }, + "default": { + "color": variant.mPrimary + }, + "dark": { + "color": variant.mPrimary + } + }, + "on_primary_container": { + "light": { + "color": variant.mOnPrimary + }, + "default": { + "color": variant.mOnPrimary + }, + "dark": { + "color": variant.mOnPrimary + } + }, + "surface_variant": { + "light": { + "color": variant.mSurfaceVariant + }, + "default": { + "color": variant.mSurfaceVariant + }, + "dark": { + "color": variant.mSurfaceVariant + } + }, + "primary_fixed_dim": { + "light": { + "color": variant.mError + }, + "default": { + "color": variant.mError + }, + "dark": { + "color": variant.mError + } + }, + "tertiary_fixed_dim": { + "light": { + "color": variant.mOutline + }, + "default": { + "color": variant.mOutline + }, + "dark": { + "color": variant.mOutline + } + }, + "surface_dim": { + "light": { + "color": variant.mOnSurfaceVariant + }, + "default": { + "color": variant.mOnSurfaceVariant + }, + "dark": { + "color": variant.mOnSurfaceVariant + } + } + } + } + + return JSON.stringify(matugenColors) + } + // Build TOML content based on settings function buildConfigToml() { return Matugen.buildConfigToml() @@ -77,6 +329,68 @@ Singleton { generateProcess.running = true } + // Generate templates from predefined color scheme + function generateFromPredefinedScheme(schemeData) { + Logger.log("Matugen", "Generating templates from predefined color scheme") + + var content = buildConfigToml() + var mode = Settings.data.colorSchemes.darkMode ? "dark" : "light" + var pathEsc = dynamicConfigPath.replace(/'/g, "'\\''") + var extraRepo = (Quickshell.shellDir + "/Assets/Matugen/extra").replace(/'/g, "'\\''") + var extraUser = (Settings.configDir + "matugen.d").replace(/'/g, "'\\''") + + // Convert predefined scheme to Matugen format + var matugenJson = convertPredefinedSchemeToMatugen(schemeData) + var jsonPath = Settings.cacheDir + "matugen.import.json" + var jsonPathEsc = jsonPath.replace(/'/g, "'\\''") + + // Write JSON file first using a separate process + jsonWriter.path = jsonPath + jsonWriter.setText(matugenJson) + + // Build the script + var script = "cat > '" + pathEsc + "' << 'EOF'\n" + content + "EOF\n" + script += "for d in '" + extraRepo + "' '" + extraUser + "'; do\n" + script += " if [ -d \"$d\" ]; then\n" + script += " for f in \"$d\"/*.toml; do\n" + script += " [ -f \"$f\" ] && { echo; echo \"# extra: $f\"; cat \"$f\"; } >> '" + pathEsc + "'\n" + script += " done\n" + script += " fi\n" + script += "done\n" + script += "matugen image --import-json '" + jsonPathEsc + "' --config '" + pathEsc + "' --mode " + mode + " '" + Quickshell.shellDir + "/Assets/Wallpaper/noctalia.png'" + + // Add user config execution if enabled + if (Settings.data.matugen.enableUserTemplates) { + var userConfigDir = (Quickshell.env("HOME") + "/.config/matugen/").replace(/'/g, "'\\''") + script += "\n# Execute user config if it exists\nif [ -f '" + userConfigDir + "config.toml' ]; then\n" + script += " matugen image --import-json '" + jsonPathEsc + "' --config '" + userConfigDir + "config.toml' --mode " + mode + " '" + Quickshell.shellDir + "/Assets/Wallpaper/noctalia.png'\n" + script += "fi" + } + + script += "\n" + pendingMatugenCommand = script + } + + // File writer for JSON import file + FileView { + id: jsonWriter + onSaved: { + Logger.log("Matugen", "JSON import file written successfully") + // Run matugen command after JSON file is written + if (pendingMatugenCommand) { + generateProcess.command = ["bash", "-lc", pendingMatugenCommand] + generateProcess.running = true + pendingMatugenCommand = "" + } + } + onSaveFailed: { + Logger.error("Matugen", "Failed to write JSON import file:", error) + } + } + + // Store the matugen command to run after JSON is written + property string pendingMatugenCommand: "" + Process { id: generateProcess workingDirectory: Quickshell.shellDir