busy_ovoerlay: added a busy_overlay widget so that both axis cameras and the sam cam source the same busy overlay settings
This commit is contained in:
+28
-15
@@ -12,15 +12,19 @@ from PySide6.QtWidgets import (
|
||||
QDockWidget,
|
||||
QTabWidget)
|
||||
|
||||
#Common imports
|
||||
from aare.common.auth_models import BatonStatus
|
||||
from aare.common.coordinate import Coordinate, SmargonCoordinate
|
||||
from aare.common.diffraction_geometry import DiffractionGeometry
|
||||
from aare.common.logger_config import setup_logger
|
||||
from aare.common.models import SampleShortInfoList, TokenData, DAQStatusModel, BeamlineStateEnum
|
||||
from aare.common.sample_geometry import SampleGeometryModel
|
||||
from aare.gui.models.gui_state_manager import UIStateManager
|
||||
from aare.gui.panels.LogPanel import LogDock
|
||||
|
||||
#Gui Models
|
||||
from aare.gui.models.gui_state_manager import UIStateManager
|
||||
|
||||
#panels
|
||||
from aare.gui.panels.LogPanel import LogDock
|
||||
from aare.gui.panels.beamline_controls import BeamlineControls
|
||||
from aare.gui.panels.beamline_state_panel import BeamlineStatePanel
|
||||
from aare.gui.panels.data_collection_settings import DataCollectionSettings
|
||||
@@ -37,33 +41,38 @@ from aare.gui.panels.tell_sample_panel import TellSamplePanel
|
||||
from aare.gui.panels.face_detection_panel import FaceDetectionPanel
|
||||
from aare.gui.panels.smargon_trace_panel import SmargonTracePanel
|
||||
from aare.gui.panels.axis_video_panel import AxisVideoPanel
|
||||
from aare.gui.panels.fluorescence_panel import FluorescencePanel
|
||||
from aare.gui.panels.automation_panel import AutomationProgressWidget
|
||||
|
||||
#Scan Logic
|
||||
from aare.gui.scan_logic.raster_grid_manager import RasterGridManager
|
||||
from aare.gui.scan_logic.rotation_scan_manager import RotationScanManager
|
||||
from aare.gui.scan_logic.sample_mount_logic import SampleMountLogic
|
||||
from aare.gui.threads.axis_video_thread import VideoThread
|
||||
|
||||
#Threads
|
||||
from aare.gui.threads.axis_video_thread import VideoThread
|
||||
from aare.gui.threads.prediction_subscriber import PredictionSubscriber
|
||||
from aare.gui.threads.daq_worker import DAQWorker
|
||||
from aare.gui.threads.jfjoch_viewer import JFJochDBusClient
|
||||
|
||||
#Tutorials
|
||||
from aare.gui.tutorials.tutorial_actions import TutorialActionExecutor
|
||||
from aare.gui.tutorials.tutorial_manager import TutorialManager
|
||||
from aare.gui.tutorials.tutorial_runtime import DictionaryTextResolver, TutorialEventBus
|
||||
from aare.gui.tutorials.tutorial_targets import MainWindowTutorialTargetResolver
|
||||
from aare.gui.tutorials.tutorial_registration import register_tutorials
|
||||
from aare.gui.tutorials.tutroial_texts import MANUAL_MOUNT_TUTORIAL
|
||||
|
||||
from aare.gui.tutorials.controls_help_dialog import ControlsHelpDialog
|
||||
|
||||
from aare.gui.threads.prediction_subscriber import PredictionSubscriber
|
||||
from aare.gui.threads.daq_worker import DAQWorker
|
||||
from aare.gui.threads.jfjoch_viewer import JFJochDBusClient
|
||||
from aare.gui.tutorials.tutorial_registration import register_tutorials
|
||||
|
||||
#Widgets
|
||||
from aare.gui.widgets.alert_banner import AlertBanner
|
||||
from aare.gui.widgets.baton_request_dialog import BatonRequestDialog, BatonPendingDialog
|
||||
from aare.gui.widgets.camera_image import SampleCameraImageLabel
|
||||
from aare.gui.widgets.no_wheel_scroll_area import NoWheelScrollArea
|
||||
from aare.gui.widgets.status_bar import StatusBar
|
||||
from aare.gui.widgets.video_image import VideoGraphicsView
|
||||
from aare.gui.panels.fluorescence_panel import FluorescencePanel
|
||||
|
||||
from aare.gui.panels.automation_panel import AutomationProgressWidget
|
||||
from aare.gui.widgets.busy_overlay import build_busy_overlay_style
|
||||
|
||||
logger = setup_logger("aareGUI")
|
||||
|
||||
@@ -1299,14 +1308,18 @@ class MainWindow(QMainWindow):
|
||||
if hasattr(self, "gonio_camera_thread") and self.gonio_camera_thread is not None:
|
||||
self.gonio_camera_thread.set_busy(s.busy)
|
||||
|
||||
axis_busy_text = self._axis_busy_text_from_status(s)
|
||||
busy_style = build_busy_overlay_style(
|
||||
is_busy=bool(s.busy),
|
||||
tell_state=s.tell_state,
|
||||
session_state=getattr(getattr(s, "session", None), "session", None),
|
||||
)
|
||||
|
||||
if hasattr(self, "beamline_view_panel") and self.beamline_view_panel is not None:
|
||||
self.beamline_view_panel.set_busy_state(bool(s.busy), axis_busy_text)
|
||||
self.beamline_view_panel.set_busy_style(busy_style)
|
||||
if hasattr(self, "gonio_view_panel") and self.gonio_view_panel is not None:
|
||||
self.gonio_view_panel.set_busy_state(bool(s.busy), axis_busy_text)
|
||||
self.gonio_view_panel.set_busy_style(busy_style)
|
||||
if hasattr(self, "beamline_combined_panel") and self.beamline_combined_panel is not None:
|
||||
self.beamline_combined_panel.set_busy_state(bool(s.busy), axis_busy_text)
|
||||
self.beamline_combined_panel.set_busy_style(busy_style)
|
||||
|
||||
self.target_stability_panel.set_beam_center(
|
||||
s.geom.beam_location_pxl.x,
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
from PySide6.QtCore import Qt, Signal
|
||||
from PySide6.QtWidgets import QWidget, QVBoxLayout, QHBoxLayout, QLabel, QPushButton
|
||||
|
||||
from aare.gui.widgets.busy_overlay import BusyOverlayStyle
|
||||
from aare.gui.widgets.video_image import VideoGraphicsView
|
||||
|
||||
|
||||
@@ -13,18 +14,46 @@ class AxisVideoPanel(QWidget):
|
||||
self._title_label = QLabel(title, self)
|
||||
self._title_label.setStyleSheet("font-weight: bold;")
|
||||
|
||||
self._status_label = QLabel("", self)
|
||||
self._status_label.setAlignment(Qt.AlignmentFlag.AlignCenter)
|
||||
self._status_label.setMinimumWidth(140)
|
||||
self._status_label.setStyleSheet(
|
||||
"QLabel {"
|
||||
" padding: 4px 10px;"
|
||||
" border-radius: 10px;"
|
||||
self._status_container = QWidget(self)
|
||||
self._status_container.setStyleSheet(
|
||||
"QWidget {"
|
||||
" border-radius: 12px;"
|
||||
" background-color: #d9e2f2;"
|
||||
" color: #2f3b52;"
|
||||
"}"
|
||||
)
|
||||
|
||||
self._status_dot = QLabel(self._status_container)
|
||||
self._status_dot.setFixedSize(10, 10)
|
||||
self._status_dot.setStyleSheet(
|
||||
"QLabel {"
|
||||
" min-width: 10px;"
|
||||
" max-width: 10px;"
|
||||
" min-height: 10px;"
|
||||
" max-height: 10px;"
|
||||
" border-radius: 5px;"
|
||||
" background-color: transparent;"
|
||||
"}"
|
||||
)
|
||||
|
||||
self._status_label = QLabel("", self._status_container)
|
||||
self._status_label.setAlignment(Qt.AlignmentFlag.AlignCenter)
|
||||
self._status_label.setStyleSheet(
|
||||
"QLabel {"
|
||||
" background-color: transparent;"
|
||||
" color: #2f3b52;"
|
||||
" font-weight: bold;"
|
||||
"}"
|
||||
)
|
||||
|
||||
status_layout = QHBoxLayout(self._status_container)
|
||||
status_layout.setContentsMargins(10, 6, 12, 6)
|
||||
status_layout.setSpacing(8)
|
||||
status_layout.addWidget(self._status_dot)
|
||||
status_layout.addWidget(self._status_label)
|
||||
|
||||
self._status_container.setMinimumWidth(190)
|
||||
self._status_container.hide()
|
||||
|
||||
self._refresh_button = QPushButton("Refresh Axis Cameras", self)
|
||||
self._refresh_button.clicked.connect(self.refresh_requested.emit)
|
||||
|
||||
@@ -34,7 +63,7 @@ class AxisVideoPanel(QWidget):
|
||||
controls_layout.setContentsMargins(0, 0, 0, 0)
|
||||
controls_layout.addWidget(self._title_label)
|
||||
controls_layout.addStretch()
|
||||
controls_layout.addWidget(self._status_label)
|
||||
controls_layout.addWidget(self._status_container)
|
||||
controls_layout.addWidget(self._refresh_button)
|
||||
|
||||
root_layout = QVBoxLayout(self)
|
||||
@@ -43,33 +72,74 @@ class AxisVideoPanel(QWidget):
|
||||
root_layout.addLayout(controls_layout)
|
||||
root_layout.addWidget(self.view)
|
||||
|
||||
def set_busy_state(self, busy: bool, text: str | None = None) -> None:
|
||||
status_text = (text or "BUSY").upper() if busy else ""
|
||||
def _all_video_views(self) -> list[VideoGraphicsView]:
|
||||
views: list[VideoGraphicsView] = []
|
||||
if isinstance(self.view, VideoGraphicsView):
|
||||
views.append(self.view)
|
||||
views.extend(self.findChildren(VideoGraphicsView))
|
||||
unique_views: list[VideoGraphicsView] = []
|
||||
for view in views:
|
||||
if view not in unique_views:
|
||||
unique_views.append(view)
|
||||
return unique_views
|
||||
|
||||
if busy:
|
||||
self._status_label.setText(status_text)
|
||||
def set_busy_style(self, style: BusyOverlayStyle | None) -> None:
|
||||
if style is None:
|
||||
self._status_label.setText("")
|
||||
self._status_container.setStyleSheet(
|
||||
"QWidget {"
|
||||
" border-radius: 12px;"
|
||||
" background-color: #d9e2f2;"
|
||||
"}"
|
||||
)
|
||||
self._status_dot.setStyleSheet(
|
||||
"QLabel {"
|
||||
" min-width: 10px;"
|
||||
" max-width: 10px;"
|
||||
" min-height: 10px;"
|
||||
" max-height: 10px;"
|
||||
" border-radius: 5px;"
|
||||
" background-color: transparent;"
|
||||
"}"
|
||||
)
|
||||
self._status_label.setStyleSheet(
|
||||
"QLabel {"
|
||||
" padding: 5px 12px;"
|
||||
" border-radius: 11px;"
|
||||
" background-color: #f7c948;"
|
||||
" color: #3b2f00;"
|
||||
" background-color: transparent;"
|
||||
" color: #2f3b52;"
|
||||
" font-weight: bold;"
|
||||
"}"
|
||||
)
|
||||
self._status_container.hide()
|
||||
else:
|
||||
self._status_label.setText("")
|
||||
self._status_label.setStyleSheet(
|
||||
"QLabel {"
|
||||
" padding: 4px 10px;"
|
||||
" border-radius: 10px;"
|
||||
" background-color: #d9e2f2;"
|
||||
" color: #2f3b52;"
|
||||
self._status_label.setText(style.text)
|
||||
self._status_container.setStyleSheet(
|
||||
"QWidget {"
|
||||
" border-radius: 12px;"
|
||||
f" background-color: {style.badge_bg};"
|
||||
"}"
|
||||
)
|
||||
self._status_dot.setStyleSheet(
|
||||
"QLabel {"
|
||||
" min-width: 10px;"
|
||||
" max-width: 10px;"
|
||||
" min-height: 10px;"
|
||||
" max-height: 10px;"
|
||||
" border-radius: 5px;"
|
||||
f" background-color: {style.accent_dot};"
|
||||
"}"
|
||||
)
|
||||
self._status_label.setStyleSheet(
|
||||
"QLabel {"
|
||||
" background-color: transparent;"
|
||||
f" color: {style.badge_fg};"
|
||||
" font-weight: bold;"
|
||||
"}"
|
||||
)
|
||||
self._status_container.show()
|
||||
|
||||
if hasattr(self.view, "set_busy_overlay"):
|
||||
self.view.set_busy_overlay(busy, status_text or "BUSY")
|
||||
for view in self._all_video_views():
|
||||
if hasattr(view, "set_busy_overlay_style"):
|
||||
view.set_busy_overlay_style(style)
|
||||
|
||||
def set_status_text(self, text: str) -> None:
|
||||
self._status_label.setText(text or "")
|
||||
@@ -0,0 +1,108 @@
|
||||
from dataclasses import dataclass
|
||||
|
||||
from PySide6.QtGui import QColor
|
||||
|
||||
from aare.common.tell_models import TellStateModel
|
||||
from aare.common.models import SessionsStateEnum
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class BusyOverlayStyle:
|
||||
text: str
|
||||
badge_bg: str
|
||||
badge_fg: str
|
||||
overlay_fill: QColor
|
||||
overlay_border: QColor
|
||||
overlay_text: QColor
|
||||
accent_dot: str
|
||||
|
||||
|
||||
def build_busy_overlay_style(
|
||||
*,
|
||||
is_busy: bool,
|
||||
tell_state: TellStateModel | None,
|
||||
session_state: SessionsStateEnum | None = None,
|
||||
) -> BusyOverlayStyle | None:
|
||||
if session_state == SessionsStateEnum.Vacant:
|
||||
return BusyOverlayStyle(
|
||||
text="SESSION VACANT",
|
||||
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",
|
||||
)
|
||||
|
||||
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",
|
||||
)
|
||||
|
||||
if not is_busy:
|
||||
return None
|
||||
|
||||
activity_value = str(getattr(getattr(tell_state, "activity", None), "value", "") or "").lower()
|
||||
|
||||
if activity_value == "mounting":
|
||||
return BusyOverlayStyle(
|
||||
text="TELL 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",
|
||||
)
|
||||
|
||||
if activity_value == "unmounting":
|
||||
return BusyOverlayStyle(
|
||||
text="TELL 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",
|
||||
)
|
||||
|
||||
if activity_value == "drying":
|
||||
return BusyOverlayStyle(
|
||||
text="TELL 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",
|
||||
)
|
||||
|
||||
if activity_value == "cooling":
|
||||
return BusyOverlayStyle(
|
||||
text="TELL 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",
|
||||
)
|
||||
|
||||
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",
|
||||
)
|
||||
@@ -23,12 +23,19 @@ from PySide6.QtWidgets import (
|
||||
QFrame,
|
||||
)
|
||||
|
||||
from aare.common.models import DAQStatusModel, AutofocusSettings, SampleCameraSettings, BeamlineStateEnum, \
|
||||
SessionsStateEnum
|
||||
from aare.gui.models.bookmark import SmargonBookmarkList
|
||||
from aare.gui.widgets.busy_overlay import build_busy_overlay_style, BusyOverlayStyle
|
||||
from aare.gui.scan_logic.raster_grid_manager import RasterGridManager
|
||||
|
||||
from aare.common.models import (
|
||||
DAQStatusModel,
|
||||
AutofocusSettings,
|
||||
SampleCameraSettings,
|
||||
BeamlineStateEnum,
|
||||
SessionsStateEnum
|
||||
)
|
||||
from aare.common.coordinate import Coordinate, SmargonCoordinate
|
||||
from aare.common.sample_geometry import SampleGeometryModel
|
||||
from aare.gui.scan_logic.raster_grid_manager import RasterGridManager
|
||||
from aare.common.logger_config import setup_logger
|
||||
|
||||
logger = setup_logger("aareGUI")
|
||||
@@ -77,6 +84,7 @@ class SampleCameraImageLabel(QGraphicsView):
|
||||
self.__last_grid_update_ts = 0.0
|
||||
self.__grid_update_min_interval_s = 1.0 / 25.0
|
||||
self.__tell_state = None
|
||||
self.__busy_overlay_style: BusyOverlayStyle | None = None
|
||||
|
||||
self.__geom = geom
|
||||
self.__bookmarks: SmargonBookmarkList = SmargonBookmarkList()
|
||||
@@ -223,9 +231,11 @@ class SampleCameraImageLabel(QGraphicsView):
|
||||
return f"TELL {activity_name}".upper()
|
||||
|
||||
def __draw_busy_overlay(self, painter: QPainter):
|
||||
if not self.__is_daq_busy:
|
||||
if self.__busy_overlay_style is None:
|
||||
return
|
||||
|
||||
style = self.__busy_overlay_style
|
||||
|
||||
painter.save()
|
||||
painter.resetTransform()
|
||||
|
||||
@@ -234,13 +244,8 @@ class SampleCameraImageLabel(QGraphicsView):
|
||||
font.setBold(True)
|
||||
painter.setFont(font)
|
||||
|
||||
painter.setPen(QPen(QColor(255, 255, 255, 200), 2, Qt.PenStyle.SolidLine))
|
||||
painter.setBrush(QColor(255, 0, 0, 150))
|
||||
|
||||
text = self.__busy_overlay_text()
|
||||
|
||||
font_metrics = QFontMetrics(font)
|
||||
text_rect = font_metrics.boundingRect(text)
|
||||
text_rect = font_metrics.boundingRect(style.text)
|
||||
|
||||
padding_x = 20
|
||||
padding_y = 14
|
||||
@@ -260,14 +265,16 @@ class SampleCameraImageLabel(QGraphicsView):
|
||||
bg_height
|
||||
)
|
||||
|
||||
painter.setPen(QPen(style.overlay_border, 2, Qt.PenStyle.SolidLine))
|
||||
painter.setBrush(style.overlay_fill)
|
||||
painter.drawRoundedRect(bg_rect, 10, 10)
|
||||
|
||||
painter.setPen(QPen(QColor(255, 255, 255), 2, Qt.PenStyle.SolidLine))
|
||||
painter.setPen(QPen(style.overlay_text, 2, Qt.PenStyle.SolidLine))
|
||||
text_pos = QPoint(
|
||||
position_x + padding_x,
|
||||
position_y + padding_y + font_metrics.ascent()
|
||||
)
|
||||
painter.drawText(text_pos, text)
|
||||
painter.drawText(text_pos, style.text)
|
||||
|
||||
painter.restore()
|
||||
|
||||
@@ -617,6 +624,15 @@ class SampleCameraImageLabel(QGraphicsView):
|
||||
self.__session_state = new_session_state
|
||||
self.update()
|
||||
|
||||
new_busy_style = build_busy_overlay_style(
|
||||
is_busy=bool(s.busy),
|
||||
tell_state=s.tell_state,
|
||||
session_state=self.__session_state,
|
||||
)
|
||||
if new_busy_style != self.__busy_overlay_style:
|
||||
self.__busy_overlay_style = new_busy_style
|
||||
self.update()
|
||||
|
||||
if s.bl.shutter_open != self.__shutter:
|
||||
self.__shutter = s.bl.shutter_open
|
||||
|
||||
|
||||
@@ -2,6 +2,8 @@ from PySide6.QtCore import Qt, Slot, QRectF
|
||||
from PySide6.QtGui import QPainter, QPixmap, QImage, QFont, QColor, QPen, QFontMetrics
|
||||
from PySide6.QtWidgets import QGraphicsView, QGraphicsScene, QGraphicsPixmapItem
|
||||
|
||||
from aare.gui.widgets.busy_overlay import BusyOverlayStyle
|
||||
|
||||
|
||||
class VideoGraphicsView(QGraphicsView):
|
||||
def __init__(self):
|
||||
@@ -30,8 +32,7 @@ class VideoGraphicsView(QGraphicsView):
|
||||
self.min_zoom = 0.1
|
||||
self.max_zoom = 5.0
|
||||
|
||||
self._busy_overlay_visible = False
|
||||
self._busy_overlay_text = "BUSY"
|
||||
self._busy_overlay_style: BusyOverlayStyle | None = None
|
||||
|
||||
@Slot(QImage)
|
||||
def update_frame(self, qt_image : QImage):
|
||||
@@ -45,9 +46,10 @@ class VideoGraphicsView(QGraphicsView):
|
||||
|
||||
self.viewport().update()
|
||||
|
||||
def set_busy_overlay(self, visible: bool, text: str = "BUSY") -> None:
|
||||
self._busy_overlay_visible = bool(visible)
|
||||
self._busy_overlay_text = str(text or "BUSY").upper()
|
||||
def set_busy_overlay_style(self, style: BusyOverlayStyle | None) -> None:
|
||||
if self._busy_overlay_style == style:
|
||||
return
|
||||
self._busy_overlay_style = style
|
||||
self.viewport().update()
|
||||
|
||||
def fit_to_view(self):
|
||||
@@ -106,9 +108,11 @@ class VideoGraphicsView(QGraphicsView):
|
||||
def drawForeground(self, painter: QPainter, rect: QRectF):
|
||||
super().drawForeground(painter, rect)
|
||||
|
||||
if not self._busy_overlay_visible:
|
||||
if self._busy_overlay_style is None:
|
||||
return
|
||||
|
||||
style = self._busy_overlay_style
|
||||
|
||||
painter.save()
|
||||
painter.resetTransform()
|
||||
painter.setRenderHint(QPainter.RenderHint.Antialiasing, True)
|
||||
@@ -118,14 +122,15 @@ class VideoGraphicsView(QGraphicsView):
|
||||
font.setBold(True)
|
||||
painter.setFont(font)
|
||||
|
||||
text = self._busy_overlay_text
|
||||
fm = QFontMetrics(font)
|
||||
text_rect = fm.boundingRect(text)
|
||||
text_rect = fm.boundingRect(style.text)
|
||||
|
||||
padding_x = 20
|
||||
dot_diameter = 14
|
||||
gap = 12
|
||||
padding_x = 22
|
||||
padding_y = 14
|
||||
bg_width = text_rect.width() + padding_x * 2
|
||||
bg_height = text_rect.height() + padding_y * 2
|
||||
bg_width = text_rect.width() + dot_diameter + gap + padding_x * 2
|
||||
bg_height = max(text_rect.height(), dot_diameter) + padding_y * 2
|
||||
|
||||
viewport_width = self.viewport().width()
|
||||
viewport_height = self.viewport().height()
|
||||
@@ -135,15 +140,19 @@ class VideoGraphicsView(QGraphicsView):
|
||||
|
||||
bg_rect = QRectF(pos_x, pos_y, bg_width, bg_height)
|
||||
|
||||
painter.setPen(QPen(QColor(255, 255, 255, 220), 2))
|
||||
painter.setBrush(QColor(200, 30, 30, 185))
|
||||
painter.setPen(QPen(style.overlay_border, 2))
|
||||
painter.setBrush(style.overlay_fill)
|
||||
painter.drawRoundedRect(bg_rect, 14, 14)
|
||||
|
||||
painter.setPen(QPen(QColor(255, 255, 255), 1))
|
||||
painter.drawText(
|
||||
bg_rect.left() + padding_x,
|
||||
bg_rect.top() + padding_y + fm.ascent(),
|
||||
text,
|
||||
)
|
||||
dot_x = bg_rect.left() + padding_x
|
||||
dot_y = bg_rect.top() + (bg_rect.height() - dot_diameter) / 2
|
||||
painter.setPen(Qt.PenStyle.NoPen)
|
||||
painter.setBrush(QColor(style.accent_dot))
|
||||
painter.drawEllipse(QRectF(dot_x, dot_y, dot_diameter, dot_diameter))
|
||||
|
||||
painter.setPen(QPen(style.overlay_text, 1))
|
||||
text_x = dot_x + dot_diameter + gap
|
||||
text_y = bg_rect.top() + padding_y + fm.ascent()
|
||||
painter.drawText(text_x, text_y, style.text)
|
||||
|
||||
painter.restore()
|
||||
Reference in New Issue
Block a user