diff --git a/src/aare/gui/tutorials/tutorial_manager.py b/src/aare/gui/tutorials/tutorial_manager.py index 87745a4d..24187eec 100644 --- a/src/aare/gui/tutorials/tutorial_manager.py +++ b/src/aare/gui/tutorials/tutorial_manager.py @@ -15,10 +15,19 @@ from PySide6.QtCore import ( QTimer, Signal, ) -from PySide6.QtGui import QColor, QPainter, QPen +from PySide6.QtGui import QPainter, QPen from PySide6.QtWidgets import QLabel, QPushButton, QWidget from aare.gui.constants import LOGGER_NAME +from aare.gui.styles import ( + DEFAULT_TEXT, + NOTE_TEXT, + SHADOW, + TUTORIAL_BORDER, + TUTORIAL_HIGHLIGHT, + WHITE, + qcolor, +) from aare.gui.tutorials.tutorial_models import ( StepFlow, StepStatus, @@ -95,11 +104,11 @@ class TutorialOverlay(QWidget): self.anim.valueChanged.connect(self.update) self.callout = QLabel(self) - self.callout.setStyleSheet(""" - background: white; - color: black; + self.callout.setStyleSheet(f""" + background: {WHITE}; + color: {DEFAULT_TEXT}; padding: 16px; - border: 2px solid #555; + border: 2px solid {TUTORIAL_BORDER}; border-radius: 10px; font-size: 16px; """) @@ -185,10 +194,10 @@ class TutorialOverlay(QWidget): def paintEvent(self, event) -> None: painter = QPainter(self) - painter.fillRect(self.rect(), QColor(0, 0, 0, int(150 * self.opacity))) + painter.fillRect(self.rect(), qcolor(SHADOW, int(150 * self.opacity))) if self.current_rect.isValid(): - pen = QPen(Qt.yellow, 4) + pen = QPen(qcolor(TUTORIAL_HIGHLIGHT), 4) painter.setPen(pen) painter.setBrush(Qt.NoBrush) painter.drawRoundedRect(self.current_rect, 8, 8) @@ -219,7 +228,7 @@ class TutorialOverlay(QWidget): if view.body.strip(): text_parts.append(view.body) if view.hint: - text_parts.append(f"{view.hint}") + text_parts.append(f"{view.hint}") self.callout.setText("

".join(text_parts)) self.callout.setMaximumWidth(460) diff --git a/src/aare/gui/widgets/alert_banner.py b/src/aare/gui/widgets/alert_banner.py index aaf0ae4d..9f4fab21 100644 --- a/src/aare/gui/widgets/alert_banner.py +++ b/src/aare/gui/widgets/alert_banner.py @@ -1,9 +1,9 @@ from aarecommon.config.logger import setup_logger from PySide6.QtCore import Qt, QTimer, Slot -from PySide6.QtGui import QColor from PySide6.QtWidgets import QFrame, QGraphicsDropShadowEffect, QHBoxLayout, QLabel, QSizePolicy from aare.gui.constants import LOGGER_NAME +from aare.gui.styles import SHADOW, qcolor logger = setup_logger(LOGGER_NAME) @@ -39,7 +39,7 @@ class AlertBanner(QFrame): shadow = QGraphicsDropShadowEffect(self) shadow.setBlurRadius(18) shadow.setOffset(0, 3) - shadow.setColor(QColor(0, 0, 0, 55)) + shadow.setColor(qcolor(SHADOW, 55)) self.setGraphicsEffect(shadow) self.setVisible(False) diff --git a/src/aare/gui/widgets/automation_progress.py b/src/aare/gui/widgets/automation_progress.py index 4c88baab..a1f000c2 100644 --- a/src/aare/gui/widgets/automation_progress.py +++ b/src/aare/gui/widgets/automation_progress.py @@ -7,6 +7,14 @@ from aarecommon.models.automation import AutomationProgress, StepStatus, Workflo from PySide6.QtCore import QTimer, Slot from PySide6.QtWidgets import QFrame, QHBoxLayout, QLabel, QVBoxLayout, QWidget +from aare.gui.styles import ( + FAINT_TEXT, + STEP_FAILED_TEXT, + STEP_PAUSED_TEXT, + STEP_RUNNING_TEXT, + STEP_SUCCESS_TEXT, +) + class CompactAutomationProgressStrip(QFrame): DEFAULT_SAMPLE_ESTIMATE_S = 150.0 @@ -89,13 +97,13 @@ class CompactAutomationProgressStrip(QFrame): @staticmethod def _step_color(status: StepStatus) -> str: return { - StepStatus.PENDING: "#64748b", - StepStatus.RUNNING: "#2563eb", - StepStatus.SUCCESS: "#15803d", - StepStatus.FAILED: "#b91c1c", - StepStatus.SKIPPED: "#64748b", - StepStatus.PAUSED: "#c2410c", - }.get(status, "#64748b") + StepStatus.PENDING: FAINT_TEXT, + StepStatus.RUNNING: STEP_RUNNING_TEXT, + StepStatus.SUCCESS: STEP_SUCCESS_TEXT, + StepStatus.FAILED: STEP_FAILED_TEXT, + StepStatus.SKIPPED: FAINT_TEXT, + StepStatus.PAUSED: STEP_PAUSED_TEXT, + }.get(status, FAINT_TEXT) def _format_step_html(self, step: WorkflowStateKind, status: StepStatus) -> str: color = self._step_color(status) @@ -163,16 +171,16 @@ class CompactAutomationProgressStrip(QFrame): eta = time.time() + queue_remaining if queue_remaining > 0 else None state_text = "Paused" - state_color = "#c2410c" + state_color = STEP_PAUSED_TEXT if progress.finished and progress.success is True: state_text = "Completed" - state_color = "#15803d" + state_color = STEP_SUCCESS_TEXT elif progress.finished and progress.success is False: state_text = "Failed" - state_color = "#b91c1c" + state_color = STEP_FAILED_TEXT elif self._running: state_text = "Running" - state_color = "#2563eb" + state_color = STEP_RUNNING_TEXT self._summary_label.setText( f"Status: " diff --git a/src/aare/gui/widgets/baton_request_dialog.py b/src/aare/gui/widgets/baton_request_dialog.py index 4ec6ae4d..0d86aa90 100644 --- a/src/aare/gui/widgets/baton_request_dialog.py +++ b/src/aare/gui/widgets/baton_request_dialog.py @@ -10,6 +10,22 @@ from PySide6.QtWidgets import ( QVBoxLayout, ) +from aare.gui.styles import ( + BATON_DANGER_BG, + BATON_DANGER_HOVER, + BATON_DANGER_PRESSED, + BATON_INFO, + BATON_OK_BG, + BATON_OK_HOVER, + BATON_OK_PRESSED, + BATON_WARN, + DIM_TEXT, + HINT_TEXT, + LIGHT_BORDER, + PROGRESS_TRACK_BG, + WHITE, +) + class BatonRequestDialog(QDialog): """ @@ -73,22 +89,22 @@ class BatonRequestDialog(QDialog): self.progress.setValue(self._timeout) self.progress.setTextVisible(False) self.progress.setFixedHeight(8) - self.progress.setStyleSheet(""" - QProgressBar { - border: 1px solid #ccc; + self.progress.setStyleSheet(f""" + QProgressBar {{ + border: 1px solid {LIGHT_BORDER}; border-radius: 4px; - background-color: #f0f0f0; - } - QProgressBar::chunk { - background-color: #4CAF50; + background-color: {PROGRESS_TRACK_BG}; + }} + QProgressBar::chunk {{ + background-color: {BATON_OK_BG}; border-radius: 3px; - } + }} """) progress_layout.addWidget(self.progress) self.time_label = QLabel(f"{self._timeout} seconds remaining") self.time_label.setAlignment(Qt.AlignmentFlag.AlignCenter) - self.time_label.setStyleSheet("color: #666;") + self.time_label.setStyleSheet(f"color: {DIM_TEXT};") progress_layout.addWidget(self.time_label) layout.addLayout(progress_layout) @@ -97,7 +113,7 @@ class BatonRequestDialog(QDialog): self.warning_label = QLabel("⚠️ If you don't respond, control will transfer automatically.") self.warning_label.setWordWrap(True) self.warning_label.setAlignment(Qt.AlignmentFlag.AlignCenter) - self.warning_label.setStyleSheet("color: #ff9800; font-style: italic;") + self.warning_label.setStyleSheet(f"color: {BATON_WARN}; font-style: italic;") layout.addWidget(self.warning_label) # Buttons @@ -106,42 +122,42 @@ class BatonRequestDialog(QDialog): self.accept_btn = QPushButton("✓ Accept") self.accept_btn.setMinimumHeight(40) - self.accept_btn.setStyleSheet(""" - QPushButton { - background-color: #4CAF50; - color: white; + self.accept_btn.setStyleSheet(f""" + QPushButton {{ + background-color: {BATON_OK_BG}; + color: {WHITE}; border: none; border-radius: 5px; font-weight: bold; font-size: 13px; - } - QPushButton:hover { - background-color: #45a049; - } - QPushButton:pressed { - background-color: #3d8b40; - } + }} + QPushButton:hover {{ + background-color: {BATON_OK_HOVER}; + }} + QPushButton:pressed {{ + background-color: {BATON_OK_PRESSED}; + }} """) self.accept_btn.clicked.connect(self._on_accept) button_layout.addWidget(self.accept_btn) self.refuse_btn = QPushButton("✗ Refuse") self.refuse_btn.setMinimumHeight(40) - self.refuse_btn.setStyleSheet(""" - QPushButton { - background-color: #f44336; - color: white; + self.refuse_btn.setStyleSheet(f""" + QPushButton {{ + background-color: {BATON_DANGER_BG}; + color: {WHITE}; border: none; border-radius: 5px; font-weight: bold; font-size: 13px; - } - QPushButton:hover { - background-color: #da190b; - } - QPushButton:pressed { - background-color: #c41000; - } + }} + QPushButton:hover {{ + background-color: {BATON_DANGER_HOVER}; + }} + QPushButton:pressed {{ + background-color: {BATON_DANGER_PRESSED}; + }} """) self.refuse_btn.clicked.connect(self._on_refuse) button_layout.addWidget(self.refuse_btn) @@ -155,7 +171,7 @@ class BatonRequestDialog(QDialog): ) info_label.setWordWrap(True) info_label.setAlignment(Qt.AlignmentFlag.AlignCenter) - info_label.setStyleSheet("color: #999;") + info_label.setStyleSheet(f"color: {HINT_TEXT};") layout.addWidget(info_label) def _start_timer(self): @@ -171,31 +187,31 @@ class BatonRequestDialog(QDialog): # Change progress bar color as time runs out if self._remaining <= 10: - self.progress.setStyleSheet(""" - QProgressBar { - border: 1px solid #ccc; + self.progress.setStyleSheet(f""" + QProgressBar {{ + border: 1px solid {LIGHT_BORDER}; border-radius: 4px; - background-color: #f0f0f0; - } - QProgressBar::chunk { - background-color: #ff9800; + background-color: {PROGRESS_TRACK_BG}; + }} + QProgressBar::chunk {{ + background-color: {BATON_WARN}; border-radius: 3px; - } + }} """) if self._remaining <= 5: - self.progress.setStyleSheet(""" - QProgressBar { - border: 1px solid #ccc; + self.progress.setStyleSheet(f""" + QProgressBar {{ + border: 1px solid {LIGHT_BORDER}; border-radius: 4px; - background-color: #f0f0f0; - } - QProgressBar::chunk { - background-color: #f44336; + background-color: {PROGRESS_TRACK_BG}; + }} + QProgressBar::chunk {{ + background-color: {BATON_DANGER_BG}; border-radius: 3px; - } + }} """) - self.time_label.setStyleSheet("color: #f44336; font-weight: bold;") + self.time_label.setStyleSheet(f"color: {BATON_DANGER_BG}; font-weight: bold;") if self._remaining <= 0: self._timer.stop() @@ -270,22 +286,22 @@ class BatonPendingDialog(QDialog): self.progress.setValue(self._timeout) self.progress.setTextVisible(False) self.progress.setFixedHeight(8) - self.progress.setStyleSheet(""" - QProgressBar { - border: 1px solid #ccc; + self.progress.setStyleSheet(f""" + QProgressBar {{ + border: 1px solid {LIGHT_BORDER}; border-radius: 4px; - background-color: #f0f0f0; - } - QProgressBar::chunk { - background-color: #2196F3; + background-color: {PROGRESS_TRACK_BG}; + }} + QProgressBar::chunk {{ + background-color: {BATON_INFO}; border-radius: 3px; - } + }} """) self.progress_layout.addWidget(self.progress) self.time_label = QLabel(f"{self._timeout} seconds remaining") self.time_label.setAlignment(Qt.AlignmentFlag.AlignCenter) - self.time_label.setStyleSheet("color: #666;") + self.time_label.setStyleSheet(f"color: {DIM_TEXT};") self.progress_layout.addWidget(self.time_label) layout.addLayout(self.progress_layout) @@ -293,17 +309,17 @@ class BatonPendingDialog(QDialog): button_layout = QHBoxLayout() self.cancel_btn = QPushButton("✗ Cancel Request") self.cancel_btn.setMinimumHeight(40) - self.cancel_btn.setStyleSheet(""" - QPushButton { - background-color: #f44336; - color: white; + self.cancel_btn.setStyleSheet(f""" + QPushButton {{ + background-color: {BATON_DANGER_BG}; + color: {WHITE}; border: none; border-radius: 5px; font-weight: bold; font-size: 13px; - } - QPushButton:hover { background-color: #da190b; } - QPushButton:pressed { background-color: #c41000; } + }} + QPushButton:hover {{ background-color: {BATON_DANGER_HOVER}; }} + QPushButton:pressed {{ background-color: {BATON_DANGER_PRESSED}; }} """) self.cancel_btn.clicked.connect(self._on_cancel) button_layout.addWidget(self.cancel_btn) @@ -332,7 +348,7 @@ class BatonPendingDialog(QDialog): def set_queued_state(self): self._timer.stop() self.header.setText("⏳ Transfer Queued") - self.header.setStyleSheet("color: #FF9800; font-weight: bold; font-size: 14px;") + self.header.setStyleSheet(f"color: {BATON_WARN}; font-weight: bold; font-size: 14px;") self.message_label.setText( "The beamline is currently busy. Your request was accepted and " "the baton will be transferred as soon as the current operation completes." diff --git a/src/aare/gui/widgets/busy_overlay.py b/src/aare/gui/widgets/busy_overlay.py index d95d5a20..d344a2d1 100644 --- a/src/aare/gui/widgets/busy_overlay.py +++ b/src/aare/gui/widgets/busy_overlay.py @@ -4,6 +4,31 @@ from aarecommon.models.models import SessionsStateEnum from aarecommon.models.tell import TellStateModel from PySide6.QtGui import QColor +from aare.gui.styles import ( + BUSY_BLUE, + BUSY_BLUE_BORDER, + BUSY_BLUE_DOT, + BUSY_ORANGE, + BUSY_ORANGE_BORDER, + BUSY_ORANGE_DOT, + BUSY_PSI_RED, + BUSY_PSI_RED_BORDER, + BUSY_PSI_RED_DOT, + BUSY_PURPLE, + BUSY_PURPLE_BORDER, + BUSY_PURPLE_DOT, + BUSY_RED_BADGE, + BUSY_RED_BORDER, + BUSY_RED_DOT, + BUSY_RED_FILL, + BUSY_YELLOW, + BUSY_YELLOW_BORDER, + BUSY_YELLOW_DOT, + BUSY_YELLOW_TEXT_DARK, + WHITE, + qcolor, +) + @dataclass(frozen=True) class BusyOverlayStyle: @@ -25,23 +50,23 @@ def build_busy_overlay_style( if session_state == SessionsStateEnum.Vacant: return BusyOverlayStyle( text="SESSION VACANT", - badge_bg="#f1c40f", - badge_fg="#ffffff", - overlay_fill=QColor(241, 196, 15, 195), - overlay_border=QColor(255, 248, 210, 235), - overlay_text=QColor(255, 255, 255), - accent_dot="#fff6bf", + badge_bg=BUSY_YELLOW, + badge_fg=WHITE, + overlay_fill=qcolor(BUSY_YELLOW, 195), + overlay_border=qcolor(BUSY_YELLOW_BORDER, 235), + overlay_text=qcolor(WHITE), + accent_dot=BUSY_YELLOW_DOT, ) if session_state in {SessionsStateEnum.OwnedByElse, SessionsStateEnum.PendingYouToElse}: return BusyOverlayStyle( text="GUEST MODE", - badge_bg="#8e44ad", - badge_fg="#ffffff", - overlay_fill=QColor(142, 68, 173, 190), - overlay_border=QColor(235, 220, 245, 230), - overlay_text=QColor(255, 255, 255), - accent_dot="#f0dfff", + badge_bg=BUSY_PURPLE, + badge_fg=WHITE, + overlay_fill=qcolor(BUSY_PURPLE, 190), + overlay_border=qcolor(BUSY_PURPLE_BORDER, 230), + overlay_text=qcolor(WHITE), + accent_dot=BUSY_PURPLE_DOT, ) if not is_busy: @@ -52,53 +77,53 @@ def build_busy_overlay_style( if activity_value == "mounting": return BusyOverlayStyle( text="ROBOT MOUNTING", - badge_bg="#d64545", - badge_fg="#ffffff", - overlay_fill=QColor(190, 40, 40, 185), - overlay_border=QColor(255, 220, 220, 230), - overlay_text=QColor(255, 255, 255), - accent_dot="#ffdddd", + badge_bg=BUSY_RED_BADGE, + badge_fg=WHITE, + overlay_fill=qcolor(BUSY_RED_FILL, 185), + overlay_border=qcolor(BUSY_RED_BORDER, 230), + overlay_text=qcolor(WHITE), + accent_dot=BUSY_RED_DOT, ) if activity_value == "unmounting": return BusyOverlayStyle( text="ROBOT UNMOUNTING", - badge_bg="#e67e22", - badge_fg="#ffffff", - overlay_fill=QColor(230, 126, 34, 190), - overlay_border=QColor(255, 234, 214, 230), - overlay_text=QColor(255, 255, 255), - accent_dot="#fff0db", + badge_bg=BUSY_ORANGE, + badge_fg=WHITE, + overlay_fill=qcolor(BUSY_ORANGE, 190), + overlay_border=qcolor(BUSY_ORANGE_BORDER, 230), + overlay_text=qcolor(WHITE), + accent_dot=BUSY_ORANGE_DOT, ) if activity_value == "drying": return BusyOverlayStyle( text="ROBOT DRYING", - badge_bg="#f1c40f", - badge_fg="#3b2f00", - overlay_fill=QColor(241, 196, 15, 195), - overlay_border=QColor(255, 248, 210, 235), - overlay_text=QColor(59, 47, 0), - accent_dot="#fff6bf", + badge_bg=BUSY_YELLOW, + badge_fg=BUSY_YELLOW_TEXT_DARK, + overlay_fill=qcolor(BUSY_YELLOW, 195), + overlay_border=qcolor(BUSY_YELLOW_BORDER, 235), + overlay_text=qcolor(BUSY_YELLOW_TEXT_DARK), + accent_dot=BUSY_YELLOW_DOT, ) if activity_value == "cooling": return BusyOverlayStyle( text="ROBOT COOLING", - badge_bg="#3498db", - badge_fg="#ffffff", - overlay_fill=QColor(52, 152, 219, 190), - overlay_border=QColor(220, 240, 255, 235), - overlay_text=QColor(255, 255, 255), - accent_dot="#dff2ff", + badge_bg=BUSY_BLUE, + badge_fg=WHITE, + overlay_fill=qcolor(BUSY_BLUE, 190), + overlay_border=qcolor(BUSY_BLUE_BORDER, 235), + overlay_text=qcolor(WHITE), + accent_dot=BUSY_BLUE_DOT, ) return BusyOverlayStyle( text="BEAMLINE BUSY", - badge_bg="#e04f39", - badge_fg="#ffffff", - overlay_fill=QColor(224, 79, 57, 195), - overlay_border=QColor(255, 225, 220, 235), - overlay_text=QColor(255, 255, 255), - accent_dot="#ffd8d1", + badge_bg=BUSY_PSI_RED, + badge_fg=WHITE, + overlay_fill=qcolor(BUSY_PSI_RED, 195), + overlay_border=qcolor(BUSY_PSI_RED_BORDER, 235), + overlay_text=qcolor(WHITE), + accent_dot=BUSY_PSI_RED_DOT, ) diff --git a/src/aare/gui/widgets/camera_image.py b/src/aare/gui/widgets/camera_image.py index 5d66ea2f..58014244 100644 --- a/src/aare/gui/widgets/camera_image.py +++ b/src/aare/gui/widgets/camera_image.py @@ -40,6 +40,26 @@ from PySide6.QtWidgets import ( from aare.gui.constants import LOGGER_NAME from aare.gui.models.bookmark import SmargonBookmarkList from aare.gui.scan_logic.raster_grid_manager import RasterGridManager +from aare.gui.styles import ( + BEAM_BUSY, + BEAM_IDLE, + BEAM_MARKING, + BEAM_OPEN, + CLASS_COLORS, + LEGEND_BG, + LEGEND_TEXT, + MARK_BADGE_BG, + MARK_TOOLTIP_GOLD, + MARK_TOOLTIP_ORANGE, + MARK_TOOLTIP_RED, + MARKER_GREEN, + PATH_END, + PATH_START, + TARGET_COLORS, + TOOLTIP_TEXT, + WHITE, + qcolor, +) from aare.gui.widgets.busy_overlay import BusyOverlayStyle, build_busy_overlay_style logger = setup_logger(LOGGER_NAME) @@ -301,13 +321,13 @@ class SampleCameraImageLabel(QGraphicsView): painter.setFont(font) if self._session_state == SessionsStateEnum.Vacant: - bg_color = QColor(255, 215, 0, 180) + bg_color = qcolor(MARK_TOOLTIP_GOLD, 180) text = "Session Vacant" elif self._session_state == SessionsStateEnum.PendingYouToElse: - bg_color = QColor(255, 165, 0, 150) + bg_color = qcolor(MARK_TOOLTIP_ORANGE, 150) text = "Baton Requested..." else: - bg_color = QColor(255, 0, 0, 150) + bg_color = qcolor(MARK_TOOLTIP_RED, 150) text = "Guest Mode" fm = QFontMetrics(font) @@ -324,11 +344,11 @@ class SampleCameraImageLabel(QGraphicsView): bg_rect = QRect(position_x, position_y, bg_w, bg_h) - painter.setPen(QPen(QColor(255, 255, 255, 220))) + painter.setPen(QPen(qcolor(WHITE, 220))) painter.setBrush(bg_color) painter.drawRoundedRect(bg_rect, 10, 10) - painter.setPen(QPen(QColor(255, 255, 255))) + painter.setPen(QPen(qcolor(WHITE))) painter.drawText(QPoint(position_x + padding, position_y + padding + fm.ascent()), text) painter.restore() @@ -360,11 +380,11 @@ class SampleCameraImageLabel(QGraphicsView): text_rect.height() + 2 * padding, ) - painter.setPen(QPen(QColor(255, 255, 255, 220), 2)) - painter.setBrush(QColor(180, 60, 0, 180)) + painter.setPen(QPen(qcolor(WHITE, 220), 2)) + painter.setBrush(qcolor(MARK_BADGE_BG, 180)) painter.drawRoundedRect(bg_rect, 10, 10) - painter.setPen(QPen(QColor(255, 255, 255))) + painter.setPen(QPen(qcolor(WHITE))) painter.drawText(QPoint(position_x, position_y + fm.ascent()), text) painter.restore() @@ -716,14 +736,7 @@ class SampleCameraImageLabel(QGraphicsView): sx = disp_w / float(img_w) sy = disp_h / float(img_h) - color_map = { - "pin": QColor("red"), - "loop_all": QColor("green"), - "loop_face": QColor("yellow"), - "crystal": QColor("blue"), - "needle": QColor("magenta"), - "ice": QColor("cyan"), - } + color_map = {label: qcolor(hex_str) for label, hex_str in CLASS_COLORS.items()} for det in self._detections: try: @@ -738,7 +751,7 @@ class SampleCameraImageLabel(QGraphicsView): logger.debug(f"Error in draw detection {det}: {e}", exc_info=True) continue - color = color_map.get(label, QColor("magenta")) + color = color_map.get(label, qcolor(CLASS_COLORS["needle"])) pen = QPen(color, 3) painter.setPen(pen) @@ -753,20 +766,16 @@ class SampleCameraImageLabel(QGraphicsView): ) painter.drawPolygon(polygon) - painter.setPen(QPen(QColor(255, 255, 255), 1)) + painter.setPen(QPen(qcolor(WHITE), 1)) painter.setBrush(color) text_bg_rect = QRect(int(x1), int(y1 - 16), int(8 + 7 * len(label)), 16) painter.drawRect(text_bg_rect) - painter.setPen(QPen(QColor(255, 255, 255))) + painter.setPen(QPen(qcolor(WHITE))) painter.drawText(QPoint(int(x1) + 2, int(y1 - 4)), f"{label} {conf:.2f}") def _target_color(self) -> QColor: - color_map = { - "Cyan": QColor(0, 255, 255), - "Dark Blue": QColor(0, 70, 160), - "Dark Red": QColor(140, 25, 25), - } - return color_map.get(self._target_color_name, QColor(0, 255, 255)) + color_map = {name: qcolor(hex_str) for name, hex_str in TARGET_COLORS.items()} + return color_map.get(self._target_color_name, qcolor(TARGET_COLORS["Cyan"])) def _coerce_target_point(self, raw) -> tuple[float, float] | None: try: @@ -824,7 +833,7 @@ class SampleCameraImageLabel(QGraphicsView): painter.setBrush(Qt.BrushStyle.NoBrush) painter.setPen(QPen(color, 3, Qt.PenStyle.SolidLine)) painter.drawEllipse(QPointF(px, py), 12, 12) - painter.setPen(QPen(QColor(255, 255, 255), 1, Qt.PenStyle.SolidLine)) + painter.setPen(QPen(qcolor(WHITE), 1, Qt.PenStyle.SolidLine)) painter.drawEllipse(QPointF(px, py), 5, 5) painter.setPen(QPen(color, 2, Qt.PenStyle.SolidLine)) @@ -847,10 +856,10 @@ class SampleCameraImageLabel(QGraphicsView): bubble_rect = QRectF(px + 16, py - 28, text_rect.width() + 16, text_rect.height() + 10) painter.setPen(QPen(color, 2)) - painter.setBrush(QColor(20, 20, 20, 190)) + painter.setBrush(qcolor(LEGEND_BG, 190)) painter.drawRoundedRect(bubble_rect, 8, 8) - painter.setPen(QPen(QColor(255, 255, 255), 1)) + painter.setPen(QPen(qcolor(WHITE), 1)) painter.drawText( QPointF(bubble_rect.left() + 8, bubble_rect.top() + 7 + fm.ascent()), label_text ) @@ -878,19 +887,19 @@ class SampleCameraImageLabel(QGraphicsView): if self._show_detections: lines.extend( [ - ("Pin", QColor("red")), - ("Loop", QColor("green")), - ("Face", QColor("yellow")), - ("Crystal", QColor("blue")), + ("Pin", qcolor(CLASS_COLORS["pin"])), + ("Loop", qcolor(CLASS_COLORS["loop_all"])), + ("Face", qcolor(CLASS_COLORS["loop_face"])), + ("Crystal", qcolor(CLASS_COLORS["crystal"])), ] ) if self._show_coords: - lines.append(("Coords tooltip", QColor(230, 230, 230))) + lines.append(("Coords tooltip", qcolor(TOOLTIP_TEXT))) - lines.append(("Beam marker: shutter open", QColor(0, 255, 0))) - lines.append(("Beam marker: idle", QColor(245, 121, 0))) - lines.append(("Beam marker: busy", QColor(255, 0, 0))) + lines.append(("Beam marker: shutter open", qcolor(BEAM_OPEN))) + lines.append(("Beam marker: idle", qcolor(BEAM_IDLE))) + lines.append(("Beam marker: busy", qcolor(BEAM_BUSY))) return lines if self._show_target_point: @@ -902,22 +911,22 @@ class SampleCameraImageLabel(QGraphicsView): if self._show_detections: lines.extend( [ - ("Prediction: Pin", QColor("red")), - ("Prediction: Loop_all", QColor("green")), - ("Prediction: Loop_face", QColor("yellow")), - ("Prediction: Crystal", QColor("blue")), - ("Prediction: Needle", QColor("magenta")), - ("Prediction: Ice", QColor("cyan")), + ("Prediction: Pin", qcolor(CLASS_COLORS["pin"])), + ("Prediction: Loop_all", qcolor(CLASS_COLORS["loop_all"])), + ("Prediction: Loop_face", qcolor(CLASS_COLORS["loop_face"])), + ("Prediction: Crystal", qcolor(CLASS_COLORS["crystal"])), + ("Prediction: Needle", qcolor(CLASS_COLORS["needle"])), + ("Prediction: Ice", qcolor(CLASS_COLORS["ice"])), ] ) if self._show_coords: - lines.append(("Cursor tooltip: pixel coordinates", QColor(230, 230, 230))) + lines.append(("Cursor tooltip: pixel coordinates", qcolor(TOOLTIP_TEXT))) - lines.append(("Beam marker: shutter open", QColor(0, 255, 0))) - lines.append(("Beam marker: idle", QColor(245, 121, 0))) - lines.append(("Beam marker: busy", QColor(255, 0, 0))) - lines.append(("Beam marker: marking mode", QColor(102, 51, 153))) + lines.append(("Beam marker: shutter open", qcolor(BEAM_OPEN))) + lines.append(("Beam marker: idle", qcolor(BEAM_IDLE))) + lines.append(("Beam marker: busy", qcolor(BEAM_BUSY))) + lines.append(("Beam marker: marking mode", qcolor(BEAM_MARKING))) return lines @@ -950,8 +959,8 @@ class SampleCameraImageLabel(QGraphicsView): height = len(lines) * line_height + 16 bg_rect = QRectF(left, max(18, top), width, height) - painter.setPen(QPen(QColor(255, 255, 255, 60), 1)) - painter.setBrush(QColor(20, 20, 20, 170)) + painter.setPen(QPen(qcolor(WHITE, 60), 1)) + painter.setBrush(qcolor(LEGEND_BG, 170)) painter.drawRoundedRect(bg_rect, 8, 8) y = bg_rect.top() + 12 @@ -966,7 +975,7 @@ class SampleCameraImageLabel(QGraphicsView): painter.setPen(Qt.PenStyle.NoPen) painter.setBrush(Qt.BrushStyle.NoBrush) - painter.setPen(QPen(QColor(240, 240, 240), 1)) + painter.setPen(QPen(qcolor(LEGEND_TEXT), 1)) painter.drawText( QPointF( bg_rect.left() + section_padding + swatch_size + text_padding, @@ -1028,7 +1037,7 @@ class SampleCameraImageLabel(QGraphicsView): if self._bounding_box is None: return - painter.setPen(QPen(QColor(50, 205, 50), 3, Qt.PenStyle.SolidLine)) + painter.setPen(QPen(qcolor(MARKER_GREEN), 3, Qt.PenStyle.SolidLine)) painter.setBrush(Qt.BrushStyle.NoBrush) painter.drawRect( @@ -1044,16 +1053,16 @@ class SampleCameraImageLabel(QGraphicsView): beam_size_pxl = self._geom.beam_size_pxl if self._state == SampleCameraImageState.BEAM_MARKING: - painter.setPen(QPen(QColor(102, 51, 153), 3, Qt.PenStyle.SolidLine)) + painter.setPen(QPen(qcolor(BEAM_MARKING), 3, Qt.PenStyle.SolidLine)) elif self._shutter: - painter.setPen(QPen(QColor(0, 255, 0), 3, Qt.PenStyle.SolidLine)) + painter.setPen(QPen(qcolor(BEAM_OPEN), 3, Qt.PenStyle.SolidLine)) elif self._is_daq_busy is True: # Use red color to indicate busy state - painter.setPen(QPen(QColor(255, 0, 0), 3, Qt.PenStyle.SolidLine)) + painter.setPen(QPen(qcolor(BEAM_BUSY), 3, Qt.PenStyle.SolidLine)) else: - painter.setPen(QPen(QColor(245, 121, 0), 3, Qt.PenStyle.SolidLine)) + painter.setPen(QPen(qcolor(BEAM_IDLE), 3, Qt.PenStyle.SolidLine)) painter.setBrush(Qt.BrushStyle.NoBrush) painter.drawRect( @@ -1077,8 +1086,8 @@ class SampleCameraImageLabel(QGraphicsView): gradient.setStart(QPointF(start.x, start.y)) # Start of the gradient (green) gradient.setFinalStop(QPointF(end.x, end.y)) # End of the gradient (red) - gradient.setColorAt(0.0, QColor("green")) # Start color - gradient.setColorAt(1.0, QColor("red")) # End color + gradient.setColorAt(0.0, qcolor(PATH_START)) # Start color + gradient.setColorAt(1.0, qcolor(PATH_END)) # End color pen = QPen() pen.setBrush(gradient) # Use gradient as the brush for the pen @@ -1091,13 +1100,13 @@ class SampleCameraImageLabel(QGraphicsView): def _draw_helical(self, painter: QPainter): if self._helical_start.sh_mm is not None: start_pxl = self._geom.smargon_to_picture(self._helical_start.sh_mm) - self._draw_circle(painter, start_pxl, QColor("green")) + self._draw_circle(painter, start_pxl, qcolor(PATH_START)) else: start_pxl = None if self._helical_end.sh_mm is not None: end_pxl = self._geom.smargon_to_picture(self._helical_end.sh_mm) - self._draw_circle(painter, end_pxl, QColor("red")) + self._draw_circle(painter, end_pxl, qcolor(PATH_END)) else: end_pxl = None diff --git a/src/aare/gui/widgets/local_contact_status_widget.py b/src/aare/gui/widgets/local_contact_status_widget.py index 4d8d45fc..00b1f879 100644 --- a/src/aare/gui/widgets/local_contact_status_widget.py +++ b/src/aare/gui/widgets/local_contact_status_widget.py @@ -9,6 +9,22 @@ from PySide6.QtCore import Qt, Slot from PySide6.QtWidgets import QFrame, QGridLayout, QLabel, QSizePolicy, QVBoxLayout from aare.gui.constants import LOGGER_NAME +from aare.gui.styles import ( + CARD_BORDER, + CHIP_BAD_BG, + CHIP_BAD_TEXT, + CHIP_INFO_BG, + CHIP_INFO_TEXT, + CHIP_NEUTRAL_BG, + CHIP_WARN_BG, + CHIP_WARN_TEXT, + HEADING_TEXT, + MUTED_TEXT, + SUBTLE_TEXT, + SUCCESS_BG, + SUCCESS_TEXT, + SURFACE, +) from aare.gui.widgets.title_label import TitleLabel logger = setup_logger(LOGGER_NAME) @@ -79,11 +95,11 @@ class LocalContactStatusWidget(QFrame): self.setFrameShadow(QFrame.Shadow.Raised) self.setObjectName("localContactStatusCard") self.setStyleSheet( - """ - QFrame#localContactStatusCard { - background: #f8fbff; - border: 1px solid #c7d4e5; - } + f""" + QFrame#localContactStatusCard {{ + background: {SURFACE}; + border: 1px solid {CARD_BORDER}; + }} """ ) self.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Maximum) @@ -96,7 +112,7 @@ class LocalContactStatusWidget(QFrame): self._summary = QLabel(summary, self) self._summary.setWordWrap(True) - self._summary.setStyleSheet("border: none; background: transparent; color: #334155;") + self._summary.setStyleSheet(f"border: none; background: transparent; color: {SUBTLE_TEXT};") layout.addWidget(self._summary) self._grid = QGridLayout() @@ -130,12 +146,12 @@ class LocalContactStatusWidget(QFrame): for row, key in enumerate(self._visible_fields): title = QLabel(self.FIELD_TITLES.get(key, key.replace("_", " ").title()), self) title.setStyleSheet( - "font-weight: 700; border: none; background: transparent; color: #1e293b;" + f"font-weight: 700; border: none; background: transparent; color: {HEADING_TEXT};" ) value = QLabel(self._badge("WAITING", tone="neutral"), self) value.setWordWrap(True) value.setTextInteractionFlags(Qt.TextInteractionFlag.TextSelectableByMouse) - value.setStyleSheet("border: none; background: transparent; color: #334155;") + value.setStyleSheet(f"border: none; background: transparent; color: {SUBTLE_TEXT};") self._row_widgets[key] = (title, value) self._grid.addWidget(title, row, 0, alignment=Qt.AlignmentFlag.AlignTop) self._grid.addWidget(value, row, 1) @@ -146,11 +162,11 @@ class LocalContactStatusWidget(QFrame): def _badge(self, text: str, *, tone: str = "neutral") -> str: palette = { - "good": ("#e7f6ea", "#1f6a3a"), - "warn": ("#fff3cd", "#7a4b00"), - "bad": ("#fdeaea", "#8b1e1e"), - "neutral": ("#e9eef5", "#475569"), - "info": ("#e8f1ff", "#12406a"), + "good": (SUCCESS_BG, SUCCESS_TEXT), + "warn": (CHIP_WARN_BG, CHIP_WARN_TEXT), + "bad": (CHIP_BAD_BG, CHIP_BAD_TEXT), + "neutral": (CHIP_NEUTRAL_BG, MUTED_TEXT), + "info": (CHIP_INFO_BG, CHIP_INFO_TEXT), } background, foreground = palette.get(tone, palette["neutral"]) return ( @@ -180,7 +196,7 @@ class LocalContactStatusWidget(QFrame): return ( f"{self._badge('ERROR', tone='bad')} " f"{self._badge(mode.upper(), tone='warn')} " - f"{error}" + f"{error}" ) if mode == "simulated": return self._badge("SIMULATED", tone="warn") diff --git a/src/aare/gui/widgets/login.py b/src/aare/gui/widgets/login.py index 38d8a1df..0f71f1f8 100644 --- a/src/aare/gui/widgets/login.py +++ b/src/aare/gui/widgets/login.py @@ -7,6 +7,8 @@ from PySide6.QtCore import QByteArray, QUrl, QUrlQuery, Slot from PySide6.QtNetwork import QNetworkAccessManager, QNetworkReply, QNetworkRequest from PySide6.QtWidgets import QDialog, QHBoxLayout, QLabel, QLineEdit, QPushButton, QVBoxLayout +from aare.gui.styles import BACKGROUND + class LoginDialog(QDialog): def __init__(self, base_url: str | None): @@ -14,7 +16,7 @@ class LoginDialog(QDialog): self.token = "" self.setWindowTitle("User Authentication") self.setMinimumWidth(400) - self.setStyleSheet("background-color: rgb(216, 228, 253);") + self.setStyleSheet(f"background-color: {BACKGROUND};") self._base_url = base_url self._reply = None self._network_manager = None diff --git a/src/aare/gui/widgets/number_line_edit.py b/src/aare/gui/widgets/number_line_edit.py index 168d68b4..802023b5 100644 --- a/src/aare/gui/widgets/number_line_edit.py +++ b/src/aare/gui/widgets/number_line_edit.py @@ -2,6 +2,8 @@ from PySide6.QtCore import Qt, Signal, Slot from PySide6.QtGui import QDoubleValidator from PySide6.QtWidgets import QCheckBox, QHBoxLayout, QLineEdit, QWidget +from aare.gui.styles import INPUT_BG, INPUT_DISABLED_BG, INPUT_DISABLED_INVALID_BG, INPUT_INVALID_BG + class NumberLineEdit(QLineEdit): newValue = Signal(float) @@ -13,7 +15,7 @@ class NumberLineEdit(QLineEdit): self._read_only: bool = False self._is_valid: bool = True - self.setStyleSheet("background-color: rgb(255, 255, 255);") + self.setStyleSheet(f"background-color: {INPUT_BG};") # Use a QDoubleValidator to only allow valid floating point numbers self.validator = QDoubleValidator() @@ -42,9 +44,9 @@ class NumberLineEdit(QLineEdit): # when text changes check validation and change the colour of the line edit self._is_valid = self.validate(text) if self._is_valid: - self.setStyleSheet("background-color: rgb(255, 255, 255);") + self.setStyleSheet(f"background-color: {INPUT_BG};") else: - self.setStyleSheet("background-color: rgb(255, 213, 213);") + self.setStyleSheet(f"background-color: {INPUT_INVALID_BG};") @Slot() def on_editing_finished(self): @@ -86,18 +88,18 @@ class NumberLineEdit(QLineEdit): super().setReadOnly(ro) self._read_only = ro if self._read_only and self._is_valid: - self.setStyleSheet("background-color: rgb(240, 240, 240);") + self.setStyleSheet(f"background-color: {INPUT_DISABLED_BG};") elif not self._read_only and self._is_valid: - self.setStyleSheet("background-color: rgb(255, 255, 255);") + self.setStyleSheet(f"background-color: {INPUT_BG};") elif self._read_only and not self._is_valid: - self.setStyleSheet("background-color: rgb(240, 225, 225);") + self.setStyleSheet(f"background-color: {INPUT_DISABLED_INVALID_BG};") elif not self._read_only and not self._is_valid: - self.setStyleSheet("background-color: rgb(255, 213, 213);") + self.setStyleSheet(f"background-color: {INPUT_INVALID_BG};") else: print( f"unknown ro state: {self._read_only} or validity {self._is_valid} default to writeable" ) - self.setStyleSheet("background-color: rgb(255, 255, 255);") + self.setStyleSheet(f"background-color: {INPUT_BG};") def get_default(self) -> float: return float(self.initial_value) @@ -167,13 +169,13 @@ class CheckedLineEdit(QWidget): if self._busy: self.check_box.setEnabled(False) - self.check_box.setStyleSheet("background-color: rgb(240, 240, 240);") + self.check_box.setStyleSheet(f"background-color: {INPUT_DISABLED_BG};") if self._checked: self.editor.force_update_value(self._internal_value) else: self.check_box.setEnabled(True) - self.check_box.setStyleSheet("background-color: rgb(255, 255, 255);") + self.check_box.setStyleSheet(f"background-color: {INPUT_BG};") self.check_box.blockSignals(False) self.blockSignals(False) diff --git a/src/aare/gui/widgets/pgroup_dialog.py b/src/aare/gui/widgets/pgroup_dialog.py index 6d467abf..296dbc9a 100644 --- a/src/aare/gui/widgets/pgroup_dialog.py +++ b/src/aare/gui/widgets/pgroup_dialog.py @@ -9,6 +9,8 @@ from PySide6.QtWidgets import ( QVBoxLayout, ) +from aare.gui.styles import DANGER_ACCENT + class PGroupDialog(QDialog): def __init__( @@ -78,9 +80,11 @@ class PGroupDialog(QDialog): def _set_error_state(self, is_error: bool, message: str | None = None) -> None: if is_error: - self.combo.setStyleSheet("border: 2px solid #d9534f;") + self.combo.setStyleSheet(f"border: 2px solid {DANGER_ACCENT};") if message: - self.label.setText(f"Set p-group: {message}") + self.label.setText( + f"Set p-group: {message}" + ) else: self.label.setText("Set p-group:") else: diff --git a/src/aare/gui/widgets/raster_grid_table.py b/src/aare/gui/widgets/raster_grid_table.py index 0c40345f..df73cfe3 100644 --- a/src/aare/gui/widgets/raster_grid_table.py +++ b/src/aare/gui/widgets/raster_grid_table.py @@ -9,6 +9,7 @@ from PySide6.QtWidgets import ( ) from aare.gui.scan_logic.raster_grid_manager import RasterGridManager +from aare.gui.styles import TABLE_SHADE_BG class RasterGridTable(QTableWidget): @@ -65,16 +66,16 @@ class RasterGridTable(QTableWidget): actions_layout.setContentsMargins(4, 4, 4, 4) actions_layout.setSpacing(4) - button_style = """ - QPushButton { + button_style = f""" + QPushButton {{ border: none; background: transparent; font-size: 14px; - } - QPushButton:hover { - background-color: #e0e0e0; + }} + QPushButton:hover {{ + background-color: {TABLE_SHADE_BG}; border-radius: 3px; - } + }} """ # Copy button diff --git a/src/aare/gui/widgets/splash_screen.py b/src/aare/gui/widgets/splash_screen.py index 91761223..314f56c0 100644 --- a/src/aare/gui/widgets/splash_screen.py +++ b/src/aare/gui/widgets/splash_screen.py @@ -1,6 +1,8 @@ from PySide6.QtCore import Qt from PySide6.QtWidgets import QApplication, QProgressBar, QSplashScreen +from aare.gui.styles import SPLASH_ACCENT, SPLASH_BG, SPLASH_BORDER, WHITE, qcolor + class LoadingSplashScreen(QSplashScreen): def __init__(self, pixmap): @@ -9,21 +11,21 @@ class LoadingSplashScreen(QSplashScreen): self.progress = QProgressBar(self) # Position the progress bar at the bottom of the splash screen self.progress.setGeometry(10, self.size().height() - 30, self.size().width() - 20, 20) - self.progress.setStyleSheet(""" - QProgressBar { - border: 1px solid #444; + self.progress.setStyleSheet(f""" + QProgressBar {{ + border: 1px solid {SPLASH_BORDER}; border-radius: 5px; text-align: center; - background-color: #222; - color: white; - } - QProgressBar::chunk { - background-color: #0078d7; - } + background-color: {SPLASH_BG}; + color: {WHITE}; + }} + QProgressBar::chunk {{ + background-color: {SPLASH_ACCENT}; + }} """) def set_progress(self, value, message=None): self.progress.setValue(value) if message: - self.showMessage(message, Qt.AlignBottom | Qt.AlignCenter, Qt.white) + self.showMessage(message, Qt.AlignBottom | Qt.AlignCenter, qcolor(WHITE)) QApplication.processEvents() diff --git a/src/aare/gui/widgets/status_bar.py b/src/aare/gui/widgets/status_bar.py index 8a600382..00466b6b 100644 --- a/src/aare/gui/widgets/status_bar.py +++ b/src/aare/gui/widgets/status_bar.py @@ -8,6 +8,15 @@ from PySide6.QtGui import QFont from PySide6.QtWidgets import QDialog, QLabel, QMenu, QMessageBox, QSizePolicy, QStatusBar from aare.gui.constants import LOGGER_NAME +from aare.gui.styles import ( + STATE_TELL_TEXT, + STATUS_ALERT, + STATUS_INFO, + STATUS_OK, + STATUS_REQUEST, + STATUS_VACANT, + STATUS_WARN, +) from aare.gui.widgets.baton_request_dialog import BatonRequestDialog from aare.gui.widgets.clickable_label import ClickableLabel from aare.gui.widgets.pgroup_dialog import PGroupDialog @@ -102,7 +111,7 @@ class StatusBar(QStatusBar): @Slot(str, bool) def show_connection_message(self, msg: str, is_error: bool = True): - color = "red" if is_error else "green" + color = STATUS_ALERT if is_error else STATUS_OK self._message_clear_timer.stop() self.message_label.setText(msg) self.message_label.setStyleSheet(f"color: {color}; font-weight: bold;") @@ -146,9 +155,9 @@ class StatusBar(QStatusBar): self.transmission.set_value(f"{status.bl.transmission:.5f}") if status.bl.ring_current_mA < 5.0: - self.ring_current.set_value(f"{status.bl.ring_current_mA:.2f}", "red") + self.ring_current.set_value(f"{status.bl.ring_current_mA:.2f}", STATUS_ALERT) elif status.bl.ring_current_mA < 390.0: - self.ring_current.set_value(f"{status.bl.ring_current_mA:.2f}", "orange") + self.ring_current.set_value(f"{status.bl.ring_current_mA:.2f}", STATUS_WARN) else: self.ring_current.set_value(f"{status.bl.ring_current_mA:.2f}") @@ -156,28 +165,28 @@ class StatusBar(QStatusBar): self.wvl.set_value(f"{status.diffraction.wavelength_angstrom:.2f}") if status.bl.cryojet_K < 110.0: - self.cryo_label.set_value(f"{status.bl.cryojet_K:.1f}", "blue") + self.cryo_label.set_value(f"{status.bl.cryojet_K:.1f}", STATUS_INFO) elif status.bl.cryojet_K < 250.0: - self.cryo_label.set_value(f"{status.bl.cryojet_K:.1f}", "orange") + self.cryo_label.set_value(f"{status.bl.cryojet_K:.1f}", STATUS_WARN) else: - self.cryo_label.set_value(f"{status.bl.cryojet_K:.1f}", "red") + self.cryo_label.set_value(f"{status.bl.cryojet_K:.1f}", STATUS_ALERT) if status.bl.shutter_open: self.shutter_label.setText( - """Fast Shutter: Open ☢️ """ + f"""Fast Shutter: Open ☢️ """ ) else: self.shutter_label.setText( - """Fast Shutter: Closed 🚪 """ + f"""Fast Shutter: Closed 🚪 """ ) if status.bl.exp_shutter_open: self.exp_shutter_label.setText( - """ExpHutch Shutter: Open """ + f"""ExpHutch Shutter: Open """ ) else: self.exp_shutter_label.setText( - """ExpHutch Shutter: Closed 🚪 """ + f"""ExpHutch Shutter: Closed 🚪 """ ) if status.session.current_pgroup is not None: @@ -188,29 +197,29 @@ class StatusBar(QStatusBar): self.state_label.setText(f"""State: {status.state.display_name()} """) tell_text = "—" - tell_color = "rgb(55, 67, 87)" + tell_color = STATE_TELL_TEXT if status.tell_state is not None: tell_text = status.tell_state.activity.display_name() if status.tell_state.activity.value == "error": - tell_color = "red" + tell_color = STATUS_ALERT elif status.tell_state.activity.value in { "mounting", "unmounting", "drying", "cooling", }: - tell_color = "orange" + tell_color = STATUS_WARN else: - tell_color = "green" + tell_color = STATUS_OK self.tell_state_label.setText(f"Tell: {tell_text} ") self.tell_state_label.setStyleSheet(f"color: {tell_color};") if status.busy: - busy_flag = """ Busy 🔒 """ + busy_flag = f""" Busy 🔒 """ else: - busy_flag = """ Idle 🔓 """ + busy_flag = f""" Idle 🔓 """ html_content = f"""Beamline: {busy_flag} """ @@ -218,15 +227,15 @@ class StatusBar(QStatusBar): session_flag = "" if status.session.session == SessionsStateEnum.Vacant: - session_flag = """ Vacant 🔓 """ + session_flag = f""" Vacant 🔓 """ elif status.session.session == SessionsStateEnum.OwnedByYou: - session_flag = """ Owned ⬤ """ + session_flag = f""" Owned ⬤ """ elif status.session.session == SessionsStateEnum.OwnedByElse: - session_flag = """ Other 🔒 """ + session_flag = f""" Other 🔒 """ elif status.session.session == SessionsStateEnum.PendingYouToElse: - session_flag = """ Waiting... ⏳ """ + session_flag = f""" Waiting... ⏳ """ elif status.session.session == SessionsStateEnum.PendingElseToYou: - session_flag = """ Request! ⚡ """ + session_flag = f""" Request! ⚡ """ html_content_session = f"""Session: {session_flag}""" self.session_label.setText(html_content_session) diff --git a/src/aare/gui/widgets/title_label.py b/src/aare/gui/widgets/title_label.py index ac9eef1f..3e1090dd 100644 --- a/src/aare/gui/widgets/title_label.py +++ b/src/aare/gui/widgets/title_label.py @@ -1,6 +1,8 @@ from PySide6.QtCore import QSettings, Qt, QTimer from PySide6.QtWidgets import QHBoxLayout, QLabel, QLayout, QPushButton +from aare.gui.styles import BANNER, BANNER_TEXT + # Universal vertical rhythm between stacked panels: each panel contributes # PANEL_VMARGIN top and bottom, the column adds PANEL_VSPACING between them, # so every banner-to-banner gap is 4 + 3 + 4 = 11px in every column. @@ -34,7 +36,7 @@ class TitleLabel(QLabel): # widgets and would paint the toggle button solid purple, overriding # the app QSS. self.setStyleSheet( - "TitleLabel { background-color: #4B0082; color: #ffffff;" + f"TitleLabel {{ background-color: {BANNER}; color: {BANNER_TEXT};" " font-size: 16px; font-weight: 700; }" ) self.setAlignment(Qt.AlignmentFlag.AlignCenter) @@ -55,8 +57,8 @@ class TitleLabel(QLabel): # Bare glyph, no pill: the shared beamlineStateToggleButton QSS paints # a translucent white background, which is unwanted on these banners. self.toggle_button.setStyleSheet( - "QPushButton { background: transparent; border: none;" - " color: #ffffff; font-size: 14px; font-weight: 700; }" + f"QPushButton {{ background: transparent; border: none;" + f" color: {BANNER_TEXT}; font-size: 14px; font-weight: 700; }}" ) self.toggle_button.setToolTip("Minimise panel") self.toggle_button.setFixedSize(21, 21)