import app.utils.paths as paths import os, json from typing import List, Dict, Any, Optional class Theme: def __init__(self, name: str, colors: Dict[str, str]) -> None: self.name: str = name self.colors: Dict[str, str] = colors def get_color(self, element: str) -> str: return self.colors.get(element, "#FFFFFF") class ThemeManager: def __init__(self) -> None: theme_path: str = os.path.join(paths.get_data_dir(), "themes") self.themes: List[Theme] = [] for theme_file in os.listdir(theme_path): if theme_file.endswith(".json"): with open(os.path.join(theme_path, theme_file), 'r', encoding='utf-8') as f: theme_data: Dict[str, Any] = json.load(f) theme: Theme = Theme(theme_data["theme_name"], theme_data["colors"]) self.themes.append(theme) self.current_theme: Theme = self.themes[0] def set_theme(self, theme: str) -> None: if theme != self.current_theme.name: found_theme: Optional[Theme] = next((t for t in self.themes if t.name == theme), None) if found_theme: self.current_theme = found_theme def get_theme(self) -> Theme: return self.current_theme def get_sheet(self) -> str: return f""" QWidget {{ background-color: {self.current_theme.get_color("background")}; color: {self.current_theme.get_color("font_color")}; }} QPushButton {{ background-color: #0A84FF; color: {self.current_theme.get_color("font_color")}; border-radius: 8px; font-size: 16px; padding: 10px 20px; border: none; }} QPushButton:hover {{ background-color: #007AFF; }} QLabel {{ color: {self.current_theme.get_color("font_color")}; }} QProgressBar {{ border: 1px solid #3C3C3E; border-radius: 5px; background-color: {self.current_theme.get_color("background2")}; text-align: center; color: {self.current_theme.get_color("font_color")}; }} QProgressBar::chunk {{ background-color: #0A84FF; border-radius: 3px; }} QFrame {{ background-color: {self.current_theme.get_color("background2")}; border: none; }} QFrame#indicator_bar {{ background-color: #0A84FF; }} QScrollBar:vertical {{ border: none; background: #E0E0E0; width: 8px; margin: 0px; }} QScrollBar::handle:vertical {{ background: #0A84FF; border-radius: 4px; min-height: 20px; }} QScrollBar::handle:vertical:hover {{ background: #3B9CFF; }} QScrollBar::add-line:vertical, QScrollBar::sub-line:vertical {{ border: none; background: none; height: 0px; }} QScrollBar::add-page:vertical, QScrollBar::sub-page:vertical {{ background: none; }} #drag_area {{ border: 2px dashed #3498db; border-radius: 10px; }} QSlider::groove:horizontal {{ border: 1px solid #3a9bdc; height: 10px; background: transparent; border-radius: 5px; }} QSlider::sub-page:horizontal {{ background: #3a9bdc; border-radius: 5px; }} QSlider::add-page:horizontal {{ background: {self.current_theme.get_color("background3")}; border-radius: 5px; }} QSlider::handle:horizontal {{ background: white; border: 2px solid #3a9bdc; width: 14px; margin: -4px 0; border-radius: 7px; }} QComboBox {{ padding: 5px; border-radius: 8px; font-size: 14px; min-height: 30px; }} QComboBox QAbstractItemView {{ border-radius: 8px; padding: 0px; outline: none; }} QComboBox QAbstractItemView::item {{ padding: 12px 15px; margin: 0px; min-height: 20px; border: 1px solid {self.current_theme.get_color("border")}; border-radius: 8px; }} QComboBox QAbstractItemView::item:hover {{ background-color: {self.current_theme.get_color("background3")}; color: {self.current_theme.get_color("font_color")}; }} QComboBox QAbstractItemView::item:selected {{ color: {self.current_theme.get_color("font_color")}; }} QTextEdit {{ border: 1px solid {self.current_theme.get_color("border")}; border-radius: 8px; padding: 10px; font-size: 14px; background-color: {self.current_theme.get_color("background2")}; color: {self.current_theme.get_color("font_color")}; }} """