style: move widget colors to the shared palette
Same mechanical swap for the widgets and the tutorial manager: painter QColors go through qcolor(), inline QSS literals become palette constants (baton dialog, busy overlay, status bar, camera overlays, splash screen, numeric inputs). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -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"<span style='color:#555;'><i>{view.hint}</i></span>")
|
||||
text_parts.append(f"<span style='color:{NOTE_TEXT};'><i>{view.hint}</i></span>")
|
||||
|
||||
self.callout.setText("<br><br>".join(text_parts))
|
||||
self.callout.setMaximumWidth(460)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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"<span style='background:transparent;'><b>Status:</b> "
|
||||
|
||||
@@ -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 <b>busy</b>. Your request was accepted and "
|
||||
"the baton will be transferred as soon as the current operation completes."
|
||||
|
||||
@@ -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,
|
||||
)
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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"<span style='color:#8b1e1e;'>{error}</span>"
|
||||
f"<span style='color:{CHIP_BAD_TEXT};'>{error}</span>"
|
||||
)
|
||||
if mode == "simulated":
|
||||
return self._badge("SIMULATED", tone="warn")
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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: <span style='color:#d9534f;'>{message}</span>")
|
||||
self.label.setText(
|
||||
f"Set p-group: <span style='color:{DANGER_ACCENT};'>{message}</span>"
|
||||
)
|
||||
else:
|
||||
self.label.setText("Set p-group:")
|
||||
else:
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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: <span style="color: red ; "> Open ☢️ </span>"""
|
||||
f"""Fast Shutter: <span style="color: {STATUS_ALERT} ; "> Open ☢️ </span>"""
|
||||
)
|
||||
else:
|
||||
self.shutter_label.setText(
|
||||
"""Fast Shutter: <span style="color: green ; "> Closed 🚪 </span>"""
|
||||
f"""Fast Shutter: <span style="color: {STATUS_OK} ; "> Closed 🚪 </span>"""
|
||||
)
|
||||
|
||||
if status.bl.exp_shutter_open:
|
||||
self.exp_shutter_label.setText(
|
||||
"""ExpHutch Shutter: <span style="color: red ; "> Open </span>"""
|
||||
f"""ExpHutch Shutter: <span style="color: {STATUS_ALERT} ; "> Open </span>"""
|
||||
)
|
||||
else:
|
||||
self.exp_shutter_label.setText(
|
||||
"""ExpHutch Shutter: <span style="color: green ; "> Closed 🚪 </span>"""
|
||||
f"""ExpHutch Shutter: <span style="color: {STATUS_OK} ; "> Closed 🚪 </span>"""
|
||||
)
|
||||
|
||||
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 = """ <span style="color: red; "> Busy 🔒 </span>"""
|
||||
busy_flag = f""" <span style="color: {STATUS_ALERT}; "> Busy 🔒 </span>"""
|
||||
else:
|
||||
busy_flag = """ <span style="color: green ; "> Idle 🔓 </span>"""
|
||||
busy_flag = f""" <span style="color: {STATUS_OK} ; "> Idle 🔓 </span>"""
|
||||
|
||||
html_content = f"""Beamline: {busy_flag} """
|
||||
|
||||
@@ -218,15 +227,15 @@ class StatusBar(QStatusBar):
|
||||
|
||||
session_flag = ""
|
||||
if status.session.session == SessionsStateEnum.Vacant:
|
||||
session_flag = """<span style="color: yellow ; "> Vacant 🔓 </span>"""
|
||||
session_flag = f"""<span style="color: {STATUS_VACANT} ; "> Vacant 🔓 </span>"""
|
||||
elif status.session.session == SessionsStateEnum.OwnedByYou:
|
||||
session_flag = """<span style="color: green ; "> Owned ⬤ </span>"""
|
||||
session_flag = f"""<span style="color: {STATUS_OK} ; "> Owned ⬤ </span>"""
|
||||
elif status.session.session == SessionsStateEnum.OwnedByElse:
|
||||
session_flag = """<span style="color: red ; "> Other 🔒 </span>"""
|
||||
session_flag = f"""<span style="color: {STATUS_ALERT} ; "> Other 🔒 </span>"""
|
||||
elif status.session.session == SessionsStateEnum.PendingYouToElse:
|
||||
session_flag = """<span style="color: orange ; "> Waiting... ⏳ </span>"""
|
||||
session_flag = f"""<span style="color: {STATUS_WARN} ; "> Waiting... ⏳ </span>"""
|
||||
elif status.session.session == SessionsStateEnum.PendingElseToYou:
|
||||
session_flag = """<span style="color: cyan ; "> Request! ⚡ </span>"""
|
||||
session_flag = f"""<span style="color: {STATUS_REQUEST} ; "> Request! ⚡ </span>"""
|
||||
|
||||
html_content_session = f"""Session: {session_flag}"""
|
||||
self.session_label.setText(html_content_session)
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user