|
|
|
@@ -21,8 +21,71 @@ def load_colors(theme: str = "dark") -> dict[str, str]:
|
|
|
|
|
return {str(k): str(v) for k, v in data.items()}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def _arrow_icon_cache_dir() -> Path:
|
|
|
|
|
import tempfile
|
|
|
|
|
|
|
|
|
|
path = Path(tempfile.gettempdir()) / "orisys_app_theme_icons"
|
|
|
|
|
path.mkdir(parents=True, exist_ok=True)
|
|
|
|
|
return path
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@lru_cache(maxsize=16)
|
|
|
|
|
def _paint_arrow(kind: str, fill: str) -> str:
|
|
|
|
|
"""Draw a small chevron PNG on demand; return its path ('' on failure)."""
|
|
|
|
|
try:
|
|
|
|
|
from PyQt5.QtCore import QPointF, Qt
|
|
|
|
|
from PyQt5.QtGui import QColor, QImage, QPainter, QPolygonF
|
|
|
|
|
except Exception: # pragma: no cover - headless import failure
|
|
|
|
|
return ""
|
|
|
|
|
try:
|
|
|
|
|
size = 14
|
|
|
|
|
safe = fill.strip().lstrip("#").replace("/", "")
|
|
|
|
|
path = _arrow_icon_cache_dir() / f"chevron_{kind}_{safe}.png"
|
|
|
|
|
if path.is_file():
|
|
|
|
|
return str(path)
|
|
|
|
|
image = QImage(size, size, QImage.Format_ARGB32)
|
|
|
|
|
image.fill(Qt.transparent)
|
|
|
|
|
painter = QPainter(image)
|
|
|
|
|
painter.setRenderHint(QPainter.Antialiasing, True)
|
|
|
|
|
painter.setBrush(QColor(fill))
|
|
|
|
|
painter.setPen(Qt.NoPen)
|
|
|
|
|
half = size / 2.0
|
|
|
|
|
top = size * 0.32
|
|
|
|
|
bottom = size * 0.68
|
|
|
|
|
if kind == "down":
|
|
|
|
|
points = [QPointF(size * 0.18, top), QPointF(size * 0.82, top), QPointF(half, bottom)]
|
|
|
|
|
else:
|
|
|
|
|
points = [
|
|
|
|
|
QPointF(size * 0.18, bottom),
|
|
|
|
|
QPointF(size * 0.82, bottom),
|
|
|
|
|
QPointF(half, top),
|
|
|
|
|
]
|
|
|
|
|
painter.drawPolygon(QPolygonF(points))
|
|
|
|
|
painter.end()
|
|
|
|
|
if not image.save(str(path), "PNG"):
|
|
|
|
|
return ""
|
|
|
|
|
return str(path)
|
|
|
|
|
except Exception: # pragma: no cover - never break theming
|
|
|
|
|
return ""
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def _arrow_image(kind: str, fill: str, size: int = 14) -> str:
|
|
|
|
|
path = _paint_arrow(kind, fill)
|
|
|
|
|
if not path:
|
|
|
|
|
return ""
|
|
|
|
|
return 'url("' + path.replace("\\", "/") + '")'
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def build_qss(theme: str = "dark") -> str:
|
|
|
|
|
c = load_colors(theme)
|
|
|
|
|
accent_text = c.get("accent_text", "#FFFFFF")
|
|
|
|
|
toolbar_bg = c.get("toolbar_bg", c["panel_bg"])
|
|
|
|
|
dim = c.get("text_secondary", "#888888")
|
|
|
|
|
muted = c.get("text_muted", "#6f757c")
|
|
|
|
|
arrow_down = _arrow_image("down", dim)
|
|
|
|
|
arrow_up = _arrow_image("up", dim)
|
|
|
|
|
arrow_down_disabled = _arrow_image("down", muted)
|
|
|
|
|
arrow_up_disabled = _arrow_image("up", muted)
|
|
|
|
|
return f"""
|
|
|
|
|
QWidget {{
|
|
|
|
|
background-color: {c['window_bg']};
|
|
|
|
@@ -37,6 +100,11 @@ QMenuBar {{
|
|
|
|
|
background-color: {c['menu_bg']};
|
|
|
|
|
color: {c['text_primary']};
|
|
|
|
|
border-bottom: 1px solid {c['panel_border']};
|
|
|
|
|
padding: 2px 4px;
|
|
|
|
|
}}
|
|
|
|
|
QMenuBar::item {{
|
|
|
|
|
padding: 5px 10px;
|
|
|
|
|
border-radius: 4px;
|
|
|
|
|
}}
|
|
|
|
|
QMenuBar::item:selected {{
|
|
|
|
|
background-color: {c['menu_hover']};
|
|
|
|
@@ -45,54 +113,433 @@ QMenu {{
|
|
|
|
|
background-color: {c['menu_bg']};
|
|
|
|
|
color: {c['text_primary']};
|
|
|
|
|
border: 1px solid {c['panel_border']};
|
|
|
|
|
border-radius: 8px;
|
|
|
|
|
padding: 4px;
|
|
|
|
|
}}
|
|
|
|
|
QMenu::item {{
|
|
|
|
|
padding: 6px 18px;
|
|
|
|
|
border-radius: 4px;
|
|
|
|
|
}}
|
|
|
|
|
QMenu::item:selected {{
|
|
|
|
|
background-color: {c['menu_hover']};
|
|
|
|
|
}}
|
|
|
|
|
QToolBar {{
|
|
|
|
|
background-color: {c['panel_bg']};
|
|
|
|
|
border-bottom: 1px solid {c['panel_border']};
|
|
|
|
|
spacing: 8px;
|
|
|
|
|
padding: 4px;
|
|
|
|
|
QMenu::separator {{
|
|
|
|
|
height: 1px;
|
|
|
|
|
background-color: {c['separator']};
|
|
|
|
|
margin: 4px 8px;
|
|
|
|
|
}}
|
|
|
|
|
QMenu::indicator {{
|
|
|
|
|
width: 14px;
|
|
|
|
|
height: 14px;
|
|
|
|
|
margin-left: 6px;
|
|
|
|
|
}}
|
|
|
|
|
QToolBar {{
|
|
|
|
|
background-color: {toolbar_bg};
|
|
|
|
|
border-bottom: 1px solid {c['panel_border']};
|
|
|
|
|
spacing: 10px;
|
|
|
|
|
padding: 8px 10px;
|
|
|
|
|
}}
|
|
|
|
|
QToolTip {{
|
|
|
|
|
background-color: {c['menu_bg']};
|
|
|
|
|
color: {c['text_primary']};
|
|
|
|
|
border: 1px solid {c['panel_border']};
|
|
|
|
|
border-radius: 6px;
|
|
|
|
|
padding: 5px 8px;
|
|
|
|
|
}}
|
|
|
|
|
/* ---------- Buttons ---------- */
|
|
|
|
|
QPushButton {{
|
|
|
|
|
background-color: {c['button_bg']};
|
|
|
|
|
color: {c['text_primary']};
|
|
|
|
|
border: 1px solid {c['panel_border']};
|
|
|
|
|
border-radius: 4px;
|
|
|
|
|
padding: 6px 12px;
|
|
|
|
|
border-radius: 8px;
|
|
|
|
|
padding: 7px 14px;
|
|
|
|
|
min-height: 28px;
|
|
|
|
|
}}
|
|
|
|
|
QPushButton:hover {{
|
|
|
|
|
background-color: {c['button_hover']};
|
|
|
|
|
border-color: {c['accent_hover']};
|
|
|
|
|
}}
|
|
|
|
|
QPushButton:pressed {{
|
|
|
|
|
background-color: {c['menu_hover']};
|
|
|
|
|
}}
|
|
|
|
|
QPushButton:focus {{
|
|
|
|
|
border-color: {c['focus_ring']};
|
|
|
|
|
}}
|
|
|
|
|
QPushButton:disabled {{
|
|
|
|
|
color: {c['text_muted']};
|
|
|
|
|
background-color: {c['window_bg']};
|
|
|
|
|
border: 1px solid {c['separator']};
|
|
|
|
|
}}
|
|
|
|
|
QPushButton#primaryButton {{
|
|
|
|
|
background-color: {c['accent']};
|
|
|
|
|
color: {accent_text};
|
|
|
|
|
border: 1px solid {c['accent']};
|
|
|
|
|
font-weight: 600;
|
|
|
|
|
padding: 7px 18px;
|
|
|
|
|
}}
|
|
|
|
|
QPushButton#primaryButton:hover {{
|
|
|
|
|
background-color: {c['accent_hover']};
|
|
|
|
|
border-color: {c['accent_hover']};
|
|
|
|
|
}}
|
|
|
|
|
QPushButton#primaryButton:pressed,
|
|
|
|
|
QPushButton#primaryButton:checked {{
|
|
|
|
|
background-color: {c['accent_hover']};
|
|
|
|
|
border-color: {c['accent']};
|
|
|
|
|
}}
|
|
|
|
|
QPushButton#primaryButton:disabled {{
|
|
|
|
|
background-color: {c['panel_border']};
|
|
|
|
|
color: {c['text_muted']};
|
|
|
|
|
border-color: {c['panel_border']};
|
|
|
|
|
}}
|
|
|
|
|
QPushButton#dangerButton {{
|
|
|
|
|
background-color: {c['danger']};
|
|
|
|
|
color: {c['danger_text']};
|
|
|
|
|
border: 1px solid {c['danger']};
|
|
|
|
|
font-weight: 600;
|
|
|
|
|
padding: 7px 18px;
|
|
|
|
|
}}
|
|
|
|
|
QPushButton#dangerButton:hover {{
|
|
|
|
|
background-color: {c['danger_hover']};
|
|
|
|
|
border-color: {c['danger_hover']};
|
|
|
|
|
}}
|
|
|
|
|
QPushButton#dangerButton:pressed,
|
|
|
|
|
QPushButton#dangerButton:checked {{
|
|
|
|
|
background-color: {c['danger_hover']};
|
|
|
|
|
border-color: {c['danger']};
|
|
|
|
|
}}
|
|
|
|
|
QPushButton#dangerButton:disabled {{
|
|
|
|
|
background-color: {c['panel_border']};
|
|
|
|
|
color: {c['text_muted']};
|
|
|
|
|
border-color: {c['panel_border']};
|
|
|
|
|
}}
|
|
|
|
|
QPushButton#ghostButton {{
|
|
|
|
|
background-color: transparent;
|
|
|
|
|
border: 1px solid {c['panel_border']};
|
|
|
|
|
color: {c['text_secondary']};
|
|
|
|
|
}}
|
|
|
|
|
QComboBox, QLineEdit, QSpinBox {{
|
|
|
|
|
QPushButton#ghostButton:hover {{
|
|
|
|
|
background-color: {c['button_hover']};
|
|
|
|
|
color: {c['text_primary']};
|
|
|
|
|
}}
|
|
|
|
|
QPushButton[compact="true"] {{
|
|
|
|
|
padding: 6px 9px;
|
|
|
|
|
font-size: 12px;
|
|
|
|
|
}}
|
|
|
|
|
QToolButton {{
|
|
|
|
|
background-color: transparent;
|
|
|
|
|
color: {c['text_secondary']};
|
|
|
|
|
border: 1px solid transparent;
|
|
|
|
|
border-radius: 6px;
|
|
|
|
|
padding: 4px 8px;
|
|
|
|
|
}}
|
|
|
|
|
QToolButton:hover {{
|
|
|
|
|
background-color: {c['button_hover']};
|
|
|
|
|
color: {c['text_primary']};
|
|
|
|
|
border-color: {c['panel_border']};
|
|
|
|
|
}}
|
|
|
|
|
/* ---------- Inputs ---------- */
|
|
|
|
|
QComboBox, QLineEdit, QSpinBox, QDoubleSpinBox, QAbstractSpinBox {{
|
|
|
|
|
background-color: {c['input_bg']};
|
|
|
|
|
color: {c['text_primary']};
|
|
|
|
|
border: 1px solid {c['input_border']};
|
|
|
|
|
border-radius: 8px;
|
|
|
|
|
padding: 5px 10px;
|
|
|
|
|
min-height: 28px;
|
|
|
|
|
selection-background-color: {c['accent']};
|
|
|
|
|
selection-color: {accent_text};
|
|
|
|
|
}}
|
|
|
|
|
QComboBox:hover, QLineEdit:hover, QSpinBox:hover, QDoubleSpinBox:hover {{
|
|
|
|
|
border-color: {c['accent_hover']};
|
|
|
|
|
}}
|
|
|
|
|
QComboBox:focus, QLineEdit:focus, QSpinBox:focus, QDoubleSpinBox:focus {{
|
|
|
|
|
border: 1px solid {c['accent']};
|
|
|
|
|
}}
|
|
|
|
|
QComboBox:disabled, QLineEdit:disabled, QSpinBox:disabled, QDoubleSpinBox:disabled {{
|
|
|
|
|
color: {c['text_muted']};
|
|
|
|
|
background-color: {c['window_bg']};
|
|
|
|
|
border-color: {c['separator']};
|
|
|
|
|
}}
|
|
|
|
|
QComboBox::drop-down {{
|
|
|
|
|
subcontrol-origin: padding;
|
|
|
|
|
subcontrol-position: top right;
|
|
|
|
|
width: 22px;
|
|
|
|
|
border: none;
|
|
|
|
|
background: transparent;
|
|
|
|
|
}}
|
|
|
|
|
QComboBox::down-arrow {{
|
|
|
|
|
image: {arrow_down};
|
|
|
|
|
width: 12px;
|
|
|
|
|
height: 12px;
|
|
|
|
|
margin-right: 4px;
|
|
|
|
|
}}
|
|
|
|
|
QComboBox::down-arrow:disabled {{
|
|
|
|
|
image: {arrow_down_disabled};
|
|
|
|
|
}}
|
|
|
|
|
QComboBox QAbstractItemView {{
|
|
|
|
|
background-color: {c['menu_bg']};
|
|
|
|
|
color: {c['text_primary']};
|
|
|
|
|
border: 1px solid {c['panel_border']};
|
|
|
|
|
border-radius: 8px;
|
|
|
|
|
padding: 4px;
|
|
|
|
|
outline: none;
|
|
|
|
|
selection-background-color: {c['menu_hover']};
|
|
|
|
|
selection-color: {c['text_primary']};
|
|
|
|
|
}}
|
|
|
|
|
QAbstractSpinBox::up-button, QAbstractSpinBox::down-button {{
|
|
|
|
|
subcontrol-origin: border;
|
|
|
|
|
width: 18px;
|
|
|
|
|
background: transparent;
|
|
|
|
|
border: none;
|
|
|
|
|
}}
|
|
|
|
|
QAbstractSpinBox::up-button {{
|
|
|
|
|
subcontrol-position: top right;
|
|
|
|
|
}}
|
|
|
|
|
QAbstractSpinBox::down-button {{
|
|
|
|
|
subcontrol-position: bottom right;
|
|
|
|
|
}}
|
|
|
|
|
QAbstractSpinBox::up-arrow {{
|
|
|
|
|
image: {arrow_up};
|
|
|
|
|
width: 10px;
|
|
|
|
|
height: 10px;
|
|
|
|
|
}}
|
|
|
|
|
QAbstractSpinBox::down-arrow {{
|
|
|
|
|
image: {arrow_down};
|
|
|
|
|
width: 10px;
|
|
|
|
|
height: 10px;
|
|
|
|
|
}}
|
|
|
|
|
QAbstractSpinBox::up-arrow:disabled {{
|
|
|
|
|
image: {arrow_up_disabled};
|
|
|
|
|
}}
|
|
|
|
|
QAbstractSpinBox::down-arrow:disabled {{
|
|
|
|
|
image: {arrow_down_disabled};
|
|
|
|
|
}}
|
|
|
|
|
/* ---------- Check / radio ---------- */
|
|
|
|
|
QCheckBox, QRadioButton {{
|
|
|
|
|
background: transparent;
|
|
|
|
|
color: {c['text_primary']};
|
|
|
|
|
spacing: 7px;
|
|
|
|
|
padding: 2px 0;
|
|
|
|
|
}}
|
|
|
|
|
QCheckBox::indicator, QRadioButton::indicator {{
|
|
|
|
|
width: 15px;
|
|
|
|
|
height: 15px;
|
|
|
|
|
background-color: {c['input_bg']};
|
|
|
|
|
border: 1px solid {c['input_border']};
|
|
|
|
|
}}
|
|
|
|
|
QCheckBox::indicator {{
|
|
|
|
|
border-radius: 4px;
|
|
|
|
|
padding: 4px 8px;
|
|
|
|
|
min-height: 24px;
|
|
|
|
|
}}
|
|
|
|
|
QRadioButton::indicator {{
|
|
|
|
|
border-radius: 8px;
|
|
|
|
|
}}
|
|
|
|
|
QCheckBox::indicator:hover, QRadioButton::indicator:hover {{
|
|
|
|
|
border-color: {c['accent_hover']};
|
|
|
|
|
}}
|
|
|
|
|
QCheckBox::indicator:checked, QRadioButton::indicator:checked {{
|
|
|
|
|
background-color: {c['accent']};
|
|
|
|
|
border: 4px solid {c['accent']};
|
|
|
|
|
}}
|
|
|
|
|
QRadioButton::indicator:checked {{
|
|
|
|
|
background-color: {c['input_bg']};
|
|
|
|
|
border: 4px solid {c['accent']};
|
|
|
|
|
}}
|
|
|
|
|
QCheckBox::indicator:disabled, QRadioButton::indicator:disabled {{
|
|
|
|
|
background-color: {c['window_bg']};
|
|
|
|
|
border-color: {c['separator']};
|
|
|
|
|
}}
|
|
|
|
|
/* ---------- Progress ---------- */
|
|
|
|
|
QProgressBar {{
|
|
|
|
|
background-color: {c['input_bg']};
|
|
|
|
|
color: {c['text_secondary']};
|
|
|
|
|
border: 1px solid {c['input_border']};
|
|
|
|
|
border-radius: 7px;
|
|
|
|
|
height: 14px;
|
|
|
|
|
text-align: center;
|
|
|
|
|
font-size: 11px;
|
|
|
|
|
}}
|
|
|
|
|
QProgressBar::chunk {{
|
|
|
|
|
background-color: {c['accent']};
|
|
|
|
|
border-radius: 6px;
|
|
|
|
|
margin: 1px;
|
|
|
|
|
}}
|
|
|
|
|
/* ---------- Tables ---------- */
|
|
|
|
|
QTableWidget, QTableView {{
|
|
|
|
|
background-color: {c['input_bg']};
|
|
|
|
|
alternate-background-color: {c['table_row_alt']};
|
|
|
|
|
color: {c['text_primary']};
|
|
|
|
|
border: 1px solid {c['panel_border']};
|
|
|
|
|
border-radius: 8px;
|
|
|
|
|
gridline-color: {c['separator']};
|
|
|
|
|
outline: none;
|
|
|
|
|
selection-background-color: {c['table_selected']};
|
|
|
|
|
selection-color: {c['text_primary']};
|
|
|
|
|
}}
|
|
|
|
|
QTableWidget::item, QTableView::item {{
|
|
|
|
|
padding: 4px 6px;
|
|
|
|
|
border: none;
|
|
|
|
|
}}
|
|
|
|
|
QTableWidget::item:selected, QTableView::item:selected {{
|
|
|
|
|
background-color: {c['table_selected']};
|
|
|
|
|
color: {c['text_primary']};
|
|
|
|
|
}}
|
|
|
|
|
QHeaderView {{
|
|
|
|
|
background-color: {c['table_header_bg']};
|
|
|
|
|
border: none;
|
|
|
|
|
}}
|
|
|
|
|
QHeaderView::section {{
|
|
|
|
|
background-color: {c['table_header_bg']};
|
|
|
|
|
color: {c['text_secondary']};
|
|
|
|
|
border: none;
|
|
|
|
|
border-right: 1px solid {c['separator']};
|
|
|
|
|
border-bottom: 1px solid {c['panel_border']};
|
|
|
|
|
padding: 5px 6px;
|
|
|
|
|
font-weight: 600;
|
|
|
|
|
font-size: 12px;
|
|
|
|
|
}}
|
|
|
|
|
QHeaderView::section:last {{
|
|
|
|
|
border-right: none;
|
|
|
|
|
}}
|
|
|
|
|
QTableCornerButton::section {{
|
|
|
|
|
background-color: {c['table_header_bg']};
|
|
|
|
|
border: none;
|
|
|
|
|
}}
|
|
|
|
|
/* ---------- Scrollbars ---------- */
|
|
|
|
|
QScrollBar:vertical {{
|
|
|
|
|
background: {c['scrollbar_bg']};
|
|
|
|
|
width: 10px;
|
|
|
|
|
margin: 0;
|
|
|
|
|
border: none;
|
|
|
|
|
}}
|
|
|
|
|
QScrollBar:horizontal {{
|
|
|
|
|
background: {c['scrollbar_bg']};
|
|
|
|
|
height: 10px;
|
|
|
|
|
margin: 0;
|
|
|
|
|
border: none;
|
|
|
|
|
}}
|
|
|
|
|
QScrollBar::handle:vertical {{
|
|
|
|
|
background: {c['scrollbar_handle']};
|
|
|
|
|
min-height: 28px;
|
|
|
|
|
border-radius: 5px;
|
|
|
|
|
margin: 2px;
|
|
|
|
|
}}
|
|
|
|
|
QScrollBar::handle:horizontal {{
|
|
|
|
|
background: {c['scrollbar_handle']};
|
|
|
|
|
min-width: 28px;
|
|
|
|
|
border-radius: 5px;
|
|
|
|
|
margin: 2px;
|
|
|
|
|
}}
|
|
|
|
|
QScrollBar::handle:vertical:hover, QScrollBar::handle:horizontal:hover {{
|
|
|
|
|
background: {c['scrollbar_handle_hover']};
|
|
|
|
|
}}
|
|
|
|
|
QScrollBar::add-line, QScrollBar::sub-line {{
|
|
|
|
|
width: 0;
|
|
|
|
|
height: 0;
|
|
|
|
|
border: none;
|
|
|
|
|
background: transparent;
|
|
|
|
|
}}
|
|
|
|
|
QScrollBar::add-page, QScrollBar::sub-page {{
|
|
|
|
|
background: transparent;
|
|
|
|
|
}}
|
|
|
|
|
QScrollArea {{
|
|
|
|
|
border: none;
|
|
|
|
|
background: transparent;
|
|
|
|
|
}}
|
|
|
|
|
/* ---------- Labels / cards ---------- */
|
|
|
|
|
QLabel {{
|
|
|
|
|
background: transparent;
|
|
|
|
|
}}
|
|
|
|
|
QLabel#panelTitle {{
|
|
|
|
|
color: {c['text_secondary']};
|
|
|
|
|
font-weight: 600;
|
|
|
|
|
font-size: 12px;
|
|
|
|
|
letter-spacing: 0.3px;
|
|
|
|
|
padding: 1px 0;
|
|
|
|
|
}}
|
|
|
|
|
QLabel#panelMeta {{
|
|
|
|
|
color: {c['text_secondary']};
|
|
|
|
|
font-weight: 500;
|
|
|
|
|
padding-right: 8px;
|
|
|
|
|
}}
|
|
|
|
|
QLabel#fieldLabel {{
|
|
|
|
|
color: {c['text_secondary']};
|
|
|
|
|
font-weight: 500;
|
|
|
|
|
}}
|
|
|
|
|
QLabel#hintText {{
|
|
|
|
|
color: {c['hint_text']};
|
|
|
|
|
background: transparent;
|
|
|
|
|
}}
|
|
|
|
|
QLabel#unitBadge {{
|
|
|
|
|
color: {c['text_secondary']};
|
|
|
|
|
background-color: {c['card_bg']};
|
|
|
|
|
border: 1px solid {c['card_border']};
|
|
|
|
|
border-radius: 6px;
|
|
|
|
|
padding: 1px 7px;
|
|
|
|
|
font-size: 11px;
|
|
|
|
|
font-weight: 600;
|
|
|
|
|
letter-spacing: 0.4px;
|
|
|
|
|
}}
|
|
|
|
|
QLabel#valueCard {{
|
|
|
|
|
background-color: {c['card_bg']};
|
|
|
|
|
border: 1px solid {c['card_border']};
|
|
|
|
|
border-radius: 8px;
|
|
|
|
|
}}
|
|
|
|
|
QLabel#statusChip {{
|
|
|
|
|
color: {c['status_idle']};
|
|
|
|
|
background: transparent;
|
|
|
|
|
font-weight: 600;
|
|
|
|
|
padding: 0 10px 0 4px;
|
|
|
|
|
}}
|
|
|
|
|
QLabel#aboutBody {{
|
|
|
|
|
color: {c['text_secondary']};
|
|
|
|
|
}}
|
|
|
|
|
/* ---------- Frames ---------- */
|
|
|
|
|
QFrame#contentPanel {{
|
|
|
|
|
background-color: {c['panel_bg']};
|
|
|
|
|
border: 1px solid {c['panel_border']};
|
|
|
|
|
border-radius: 6px;
|
|
|
|
|
border-radius: 10px;
|
|
|
|
|
}}
|
|
|
|
|
QFrame#cardPanel {{
|
|
|
|
|
background-color: {c['card_bg']};
|
|
|
|
|
border: 1px solid {c['card_border']};
|
|
|
|
|
border-radius: 8px;
|
|
|
|
|
}}
|
|
|
|
|
QFrame#sectionSeparator {{
|
|
|
|
|
background-color: {c['separator']};
|
|
|
|
|
border: none;
|
|
|
|
|
max-width: 1px;
|
|
|
|
|
min-width: 1px;
|
|
|
|
|
}}
|
|
|
|
|
QGroupBox {{
|
|
|
|
|
background-color: {c['card_bg']};
|
|
|
|
|
border: 1px solid {c['card_border']};
|
|
|
|
|
border-radius: 8px;
|
|
|
|
|
margin-top: 10px;
|
|
|
|
|
padding: 10px 8px 8px 8px;
|
|
|
|
|
font-weight: 600;
|
|
|
|
|
}}
|
|
|
|
|
QGroupBox::title {{
|
|
|
|
|
subcontrol-origin: margin;
|
|
|
|
|
subcontrol-position: top left;
|
|
|
|
|
left: 10px;
|
|
|
|
|
padding: 0 4px;
|
|
|
|
|
color: {c['text_secondary']};
|
|
|
|
|
}}
|
|
|
|
|
/* ---------- Status bar ---------- */
|
|
|
|
|
QStatusBar {{
|
|
|
|
|
background-color: {c['panel_bg']};
|
|
|
|
|
color: {c['text_secondary']};
|
|
|
|
|
border-top: 1px solid {c['panel_border']};
|
|
|
|
|
}}
|
|
|
|
|
QStatusBar::item {{
|
|
|
|
|
border: none;
|
|
|
|
|
}}
|
|
|
|
|
QSplitter::handle {{
|
|
|
|
|
background-color: {c['window_bg']};
|
|
|
|
|
width: 6px;
|
|
|
|
|
height: 6px;
|
|
|
|
|
}}
|
|
|
|
|
QSplitter::handle:hover {{
|
|
|
|
|
background-color: {c['accent_hover']};
|
|
|
|
|
}}
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
@@ -103,3 +550,4 @@ def color(theme: str, key: str, default: str = "#888888") -> str:
|
|
|
|
|
|
|
|
|
|
def clear_theme_cache() -> None:
|
|
|
|
|
load_colors.cache_clear()
|
|
|
|
|
_paint_arrow.cache_clear()
|
|
|
|
|