matugen: initial commit for predefined color schemes

This commit is contained in:
Ly-sec
2025-10-02 00:44:38 +02:00
parent 49a0c8449f
commit 42af310ccf
11 changed files with 369 additions and 5 deletions
+5 -5
View File
@@ -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}}
+4
View File
@@ -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": {
+4
View File
@@ -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": {
+4
View File
@@ -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": {
+4
View File
@@ -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": {
+4
View File
@@ -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": {
+4
View File
@@ -501,6 +501,10 @@
"section": {
"label": "预定义配色方案",
"description": "从预定义配色方案集合中选择。"
},
"generate-templates": {
"label": "为预定义方案生成模板",
"description": "使用预定义配色方案时生成 Matugen 模板(GTK、终端主题等)。"
}
},
"matugen": {
+1
View File
@@ -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
+15
View File
@@ -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
+10
View File
@@ -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
+314
View File
@@ -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