refactor: externalize app configuration to JSON and unify UI color scheme constants
This commit is contained in:
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"app_name": "fcco Converter",
|
||||
"app_version": "2.0.0",
|
||||
"repo_owner": "public",
|
||||
"repo_name": "fcco-Converter",
|
||||
"gitea_api_base": "https://git.joelunger.de/api/v1"
|
||||
}
|
||||
@@ -7,8 +7,59 @@ Verwendet pathlib für alle Pfadoperationen.
|
||||
|
||||
import json
|
||||
import platform
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
# ---- Globale App-Informationen (aus config.json) ----
|
||||
APP_INFO = {
|
||||
"app_name": "fcco Converter",
|
||||
"app_version": "2.0.0",
|
||||
"repo_owner": "public",
|
||||
"repo_name": "fcco-Converter",
|
||||
"gitea_api_base": "https://git.joelunger.de/api/v1"
|
||||
}
|
||||
|
||||
def _load_app_info():
|
||||
try:
|
||||
# Finde config.json relativ zum Skript oder im PyInstaller Bundle
|
||||
if getattr(sys, "frozen", False):
|
||||
base_dir = Path(sys.executable).parent
|
||||
else:
|
||||
base_dir = Path(__file__).parent.parent
|
||||
|
||||
config_path = base_dir / "config.json"
|
||||
if config_path.exists():
|
||||
with open(config_path, "r", encoding="utf-8") as f:
|
||||
data = json.load(f)
|
||||
APP_INFO.update(data)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
_load_app_info()
|
||||
|
||||
# =========================================================================
|
||||
# Farbschema
|
||||
# =========================================================================
|
||||
|
||||
T = {
|
||||
"bg": "#000000",
|
||||
"surface": "#111111",
|
||||
"elevated": "#1a1a1a",
|
||||
"card": "#222222",
|
||||
"input": "#000000",
|
||||
"accent": "#ffffff",
|
||||
"accent_h": "#e6e6e6",
|
||||
"success": "#ffffff",
|
||||
"success_h": "#e6e6e6",
|
||||
"warn": "#ffffff",
|
||||
"error": "#ffffff",
|
||||
"text": "#ffffff",
|
||||
"text2": "#b3b3b3",
|
||||
"muted": "#808080",
|
||||
"border": "#333333",
|
||||
"btn2": "#1a1a1a",
|
||||
"btn2_h": "#333333",
|
||||
}
|
||||
|
||||
# Standardmäßige Export-Kategorien
|
||||
DEFAULT_EXPORT_PATHS = {
|
||||
|
||||
+33
-48
@@ -29,6 +29,8 @@ from .config import (
|
||||
load_settings,
|
||||
save_settings,
|
||||
save_export_history,
|
||||
T,
|
||||
APP_INFO,
|
||||
)
|
||||
from .converter import run_batch_conversion, _ensure_ffmpeg
|
||||
from .metadata import (
|
||||
@@ -50,25 +52,7 @@ IS_MACOS = platform.system() == "Darwin"
|
||||
# Farbschema
|
||||
# =========================================================================
|
||||
|
||||
T = {
|
||||
"bg": "#000000",
|
||||
"surface": "#111111",
|
||||
"elevated": "#1a1a1a",
|
||||
"card": "#222222",
|
||||
"input": "#000000",
|
||||
"accent": "#ffffff",
|
||||
"accent_h": "#e6e6e6",
|
||||
"success": "#ffffff",
|
||||
"success_h": "#e6e6e6",
|
||||
"warn": "#ffffff",
|
||||
"error": "#ffffff",
|
||||
"text": "#ffffff",
|
||||
"text2": "#b3b3b3",
|
||||
"muted": "#808080",
|
||||
"border": "#333333",
|
||||
"btn2": "#1a1a1a",
|
||||
"btn2_h": "#333333",
|
||||
}
|
||||
# (Farben werden jetzt aus config.T importiert)
|
||||
|
||||
|
||||
# =========================================================================
|
||||
@@ -82,7 +66,7 @@ class App(ctk.CTk):
|
||||
ctk.set_appearance_mode("dark")
|
||||
ctk.set_default_color_theme("blue")
|
||||
|
||||
self.title(f"fcco Converter v{get_current_version()}")
|
||||
self.title(f"{APP_INFO['app_name']} V{APP_INFO['app_version']}")
|
||||
self.geometry("900x700")
|
||||
self.minsize(700, 500)
|
||||
self.configure(fg_color=T["bg"])
|
||||
@@ -227,8 +211,8 @@ class App(ctk.CTk):
|
||||
self.conv_btn = self._btn(
|
||||
tb, text=" Konvertieren", command=self._convert,
|
||||
image=self.icons.play, width=160, height=36,
|
||||
fg_color=T["accent"], hover_color=T["accent_h"],
|
||||
text_color="#000000", font=ctk.CTkFont(size=14, weight="bold"))
|
||||
fg_color=T["btn2"], hover_color=T["btn2_h"],
|
||||
text_color="#ffffff", font=ctk.CTkFont(size=14, weight="bold"))
|
||||
self.conv_btn.grid(row=0, column=3, sticky="e")
|
||||
|
||||
def _make_filelist(self):
|
||||
@@ -576,7 +560,7 @@ class App(ctk.CTk):
|
||||
ctype_var = ctk.StringVar(value="Gottesdienst")
|
||||
for i, opt in enumerate(["Gottesdienst", "Hochzeit", "Weissagung", "Jugend", "Sonstiges"]):
|
||||
ctk.CTkRadioButton(mid, text=opt, variable=ctype_var, value=opt,
|
||||
fg_color=T["accent"], hover_color=T["accent_h"],
|
||||
fg_color=T["btn2"], hover_color=T["btn2_h"], checkmark_color="#ffffff",
|
||||
border_color=T["border"], text_color=T["text"],
|
||||
font=ctk.CTkFont(size=12)
|
||||
).grid(row=i+1, column=0, sticky="w", pady=1, padx=(0, 24))
|
||||
@@ -623,8 +607,8 @@ class App(ctk.CTk):
|
||||
|
||||
self._btn(bf, text=" Konvertieren starten", command=_ok,
|
||||
image=self.icons.play, width=180, height=34,
|
||||
fg_color=T["accent"], hover_color=T["accent_h"],
|
||||
text_color="#000000", font=ctk.CTkFont(weight="bold")
|
||||
fg_color=T["btn2"], hover_color=T["btn2_h"],
|
||||
text_color="#ffffff", font=ctk.CTkFont(weight="bold")
|
||||
).pack(side="right")
|
||||
|
||||
# Fokus (KEIN grab_set auf macOS!)
|
||||
@@ -650,10 +634,11 @@ class App(ctk.CTk):
|
||||
|
||||
tabs = ctk.CTkTabview(w, fg_color=T["surface"],
|
||||
segmented_button_fg_color=T["elevated"],
|
||||
segmented_button_selected_color=T["accent"],
|
||||
segmented_button_selected_hover_color=T["accent_h"],
|
||||
segmented_button_selected_color=T["border"],
|
||||
segmented_button_selected_hover_color=T["btn2_h"],
|
||||
segmented_button_unselected_color=T["elevated"],
|
||||
segmented_button_unselected_hover_color=T["btn2_h"])
|
||||
segmented_button_unselected_hover_color=T["btn2_h"],
|
||||
text_color=T["text"])
|
||||
tabs.pack(fill="both", expand=True, padx=12, pady=(12, 4))
|
||||
|
||||
t1 = tabs.add("Allgemein")
|
||||
@@ -681,8 +666,8 @@ class App(ctk.CTk):
|
||||
font=ctk.CTkFont(size=12)).pack(anchor="w")
|
||||
av = ctk.StringVar(value=self.settings.get("appearance_mode", "Dark"))
|
||||
ctk.CTkOptionMenu(s1, values=["Dark", "Light", "System"], variable=av,
|
||||
fg_color=T["input"], button_color=T["accent"],
|
||||
button_hover_color=T["accent_h"], text_color=T["text"],
|
||||
fg_color=T["input"], button_color=T["btn2"],
|
||||
button_hover_color=T["btn2_h"], text_color=T["text"],
|
||||
command=lambda v: ctk.set_appearance_mode(v)
|
||||
).pack(anchor="w", pady=(2, 10))
|
||||
wg["appearance"] = av
|
||||
@@ -690,7 +675,7 @@ class App(ctk.CTk):
|
||||
self._slabel(s1, "Updates")
|
||||
uv = ctk.BooleanVar(value=self.settings.get("check_updates_on_start", True))
|
||||
ctk.CTkCheckBox(s1, text="Beim Start auf Updates prüfen", variable=uv,
|
||||
fg_color=T["accent"], hover_color=T["accent_h"],
|
||||
fg_color=T["btn2"], hover_color=T["btn2_h"], checkmark_color="#ffffff",
|
||||
border_color=T["border"], text_color=T["text"],
|
||||
font=ctk.CTkFont(size=12)).pack(anchor="w", pady=4)
|
||||
wg["auto_update"] = uv
|
||||
@@ -702,16 +687,16 @@ class App(ctk.CTk):
|
||||
self._slabel(s2, "Ausgabeformat")
|
||||
fv = ctk.StringVar(value=self.settings.get("audio", {}).get("output_format", "mp3"))
|
||||
ctk.CTkOptionMenu(s2, values=OUTPUT_FORMAT_OPTIONS, variable=fv,
|
||||
fg_color=T["input"], button_color=T["accent"],
|
||||
button_hover_color=T["accent_h"], text_color=T["text"]
|
||||
fg_color=T["input"], button_color=T["btn2"],
|
||||
button_hover_color=T["btn2_h"], text_color=T["text"]
|
||||
).pack(anchor="w", pady=(2, 10))
|
||||
wg["fmt"] = fv
|
||||
|
||||
self._slabel(s2, "Encoding")
|
||||
mv = ctk.StringVar(value=self.settings.get("audio", {}).get("encoding_mode", "CBR"))
|
||||
ctk.CTkOptionMenu(s2, values=ENCODING_MODE_OPTIONS, variable=mv,
|
||||
fg_color=T["input"], button_color=T["accent"],
|
||||
button_hover_color=T["accent_h"], text_color=T["text"]
|
||||
fg_color=T["input"], button_color=T["btn2"],
|
||||
button_hover_color=T["btn2_h"], text_color=T["text"]
|
||||
).pack(anchor="w", pady=(2, 6))
|
||||
wg["mode"] = mv
|
||||
|
||||
@@ -719,8 +704,8 @@ class App(ctk.CTk):
|
||||
font=ctk.CTkFont(size=12)).pack(anchor="w", pady=(4, 0))
|
||||
bv = ctk.StringVar(value=self.settings.get("audio", {}).get("bitrate", "192"))
|
||||
ctk.CTkOptionMenu(s2, values=BITRATE_OPTIONS, variable=bv,
|
||||
fg_color=T["input"], button_color=T["accent"],
|
||||
button_hover_color=T["accent_h"], text_color=T["text"]
|
||||
fg_color=T["input"], button_color=T["btn2"],
|
||||
button_hover_color=T["btn2_h"], text_color=T["text"]
|
||||
).pack(anchor="w", pady=(2, 6))
|
||||
wg["br"] = bv
|
||||
|
||||
@@ -728,8 +713,8 @@ class App(ctk.CTk):
|
||||
font=ctk.CTkFont(size=12)).pack(anchor="w", pady=(4, 0))
|
||||
vv = ctk.StringVar(value=self.settings.get("audio", {}).get("vbr_quality", "2"))
|
||||
ctk.CTkOptionMenu(s2, values=VBR_QUALITY_OPTIONS, variable=vv,
|
||||
fg_color=T["input"], button_color=T["accent"],
|
||||
button_hover_color=T["accent_h"], text_color=T["text"]
|
||||
fg_color=T["input"], button_color=T["btn2"],
|
||||
button_hover_color=T["btn2_h"], text_color=T["text"]
|
||||
).pack(anchor="w", pady=(2, 10))
|
||||
wg["vbr"] = vv
|
||||
|
||||
@@ -738,8 +723,8 @@ class App(ctk.CTk):
|
||||
font=ctk.CTkFont(size=12)).pack(anchor="w")
|
||||
sv = ctk.StringVar(value=self.settings.get("audio", {}).get("sample_rate", "Original"))
|
||||
ctk.CTkOptionMenu(s2, values=SAMPLERATE_OPTIONS, variable=sv,
|
||||
fg_color=T["input"], button_color=T["accent"],
|
||||
button_hover_color=T["accent_h"], text_color=T["text"]
|
||||
fg_color=T["input"], button_color=T["btn2"],
|
||||
button_hover_color=T["btn2_h"], text_color=T["text"]
|
||||
).pack(anchor="w", pady=(2, 6))
|
||||
wg["sr"] = sv
|
||||
|
||||
@@ -747,15 +732,15 @@ class App(ctk.CTk):
|
||||
font=ctk.CTkFont(size=12)).pack(anchor="w", pady=(4, 0))
|
||||
cv = ctk.StringVar(value=self.settings.get("audio", {}).get("channels", "Original"))
|
||||
ctk.CTkOptionMenu(s2, values=CHANNEL_OPTIONS, variable=cv,
|
||||
fg_color=T["input"], button_color=T["accent"],
|
||||
button_hover_color=T["accent_h"], text_color=T["text"]
|
||||
fg_color=T["input"], button_color=T["btn2"],
|
||||
button_hover_color=T["btn2_h"], text_color=T["text"]
|
||||
).pack(anchor="w", pady=(2, 10))
|
||||
wg["ch"] = cv
|
||||
|
||||
self._slabel(s2, "Optionen")
|
||||
ov = ctk.BooleanVar(value=self.settings.get("audio", {}).get("overwrite_existing", True))
|
||||
ctk.CTkCheckBox(s2, text="Bestehende Dateien überschreiben", variable=ov,
|
||||
fg_color=T["accent"], hover_color=T["accent_h"],
|
||||
fg_color=T["btn2"], hover_color=T["btn2_h"], checkmark_color="#ffffff",
|
||||
border_color=T["border"], text_color=T["text"],
|
||||
font=ctk.CTkFont(size=12)).pack(anchor="w", pady=3)
|
||||
wg["ow"] = ov
|
||||
@@ -796,14 +781,14 @@ class App(ctk.CTk):
|
||||
self._slabel(s3, "Automatisierung")
|
||||
atv = ctk.BooleanVar(value=self.settings.get("metadata", {}).get("auto_track_number", True))
|
||||
ctk.CTkCheckBox(s3, text="Tracknummer automatisch vergeben", variable=atv,
|
||||
fg_color=T["accent"], hover_color=T["accent_h"],
|
||||
fg_color=T["btn2"], hover_color=T["btn2_h"], checkmark_color="#ffffff",
|
||||
border_color=T["border"], text_color=T["text"],
|
||||
font=ctk.CTkFont(size=12)).pack(anchor="w", pady=3)
|
||||
wg["auto_track"] = atv
|
||||
|
||||
aav = ctk.BooleanVar(value=self.settings.get("metadata", {}).get("auto_album_from_folder", True))
|
||||
ctk.CTkCheckBox(s3, text="Albumname aus Ordnername ableiten", variable=aav,
|
||||
fg_color=T["accent"], hover_color=T["accent_h"],
|
||||
fg_color=T["btn2"], hover_color=T["btn2_h"], checkmark_color="#ffffff",
|
||||
border_color=T["border"], text_color=T["text"],
|
||||
font=ctk.CTkFont(size=12)).pack(anchor="w", pady=3)
|
||||
wg["auto_album"] = aav
|
||||
@@ -848,8 +833,8 @@ class App(ctk.CTk):
|
||||
|
||||
self._btn(bf, text=" Speichern", command=lambda: self._save_s(wg, w),
|
||||
image=self.icons.save, width=140, height=34,
|
||||
fg_color=T["accent"], hover_color=T["accent_h"],
|
||||
text_color="#000000", font=ctk.CTkFont(weight="bold")
|
||||
fg_color=T["btn2"], hover_color=T["btn2_h"],
|
||||
text_color="#ffffff", font=ctk.CTkFont(weight="bold")
|
||||
).pack(side="right")
|
||||
|
||||
w.after(50, lambda: (w.lift(), w.focus_force()))
|
||||
|
||||
@@ -17,14 +17,13 @@ from typing import Callable
|
||||
from urllib.request import urlopen, Request
|
||||
from urllib.error import URLError
|
||||
import json
|
||||
from .config import APP_INFO
|
||||
|
||||
# Aktuelle Version des Programms
|
||||
CURRENT_VERSION = "2.0.0"
|
||||
|
||||
# Gitea API-URL für Releases
|
||||
GITEA_API_BASE = "https://git.joelunger.de/api/v1"
|
||||
REPO_OWNER = "public"
|
||||
REPO_NAME = "fcco-Converter"
|
||||
# Aktuelle Version des Programms und Repos (aus config.json)
|
||||
CURRENT_VERSION = APP_INFO["app_version"]
|
||||
GITEA_API_BASE = APP_INFO["gitea_api_base"]
|
||||
REPO_OWNER = APP_INFO["repo_owner"]
|
||||
REPO_NAME = APP_INFO["repo_name"]
|
||||
RELEASES_URL = f"{GITEA_API_BASE}/repos/{REPO_OWNER}/{REPO_NAME}/releases"
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user