|
|
@@ -33,7 +33,7 @@ try:
|
|
|
except ImportError:
|
|
|
_HAS_HTTPX = False
|
|
|
|
|
|
-from src import i18n
|
|
|
+from src import i18n, theme
|
|
|
|
|
|
# -- colour palette -------------------------------------------------------------
|
|
|
_BG_DARK = "#1a1a2e"
|
|
|
@@ -544,7 +544,8 @@ class ScanningTab(QWidget):
|
|
|
|
|
|
def __init__(self, parent: QWidget | None = None) -> None:
|
|
|
super().__init__(parent)
|
|
|
- self.setStyleSheet(f"background: {_BG_DARK};")
|
|
|
+ p = theme.palette()
|
|
|
+ self.setStyleSheet(f"background: {p['bg']};")
|
|
|
|
|
|
self._viewers: list[MriViewerWidget] = []
|
|
|
self._scan_tick: int = 0
|
|
|
@@ -560,13 +561,15 @@ class ScanningTab(QWidget):
|
|
|
root.setContentsMargins(0, 0, 0, 0)
|
|
|
root.setSpacing(0)
|
|
|
|
|
|
- vsplit = QSplitter(Qt.Vertical)
|
|
|
- vsplit.setStyleSheet("QSplitter::handle { background: #333344; height: 3px; }")
|
|
|
- vsplit.addWidget(self._build_upper_area())
|
|
|
- vsplit.addWidget(self._build_bottom_panel())
|
|
|
- vsplit.setSizes([700, 140])
|
|
|
- vsplit.setChildrenCollapsible(False)
|
|
|
- root.addWidget(vsplit, stretch=1)
|
|
|
+ self._vsplit = QSplitter(Qt.Vertical)
|
|
|
+ self._vsplit.setStyleSheet(
|
|
|
+ f"QSplitter::handle {{ background: {p['border2']}; height: 3px; }}"
|
|
|
+ )
|
|
|
+ self._vsplit.addWidget(self._build_upper_area())
|
|
|
+ self._vsplit.addWidget(self._build_bottom_panel())
|
|
|
+ self._vsplit.setSizes([700, 140])
|
|
|
+ self._vsplit.setChildrenCollapsible(False)
|
|
|
+ root.addWidget(self._vsplit, stretch=1)
|
|
|
|
|
|
self._setup_animation()
|
|
|
self._update_matrix_display()
|
|
|
@@ -606,25 +609,88 @@ class ScanningTab(QWidget):
|
|
|
|
|
|
# -- layout builders ----------------------------------------------------
|
|
|
|
|
|
+ def apply_theme(self) -> None:
|
|
|
+ p = theme.palette()
|
|
|
+ dark = theme.is_dark()
|
|
|
+ self.setStyleSheet(f"background: {p['bg']};")
|
|
|
+ self._vsplit.setStyleSheet(
|
|
|
+ f"QSplitter::handle {{ background: {p['border2']}; height: 3px; }}"
|
|
|
+ )
|
|
|
+ self._upper_container.setStyleSheet(f"background: {p['bg']};")
|
|
|
+ self._hsplit.setStyleSheet(
|
|
|
+ f"QSplitter::handle {{ background: {p['border2']}; width: 3px; }}"
|
|
|
+ )
|
|
|
+ self._protocol_container.setStyleSheet(f"background: {p['panel']};")
|
|
|
+ self._image_grid_container.setStyleSheet(f"background: {p['bg']};")
|
|
|
+ self._bottom_panel.setStyleSheet(
|
|
|
+ f"background: {p['surface']}; border-top: 1px solid {p['border2']};"
|
|
|
+ )
|
|
|
+ self._action_bar.setStyleSheet(
|
|
|
+ f"background: {p['surface']}; border-top: 1px solid {p['border']};"
|
|
|
+ )
|
|
|
+ self._param_tabs.setStyleSheet(f"""
|
|
|
+ QTabWidget::pane {{ border: none; background: {p['surface']}; }}
|
|
|
+ QTabBar::tab {{
|
|
|
+ background: {p['bg']}; color: {p['text_dim']};
|
|
|
+ padding: 5px 14px; border: 1px solid {p['border']};
|
|
|
+ border-bottom: none; margin-right: 2px; font-size: 11px;
|
|
|
+ }}
|
|
|
+ QTabBar::tab:selected {{ background: {p['surface']}; color: {p['text']}; }}
|
|
|
+ QTabBar::tab:hover:!selected {{ background: {p['panel']}; }}
|
|
|
+ """)
|
|
|
+ self._status_label.setStyleSheet(f"color: {p['text_muted']}; font-size: 11px;")
|
|
|
+ scan_btn_css: str
|
|
|
+ if dark:
|
|
|
+ scan_btn_css = (
|
|
|
+ "QPushButton {"
|
|
|
+ " background: #1a3a1a; color: #88ee88;"
|
|
|
+ " border: 1px solid #336633; border-radius: 4px;"
|
|
|
+ " font-size: 12px; font-weight: bold; padding: 5px 16px;"
|
|
|
+ "}"
|
|
|
+ "QPushButton:checked {"
|
|
|
+ " background: #3a1a1a; color: #ee8888; border-color: #663333;"
|
|
|
+ "}"
|
|
|
+ "QPushButton:hover:!checked { background: #1e4a1e; }"
|
|
|
+ )
|
|
|
+ else:
|
|
|
+ scan_btn_css = (
|
|
|
+ "QPushButton {"
|
|
|
+ " background: #e8f5e9; color: #1b5e20;"
|
|
|
+ " border: 1px solid #4caf50; border-radius: 4px;"
|
|
|
+ " font-size: 12px; font-weight: bold; padding: 5px 16px;"
|
|
|
+ "}"
|
|
|
+ "QPushButton:checked {"
|
|
|
+ " background: #ffebee; color: #b71c1c; border-color: #ef5350;"
|
|
|
+ "}"
|
|
|
+ "QPushButton:hover:!checked { background: #c8e6c9; }"
|
|
|
+ )
|
|
|
+ self._btn_scan.setStyleSheet(scan_btn_css)
|
|
|
+
|
|
|
def _build_upper_area(self) -> QWidget:
|
|
|
+ p = theme.palette()
|
|
|
container = QWidget()
|
|
|
- container.setStyleSheet(f"background: {_BG_DARK};")
|
|
|
+ container.setStyleSheet(f"background: {p['bg']};")
|
|
|
+ self._upper_container = container
|
|
|
lay = QVBoxLayout(container)
|
|
|
lay.setContentsMargins(0, 0, 0, 0)
|
|
|
lay.setSpacing(0)
|
|
|
|
|
|
- hsplit = QSplitter(Qt.Horizontal)
|
|
|
- hsplit.setStyleSheet("QSplitter::handle { background: #333344; width: 3px; }")
|
|
|
- hsplit.addWidget(self._build_protocol_panel())
|
|
|
- hsplit.addWidget(self._build_image_grid())
|
|
|
- hsplit.setSizes([220, 980])
|
|
|
- hsplit.setChildrenCollapsible(False)
|
|
|
- lay.addWidget(hsplit)
|
|
|
+ self._hsplit = QSplitter(Qt.Horizontal)
|
|
|
+ self._hsplit.setStyleSheet(
|
|
|
+ f"QSplitter::handle {{ background: {p['border2']}; width: 3px; }}"
|
|
|
+ )
|
|
|
+ self._hsplit.addWidget(self._build_protocol_panel())
|
|
|
+ self._hsplit.addWidget(self._build_image_grid())
|
|
|
+ self._hsplit.setSizes([220, 980])
|
|
|
+ self._hsplit.setChildrenCollapsible(False)
|
|
|
+ lay.addWidget(self._hsplit)
|
|
|
return container
|
|
|
|
|
|
def _build_protocol_panel(self) -> QWidget:
|
|
|
+ p = theme.palette()
|
|
|
container = QWidget()
|
|
|
- container.setStyleSheet(f"background: {_PANEL_BG};")
|
|
|
+ container.setStyleSheet(f"background: {p['panel']};")
|
|
|
+ self._protocol_container = container
|
|
|
lay = QVBoxLayout(container)
|
|
|
lay.setContentsMargins(0, 0, 0, 0)
|
|
|
lay.setSpacing(0)
|
|
|
@@ -718,8 +784,10 @@ class ScanningTab(QWidget):
|
|
|
return container
|
|
|
|
|
|
def _build_image_grid(self) -> QWidget:
|
|
|
+ p = theme.palette()
|
|
|
container = QWidget()
|
|
|
- container.setStyleSheet(f"background: {_BG_DARK};")
|
|
|
+ container.setStyleSheet(f"background: {p['bg']};")
|
|
|
+ self._image_grid_container = container
|
|
|
grid = QGridLayout(container)
|
|
|
grid.setContentsMargins(6, 6, 6, 6)
|
|
|
grid.setSpacing(6)
|
|
|
@@ -734,8 +802,12 @@ class ScanningTab(QWidget):
|
|
|
return container
|
|
|
|
|
|
def _build_bottom_panel(self) -> QWidget:
|
|
|
+ p = theme.palette()
|
|
|
panel = QWidget()
|
|
|
- panel.setStyleSheet("background: #16162a; border-top: 1px solid #333355;")
|
|
|
+ panel.setStyleSheet(
|
|
|
+ f"background: {p['surface']}; border-top: 1px solid {p['border2']};"
|
|
|
+ )
|
|
|
+ self._bottom_panel = panel
|
|
|
|
|
|
outer = QVBoxLayout(panel)
|
|
|
outer.setContentsMargins(0, 0, 0, 0)
|
|
|
@@ -743,15 +815,15 @@ class ScanningTab(QWidget):
|
|
|
|
|
|
# -- parameter tabs -------------------------------------------------
|
|
|
self._param_tabs = QTabWidget()
|
|
|
- self._param_tabs.setStyleSheet("""
|
|
|
- QTabWidget::pane { border: none; background: #16162a; }
|
|
|
- QTabBar::tab {
|
|
|
- background: #1e1e38; color: #aaaacc;
|
|
|
- padding: 5px 14px; border: 1px solid #333355;
|
|
|
+ self._param_tabs.setStyleSheet(f"""
|
|
|
+ QTabWidget::pane {{ border: none; background: {p['surface']}; }}
|
|
|
+ QTabBar::tab {{
|
|
|
+ background: {p['bg']}; color: {p['text_dim']};
|
|
|
+ padding: 5px 14px; border: 1px solid {p['border']};
|
|
|
border-bottom: none; margin-right: 2px; font-size: 11px;
|
|
|
- }
|
|
|
- QTabBar::tab:selected { background: #252545; color: #ffffff; }
|
|
|
- QTabBar::tab:hover:!selected { background: #222240; }
|
|
|
+ }}
|
|
|
+ QTabBar::tab:selected {{ background: {p['surface']}; color: {p['text']}; }}
|
|
|
+ QTabBar::tab:hover:!selected {{ background: {p['panel']}; }}
|
|
|
""")
|
|
|
|
|
|
_placeholder_keys = ["tab_main", "tab_contrast", "tab_resolution", "tab_system"]
|
|
|
@@ -773,30 +845,46 @@ class ScanningTab(QWidget):
|
|
|
|
|
|
# -- bottom action bar ----------------------------------------------
|
|
|
action_bar = QWidget()
|
|
|
- action_bar.setStyleSheet("background: #16162a; border-top: 1px solid #2a2a4a;")
|
|
|
+ self._action_bar = action_bar
|
|
|
+ action_bar.setStyleSheet(
|
|
|
+ f"background: {p['surface']}; border-top: 1px solid {p['border']};"
|
|
|
+ )
|
|
|
action_lay = QHBoxLayout(action_bar)
|
|
|
action_lay.setContentsMargins(12, 6, 12, 6)
|
|
|
action_lay.setSpacing(12)
|
|
|
|
|
|
self._status_label = QLabel(i18n.tr("no_data"))
|
|
|
- self._status_label.setStyleSheet("color: #666688; font-size: 11px;")
|
|
|
+ self._status_label.setStyleSheet(f"color: {p['text_muted']}; font-size: 11px;")
|
|
|
action_lay.addWidget(self._status_label)
|
|
|
action_lay.addStretch()
|
|
|
|
|
|
self._btn_scan = QPushButton(i18n.tr("btn_scan"))
|
|
|
self._btn_scan.setCheckable(True)
|
|
|
self._btn_scan.setMinimumWidth(140)
|
|
|
- self._btn_scan.setStyleSheet(
|
|
|
- "QPushButton {"
|
|
|
- " background: #1a3a1a; color: #88ee88;"
|
|
|
- " border: 1px solid #336633; border-radius: 4px;"
|
|
|
- " font-size: 12px; font-weight: bold; padding: 5px 16px;"
|
|
|
- "}"
|
|
|
- "QPushButton:checked {"
|
|
|
- " background: #3a1a1a; color: #ee8888; border-color: #663333;"
|
|
|
- "}"
|
|
|
- "QPushButton:hover:!checked { background: #1e4a1e; }"
|
|
|
- )
|
|
|
+ if theme.is_dark():
|
|
|
+ self._btn_scan.setStyleSheet(
|
|
|
+ "QPushButton {"
|
|
|
+ " background: #1a3a1a; color: #88ee88;"
|
|
|
+ " border: 1px solid #336633; border-radius: 4px;"
|
|
|
+ " font-size: 12px; font-weight: bold; padding: 5px 16px;"
|
|
|
+ "}"
|
|
|
+ "QPushButton:checked {"
|
|
|
+ " background: #3a1a1a; color: #ee8888; border-color: #663333;"
|
|
|
+ "}"
|
|
|
+ "QPushButton:hover:!checked { background: #1e4a1e; }"
|
|
|
+ )
|
|
|
+ else:
|
|
|
+ self._btn_scan.setStyleSheet(
|
|
|
+ "QPushButton {"
|
|
|
+ " background: #e8f5e9; color: #1b5e20;"
|
|
|
+ " border: 1px solid #4caf50; border-radius: 4px;"
|
|
|
+ " font-size: 12px; font-weight: bold; padding: 5px 16px;"
|
|
|
+ "}"
|
|
|
+ "QPushButton:checked {"
|
|
|
+ " background: #ffebee; color: #b71c1c; border-color: #ef5350;"
|
|
|
+ "}"
|
|
|
+ "QPushButton:hover:!checked { background: #c8e6c9; }"
|
|
|
+ )
|
|
|
self._btn_scan.toggled.connect(self._on_scan_toggled)
|
|
|
action_lay.addWidget(self._btn_scan)
|
|
|
|
|
|
@@ -805,7 +893,7 @@ class ScanningTab(QWidget):
|
|
|
|
|
|
def _build_geometry_tab(self) -> QWidget:
|
|
|
w = QWidget()
|
|
|
- w.setStyleSheet("background: #16162a;")
|
|
|
+ w.setStyleSheet(f"background: {theme.palette()['surface']};")
|
|
|
lay = QHBoxLayout(w)
|
|
|
lay.setContentsMargins(12, 8, 12, 8)
|
|
|
lay.setSpacing(16)
|