diff --git a/src/aare/gui/panels/automation_panel.py b/src/aare/gui/panels/automation_panel.py index 3a9fa166..3cd4496b 100644 --- a/src/aare/gui/panels/automation_panel.py +++ b/src/aare/gui/panels/automation_panel.py @@ -15,6 +15,9 @@ from aare.gui.styles import ( AUTOMATION_TITLE_TEXT, CARD_BORDER, FAINT_TEXT, + FONT_BODY, + FONT_LABEL, + FONT_TITLE, MUTED_TEXT, STEP_ACTIVE_BG, STEP_ACTIVE_BORDER, @@ -62,13 +65,13 @@ class AutomationProgressWidget(QWidget): self._title_label = QLabel("Automation progress") self._title_label.setStyleSheet( - f"font-size: 16px; font-weight: 700; color: {AUTOMATION_TITLE_TEXT}; margin-bottom: 2px;" + f"font-size: {FONT_TITLE}; font-weight: 700; color: {AUTOMATION_TITLE_TEXT}; margin-bottom: 2px;" ) layout.addWidget(self._title_label) self._stats_label = QLabel() self._stats_label.setStyleSheet( - f"color: {AUTOMATION_HINT_TEXT}; font-size: 13px; " + f"color: {AUTOMATION_HINT_TEXT}; font-size: {FONT_LABEL}; font-weight: 700; " f"background-color: {SURFACE}; border: 1px solid {CARD_BORDER}; " "border-radius: 8px; padding: 10px;" ) @@ -140,7 +143,7 @@ class AutomationProgressWidget(QWidget): def _style_for_status(status: StepStatus) -> str: base = ( "padding: 10px 12px; border-radius: 10px; " - "font-size: 14px; border: 1px solid transparent;" + f"font-size: {FONT_BODY}; border: 1px solid transparent;" ) if status == StepStatus.SUCCESS: diff --git a/src/aare/gui/panels/beamline_recovery_panel.py b/src/aare/gui/panels/beamline_recovery_panel.py index f1d1d038..aa5c5a85 100644 --- a/src/aare/gui/panels/beamline_recovery_panel.py +++ b/src/aare/gui/panels/beamline_recovery_panel.py @@ -23,11 +23,13 @@ from aare.gui.styles import ( CHIP_INFO_TEXT, CHIP_WARN_BG, CHIP_WARN_TEXT, + FLAT_CARD_RADIUS, INFO_CARD_BG, INFO_CARD_BORDER, PENDING_CARD_BG, PENDING_CARD_BORDER, WARN_CARD_BORDER, + card_style, ) from aare.gui.threads.daq_worker import DAQWorker @@ -49,13 +51,14 @@ class RecoveryPanel(QWidget): ) self._warning_primary.setWordWrap(True) self._warning_primary.setStyleSheet( - "QLabel {" - f" background: {CHIP_WARN_BG};" - f" color: {CHIP_WARN_TEXT};" - f" border: 1px solid {WARN_CARD_BORDER};" - " padding: 10px;" - " font-weight: 600;" - "}" + card_style( + CHIP_WARN_BG, + WARN_CARD_BORDER, + CHIP_WARN_TEXT, + selector="QLabel", + radius=FLAT_CARD_RADIUS, + extra="padding: 10px; font-weight: 600;", + ) ) layout.addWidget(self._warning_primary) @@ -65,88 +68,95 @@ class RecoveryPanel(QWidget): ) self._warning_secondary.setWordWrap(True) self._warning_secondary.setStyleSheet( - "QLabel {" - f" background: {CHIP_BAD_BG};" - f" color: {CHIP_BAD_TEXT};" - f" border: 1px solid {BAD_CARD_BORDER};" - " padding: 10px;" - " font-weight: 600;" - "}" + card_style( + CHIP_BAD_BG, + BAD_CARD_BORDER, + CHIP_BAD_TEXT, + selector="QLabel", + radius=FLAT_CARD_RADIUS, + extra="padding: 10px; font-weight: 600;", + ) ) layout.addWidget(self._warning_secondary) self._last_action = QLabel("Last action: -", self) self._last_action.setWordWrap(True) self._last_action.setStyleSheet( - "QLabel {" - f" background: {INFO_CARD_BG};" - f" color: {CHIP_INFO_TEXT};" - f" border: 1px solid {INFO_CARD_BORDER};" - " padding: 10px;" - " font-weight: 600;" - "}" + card_style( + INFO_CARD_BG, + INFO_CARD_BORDER, + CHIP_INFO_TEXT, + selector="QLabel", + radius=FLAT_CARD_RADIUS, + extra="padding: 10px; font-weight: 600;", + ) ) layout.addWidget(self._last_action) self._take_over_btn = QPushButton("Take over beamline", self) self._take_over_btn.setStyleSheet( - "QPushButton {" - f" background: {PENDING_CARD_BG};" - f" border: 1px solid {PENDING_CARD_BORDER};" - " padding: 10px;" - " font-weight: 600;" - "}" + card_style( + PENDING_CARD_BG, + PENDING_CARD_BORDER, + selector="QPushButton", + radius=FLAT_CARD_RADIUS, + extra="padding: 10px; font-weight: 600;", + ) ) self._take_over_btn.clicked.connect(self._take_over_beamline) layout.addWidget(self._take_over_btn) self._free_beamline_btn = QPushButton("Free beamline", self) self._free_beamline_btn.setStyleSheet( - "QPushButton {" - f" background: {PENDING_CARD_BG};" - f" border: 1px solid {PENDING_CARD_BORDER};" - " padding: 10px;" - " font-weight: 600;" - "}" + card_style( + PENDING_CARD_BG, + PENDING_CARD_BORDER, + selector="QPushButton", + radius=FLAT_CARD_RADIUS, + extra="padding: 10px; font-weight: 600;", + ) ) self._free_beamline_btn.clicked.connect(self._free_beamline) layout.addWidget(self._free_beamline_btn) self._recover_beamline_btn = QPushButton("Recover beamline", self) self._recover_beamline_btn.setStyleSheet( - "QPushButton {" - f" background: {CHIP_BAD_BG};" - f" color: {CHIP_BAD_TEXT};" - f" border: 1px solid {BAD_CARD_BORDER};" - " padding: 10px;" - " font-weight: 700;" - "}" + card_style( + CHIP_BAD_BG, + BAD_CARD_BORDER, + CHIP_BAD_TEXT, + selector="QPushButton", + radius=FLAT_CARD_RADIUS, + extra="padding: 10px; font-weight: 700;", + ) ) self._recover_beamline_btn.clicked.connect(self._recover_beamline) layout.addWidget(self._recover_beamline_btn) self._recovery_unmount_btn = QPushButton("Unmount sample (recovery)", self) self._recovery_unmount_btn.setStyleSheet( - "QPushButton {" - f" background: {CHIP_BAD_BG};" - f" color: {CHIP_BAD_TEXT};" - f" border: 1px solid {BAD_CARD_BORDER};" - " padding: 10px;" - " font-weight: 700;" - "}" + card_style( + CHIP_BAD_BG, + BAD_CARD_BORDER, + CHIP_BAD_TEXT, + selector="QPushButton", + radius=FLAT_CARD_RADIUS, + extra="padding: 10px; font-weight: 700;", + ) ) self._recovery_unmount_btn.clicked.connect(self._recovery_unmount_sample) layout.addWidget(self._recovery_unmount_btn) self._resync_sample_btn = QPushButton("Resync sample from TELL", self) self._resync_sample_btn.setStyleSheet( - "QPushButton {" - f" background: {INFO_CARD_BG};" - f" color: {CHIP_INFO_TEXT};" - f" border: 1px solid {INFO_CARD_BORDER};" - " padding: 10px;" - " font-weight: 600;" - "}" + card_style( + INFO_CARD_BG, + INFO_CARD_BORDER, + CHIP_INFO_TEXT, + selector="QPushButton", + radius=FLAT_CARD_RADIUS, + extra="padding: 10px; font-weight: 600;", + ) ) self._resync_sample_btn.clicked.connect(self._resync_sample) layout.addWidget(self._resync_sample_btn) diff --git a/src/aare/gui/panels/developer_help_dialog.py b/src/aare/gui/panels/developer_help_dialog.py index fb818a24..a8c2b47a 100644 --- a/src/aare/gui/panels/developer_help_dialog.py +++ b/src/aare/gui/panels/developer_help_dialog.py @@ -38,6 +38,7 @@ from aare.gui.styles import ( PANEL_BORDER_DARK, PANEL_BORDER_LIGHT, WHITE, + card_style, ) from aare.gui.threads.daq_worker import DAQWorker @@ -69,12 +70,7 @@ class DeveloperHelpDialog(QDialog): self._banner.setWordWrap(True) self._banner.setTextInteractionFlags(Qt.TextInteractionFlag.TextSelectableByMouse) self._banner.setStyleSheet( - "QLabel {" - f" background: {PANEL_BG_SOFT};" - f" border: 1px solid {PANEL_BORDER};" - " border-radius: 6px;" - " padding: 6px 8px;" - "}" + card_style(PANEL_BG_SOFT, PANEL_BORDER, selector="QLabel", extra="padding: 6px 8px;") ) root.addWidget(self._banner) @@ -153,10 +149,7 @@ class DeveloperHelpDialog(QDialog): self._details_frame = QFrame(self) self._details_frame.setFrameShape(QFrame.Shape.StyledPanel) - self._details_frame.setStyleSheet( - f"QFrame {{ background: {PANEL_BG_FAINT}; border: 1px solid {PANEL_BORDER};" - " border-radius: 6px;}" - ) + self._details_frame.setStyleSheet(card_style(PANEL_BG_FAINT, PANEL_BORDER)) details_layout = QVBoxLayout(self._details_frame) details_layout.setContentsMargins(10, 10, 10, 10) @@ -186,12 +179,7 @@ class DeveloperHelpDialog(QDialog): self._detail_help.setWordWrap(True) self._detail_help.setTextInteractionFlags(Qt.TextInteractionFlag.TextSelectableByMouse) self._detail_help.setStyleSheet( - "QLabel {" - f" background: {WHITE};" - f" border: 1px solid {PANEL_BORDER_LIGHT};" - " border-radius: 6px;" - " padding: 8px;" - "}" + card_style(WHITE, PANEL_BORDER_LIGHT, selector="QLabel", extra="padding: 8px;") ) details_layout.addWidget(QLabel("Help:", self)) details_layout.addWidget(self._detail_help, 1) diff --git a/src/aare/gui/panels/local_contact_panel.py b/src/aare/gui/panels/local_contact_panel.py index 8153b9c8..1d6b523e 100644 --- a/src/aare/gui/panels/local_contact_panel.py +++ b/src/aare/gui/panels/local_contact_panel.py @@ -37,6 +37,7 @@ from aare.gui.styles import ( CHIP_BAD_TEXT, HEADING_TEXT, SURFACE, + card_style, ) from aare.gui.threads.daq_worker import DAQWorker from aare.gui.widgets.local_contact_status_widget import LocalContactStatusWidget @@ -121,8 +122,7 @@ class LocalContactPanel(QFrame): self._transfer_error_frame = QFrame(self) self._transfer_error_frame.setVisible(False) self._transfer_error_frame.setStyleSheet( - f"QFrame {{ background: {CHIP_BAD_BG}; color: {CHIP_BAD_TEXT};" - f" border: 1px solid {BAD_CARD_BORDER};}}" + card_style(CHIP_BAD_BG, BAD_CARD_BORDER, CHIP_BAD_TEXT) ) transfer_error_layout = QVBoxLayout(self._transfer_error_frame) transfer_error_layout.setContentsMargins(10, 10, 10, 10) diff --git a/src/aare/gui/panels/log_panel.py b/src/aare/gui/panels/log_panel.py index 659c8ae8..cd90338c 100644 --- a/src/aare/gui/panels/log_panel.py +++ b/src/aare/gui/panels/log_panel.py @@ -14,6 +14,7 @@ from PySide6.QtWidgets import ( from aare.gui.log import QtLogEmitter, QtLogHandler from aare.gui.styles import ( + FLAT_CARD_RADIUS, LOG_BORDER, LOG_ERROR_BG, LOG_ERROR_BORDER, @@ -24,6 +25,7 @@ from aare.gui.styles import ( LOG_SUCCESS_BORDER, LOG_WARN_BG, LOG_WARN_BORDER, + card_style, ) @@ -72,6 +74,7 @@ class RuntimeNotificationWidget(QFrame): button_layout.addWidget(self._clear_button) self._body = QWidget(self) + self._body.setObjectName("runtimeNotificationBody") body_layout = QVBoxLayout(self._body) body_layout.setContentsMargins(0, 0, 0, 0) body_layout.setSpacing(8) @@ -90,32 +93,41 @@ class RuntimeNotificationWidget(QFrame): self._sticky = True self.setStyleSheet( - f""" - QFrame#runtimeNotification {{ - border: 1px solid {LOG_BORDER}; - border-radius: 8px; - background-color: {LOG_PANEL_BG}; - }} - QFrame#runtimeNotification[noticeLevel="error"] {{ - background-color: {LOG_ERROR_BG}; - border: 1px solid {LOG_ERROR_BORDER}; - }} - QFrame#runtimeNotification[noticeLevel="warning"] {{ - background-color: {LOG_WARN_BG}; - border: 1px solid {LOG_WARN_BORDER}; - }} - QFrame#runtimeNotification[noticeLevel="success"] {{ - background-color: {LOG_SUCCESS_BG}; - border: 1px solid {LOG_SUCCESS_BORDER}; - }} - QFrame#runtimeNotification[noticeLevel="info"] {{ - background-color: {LOG_INFO_BG}; - border: 1px solid {LOG_INFO_BORDER}; - }} - QLabel#runtimeNotificationTitle {{ - font-weight: bold; - }} - """ + card_style( + LOG_PANEL_BG, + LOG_BORDER, + selector="QFrame#runtimeNotification", + radius=FLAT_CARD_RADIUS, + ) + + card_style( + LOG_ERROR_BG, + LOG_ERROR_BORDER, + selector='QFrame#runtimeNotification[noticeLevel="error"]', + radius=FLAT_CARD_RADIUS, + ) + + card_style( + LOG_WARN_BG, + LOG_WARN_BORDER, + selector='QFrame#runtimeNotification[noticeLevel="warning"]', + radius=FLAT_CARD_RADIUS, + ) + + card_style( + LOG_SUCCESS_BG, + LOG_SUCCESS_BORDER, + selector='QFrame#runtimeNotification[noticeLevel="success"]', + radius=FLAT_CARD_RADIUS, + ) + + card_style( + LOG_INFO_BG, + LOG_INFO_BORDER, + selector='QFrame#runtimeNotification[noticeLevel="info"]', + radius=FLAT_CARD_RADIUS, + ) + # Transparent children: the app-wide QWidget background rule would + # otherwise paint opaque strips over the card tint. + + " QLabel#runtimeNotificationTitle { font-weight: bold; background: transparent; }" + + " QLabel#runtimeNotificationMessage { background: transparent; }" + + " QWidget#runtimeNotificationBody { background: transparent; }" ) def _set_level(self, level: str) -> None: diff --git a/src/aare/gui/panels/portrait_mode.py b/src/aare/gui/panels/portrait_mode.py index 288a8856..5d66f104 100644 --- a/src/aare/gui/panels/portrait_mode.py +++ b/src/aare/gui/panels/portrait_mode.py @@ -32,6 +32,11 @@ from aare.gui.styles import ( DARK_SUCCESS_BG, DARK_SUCCESS_BORDER, DARK_SUCCESS_TEXT, + FONT_FINE, + FONT_HERO, + FONT_HINT, + FONT_LABEL, + FONT_VALUE, WHITE, qcolor, ) @@ -213,13 +218,13 @@ class QueueItemCard(QFrame): badge.setText("▶") badge.setStyleSheet(f""" color: {ACCENT}; background: {ACCENT_DIM}; - border-radius: 16px; font-size: 12px; font-weight: bold; + border-radius: 16px; font-size: {FONT_HINT}; font-weight: bold; """) else: badge.setText(str(index)) badge.setStyleSheet(f""" color: {SUBTEXT}; background: {BUTTON_BG}; - border-radius: 16px; font-size: 12px; + border-radius: 16px; font-size: {FONT_HINT}; """) layout.addWidget(badge) @@ -229,11 +234,11 @@ class QueueItemCard(QFrame): title_lbl = QLabel(title) title_lbl.setStyleSheet( - f"color: {TEXT}; font-size: 13px; font-weight: 600; background: transparent;" + f"color: {TEXT}; font-size: {FONT_LABEL}; font-weight: 700; background: transparent;" ) title_lbl.setWordWrap(False) sub_lbl = QLabel(subtitle) - sub_lbl.setStyleSheet(f"color: {SUBTEXT}; font-size: 11px; background: transparent;") + sub_lbl.setStyleSheet(f"color: {SUBTEXT}; font-size: {FONT_FINE}; background: transparent;") text_col.addWidget(title_lbl) text_col.addWidget(sub_lbl) layout.addLayout(text_col, stretch=1) @@ -292,7 +297,7 @@ class PortraitModePanel(QWidget): title = QLabel("S A M C A M E R A") title.setAlignment(Qt.AlignCenter) title.setStyleSheet( - f"color: {ACCENT}; font-size: 13px; letter-spacing: 3px; font-weight: 600;" + f"color: {ACCENT}; font-size: {FONT_LABEL}; letter-spacing: 3px; font-weight: 700;" ) layout.addWidget(title) @@ -311,7 +316,7 @@ class PortraitModePanel(QWidget): self._alert_toast_label = QLabel("") self._alert_toast_label.setWordWrap(True) self._alert_toast_label.setStyleSheet( - f"color: {DARK_ERROR_TEXT}; font-size: 11px; font-weight: 600; background: transparent;" + f"color: {DARK_ERROR_TEXT}; font-size: {FONT_FINE}; font-weight: 600; background: transparent;" ) toast_layout.addWidget(self._alert_toast_label) # Dismiss button @@ -322,7 +327,7 @@ class PortraitModePanel(QWidget): color: {SUBTEXT}; background: transparent; border: none; - font-size: 11px; + font-size: {FONT_FINE}; }} QPushButton:hover {{ color: {TEXT}; }} """) @@ -347,9 +352,9 @@ class PortraitModePanel(QWidget): # Sample name labels self._name_lbl = QLabel("—") - self._name_lbl.setStyleSheet(f"color: {TEXT}; font-size: 18px; font-weight: 700;") + self._name_lbl.setStyleSheet(f"color: {TEXT}; font-size: {FONT_VALUE}; font-weight: 700;") self._sub_lbl = QLabel("No sample queued") - self._sub_lbl.setStyleSheet(f"color: {SUBTEXT}; font-size: 12px;") + self._sub_lbl.setStyleSheet(f"color: {SUBTEXT}; font-size: {FONT_HINT};") layout.addWidget(self._name_lbl) layout.addWidget(self._sub_lbl) @@ -381,7 +386,7 @@ class PortraitModePanel(QWidget): border-radius: 26px; background: {BUTTON_BG}; color: {ACCENT}; - font-size: 28px; + font-size: {FONT_HERO}; font-weight: bold; }} QPushButton:checked {{ @@ -408,11 +413,11 @@ class PortraitModePanel(QWidget): up_next_row = QHBoxLayout() up_next_lbl = QLabel("UP NEXT") up_next_lbl.setStyleSheet( - f"color: {ACCENT}; font-size: 11px; letter-spacing: 2px; font-weight: 700;" + f"color: {ACCENT}; font-size: {FONT_FINE}; letter-spacing: 2px; font-weight: 700;" ) self._samples_count_lbl = QLabel("0 SAMPLES") self._samples_count_lbl.setStyleSheet( - f"color: {SUBTEXT}; font-size: 11px; letter-spacing: 1px;" + f"color: {SUBTEXT}; font-size: {FONT_FINE}; letter-spacing: 1px;" ) up_next_row.addWidget(up_next_lbl) up_next_row.addStretch() @@ -460,7 +465,7 @@ class PortraitModePanel(QWidget): title = QLabel("SAMPLE QUEUE") title.setAlignment(Qt.AlignCenter) title.setStyleSheet( - f"color: {ACCENT}; font-size: 13px; letter-spacing: 3px; font-weight: 700;" + f"color: {ACCENT}; font-size: {FONT_LABEL}; letter-spacing: 3px; font-weight: 700;" ) layout.addWidget(title) @@ -598,7 +603,9 @@ class PortraitModePanel(QWidget): if not samples: placeholder = QLabel("No samples in queue") - placeholder.setStyleSheet(f"color: {SUBTEXT}; font-size: 13px;") + placeholder.setStyleSheet( + f"color: {SUBTEXT}; font-size: {FONT_LABEL}; font-weight: 700;" + ) placeholder.setAlignment(Qt.AlignCenter) self._queue_inner_layout.addWidget(placeholder) return @@ -634,7 +641,7 @@ class PortraitModePanel(QWidget): border: 1.5px solid {ACCENT}; border-radius: 14px; color: {ACCENT}; - font-size: 12px; + font-size: {FONT_HINT}; font-weight: 700; letter-spacing: 1.5px; }} @@ -677,7 +684,7 @@ class PortraitModePanel(QWidget): }} """) self._alert_toast_label.setStyleSheet( - f"color: {text_color}; font-size: 11px; font-weight: 600; background: transparent;" + f"color: {text_color}; font-size: {FONT_FINE}; font-weight: 600; background: transparent;" ) self._alert_toast.setVisible(True) diff --git a/src/aare/gui/panels/prediction_metrics_panel.py b/src/aare/gui/panels/prediction_metrics_panel.py index 44f2cab2..7302ea30 100644 --- a/src/aare/gui/panels/prediction_metrics_panel.py +++ b/src/aare/gui/panels/prediction_metrics_panel.py @@ -49,6 +49,8 @@ from aare.gui.styles import ( CHART_ORANGE, CHART_RED, CONFIDENCE_BIN_COLORS, + FONT_BODY, + FONT_TITLE, qcolor, ) from aare.gui.styles import CHART_CLASS_COLORS as CLASS_COLORS @@ -208,7 +210,7 @@ class ObjectCountWidget(QWidget): # Create colored indicator square indicator = QLabel("■") - indicator.setStyleSheet(f"color: {color}; font-size: 16px;") + indicator.setStyleSheet(f"color: {color}; font-size: {FONT_TITLE};") indicator.setFixedWidth(20) # Class name label @@ -217,7 +219,7 @@ class ObjectCountWidget(QWidget): # Count label with matching color count_label = QLabel("0") - count_label.setStyleSheet(f"color: {color}; font-size: 14px; font-weight: bold;") + count_label.setStyleSheet(f"color: {color}; font-size: {FONT_BODY}; font-weight: bold;") count_label.setAlignment(Qt.AlignmentFlag.AlignRight) row = i // 2 diff --git a/src/aare/gui/tutorials/tutorial_manager.py b/src/aare/gui/tutorials/tutorial_manager.py index 24187eec..8180a238 100644 --- a/src/aare/gui/tutorials/tutorial_manager.py +++ b/src/aare/gui/tutorials/tutorial_manager.py @@ -21,6 +21,8 @@ from PySide6.QtWidgets import QLabel, QPushButton, QWidget from aare.gui.constants import LOGGER_NAME from aare.gui.styles import ( DEFAULT_TEXT, + FONT_BODY_LG, + FONT_TITLE, NOTE_TEXT, SHADOW, TUTORIAL_BORDER, @@ -110,17 +112,17 @@ class TutorialOverlay(QWidget): padding: 16px; border: 2px solid {TUTORIAL_BORDER}; border-radius: 10px; - font-size: 16px; + font-size: {FONT_TITLE}; """) self.callout.setWordWrap(True) self.callout.hide() - button_style = """ - QPushButton { - font-size: 15px; - font-weight: 600; + button_style = f""" + QPushButton {{ + font-size: {FONT_BODY_LG}; + font-weight: 700; padding: 10px 16px; - } + }} """ self.back_button = QPushButton("Back", self) diff --git a/src/aare/gui/widgets/automation_progress.py b/src/aare/gui/widgets/automation_progress.py index a1f000c2..af5ccfda 100644 --- a/src/aare/gui/widgets/automation_progress.py +++ b/src/aare/gui/widgets/automation_progress.py @@ -9,6 +9,8 @@ from PySide6.QtWidgets import QFrame, QHBoxLayout, QLabel, QVBoxLayout, QWidget from aare.gui.styles import ( FAINT_TEXT, + FONT_HINT, + FONT_VALUE, STEP_FAILED_TEXT, STEP_PAUSED_TEXT, STEP_RUNNING_TEXT, @@ -111,8 +113,8 @@ class CompactAutomationProgressStrip(QFrame): title = self._step_title(step) return ( f"