DarkMode ist existent yeah
Dieser Commit ist enthalten in:
8
themes/__init__.py
Normale Datei
8
themes/__init__.py
Normale Datei
@ -0,0 +1,8 @@
|
||||
"""
|
||||
Theme System Package
|
||||
"""
|
||||
|
||||
from themes.theme_config import ThemeConfig
|
||||
from themes.qss_generator import QSSGenerator
|
||||
|
||||
__all__ = ['ThemeConfig', 'QSSGenerator']
|
||||
805
themes/qss_generator.py
Normale Datei
805
themes/qss_generator.py
Normale Datei
@ -0,0 +1,805 @@
|
||||
"""
|
||||
QSS Generator - Dynamically generates Qt Stylesheets from Theme Configuration
|
||||
"""
|
||||
|
||||
from themes.theme_config import ThemeConfig
|
||||
|
||||
|
||||
class QSSGenerator:
|
||||
"""
|
||||
Generates complete QSS stylesheets from theme configuration.
|
||||
This ensures all styling is consistent and centralized.
|
||||
"""
|
||||
|
||||
@staticmethod
|
||||
def generate(theme_name: str) -> str:
|
||||
"""
|
||||
Generate complete QSS for the specified theme.
|
||||
|
||||
Args:
|
||||
theme_name: 'light' or 'dark'
|
||||
|
||||
Returns:
|
||||
Complete QSS stylesheet as string
|
||||
"""
|
||||
theme = ThemeConfig.get_theme(theme_name)
|
||||
fonts = ThemeConfig.FONTS
|
||||
sizes = ThemeConfig.FONT_SIZES
|
||||
weights = ThemeConfig.FONT_WEIGHTS
|
||||
spacing = ThemeConfig.SPACING
|
||||
radius = ThemeConfig.RADIUS
|
||||
|
||||
qss = f"""
|
||||
/* ==================== AUTO-GENERATED THEME: {theme_name.upper()} ==================== */
|
||||
/* Generated from themes/theme_config.py - DO NOT EDIT DIRECTLY */
|
||||
|
||||
/* ==================== MAIN WINDOW ==================== */
|
||||
QMainWindow {{
|
||||
background-color: {theme['bg_primary']};
|
||||
color: {theme['text_primary']};
|
||||
}}
|
||||
|
||||
/* ==================== BASE WIDGETS ==================== */
|
||||
QWidget {{
|
||||
background-color: {theme['bg_primary']};
|
||||
color: {theme['text_primary']};
|
||||
font-family: {fonts['secondary']};
|
||||
font-size: {sizes['base']};
|
||||
}}
|
||||
|
||||
/* Content Stack - Main content area */
|
||||
QStackedWidget#content_stack {{
|
||||
background-color: {theme['bg_secondary']};
|
||||
}}
|
||||
|
||||
/* ==================== LABELS ==================== */
|
||||
QLabel {{
|
||||
color: {theme['text_primary']};
|
||||
background-color: transparent;
|
||||
padding: 2px;
|
||||
}}
|
||||
|
||||
/* Platform Title */
|
||||
QLabel#platform_title {{
|
||||
font-family: {fonts['primary']};
|
||||
font-size: {sizes['3xl']};
|
||||
font-weight: {weights['bold']};
|
||||
color: {theme['text_accent']};
|
||||
padding: {spacing['md']};
|
||||
letter-spacing: 1px;
|
||||
}}
|
||||
|
||||
/* Secondary Labels */
|
||||
QLabel#secondary_text {{
|
||||
color: {theme['text_secondary']};
|
||||
}}
|
||||
|
||||
/* Platform Name Labels */
|
||||
QLabel#platform_name_label {{
|
||||
color: {theme['platform_label']};
|
||||
font-family: {fonts['primary']};
|
||||
font-weight: {weights['semibold']};
|
||||
letter-spacing: 0.5px;
|
||||
}}
|
||||
|
||||
/* ==================== PLATFORM BUTTONS ==================== */
|
||||
PlatformButton {{
|
||||
background-color: transparent;
|
||||
}}
|
||||
|
||||
QPushButton#platform_icon_button {{
|
||||
background-color: {theme['platform_bg']};
|
||||
border: 1px solid {theme['platform_border']};
|
||||
border-radius: {radius['xl']};
|
||||
padding: {spacing['xl']};
|
||||
}}
|
||||
|
||||
QPushButton#platform_icon_button:hover {{
|
||||
background-color: {theme['platform_hover']};
|
||||
border: 1px solid {theme['platform_border_hover']};
|
||||
}}
|
||||
|
||||
QPushButton#platform_icon_button:pressed {{
|
||||
background-color: {theme['platform_pressed']};
|
||||
border: 1px solid {theme['platform_border_hover']};
|
||||
}}
|
||||
|
||||
QPushButton#platform_icon_button:disabled {{
|
||||
background-color: {theme['bg_tertiary']};
|
||||
opacity: 0.5;
|
||||
}}
|
||||
|
||||
/* ==================== BUTTONS ==================== */
|
||||
QPushButton {{
|
||||
background-color: {theme['btn_primary_bg']};
|
||||
color: {theme['btn_primary_text']};
|
||||
border: none;
|
||||
border-radius: {radius['round']};
|
||||
padding: 0 {spacing['xl']};
|
||||
font-family: {fonts['primary']};
|
||||
font-size: {sizes['base']};
|
||||
font-weight: {weights['semibold']};
|
||||
min-height: 48px;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.5px;
|
||||
}}
|
||||
|
||||
QPushButton:hover {{
|
||||
background-color: {theme['accent_hover']};
|
||||
}}
|
||||
|
||||
QPushButton:pressed {{
|
||||
background-color: {theme['accent_pressed']};
|
||||
}}
|
||||
|
||||
QPushButton:disabled {{
|
||||
background-color: {theme['bg_tertiary']};
|
||||
color: {theme['text_tertiary']};
|
||||
opacity: 0.5;
|
||||
}}
|
||||
|
||||
/* Secondary Buttons */
|
||||
QPushButton#secondary_button {{
|
||||
background-color: {theme['btn_secondary_bg']};
|
||||
color: {theme['btn_secondary_text']};
|
||||
border: 1px solid {theme['btn_secondary_border']};
|
||||
}}
|
||||
|
||||
QPushButton#secondary_button:hover {{
|
||||
background-color: {theme['bg_hover']};
|
||||
}}
|
||||
|
||||
/* Danger Buttons */
|
||||
QPushButton#danger_button {{
|
||||
background-color: {theme['btn_danger_bg']};
|
||||
color: {theme['btn_danger_text']};
|
||||
}}
|
||||
|
||||
QPushButton#danger_button:hover {{
|
||||
background-color: {theme['error']};
|
||||
}}
|
||||
|
||||
/* ==================== TAB NAVIGATION ==================== */
|
||||
TabNavigation, QWidget#tab_navigation {{
|
||||
background-color: {theme['nav_bg']};
|
||||
border-bottom: 1px solid {theme['nav_border']};
|
||||
}}
|
||||
|
||||
TabNavigation QPushButton {{
|
||||
background-color: {theme['nav_item']};
|
||||
color: {theme['nav_text']};
|
||||
border: none;
|
||||
border-radius: 0;
|
||||
padding: 6px {spacing['lg']} {spacing['sm']};
|
||||
font-weight: {weights['medium']};
|
||||
min-height: 48px;
|
||||
text-transform: none;
|
||||
}}
|
||||
|
||||
TabNavigation QPushButton:hover {{
|
||||
background-color: {theme['nav_item_hover']};
|
||||
color: {theme['text_primary']};
|
||||
}}
|
||||
|
||||
TabNavigation QPushButton:checked {{
|
||||
background-color: {theme['nav_item_active']};
|
||||
color: {theme['nav_text_active']};
|
||||
border-bottom: 2px solid {theme['accent']};
|
||||
}}
|
||||
|
||||
/* Tab Badge */
|
||||
TabNavigation QLabel#badge {{
|
||||
background-color: {theme['accent']};
|
||||
color: {theme['btn_primary_text']};
|
||||
padding: 2px 6px;
|
||||
border-radius: 10px;
|
||||
font-size: {sizes['xs']};
|
||||
font-weight: {weights['semibold']};
|
||||
}}
|
||||
|
||||
/* ==================== ACCOUNTS OVERVIEW ==================== */
|
||||
AccountsOverviewView, QWidget#accounts_overview {{
|
||||
background-color: {theme['bg_secondary']};
|
||||
}}
|
||||
|
||||
/* Filter Sidebar */
|
||||
QWidget#filter_sidebar {{
|
||||
background-color: {theme['surface_sidebar']};
|
||||
border-right: 1px solid {theme['border_default']};
|
||||
}}
|
||||
|
||||
/* Filter Buttons */
|
||||
QPushButton#filter_button {{
|
||||
background-color: transparent;
|
||||
color: {theme['text_secondary']};
|
||||
border: none;
|
||||
padding: {spacing['sm']} {spacing['md']};
|
||||
text-align: left;
|
||||
font-size: {sizes['base']};
|
||||
}}
|
||||
|
||||
QPushButton#filter_button:hover {{
|
||||
background-color: {theme['bg_hover']};
|
||||
color: {theme['text_primary']};
|
||||
}}
|
||||
|
||||
QPushButton#filter_button[selected="true"] {{
|
||||
background-color: {theme['bg_selected']};
|
||||
color: {theme['text_accent']};
|
||||
border-left: 3px solid {theme['accent']};
|
||||
}}
|
||||
|
||||
/* Content Area */
|
||||
QWidget#accounts_content {{
|
||||
background-color: {theme['bg_secondary']};
|
||||
}}
|
||||
|
||||
/* ==================== ACCOUNT CARDS ==================== */
|
||||
AccountCard, QFrame#account_card {{
|
||||
background-color: {theme['surface_card']};
|
||||
border: 1px solid {theme['border_subtle']};
|
||||
border-radius: {radius['lg']};
|
||||
padding: {spacing['md']};
|
||||
}}
|
||||
|
||||
AccountCard:hover, QFrame#account_card:hover {{
|
||||
border: 1px solid {theme['accent']};
|
||||
}}
|
||||
|
||||
/* Account Card Buttons */
|
||||
QPushButton#login_button {{
|
||||
background-color: {theme['accent']};
|
||||
color: {theme['btn_primary_text']};
|
||||
border-radius: {radius['md']};
|
||||
padding: {spacing['sm']} {spacing['md']};
|
||||
font-size: {sizes['sm']};
|
||||
min-height: 36px;
|
||||
}}
|
||||
|
||||
QPushButton#login_button:hover {{
|
||||
background-color: {theme['accent_hover']};
|
||||
}}
|
||||
|
||||
QPushButton#export_button {{
|
||||
background-color: {theme['success']};
|
||||
color: #FFFFFF;
|
||||
border-radius: {radius['md']};
|
||||
padding: {spacing['sm']} {spacing['md']};
|
||||
font-size: {sizes['sm']};
|
||||
min-height: 36px;
|
||||
}}
|
||||
|
||||
QPushButton#delete_button {{
|
||||
background-color: {theme['btn_danger_bg']};
|
||||
color: {theme['btn_danger_text']};
|
||||
border-radius: {radius['md']};
|
||||
padding: {spacing['sm']} {spacing['md']};
|
||||
font-size: {sizes['sm']};
|
||||
min-height: 36px;
|
||||
}}
|
||||
|
||||
/* ==================== INPUT FIELDS ==================== */
|
||||
QLineEdit, QSpinBox, QTextEdit, QPlainTextEdit {{
|
||||
background-color: {theme['input_bg']};
|
||||
color: {theme['text_primary']};
|
||||
border: 1px solid {theme['input_border']};
|
||||
border-radius: {radius['md']};
|
||||
padding: {spacing['sm']} {spacing['md']};
|
||||
font-size: {sizes['base']};
|
||||
}}
|
||||
|
||||
QLineEdit:focus, QSpinBox:focus, QTextEdit:focus, QPlainTextEdit:focus {{
|
||||
background-color: {theme['input_focus_bg']};
|
||||
border: 2px solid {theme['input_focus_border']};
|
||||
outline: none;
|
||||
}}
|
||||
|
||||
QLineEdit:disabled, QSpinBox:disabled, QTextEdit:disabled {{
|
||||
background-color: {theme['bg_tertiary']};
|
||||
color: {theme['text_tertiary']};
|
||||
}}
|
||||
|
||||
/* ==================== COMBOBOX ==================== */
|
||||
QComboBox {{
|
||||
background-color: {theme['input_bg']};
|
||||
color: {theme['text_primary']};
|
||||
border: 1px solid {theme['input_border']};
|
||||
border-radius: {radius['md']};
|
||||
padding: {spacing['sm']} {spacing['md']};
|
||||
min-height: 32px;
|
||||
}}
|
||||
|
||||
QComboBox:hover {{
|
||||
border: 1px solid {theme['accent']};
|
||||
}}
|
||||
|
||||
QComboBox:focus {{
|
||||
border: 2px solid {theme['input_focus_border']};
|
||||
}}
|
||||
|
||||
QComboBox::drop-down {{
|
||||
border: none;
|
||||
width: 20px;
|
||||
background-color: transparent;
|
||||
}}
|
||||
|
||||
QComboBox::down-arrow {{
|
||||
image: none;
|
||||
border-left: 5px solid transparent;
|
||||
border-right: 5px solid transparent;
|
||||
border-top: 5px solid {theme['accent']};
|
||||
width: 0;
|
||||
height: 0;
|
||||
margin-right: 5px;
|
||||
}}
|
||||
|
||||
QComboBox QAbstractItemView {{
|
||||
background-color: {theme['surface_card']};
|
||||
border: 1px solid {theme['border_default']};
|
||||
border-radius: {radius['md']};
|
||||
selection-background-color: {theme['bg_selected']};
|
||||
selection-color: {theme['text_accent']};
|
||||
color: {theme['text_primary']};
|
||||
}}
|
||||
|
||||
/* ==================== TABLES ==================== */
|
||||
QTableWidget {{
|
||||
background-color: {theme['surface_card']};
|
||||
alternate-background-color: {theme['bg_secondary']};
|
||||
gridline-color: {theme['border_subtle']};
|
||||
border: none;
|
||||
color: {theme['text_primary']};
|
||||
}}
|
||||
|
||||
QTableWidget::item {{
|
||||
padding: {spacing['sm']} {spacing['md']};
|
||||
color: {theme['text_primary']};
|
||||
}}
|
||||
|
||||
QTableWidget::item:selected {{
|
||||
background-color: {theme['bg_selected']};
|
||||
color: {theme['text_accent']};
|
||||
}}
|
||||
|
||||
QHeaderView::section {{
|
||||
background-color: {theme['bg_tertiary']};
|
||||
color: {theme['text_primary']};
|
||||
padding: {spacing['sm']} {spacing['md']};
|
||||
border: none;
|
||||
font-weight: {weights['semibold']};
|
||||
text-transform: uppercase;
|
||||
font-size: {sizes['sm']};
|
||||
letter-spacing: 0.5px;
|
||||
}}
|
||||
|
||||
/* ==================== SCROLL AREAS ==================== */
|
||||
QScrollArea {{
|
||||
background-color: {theme['bg_primary']};
|
||||
border: none;
|
||||
}}
|
||||
|
||||
QScrollArea > QWidget > QWidget {{
|
||||
background-color: {theme['bg_primary']};
|
||||
}}
|
||||
|
||||
/* ==================== SCROLLBARS ==================== */
|
||||
QScrollBar:vertical {{
|
||||
background-color: {theme['scrollbar_bg']};
|
||||
width: 8px;
|
||||
border-radius: 4px;
|
||||
}}
|
||||
|
||||
QScrollBar::handle:vertical {{
|
||||
background-color: {theme['scrollbar_handle']};
|
||||
min-height: 20px;
|
||||
border-radius: 4px;
|
||||
}}
|
||||
|
||||
QScrollBar::handle:vertical:hover {{
|
||||
background-color: {theme['scrollbar_handle_hover']};
|
||||
}}
|
||||
|
||||
QScrollBar:horizontal {{
|
||||
background-color: {theme['scrollbar_bg']};
|
||||
height: 8px;
|
||||
border-radius: 4px;
|
||||
}}
|
||||
|
||||
QScrollBar::handle:horizontal {{
|
||||
background-color: {theme['scrollbar_handle']};
|
||||
min-width: 20px;
|
||||
border-radius: 4px;
|
||||
}}
|
||||
|
||||
QScrollBar::handle:horizontal:hover {{
|
||||
background-color: {theme['scrollbar_handle_hover']};
|
||||
}}
|
||||
|
||||
QScrollBar::add-line, QScrollBar::sub-line {{
|
||||
border: none;
|
||||
background: none;
|
||||
}}
|
||||
|
||||
/* ==================== PROGRESS BAR ==================== */
|
||||
QProgressBar {{
|
||||
background-color: {theme['bg_tertiary']};
|
||||
border: none;
|
||||
border-radius: 4px;
|
||||
height: 8px;
|
||||
text-align: center;
|
||||
}}
|
||||
|
||||
QProgressBar::chunk {{
|
||||
background-color: {theme['accent']};
|
||||
border-radius: 4px;
|
||||
}}
|
||||
|
||||
/* ==================== TOOLTIPS ==================== */
|
||||
QToolTip {{
|
||||
background-color: {theme['bg_tertiary']};
|
||||
color: {theme['text_primary']};
|
||||
border: 1px solid {theme['border_default']};
|
||||
border-radius: {radius['md']};
|
||||
padding: {spacing['sm']} {spacing['sm']};
|
||||
font-size: {sizes['sm']};
|
||||
}}
|
||||
|
||||
/* ==================== MESSAGE BOXES ==================== */
|
||||
QMessageBox {{
|
||||
background-color: {theme['bg_primary']};
|
||||
}}
|
||||
|
||||
QMessageBox QLabel {{
|
||||
color: {theme['text_primary']};
|
||||
}}
|
||||
|
||||
QMessageBox QPushButton {{
|
||||
background-color: {theme['bg_tertiary']};
|
||||
color: {theme['text_primary']};
|
||||
border: 1px solid {theme['border_default']};
|
||||
border-radius: 4px;
|
||||
padding: 6px 20px;
|
||||
min-width: 80px;
|
||||
min-height: 26px;
|
||||
font-weight: {weights['medium']};
|
||||
text-transform: none;
|
||||
}}
|
||||
|
||||
QMessageBox QPushButton:hover {{
|
||||
background-color: {theme['bg_hover']};
|
||||
border-color: {theme['accent']};
|
||||
}}
|
||||
|
||||
/* Delete Buttons in Message Boxes */
|
||||
QMessageBox QPushButton[text="Löschen"], QMessageBox QPushButton[text="Delete"] {{
|
||||
background-color: {theme['btn_danger_bg']};
|
||||
color: {theme['btn_danger_text']};
|
||||
border: none;
|
||||
}}
|
||||
|
||||
/* ==================== STATUS BAR ==================== */
|
||||
QStatusBar {{
|
||||
background-color: {theme['bg_secondary']};
|
||||
color: {theme['text_secondary']};
|
||||
font-size: {sizes['sm']};
|
||||
padding: {spacing['sm']};
|
||||
border-top: 1px solid {theme['border_subtle']};
|
||||
}}
|
||||
|
||||
/* ==================== MENU BAR ==================== */
|
||||
QMenuBar {{
|
||||
background-color: {theme['bg_primary']};
|
||||
color: {theme['text_primary']};
|
||||
padding: 4px;
|
||||
}}
|
||||
|
||||
QMenuBar::item {{
|
||||
padding: {spacing['sm']} {spacing['md']};
|
||||
background-color: transparent;
|
||||
color: {theme['text_primary']};
|
||||
}}
|
||||
|
||||
QMenuBar::item:selected {{
|
||||
background-color: {theme['bg_hover']};
|
||||
color: {theme['text_accent']};
|
||||
}}
|
||||
|
||||
/* Logo button in menu bar */
|
||||
QPushButton#logo_button {{
|
||||
background-color: transparent;
|
||||
border: none;
|
||||
padding: 5px;
|
||||
}}
|
||||
|
||||
QPushButton#logo_button:hover {{
|
||||
background-color: {theme['bg_hover']};
|
||||
border-radius: {radius['sm']};
|
||||
}}
|
||||
|
||||
QWidget#menubar_right_container {{
|
||||
background: transparent;
|
||||
}}
|
||||
|
||||
/* ==================== CHECKBOXES & RADIO BUTTONS ==================== */
|
||||
QCheckBox, QRadioButton {{
|
||||
spacing: 8px;
|
||||
color: {theme['text_primary']};
|
||||
}}
|
||||
|
||||
QCheckBox::indicator, QRadioButton::indicator {{
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
border: 2px solid {theme['border_strong']};
|
||||
background-color: {theme['input_bg']};
|
||||
}}
|
||||
|
||||
QCheckBox::indicator {{
|
||||
border-radius: 4px;
|
||||
}}
|
||||
|
||||
QRadioButton::indicator {{
|
||||
border-radius: 10px;
|
||||
}}
|
||||
|
||||
QCheckBox::indicator:checked, QRadioButton::indicator:checked {{
|
||||
background-color: {theme['accent']};
|
||||
border-color: {theme['accent']};
|
||||
}}
|
||||
|
||||
/* ==================== GROUP BOXES ==================== */
|
||||
QGroupBox {{
|
||||
background-color: {theme['surface_card']};
|
||||
border: 1px solid {theme['border_default']};
|
||||
border-radius: {radius['xl']};
|
||||
padding: {spacing['xl']};
|
||||
margin-top: {spacing['md']};
|
||||
font-family: {fonts['primary']};
|
||||
font-weight: {weights['semibold']};
|
||||
color: {theme['text_primary']};
|
||||
}}
|
||||
|
||||
QGroupBox::title {{
|
||||
color: {theme['text_accent']};
|
||||
font-size: {sizes['lg']};
|
||||
subcontrol-origin: margin;
|
||||
left: {spacing['md']};
|
||||
padding: 0 {spacing['sm']};
|
||||
background-color: {theme['surface_card']};
|
||||
}}
|
||||
|
||||
/* ==================== TABS ==================== */
|
||||
QTabWidget::pane {{
|
||||
background-color: {theme['bg_secondary']};
|
||||
border: none;
|
||||
}}
|
||||
|
||||
QTabBar::tab {{
|
||||
background-color: transparent;
|
||||
color: {theme['text_secondary']};
|
||||
padding: {spacing['sm']} {spacing['lg']};
|
||||
font-size: {sizes['base']};
|
||||
font-weight: {weights['medium']};
|
||||
border: none;
|
||||
}}
|
||||
|
||||
QTabBar::tab:hover {{
|
||||
background-color: {theme['bg_hover']};
|
||||
color: {theme['text_primary']};
|
||||
}}
|
||||
|
||||
QTabBar::tab:selected {{
|
||||
color: {theme['text_accent']};
|
||||
background-color: transparent;
|
||||
border-bottom: 2px solid {theme['accent']};
|
||||
font-weight: {weights['semibold']};
|
||||
}}
|
||||
|
||||
/* ==================== DIALOGS ==================== */
|
||||
QDialog {{
|
||||
background-color: {theme['surface_modal']};
|
||||
color: {theme['text_primary']};
|
||||
}}
|
||||
|
||||
/* ==================== LOG OUTPUT ==================== */
|
||||
QTextEdit#log_output {{
|
||||
background-color: {theme['bg_tertiary']};
|
||||
color: {theme['text_primary']};
|
||||
font-family: {fonts['monospace']};
|
||||
font-size: {sizes['sm']};
|
||||
border: none;
|
||||
border-radius: {radius['md']};
|
||||
padding: {spacing['md']};
|
||||
}}
|
||||
|
||||
/* ==================== BADGES ==================== */
|
||||
QLabel#badge {{
|
||||
background-color: {theme['bg_tertiary']};
|
||||
color: {theme['text_primary']};
|
||||
padding: 4px 12px;
|
||||
border-radius: 12px;
|
||||
font-size: {sizes['xs']};
|
||||
font-weight: {weights['semibold']};
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.5px;
|
||||
}}
|
||||
|
||||
QLabel#badge_primary {{
|
||||
background-color: {theme['accent']};
|
||||
color: {theme['btn_primary_text']};
|
||||
}}
|
||||
|
||||
QLabel#badge_success {{
|
||||
background-color: {theme['success']};
|
||||
color: #FFFFFF;
|
||||
}}
|
||||
|
||||
QLabel#badge_warning {{
|
||||
background-color: {theme['warning']};
|
||||
color: #000000;
|
||||
}}
|
||||
|
||||
QLabel#badge_error {{
|
||||
background-color: {theme['error']};
|
||||
color: #FFFFFF;
|
||||
}}
|
||||
|
||||
/* ==================== ACCOUNTS OVERVIEW SPECIFIC ==================== */
|
||||
QLabel#platform_header {{
|
||||
color: {theme['text_primary']};
|
||||
padding: 8px 0;
|
||||
font-family: {fonts['primary']};
|
||||
font-size: {sizes['lg']};
|
||||
font-weight: {weights['semibold']};
|
||||
}}
|
||||
|
||||
QPushButton#delete_confirm_button {{
|
||||
background-color: {theme['error']};
|
||||
color: #FFFFFF;
|
||||
border: 1px solid {theme['error']};
|
||||
border-radius: {radius['sm']};
|
||||
padding: 6px 20px;
|
||||
min-width: 80px;
|
||||
min-height: 26px;
|
||||
font-weight: {weights['medium']};
|
||||
}}
|
||||
|
||||
QPushButton#delete_confirm_button:hover {{
|
||||
background-color: {theme['error_dark']};
|
||||
border-color: {theme['error_dark']};
|
||||
}}
|
||||
|
||||
QPushButton#delete_confirm_button:pressed {{
|
||||
background-color: {theme['error_dark']};
|
||||
}}
|
||||
|
||||
/* ==================== ACCOUNT CARD ==================== */
|
||||
QFrame#accountCard {{
|
||||
background-color: {theme['surface_card']};
|
||||
border: 2px solid {theme['border_default']};
|
||||
border-radius: {radius['md']};
|
||||
padding: 16px;
|
||||
}}
|
||||
|
||||
QFrame#accountCard:hover {{
|
||||
border: 2px solid {theme['accent']};
|
||||
}}
|
||||
|
||||
QFrame#accountCard[status="active"] {{
|
||||
background-color: {theme['success_bg']};
|
||||
border: 2px solid {theme['success']};
|
||||
}}
|
||||
|
||||
QFrame#accountCard[status="active"]:hover {{
|
||||
border: 2px solid {theme['success']};
|
||||
}}
|
||||
|
||||
QFrame#accountCard[status="inactive"] {{
|
||||
background-color: {theme['error_bg']};
|
||||
border: 2px solid {theme['error']};
|
||||
}}
|
||||
|
||||
QFrame#accountCard[status="inactive"]:hover {{
|
||||
border: 2px solid {theme['error_dark']};
|
||||
}}
|
||||
|
||||
QLabel#account_username {{
|
||||
color: {theme['text_primary']};
|
||||
font-family: {fonts['primary']};
|
||||
font-size: 16px;
|
||||
font-weight: {weights['semibold']};
|
||||
}}
|
||||
|
||||
QLabel#account_detail_text {{
|
||||
color: {theme['text_secondary']};
|
||||
font-size: {sizes['sm']};
|
||||
font-family: {fonts['primary']};
|
||||
}}
|
||||
|
||||
QLabel#account_date_text {{
|
||||
color: {theme['text_tertiary']};
|
||||
font-size: {sizes['xs']};
|
||||
font-family: {fonts['primary']};
|
||||
}}
|
||||
|
||||
QPushButton#account_icon_btn {{
|
||||
background: transparent;
|
||||
border: none;
|
||||
padding: 2px;
|
||||
min-width: 20px;
|
||||
max-width: 20px;
|
||||
min-height: 20px;
|
||||
max-height: 20px;
|
||||
}}
|
||||
|
||||
QPushButton#account_icon_btn:hover {{
|
||||
background-color: {theme['bg_hover']};
|
||||
border-radius: {radius['sm']};
|
||||
}}
|
||||
|
||||
QPushButton#account_login_btn {{
|
||||
background-color: {theme['accent']};
|
||||
color: {theme['btn_primary_text']};
|
||||
border: none;
|
||||
border-radius: {radius['sm']};
|
||||
padding: 6px 16px;
|
||||
font-size: {sizes['xs']};
|
||||
font-weight: {weights['medium']};
|
||||
font-family: {fonts['primary']};
|
||||
min-width: 60px;
|
||||
}}
|
||||
|
||||
QPushButton#account_login_btn:hover {{
|
||||
background-color: {theme['accent_hover']};
|
||||
}}
|
||||
|
||||
QPushButton#account_login_btn:pressed {{
|
||||
background-color: {theme['accent_pressed']};
|
||||
}}
|
||||
|
||||
QPushButton#account_export_btn {{
|
||||
background-color: {theme['success']};
|
||||
color: #FFFFFF;
|
||||
border: none;
|
||||
border-radius: {radius['sm']};
|
||||
padding: 4px 12px;
|
||||
font-size: {sizes['xs']};
|
||||
font-weight: {weights['medium']};
|
||||
font-family: {fonts['primary']};
|
||||
min-width: 120px;
|
||||
min-height: 36px;
|
||||
text-align: center;
|
||||
}}
|
||||
|
||||
QPushButton#account_export_btn:hover {{
|
||||
background-color: {theme['success']};
|
||||
opacity: 0.9;
|
||||
}}
|
||||
|
||||
QPushButton#account_export_btn:pressed {{
|
||||
background-color: {theme['success']};
|
||||
opacity: 0.8;
|
||||
}}
|
||||
|
||||
QPushButton#account_delete_btn {{
|
||||
background-color: {theme['error']};
|
||||
color: #FFFFFF;
|
||||
border: none;
|
||||
border-radius: {radius['sm']};
|
||||
padding: 8px 16px;
|
||||
font-size: {sizes['xs']};
|
||||
font-weight: {weights['medium']};
|
||||
font-family: {fonts['primary']};
|
||||
min-width: 90px;
|
||||
}}
|
||||
|
||||
QPushButton#account_delete_btn:hover {{
|
||||
background-color: {theme['error_dark']};
|
||||
}}
|
||||
|
||||
QPushButton#account_delete_btn:pressed {{
|
||||
background-color: {theme['error_dark']};
|
||||
opacity: 0.9;
|
||||
}}
|
||||
"""
|
||||
|
||||
return qss
|
||||
247
themes/theme_config.py
Normale Datei
247
themes/theme_config.py
Normale Datei
@ -0,0 +1,247 @@
|
||||
"""
|
||||
Theme Configuration - Single Source of Truth for all UI Colors and Styles
|
||||
Based on IntelSight Corporate Design System
|
||||
"""
|
||||
|
||||
class ThemeConfig:
|
||||
"""
|
||||
Centralized theme configuration.
|
||||
All colors, fonts, and styling values should be defined here.
|
||||
NO hardcoded colors in widgets!
|
||||
"""
|
||||
|
||||
THEMES = {
|
||||
'light': {
|
||||
# ========== BACKGROUNDS ==========
|
||||
'bg_primary': '#FFFFFF', # Main window background
|
||||
'bg_secondary': '#F8FAFC', # Content areas, cards
|
||||
'bg_tertiary': '#F5F7FF', # Input fields, subtle backgrounds
|
||||
'bg_hover': '#F0F4FF', # Hover states
|
||||
'bg_selected': '#E8EBFF', # Selected items
|
||||
|
||||
# ========== SURFACES ==========
|
||||
'surface_card': '#FFFFFF', # Card backgrounds
|
||||
'surface_modal': '#FFFFFF', # Modal backgrounds
|
||||
'surface_sidebar': '#FAFBFC', # Sidebar background
|
||||
|
||||
# ========== TEXT ==========
|
||||
'text_primary': '#1E1E1E', # Main text
|
||||
'text_secondary': '#666666', # Secondary text
|
||||
'text_tertiary': '#999999', # Disabled/hint text
|
||||
'text_accent': '#232D53', # Headers, important text
|
||||
|
||||
# ========== BRAND COLORS ==========
|
||||
'accent': '#0099CC', # Primary accent (buttons, links)
|
||||
'accent_hover': '#0078A3', # Accent hover state
|
||||
'accent_pressed': '#005C7A', # Accent pressed state
|
||||
|
||||
# ========== PLATFORM BUTTONS ==========
|
||||
'platform_bg': '#F5F7FF', # Platform button background
|
||||
'platform_hover': '#E8EBFF', # Platform button hover
|
||||
'platform_pressed': '#DCE2FF', # Platform button pressed
|
||||
'platform_border': 'transparent', # Platform button border
|
||||
'platform_border_hover': '#0099CC', # Platform button border hover
|
||||
'platform_label': '#232D53', # Platform name text
|
||||
|
||||
# ========== NAVIGATION ==========
|
||||
'nav_bg': '#FFFFFF', # Navigation background
|
||||
'nav_border': '#E2E8F0', # Navigation borders
|
||||
'nav_item': 'transparent', # Nav item background
|
||||
'nav_item_hover': '#F7FAFC', # Nav item hover
|
||||
'nav_item_active': '#E6F2FF', # Nav item active
|
||||
'nav_text': '#2D3748', # Nav text
|
||||
'nav_text_active': '#1E40AF', # Nav active text
|
||||
|
||||
# ========== INPUTS ==========
|
||||
'input_bg': '#F5F7FF', # Input background
|
||||
'input_border': '#E0E6FF', # Input border
|
||||
'input_focus_bg': '#FFFFFF', # Input focused background
|
||||
'input_focus_border': '#0099CC', # Input focused border
|
||||
|
||||
# ========== BUTTONS ==========
|
||||
'btn_primary_bg': '#0099CC', # Primary button
|
||||
'btn_primary_text': '#FFFFFF', # Primary button text
|
||||
'btn_secondary_bg': 'transparent', # Secondary button
|
||||
'btn_secondary_text': '#232D53', # Secondary button text
|
||||
'btn_secondary_border': '#232D53', # Secondary button border
|
||||
'btn_danger_bg': '#F44336', # Danger button
|
||||
'btn_danger_text': '#FFFFFF', # Danger button text
|
||||
|
||||
# ========== STATUS COLORS ==========
|
||||
'success': '#4CAF50', # Success states
|
||||
'success_bg': '#E8F5E9', # Success background
|
||||
'warning': '#FFC107', # Warning states
|
||||
'warning_bg': '#FFF8E1', # Warning background
|
||||
'error': '#F44336', # Error states
|
||||
'error_dark': '#D32F2F', # Error dark for hover
|
||||
'error_bg': '#FFEBEE', # Error background
|
||||
'info': '#2196F3', # Info states
|
||||
'info_bg': '#E3F2FD', # Info background
|
||||
|
||||
# ========== BORDERS ==========
|
||||
'border_default': '#E0E6FF', # Default borders
|
||||
'border_subtle': '#F0F0F0', # Subtle borders
|
||||
'border_strong': '#CCCCCC', # Strong borders
|
||||
|
||||
# ========== SHADOWS ==========
|
||||
'shadow_sm': '0 1px 3px rgba(0,0,0,0.12)',
|
||||
'shadow_md': '0 4px 6px rgba(0,0,0,0.15)',
|
||||
'shadow_lg': '0 10px 20px rgba(0,0,0,0.15)',
|
||||
|
||||
# ========== SCROLLBAR ==========
|
||||
'scrollbar_bg': '#F5F7FF',
|
||||
'scrollbar_handle': '#0099CC',
|
||||
'scrollbar_handle_hover': '#0078A3',
|
||||
|
||||
# ========== LOGO ==========
|
||||
'logo_path': 'intelsight-logo.svg',
|
||||
},
|
||||
|
||||
'dark': {
|
||||
# ========== BACKGROUNDS ==========
|
||||
'bg_primary': '#000000', # Main window background
|
||||
'bg_secondary': '#0A0A0A', # Content areas
|
||||
'bg_tertiary': '#1A1F3A', # Cards, elevated surfaces
|
||||
'bg_hover': '#232D53', # Hover states
|
||||
'bg_selected': '#2A3560', # Selected items
|
||||
|
||||
# ========== SURFACES ==========
|
||||
'surface_card': '#1A1F3A', # Card backgrounds
|
||||
'surface_modal': '#0A0A0A', # Modal backgrounds
|
||||
'surface_sidebar': '#0A0A0A', # Sidebar background
|
||||
|
||||
# ========== TEXT ==========
|
||||
'text_primary': '#FFFFFF', # Main text
|
||||
'text_secondary': 'rgba(255,255,255,0.7)', # Secondary text
|
||||
'text_tertiary': 'rgba(255,255,255,0.5)', # Disabled/hint text
|
||||
'text_accent': '#00D4FF', # Headers, important text
|
||||
|
||||
# ========== BRAND COLORS ==========
|
||||
'accent': '#00D4FF', # Primary accent (buttons, links)
|
||||
'accent_hover': '#00B8E6', # Accent hover state
|
||||
'accent_pressed': '#0099CC', # Accent pressed state
|
||||
|
||||
# ========== PLATFORM BUTTONS ==========
|
||||
'platform_bg': '#1A1F3A', # Platform button background
|
||||
'platform_hover': '#232D53', # Platform button hover
|
||||
'platform_pressed': '#2A3560', # Platform button pressed
|
||||
'platform_border': 'transparent', # Platform button border
|
||||
'platform_border_hover': '#00D4FF', # Platform button border hover
|
||||
'platform_label': '#FFFFFF', # Platform name text
|
||||
|
||||
# ========== NAVIGATION ==========
|
||||
'nav_bg': '#0A0A0A', # Navigation background
|
||||
'nav_border': 'rgba(255,255,255,0.1)', # Navigation borders
|
||||
'nav_item': 'transparent', # Nav item background
|
||||
'nav_item_hover': 'rgba(35,45,83,0.3)', # Nav item hover
|
||||
'nav_item_active': '#232D53', # Nav item active
|
||||
'nav_text': 'rgba(255,255,255,0.6)', # Nav text
|
||||
'nav_text_active': '#00D4FF', # Nav active text
|
||||
|
||||
# ========== INPUTS ==========
|
||||
'input_bg': '#232D53', # Input background
|
||||
'input_border': 'transparent', # Input border
|
||||
'input_focus_bg': '#2A3560', # Input focused background
|
||||
'input_focus_border': '#00D4FF', # Input focused border
|
||||
|
||||
# ========== BUTTONS ==========
|
||||
'btn_primary_bg': '#00D4FF', # Primary button
|
||||
'btn_primary_text': '#000000', # Primary button text
|
||||
'btn_secondary_bg': 'transparent', # Secondary button
|
||||
'btn_secondary_text': '#FFFFFF', # Secondary button text
|
||||
'btn_secondary_border': '#232D53', # Secondary button border
|
||||
'btn_danger_bg': '#FF4444', # Danger button
|
||||
'btn_danger_text': '#FFFFFF', # Danger button text
|
||||
|
||||
# ========== STATUS COLORS ==========
|
||||
'success': '#4CAF50', # Success states
|
||||
'success_bg': 'rgba(76,175,80,0.2)', # Success background
|
||||
'warning': '#FFC107', # Warning states
|
||||
'warning_bg': 'rgba(255,193,7,0.2)', # Warning background
|
||||
'error': '#FF4444', # Error states
|
||||
'error_dark': '#CC0000', # Error dark for hover
|
||||
'error_bg': 'rgba(255,68,68,0.2)', # Error background
|
||||
'info': '#2196F3', # Info states
|
||||
'info_bg': 'rgba(33,150,243,0.2)', # Info background
|
||||
|
||||
# ========== BORDERS ==========
|
||||
'border_default': 'rgba(255,255,255,0.1)', # Default borders
|
||||
'border_subtle': 'rgba(255,255,255,0.05)', # Subtle borders
|
||||
'border_strong': 'rgba(255,255,255,0.2)', # Strong borders
|
||||
|
||||
# ========== SHADOWS ==========
|
||||
'shadow_sm': '0 1px 3px rgba(0,0,0,0.3)',
|
||||
'shadow_md': '0 4px 6px rgba(0,0,0,0.4)',
|
||||
'shadow_lg': '0 10px 20px rgba(0,0,0,0.5)',
|
||||
|
||||
# ========== SCROLLBAR ==========
|
||||
'scrollbar_bg': '#1A1F3A',
|
||||
'scrollbar_handle': '#00D4FF',
|
||||
'scrollbar_handle_hover': '#00B8E6',
|
||||
|
||||
# ========== LOGO ==========
|
||||
'logo_path': 'intelsight-dark.svg',
|
||||
}
|
||||
}
|
||||
|
||||
@classmethod
|
||||
def get_theme(cls, theme_name: str) -> dict:
|
||||
"""Get theme configuration by name"""
|
||||
return cls.THEMES.get(theme_name, cls.THEMES['light'])
|
||||
|
||||
@classmethod
|
||||
def get_color(cls, theme_name: str, color_key: str) -> str:
|
||||
"""Get specific color from theme"""
|
||||
theme = cls.get_theme(theme_name)
|
||||
return theme.get(color_key, '#000000')
|
||||
|
||||
# ========== TYPOGRAPHY ==========
|
||||
FONTS = {
|
||||
'primary': "'Poppins', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif",
|
||||
'secondary': "-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Arial, sans-serif",
|
||||
'monospace': "'SF Mono', Monaco, 'Cascadia Code', 'Roboto Mono', monospace",
|
||||
}
|
||||
|
||||
FONT_SIZES = {
|
||||
'xs': '11px',
|
||||
'sm': '12px',
|
||||
'base': '14px',
|
||||
'lg': '16px',
|
||||
'xl': '18px',
|
||||
'2xl': '24px',
|
||||
'3xl': '32px',
|
||||
}
|
||||
|
||||
FONT_WEIGHTS = {
|
||||
'regular': '400',
|
||||
'medium': '500',
|
||||
'semibold': '600',
|
||||
'bold': '700',
|
||||
}
|
||||
|
||||
# ========== SPACING ==========
|
||||
SPACING = {
|
||||
'xs': '4px',
|
||||
'sm': '8px',
|
||||
'md': '16px',
|
||||
'lg': '24px',
|
||||
'xl': '32px',
|
||||
'2xl': '40px',
|
||||
}
|
||||
|
||||
# ========== BORDER RADIUS ==========
|
||||
RADIUS = {
|
||||
'sm': '4px',
|
||||
'md': '8px',
|
||||
'lg': '12px',
|
||||
'xl': '16px',
|
||||
'round': '24px',
|
||||
'full': '50%',
|
||||
}
|
||||
|
||||
# ========== TRANSITIONS ==========
|
||||
TRANSITIONS = {
|
||||
'fast': '0.2s ease',
|
||||
'normal': '0.3s ease',
|
||||
'slow': '0.5s ease',
|
||||
}
|
||||
In neuem Issue referenzieren
Einen Benutzer sperren