Settings window #21

Merged
Zacharias-Brohn merged 2 commits from settingsWindow into main 2026-03-07 17:54:39 +01:00
3 changed files with 69 additions and 49 deletions
Showing only changes of commit c0f4434fd4 - Show all commits
+1
View File
@@ -169,6 +169,7 @@ Singleton {
color: { color: {
wallust: general.color.wallust, wallust: general.color.wallust,
mode: general.color.mode, mode: general.color.mode,
smart: general.color.smart,
schemeGeneration: general.color.schemeGeneration, schemeGeneration: general.color.schemeGeneration,
scheduleDarkStart: general.color.scheduleDarkStart, scheduleDarkStart: general.color.scheduleDarkStart,
scheduleDarkEnd: general.color.scheduleDarkEnd, scheduleDarkEnd: general.color.scheduleDarkEnd,
+1
View File
@@ -23,6 +23,7 @@ JsonObject {
property int scheduleDarkEnd: 0 property int scheduleDarkEnd: 0
property int scheduleDarkStart: 0 property int scheduleDarkStart: 0
property bool schemeGeneration: true property bool schemeGeneration: true
property bool smart: false
property bool wallust: false property bool wallust: false
} }
component Idle: JsonObject { component Idle: JsonObject {
+67 -49
View File
@@ -12,6 +12,7 @@ from materialyoucolor.quantize import QuantizeCelebi
from materialyoucolor.score.score import Score from materialyoucolor.score.score import Score
from materialyoucolor.dynamiccolor.material_dynamic_colors import MaterialDynamicColors from materialyoucolor.dynamiccolor.material_dynamic_colors import MaterialDynamicColors
from materialyoucolor.hct.hct import Hct from materialyoucolor.hct.hct import Hct
from materialyoucolor.utils.color_utils import argb_from_rgb
from materialyoucolor.utils.math_utils import difference_degrees, rotation_direction, sanitize_degrees_double from materialyoucolor.utils.math_utils import difference_degrees, rotation_direction, sanitize_degrees_double
app = typer.Typer() app = typer.Typer()
@@ -47,35 +48,40 @@ def generate(
raise typer.BadParameter( raise typer.BadParameter(
"Use either --image-path or --preset, not both.") "Use either --image-path or --preset, not both.")
if scheme is None: cli_mode = mode is not None
with CONFIG.open() as f:
scheme = json.load(f)["colors"]["schemeType"]
match scheme: def get_scheme_class(scheme_name: str):
case "fruit-salad": match scheme_name:
from materialyoucolor.scheme.scheme_fruit_salad import SchemeFruitSalad as Scheme case "fruit-salad":
case 'expressive': from materialyoucolor.scheme.scheme_fruit_salad import SchemeFruitSalad
from materialyoucolor.scheme.scheme_expressive import SchemeExpressive as Scheme return SchemeFruitSalad
case 'monochrome': case "expressive":
from materialyoucolor.scheme.scheme_monochrome import SchemeMonochrome as Scheme from materialyoucolor.scheme.scheme_expressive import SchemeExpressive
case 'rainbow': return SchemeExpressive
from materialyoucolor.scheme.scheme_rainbow import SchemeRainbow as Scheme case "monochrome":
case 'tonal-spot': from materialyoucolor.scheme.scheme_monochrome import SchemeMonochrome
from materialyoucolor.scheme.scheme_tonal_spot import SchemeTonalSpot as Scheme return SchemeMonochrome
case 'neutral': case "rainbow":
from materialyoucolor.scheme.scheme_neutral import SchemeNeutral as Scheme from materialyoucolor.scheme.scheme_rainbow import SchemeRainbow
case 'fidelity': return SchemeRainbow
from materialyoucolor.scheme.scheme_fidelity import SchemeFidelity as Scheme case "tonal-spot":
case 'content': from materialyoucolor.scheme.scheme_tonal_spot import SchemeTonalSpot
from materialyoucolor.scheme.scheme_content import SchemeContent as Scheme return SchemeTonalSpot
case 'vibrant': case "neutral":
from materialyoucolor.scheme.scheme_vibrant import SchemeVibrant as Scheme from materialyoucolor.scheme.scheme_neutral import SchemeNeutral
case _: return SchemeNeutral
from materialyoucolor.scheme.scheme_fruit_salad import SchemeFruitSalad as Scheme case "fidelity":
from materialyoucolor.scheme.scheme_fidelity import SchemeFidelity
if mode is None: return SchemeFidelity
with CONFIG.open() as f: case "content":
mode = json.load(f)["general"]["color"]["mode"] from materialyoucolor.scheme.scheme_content import SchemeContent
return SchemeContent
case "vibrant":
from materialyoucolor.scheme.scheme_vibrant import SchemeVibrant
return SchemeVibrant
case _:
from materialyoucolor.scheme.scheme_fruit_salad import SchemeFruitSalad
return SchemeFruitSalad
def hex_to_hct(hex_color: str) -> Hct: def hex_to_hct(hex_color: str) -> Hct:
s = hex_color.strip() s = hex_color.strip()
@@ -226,6 +232,16 @@ def generate(
except (PermissionError, OSError, BlockingIOError): except (PermissionError, OSError, BlockingIOError):
pass pass
def smart_mode(image_path: Path) -> str:
is_dark = ""
with Image.open(image_path) as img:
img.thumbnail((1, 1), Image.LANCZOS)
hct = Hct.from_int(argb_from_rgb(*img.getpixel((0, 0))))
is_dark = "light" if hct.tone > 60 else "dark"
return is_dark
def build_template_context( def build_template_context(
*, *,
colors: dict[str, str], colors: dict[str, str],
@@ -375,11 +391,11 @@ def generate(
raise typer.BadParameter( raise typer.BadParameter(
f"Preset '{name}' not found. Available presets: {', '.join(PRESETS.keys())}") f"Preset '{name}' not found. Available presets: {', '.join(PRESETS.keys())}")
def generate_color_scheme(seed: Hct, mode: str) -> dict[str, str]: def generate_color_scheme(seed: Hct, mode: str, scheme_class) -> dict[str, str]:
is_dark = mode.lower() == "dark" is_dark = mode.lower() == "dark"
scheme = Scheme( scheme = scheme_class(
seed, seed,
is_dark, is_dark,
0.0 0.0
@@ -398,36 +414,38 @@ def generate(
return "#{:06X}".format(argb_int & 0xFFFFFF) return "#{:06X}".format(argb_int & 0xFFFFFF)
try: try:
with CONFIG.open() as f:
config = json.load(f)
scheme = scheme or config["colors"]["schemeType"]
config_mode = config["general"]["color"]["mode"]
smart = bool(config["general"]["color"].get("smart", False))
scheme_class = get_scheme_class(scheme)
if preset: if preset:
seed = seed_from_preset(preset) seed = seed_from_preset(preset)
colors = generate_color_scheme(seed, mode) effective_mode = mode or config_mode
name, flavor = preset.split(":") name, flavor = preset.split(":")
elif image_path: else:
image_path = image_path or Path(WALL_PATH)
generate_thumbnail(image_path, str(THUMB_PATH)) generate_thumbnail(image_path, str(THUMB_PATH))
seed = seed_from_image(THUMB_PATH) seed = seed_from_image(THUMB_PATH)
colors = generate_color_scheme(seed, mode)
name = "dynamic" name = "dynamic"
flavor = "default" flavor = "default"
elif mode:
generate_thumbnail(WALL_PATH, str(THUMB_PATH))
seed = seed_from_image(THUMB_PATH)
colors = generate_color_scheme(seed, mode)
name = "dynamic"
flavor = "default"
elif scheme:
with OUTPUT.open() as f:
js = json.load(f)
seed = Hct.from_int(js["seed"])
mode = str(js["mode"])
colors = generate_color_scheme(seed, mode) if smart:
name = "dynamic" effective_mode = smart_mode(THUMB_PATH)
flavor = "default" elif mode is not None:
effective_mode = mode
else:
effective_mode = config_mode
colors = generate_color_scheme(seed, effective_mode, scheme_class)
output_dict = { output_dict = {
"name": name, "name": name,
"flavor": flavor, "flavor": flavor,
"mode": mode, "mode": effective_mode,
"variant": scheme, "variant": scheme,
"colors": colors, "colors": colors,
"seed": seed.to_int() "seed": seed.to_int()
@@ -438,7 +456,7 @@ def generate(
ctx = build_template_context( ctx = build_template_context(
colors=colors, colors=colors,
seed=seed, seed=seed,
mode=mode, mode=effective_mode,
wallpaper_path=wp, wallpaper_path=wp,
name=name, name=name,
flavor=flavor, flavor=flavor,